17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*5e1c24c3Sss150715 * Common Development and Distribution License (the "License"). 6*5e1c24c3Sss150715 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*5e1c24c3Sss150715 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * Data-Link Provider Interface (Version 2) 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/stat.h> 377c478bd9Sstevel@tonic-gate #include <fcntl.h> 387c478bd9Sstevel@tonic-gate #include <unistd.h> 397c478bd9Sstevel@tonic-gate #include <poll.h> 407c478bd9Sstevel@tonic-gate #include <stropts.h> 417c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 427c478bd9Sstevel@tonic-gate #include <errno.h> 437c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 447c478bd9Sstevel@tonic-gate #include <ctype.h> 457c478bd9Sstevel@tonic-gate #include <libdlpi.h> 467c478bd9Sstevel@tonic-gate #include <libdladm.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate typedef enum dlpi_multi_op { 497c478bd9Sstevel@tonic-gate DLPI_MULTI_DISABLE = 0, 507c478bd9Sstevel@tonic-gate DLPI_MULTI_ENABLE 517c478bd9Sstevel@tonic-gate } dlpi_multi_op_t; 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate typedef enum dlpi_promisc_op { 547c478bd9Sstevel@tonic-gate DLPI_PROMISC_OFF = 0, 557c478bd9Sstevel@tonic-gate DLPI_PROMISC_ON 567c478bd9Sstevel@tonic-gate } dlpi_promisc_op_t; 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate const char *i_dlpi_mac_type[] = { 597c478bd9Sstevel@tonic-gate "CSMA/CD", /* 0x00 */ 607c478bd9Sstevel@tonic-gate "Token Bus", /* 0x01 */ 617c478bd9Sstevel@tonic-gate "Token Ring", /* 0x02 */ 627c478bd9Sstevel@tonic-gate "Metro Net", /* 0x03 */ 637c478bd9Sstevel@tonic-gate "Ethernet", /* 0x04 */ 647c478bd9Sstevel@tonic-gate "HDLC", /* 0x05 */ 657c478bd9Sstevel@tonic-gate "Sync Character", /* 0x06 */ 667c478bd9Sstevel@tonic-gate "CTCA", /* 0x07 */ 677c478bd9Sstevel@tonic-gate "FDDI", /* 0x08 */ 68*5e1c24c3Sss150715 "unknown", /* 0x09 */ 697c478bd9Sstevel@tonic-gate "Frame Relay (LAPF)", /* 0x0a */ 707c478bd9Sstevel@tonic-gate "MP Frame Relay", /* 0x0b */ 717c478bd9Sstevel@tonic-gate "Async Character", /* 0x0c */ 727c478bd9Sstevel@tonic-gate "X.25 (Classic IP)", /* 0x0d */ 737c478bd9Sstevel@tonic-gate "Software Loopback", /* 0x0e */ 747c478bd9Sstevel@tonic-gate "undefined", /* 0x0f */ 757c478bd9Sstevel@tonic-gate "Fiber Channel", /* 0x10 */ 767c478bd9Sstevel@tonic-gate "ATM", /* 0x11 */ 777c478bd9Sstevel@tonic-gate "ATM (Classic IP)", /* 0x12 */ 787c478bd9Sstevel@tonic-gate "X.25 (LAPB)", /* 0x13 */ 797c478bd9Sstevel@tonic-gate "ISDN", /* 0x14 */ 807c478bd9Sstevel@tonic-gate "HIPPI", /* 0x15 */ 817c478bd9Sstevel@tonic-gate "100BaseVG Ethernet", /* 0x16 */ 827c478bd9Sstevel@tonic-gate "100BaseVG Token Ring", /* 0x17 */ 837c478bd9Sstevel@tonic-gate "Ethernet/IEEE 802.3", /* 0x18 */ 847c478bd9Sstevel@tonic-gate "100BaseT", /* 0x19 */ 857c478bd9Sstevel@tonic-gate "Infiniband" /* 0x1a */ 867c478bd9Sstevel@tonic-gate }; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate static int i_dlpi_ifrm_num(char *, unsigned int *); 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate const char * 917c478bd9Sstevel@tonic-gate dlpi_mac_type(uint_t type) 927c478bd9Sstevel@tonic-gate { 937c478bd9Sstevel@tonic-gate if (type >= sizeof (i_dlpi_mac_type) / sizeof (i_dlpi_mac_type[0])) 947c478bd9Sstevel@tonic-gate return ("ERROR"); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate return (i_dlpi_mac_type[type]); 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate static int 1007c478bd9Sstevel@tonic-gate strputmsg(int fd, uint8_t *ctl_buf, size_t ctl_len, int flags) 1017c478bd9Sstevel@tonic-gate { 1027c478bd9Sstevel@tonic-gate struct strbuf ctl; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate ctl.buf = (char *)ctl_buf; 1057c478bd9Sstevel@tonic-gate ctl.len = ctl_len; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate return (putmsg(fd, &ctl, NULL, flags)); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate static int 1117c478bd9Sstevel@tonic-gate strgetmsg(int fd, int timeout, char *ctl_buf, 1127c478bd9Sstevel@tonic-gate size_t *ctl_lenp, char *data_buf, size_t *data_lenp) 1137c478bd9Sstevel@tonic-gate { 1147c478bd9Sstevel@tonic-gate struct strbuf ctl; 1157c478bd9Sstevel@tonic-gate struct strbuf data; 1167c478bd9Sstevel@tonic-gate int res; 1177c478bd9Sstevel@tonic-gate struct pollfd pfd; 1187c478bd9Sstevel@tonic-gate int flags = 0; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate pfd.fd = fd; 1217c478bd9Sstevel@tonic-gate pfd.events = POLLIN | POLLPRI; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate switch (poll(&pfd, 1, timeout)) { 1247c478bd9Sstevel@tonic-gate default: 1257c478bd9Sstevel@tonic-gate ctl.buf = ctl_buf; 1267c478bd9Sstevel@tonic-gate ctl.len = 0; 1277c478bd9Sstevel@tonic-gate ctl.maxlen = (ctl_lenp != NULL) ? *ctl_lenp : 0; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate data.buf = data_buf; 1307c478bd9Sstevel@tonic-gate data.len = 0; 1317c478bd9Sstevel@tonic-gate data.maxlen = (data_lenp != NULL) ? *data_lenp : 0; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if ((res = getmsg(fd, &ctl, &data, &flags)) < 0) 1347c478bd9Sstevel@tonic-gate goto failed; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate if (ctl_buf != NULL) { 1377c478bd9Sstevel@tonic-gate if (res & MORECTL) { 1387c478bd9Sstevel@tonic-gate errno = E2BIG; 1397c478bd9Sstevel@tonic-gate goto failed; 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate *ctl_lenp = ctl.len; 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate if (data_buf != NULL) { 1467c478bd9Sstevel@tonic-gate if (res & MOREDATA) { 1477c478bd9Sstevel@tonic-gate errno = E2BIG; 1487c478bd9Sstevel@tonic-gate goto failed; 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate *data_lenp = data.len; 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate break; 1557c478bd9Sstevel@tonic-gate case 0: 1567c478bd9Sstevel@tonic-gate errno = ETIME; 1577c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 1587c478bd9Sstevel@tonic-gate case -1: 1597c478bd9Sstevel@tonic-gate goto failed; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate return (0); 1637c478bd9Sstevel@tonic-gate failed: 1647c478bd9Sstevel@tonic-gate return (-1); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate int 1687c478bd9Sstevel@tonic-gate dlpi_open(const char *provider) 1697c478bd9Sstevel@tonic-gate { 1707c478bd9Sstevel@tonic-gate char devname[MAXPATHLEN]; 1717c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 1727c478bd9Sstevel@tonic-gate int fd; 1737c478bd9Sstevel@tonic-gate struct stat st; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate (void) snprintf(devname, MAXPATHLEN, "/dev/%s", provider); 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate if ((fd = open(devname, O_RDWR)) != -1) 1787c478bd9Sstevel@tonic-gate return (fd); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate (void) snprintf(path, MAXPATHLEN, "/devices/pseudo/clone@0:%s", 1817c478bd9Sstevel@tonic-gate provider); 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate if (stat(path, &st) == 0) { 1847c478bd9Sstevel@tonic-gate (void) strlcpy(devname, path, sizeof (devname)); 1857c478bd9Sstevel@tonic-gate if ((fd = open(devname, O_RDWR)) != -1) 1867c478bd9Sstevel@tonic-gate return (fd); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate return (-1); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate int 1937c478bd9Sstevel@tonic-gate dlpi_close(int fd) 1947c478bd9Sstevel@tonic-gate { 1957c478bd9Sstevel@tonic-gate return (close(fd)); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate int 1997c478bd9Sstevel@tonic-gate dlpi_info(int fd, int timeout, dl_info_ack_t *ackp, 2007c478bd9Sstevel@tonic-gate union DL_qos_types *selp, union DL_qos_types *rangep, 2017c478bd9Sstevel@tonic-gate uint8_t *addrp, size_t *addrlenp, uint8_t *brdcst_addrp, 2027c478bd9Sstevel@tonic-gate size_t *brdcst_addrlenp) 2037c478bd9Sstevel@tonic-gate { 2047c478bd9Sstevel@tonic-gate int rc = -1; 2057c478bd9Sstevel@tonic-gate size_t size; 2067c478bd9Sstevel@tonic-gate dl_info_ack_t *buf; 2077c478bd9Sstevel@tonic-gate dl_info_req_t dlir; 2087c478bd9Sstevel@tonic-gate dl_info_ack_t *dliap; 2097c478bd9Sstevel@tonic-gate union DL_qos_types *uqtp; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate size = sizeof (dl_info_ack_t); /* DL_INFO_ACK */ 2127c478bd9Sstevel@tonic-gate size += sizeof (union DL_qos_types); /* QoS selections */ 2137c478bd9Sstevel@tonic-gate size += sizeof (union DL_qos_types); /* QoS ranges */ 2147c478bd9Sstevel@tonic-gate size += MAXADDRLEN + MAXSAPLEN; /* DLSAP Address */ 2157c478bd9Sstevel@tonic-gate size += MAXADDRLEN; /* Broadcast Address */ 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 2187c478bd9Sstevel@tonic-gate return (-1); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate dlir.dl_primitive = DL_INFO_REQ; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlir, DL_INFO_REQ_SIZE, RS_HIPRI) == -1) 2237c478bd9Sstevel@tonic-gate goto done; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 2267c478bd9Sstevel@tonic-gate goto done; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if (size < DL_INFO_ACK_SIZE) { 2297c478bd9Sstevel@tonic-gate errno = EBADMSG; 2307c478bd9Sstevel@tonic-gate goto done; 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate dliap = (dl_info_ack_t *)buf; 2347c478bd9Sstevel@tonic-gate if (dliap->dl_primitive != DL_INFO_ACK || 2357c478bd9Sstevel@tonic-gate dliap->dl_version != DL_VERSION_2) { 2367c478bd9Sstevel@tonic-gate errno = EPROTO; 2377c478bd9Sstevel@tonic-gate goto done; 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate (void) memcpy(ackp, buf, DL_INFO_ACK_SIZE); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate if (dliap->dl_qos_offset != 0) { 2437c478bd9Sstevel@tonic-gate if (dliap->dl_qos_length < sizeof (t_uscalar_t)) { 2447c478bd9Sstevel@tonic-gate errno = EPROTO; 2457c478bd9Sstevel@tonic-gate goto done; 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate uqtp = (union DL_qos_types *) 2497c478bd9Sstevel@tonic-gate ((uintptr_t)buf + dliap->dl_qos_offset); 2507c478bd9Sstevel@tonic-gate if (uqtp->dl_qos_type != DL_QOS_CO_SEL1 && 2517c478bd9Sstevel@tonic-gate uqtp->dl_qos_type != DL_QOS_CL_SEL1) { 2527c478bd9Sstevel@tonic-gate errno = EPROTO; 2537c478bd9Sstevel@tonic-gate goto done; 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate if (selp != NULL) 2577c478bd9Sstevel@tonic-gate (void) memcpy(selp, (char *)buf + dliap->dl_qos_offset, 2587c478bd9Sstevel@tonic-gate dliap->dl_qos_length); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate if (dliap->dl_qos_range_offset != 0) { 2627c478bd9Sstevel@tonic-gate if (dliap->dl_qos_range_length < sizeof (t_uscalar_t)) { 2637c478bd9Sstevel@tonic-gate errno = EPROTO; 2647c478bd9Sstevel@tonic-gate goto done; 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate uqtp = (union DL_qos_types *) 2687c478bd9Sstevel@tonic-gate ((uintptr_t)buf + dliap->dl_qos_range_offset); 2697c478bd9Sstevel@tonic-gate if (uqtp->dl_qos_type != DL_QOS_CO_RANGE1 && 2707c478bd9Sstevel@tonic-gate uqtp->dl_qos_type != DL_QOS_CL_RANGE1) { 2717c478bd9Sstevel@tonic-gate errno = EPROTO; 2727c478bd9Sstevel@tonic-gate goto done; 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate if (rangep != NULL) 2767c478bd9Sstevel@tonic-gate (void) memcpy(rangep, 2777c478bd9Sstevel@tonic-gate (char *)buf + dliap->dl_qos_range_offset, 2787c478bd9Sstevel@tonic-gate dliap->dl_qos_range_length); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate if (dliap->dl_addr_offset != 0) { 2827c478bd9Sstevel@tonic-gate if (dliap->dl_addr_length == 0) { 2837c478bd9Sstevel@tonic-gate errno = EPROTO; 2847c478bd9Sstevel@tonic-gate goto done; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate if (addrlenp != NULL) 2887c478bd9Sstevel@tonic-gate *addrlenp = dliap->dl_addr_length; 2897c478bd9Sstevel@tonic-gate if (addrp != NULL) 2907c478bd9Sstevel@tonic-gate (void) memcpy(addrp, 2917c478bd9Sstevel@tonic-gate (char *)buf + dliap->dl_addr_offset, 2927c478bd9Sstevel@tonic-gate dliap->dl_addr_length); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate if (dliap->dl_brdcst_addr_offset != 0) { 2967c478bd9Sstevel@tonic-gate if (dliap->dl_brdcst_addr_length == 0) { 2977c478bd9Sstevel@tonic-gate errno = EPROTO; 2987c478bd9Sstevel@tonic-gate goto done; 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate if (brdcst_addrlenp != NULL) 3027c478bd9Sstevel@tonic-gate *brdcst_addrlenp = dliap->dl_brdcst_addr_length; 3037c478bd9Sstevel@tonic-gate if (brdcst_addrp != NULL) 3047c478bd9Sstevel@tonic-gate (void) memcpy(brdcst_addrp, 3057c478bd9Sstevel@tonic-gate (char *)buf + dliap->dl_brdcst_addr_offset, 3067c478bd9Sstevel@tonic-gate dliap->dl_brdcst_addr_length); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate rc = 0; /* success */ 3107c478bd9Sstevel@tonic-gate done: 3117c478bd9Sstevel@tonic-gate free(buf); 3127c478bd9Sstevel@tonic-gate return (rc); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate int 3167c478bd9Sstevel@tonic-gate dlpi_attach(int fd, int timeout, uint_t ppa) 3177c478bd9Sstevel@tonic-gate { 3187c478bd9Sstevel@tonic-gate int rc = -1; 3197c478bd9Sstevel@tonic-gate size_t size; 3207c478bd9Sstevel@tonic-gate dl_attach_req_t dlar; 3217c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 3227c478bd9Sstevel@tonic-gate union DL_primitives *buf; 3237c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate size = 0; 3267c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 3277c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 3307c478bd9Sstevel@tonic-gate return (-1); 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate dlar.dl_primitive = DL_ATTACH_REQ; 3337c478bd9Sstevel@tonic-gate dlar.dl_ppa = ppa; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlar, DL_ATTACH_REQ_SIZE, 0) == -1) 3367c478bd9Sstevel@tonic-gate goto done; 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 3397c478bd9Sstevel@tonic-gate goto done; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 3427c478bd9Sstevel@tonic-gate errno = EBADMSG; 3437c478bd9Sstevel@tonic-gate goto done; 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 3477c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 3487c478bd9Sstevel@tonic-gate case DL_OK_ACK: 3497c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 3507c478bd9Sstevel@tonic-gate errno = EBADMSG; 3517c478bd9Sstevel@tonic-gate goto done; 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate break; 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 3567c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 3577c478bd9Sstevel@tonic-gate errno = EBADMSG; 3587c478bd9Sstevel@tonic-gate goto done; 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 3627c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 3637c478bd9Sstevel@tonic-gate case DL_BADPPA: 3647c478bd9Sstevel@tonic-gate errno = EINVAL; 3657c478bd9Sstevel@tonic-gate break; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate case DL_ACCESS: 3687c478bd9Sstevel@tonic-gate errno = EPERM; 3697c478bd9Sstevel@tonic-gate break; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate case DL_SYSERR: 3727c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 3737c478bd9Sstevel@tonic-gate break; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate default: 3767c478bd9Sstevel@tonic-gate errno = EPROTO; 3777c478bd9Sstevel@tonic-gate break; 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate goto done; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate default: 3837c478bd9Sstevel@tonic-gate errno = EBADMSG; 3847c478bd9Sstevel@tonic-gate goto done; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate rc = 0; /* success */ 3887c478bd9Sstevel@tonic-gate done: 3897c478bd9Sstevel@tonic-gate free(buf); 3907c478bd9Sstevel@tonic-gate return (rc); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate int 3947c478bd9Sstevel@tonic-gate dlpi_detach(int fd, int timeout) 3957c478bd9Sstevel@tonic-gate { 3967c478bd9Sstevel@tonic-gate int rc = -1; 3977c478bd9Sstevel@tonic-gate size_t size; 3987c478bd9Sstevel@tonic-gate dl_detach_req_t dldr; 3997c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 4007c478bd9Sstevel@tonic-gate union DL_primitives *buf; 4017c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate size = 0; 4047c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 4057c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 4087c478bd9Sstevel@tonic-gate return (-1); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate dldr.dl_primitive = DL_DETACH_REQ; 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dldr, DL_DETACH_REQ_SIZE, 0) == -1) 4137c478bd9Sstevel@tonic-gate goto done; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 4167c478bd9Sstevel@tonic-gate goto done; 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 4197c478bd9Sstevel@tonic-gate errno = EBADMSG; 4207c478bd9Sstevel@tonic-gate goto done; 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 4247c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 4257c478bd9Sstevel@tonic-gate case DL_OK_ACK: 4267c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 4277c478bd9Sstevel@tonic-gate errno = EBADMSG; 4287c478bd9Sstevel@tonic-gate goto done; 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate break; 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 4337c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 4347c478bd9Sstevel@tonic-gate errno = EBADMSG; 4357c478bd9Sstevel@tonic-gate goto done; 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 4397c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 4407c478bd9Sstevel@tonic-gate case DL_SYSERR: 4417c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 4427c478bd9Sstevel@tonic-gate break; 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate default: 4457c478bd9Sstevel@tonic-gate errno = EPROTO; 4467c478bd9Sstevel@tonic-gate break; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate goto done; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate default: 4517c478bd9Sstevel@tonic-gate errno = EBADMSG; 4527c478bd9Sstevel@tonic-gate goto done; 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate rc = 0; /* success */ 4567c478bd9Sstevel@tonic-gate done: 4577c478bd9Sstevel@tonic-gate free(buf); 4587c478bd9Sstevel@tonic-gate return (rc); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate int 4627c478bd9Sstevel@tonic-gate dlpi_bind(int fd, int timeout, uint_t sap, uint16_t mode, 4637c478bd9Sstevel@tonic-gate boolean_t conn_mgmt, uint32_t *max_conn_ind, 4647c478bd9Sstevel@tonic-gate uint32_t *xid_test, uint8_t *addrp, size_t *addrlenp) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate int rc = -1; 4677c478bd9Sstevel@tonic-gate size_t size; 4687c478bd9Sstevel@tonic-gate dl_bind_req_t dlbr; 4697c478bd9Sstevel@tonic-gate dl_bind_ack_t *dlbap; 4707c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 4717c478bd9Sstevel@tonic-gate union DL_primitives *buf; 4727c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate size = 0; 4757c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_bind_ack_t) + MAXADDRLEN + MAXSAPLEN, size); 4767c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 4797c478bd9Sstevel@tonic-gate return (-1); 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate dlbr.dl_primitive = DL_BIND_REQ; 4827c478bd9Sstevel@tonic-gate dlbr.dl_sap = sap; 4837c478bd9Sstevel@tonic-gate dlbr.dl_service_mode = mode; 4847c478bd9Sstevel@tonic-gate dlbr.dl_conn_mgmt = (conn_mgmt) ? 1 : 0; 4857c478bd9Sstevel@tonic-gate dlbr.dl_max_conind = (max_conn_ind != NULL) ? *max_conn_ind : 0; 4867c478bd9Sstevel@tonic-gate dlbr.dl_xidtest_flg = (xid_test != NULL) ? *xid_test : 0; 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlbr, DL_BIND_REQ_SIZE, 0) == -1) 4897c478bd9Sstevel@tonic-gate goto done; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 4927c478bd9Sstevel@tonic-gate goto done; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 4957c478bd9Sstevel@tonic-gate errno = EBADMSG; 4967c478bd9Sstevel@tonic-gate goto done; 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 5007c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 5017c478bd9Sstevel@tonic-gate case DL_BIND_ACK: 5027c478bd9Sstevel@tonic-gate if (size < DL_BIND_ACK_SIZE) { 5037c478bd9Sstevel@tonic-gate errno = EBADMSG; 5047c478bd9Sstevel@tonic-gate goto done; 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate dlbap = (dl_bind_ack_t *)buf; 5087c478bd9Sstevel@tonic-gate if (max_conn_ind != NULL) 5097c478bd9Sstevel@tonic-gate *max_conn_ind = dlbap->dl_max_conind; 5107c478bd9Sstevel@tonic-gate if (xid_test != NULL) 5117c478bd9Sstevel@tonic-gate *xid_test = dlbap->dl_xidtest_flg; 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate if (dlbap->dl_addr_offset != 0) { 5147c478bd9Sstevel@tonic-gate if (dlbap->dl_addr_length == 0) { 5157c478bd9Sstevel@tonic-gate errno = EPROTO; 5167c478bd9Sstevel@tonic-gate goto done; 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate if (addrlenp != NULL) 5207c478bd9Sstevel@tonic-gate *addrlenp = dlbap->dl_addr_length; 5217c478bd9Sstevel@tonic-gate if (addrp != NULL) 5227c478bd9Sstevel@tonic-gate (void) memcpy(addrp, 5237c478bd9Sstevel@tonic-gate (char *)buf + dlbap->dl_addr_offset, 5247c478bd9Sstevel@tonic-gate dlbap->dl_addr_length); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate break; 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 5307c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 5317c478bd9Sstevel@tonic-gate errno = EBADMSG; 5327c478bd9Sstevel@tonic-gate goto done; 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 5367c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 5377c478bd9Sstevel@tonic-gate case DL_BADADDR: 5387c478bd9Sstevel@tonic-gate errno = EINVAL; 5397c478bd9Sstevel@tonic-gate break; 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate case DL_INITFAILED: 5427c478bd9Sstevel@tonic-gate case DL_NOTINIT: 5437c478bd9Sstevel@tonic-gate errno = EIO; 5447c478bd9Sstevel@tonic-gate break; 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate case DL_ACCESS: 5477c478bd9Sstevel@tonic-gate errno = EACCES; 5487c478bd9Sstevel@tonic-gate break; 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate case DL_NOADDR: 5517c478bd9Sstevel@tonic-gate errno = EFAULT; 5527c478bd9Sstevel@tonic-gate break; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate case DL_UNSUPPORTED: 5557c478bd9Sstevel@tonic-gate case DL_NOAUTO: 5567c478bd9Sstevel@tonic-gate case DL_NOXIDAUTO: 5577c478bd9Sstevel@tonic-gate case DL_NOTESTAUTO: 5587c478bd9Sstevel@tonic-gate errno = ENOTSUP; 5597c478bd9Sstevel@tonic-gate break; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate case DL_SYSERR: 5627c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 5637c478bd9Sstevel@tonic-gate break; 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate default: 5667c478bd9Sstevel@tonic-gate errno = EPROTO; 5677c478bd9Sstevel@tonic-gate break; 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate goto done; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate default: 5727c478bd9Sstevel@tonic-gate errno = EBADMSG; 5737c478bd9Sstevel@tonic-gate goto done; 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate rc = 0; /* success */ 5777c478bd9Sstevel@tonic-gate done: 5787c478bd9Sstevel@tonic-gate free(buf); 5797c478bd9Sstevel@tonic-gate return (rc); 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate int 5837c478bd9Sstevel@tonic-gate dlpi_unbind(int fd, int timeout) 5847c478bd9Sstevel@tonic-gate { 5857c478bd9Sstevel@tonic-gate int rc = -1; 5867c478bd9Sstevel@tonic-gate size_t size; 5877c478bd9Sstevel@tonic-gate dl_unbind_req_t dlubr; 5887c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 5897c478bd9Sstevel@tonic-gate union DL_primitives *buf; 5907c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate size = 0; 5937c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 5947c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 5977c478bd9Sstevel@tonic-gate return (-1); 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate dlubr.dl_primitive = DL_UNBIND_REQ; 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlubr, DL_UNBIND_REQ_SIZE, 0) == -1) 6027c478bd9Sstevel@tonic-gate goto done; 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 6057c478bd9Sstevel@tonic-gate goto done; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 6087c478bd9Sstevel@tonic-gate errno = EBADMSG; 6097c478bd9Sstevel@tonic-gate goto done; 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 6137c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 6147c478bd9Sstevel@tonic-gate case DL_OK_ACK: 6157c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 6167c478bd9Sstevel@tonic-gate errno = EBADMSG; 6177c478bd9Sstevel@tonic-gate goto done; 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate break; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 6227c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 6237c478bd9Sstevel@tonic-gate errno = EBADMSG; 6247c478bd9Sstevel@tonic-gate goto done; 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 6287c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 6297c478bd9Sstevel@tonic-gate case DL_SYSERR: 6307c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 6317c478bd9Sstevel@tonic-gate break; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate default: 6347c478bd9Sstevel@tonic-gate errno = EPROTO; 6357c478bd9Sstevel@tonic-gate break; 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate goto done; 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate default: 6407c478bd9Sstevel@tonic-gate errno = EBADMSG; 6417c478bd9Sstevel@tonic-gate goto done; 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate rc = 0; /* success */ 6457c478bd9Sstevel@tonic-gate done: 6467c478bd9Sstevel@tonic-gate free(buf); 6477c478bd9Sstevel@tonic-gate return (rc); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate static int 6517c478bd9Sstevel@tonic-gate i_dlpi_multi(int fd, int timeout, dlpi_multi_op_t op, 6527c478bd9Sstevel@tonic-gate uint8_t *addrp, size_t addr_length) 6537c478bd9Sstevel@tonic-gate { 6547c478bd9Sstevel@tonic-gate int rc = -1; 6557c478bd9Sstevel@tonic-gate size_t opsize; 6567c478bd9Sstevel@tonic-gate size_t size; 6577c478bd9Sstevel@tonic-gate dl_enabmulti_req_t *dlemrp; 6587c478bd9Sstevel@tonic-gate dl_disabmulti_req_t *dldmrp; 6597c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 6607c478bd9Sstevel@tonic-gate union DL_primitives *buf; 6617c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate opsize = (op == DLPI_MULTI_ENABLE) ? sizeof (dl_enabmulti_req_t) : 6647c478bd9Sstevel@tonic-gate sizeof (dl_disabmulti_req_t); 6657c478bd9Sstevel@tonic-gate opsize += addr_length; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate size = 0; 6687c478bd9Sstevel@tonic-gate size = MAX(opsize, size); 6697c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 6707c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 6737c478bd9Sstevel@tonic-gate return (-1); 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate if (op == DLPI_MULTI_ENABLE) { 6767c478bd9Sstevel@tonic-gate dlemrp = (dl_enabmulti_req_t *)buf; 6777c478bd9Sstevel@tonic-gate dlemrp->dl_primitive = DL_ENABMULTI_REQ; 6787c478bd9Sstevel@tonic-gate dlemrp->dl_addr_length = addr_length; 6797c478bd9Sstevel@tonic-gate dlemrp->dl_addr_offset = sizeof (dl_enabmulti_req_t); 6807c478bd9Sstevel@tonic-gate (void) memcpy(&dlemrp[1], addrp, addr_length); 6817c478bd9Sstevel@tonic-gate } else { 6827c478bd9Sstevel@tonic-gate dldmrp = (dl_disabmulti_req_t *)buf; 6837c478bd9Sstevel@tonic-gate dldmrp->dl_primitive = DL_DISABMULTI_REQ; 6847c478bd9Sstevel@tonic-gate dldmrp->dl_addr_length = addr_length; 6857c478bd9Sstevel@tonic-gate dldmrp->dl_addr_offset = sizeof (dl_disabmulti_req_t); 6867c478bd9Sstevel@tonic-gate (void) memcpy(&dldmrp[1], addrp, addr_length); 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)buf, opsize, 0) == -1) 6907c478bd9Sstevel@tonic-gate goto done; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 6937c478bd9Sstevel@tonic-gate goto done; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 6967c478bd9Sstevel@tonic-gate errno = EBADMSG; 6977c478bd9Sstevel@tonic-gate goto done; 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 7017c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 7027c478bd9Sstevel@tonic-gate case DL_OK_ACK: 7037c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 7047c478bd9Sstevel@tonic-gate errno = EBADMSG; 7057c478bd9Sstevel@tonic-gate goto done; 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate break; 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 7107c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 7117c478bd9Sstevel@tonic-gate errno = EBADMSG; 7127c478bd9Sstevel@tonic-gate goto done; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 7167c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 7177c478bd9Sstevel@tonic-gate case DL_BADADDR: 7187c478bd9Sstevel@tonic-gate errno = EINVAL; 7197c478bd9Sstevel@tonic-gate break; 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate case DL_TOOMANY: 7227c478bd9Sstevel@tonic-gate errno = ENOSPC; 7237c478bd9Sstevel@tonic-gate break; 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate case DL_NOTSUPPORTED: 7267c478bd9Sstevel@tonic-gate errno = ENOTSUP; 7277c478bd9Sstevel@tonic-gate break; 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate case DL_NOTENAB: 7307c478bd9Sstevel@tonic-gate errno = EINVAL; 7317c478bd9Sstevel@tonic-gate break; 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate case DL_SYSERR: 7347c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 7357c478bd9Sstevel@tonic-gate break; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate default: 7387c478bd9Sstevel@tonic-gate errno = EPROTO; 7397c478bd9Sstevel@tonic-gate break; 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate goto done; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate default: 7447c478bd9Sstevel@tonic-gate errno = EBADMSG; 7457c478bd9Sstevel@tonic-gate goto done; 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate rc = 0; /* success */ 7497c478bd9Sstevel@tonic-gate done: 7507c478bd9Sstevel@tonic-gate free(buf); 7517c478bd9Sstevel@tonic-gate return (rc); 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate int 7557c478bd9Sstevel@tonic-gate dlpi_enabmulti(int fd, int timeout, uint8_t *addrp, 7567c478bd9Sstevel@tonic-gate size_t addr_length) 7577c478bd9Sstevel@tonic-gate { 7587c478bd9Sstevel@tonic-gate return (i_dlpi_multi(fd, timeout, DLPI_MULTI_ENABLE, addrp, 7597c478bd9Sstevel@tonic-gate addr_length)); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate int 7637c478bd9Sstevel@tonic-gate dlpi_disabmulti(int fd, int timeout, uint8_t *addrp, 7647c478bd9Sstevel@tonic-gate size_t addr_length) 7657c478bd9Sstevel@tonic-gate { 7667c478bd9Sstevel@tonic-gate return (i_dlpi_multi(fd, timeout, DLPI_MULTI_DISABLE, addrp, 7677c478bd9Sstevel@tonic-gate addr_length)); 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate static int 7717c478bd9Sstevel@tonic-gate i_dlpi_promisc(int fd, int timeout, dlpi_promisc_op_t op, 7727c478bd9Sstevel@tonic-gate uint_t level) 7737c478bd9Sstevel@tonic-gate { 7747c478bd9Sstevel@tonic-gate int rc = -1; 7757c478bd9Sstevel@tonic-gate size_t opsize; 7767c478bd9Sstevel@tonic-gate size_t size; 7777c478bd9Sstevel@tonic-gate dl_promiscon_req_t *dlpnrp; 7787c478bd9Sstevel@tonic-gate dl_promiscoff_req_t *dlpfrp; 7797c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 7807c478bd9Sstevel@tonic-gate union DL_primitives *buf; 7817c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate opsize = (op == DLPI_PROMISC_ON) ? sizeof (dl_promiscon_req_t) : 7847c478bd9Sstevel@tonic-gate sizeof (dl_promiscoff_req_t); 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate size = 0; 7877c478bd9Sstevel@tonic-gate size = MAX(opsize, size); 7887c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 7897c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 7927c478bd9Sstevel@tonic-gate return (-1); 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate if (op == DLPI_PROMISC_ON) { 7957c478bd9Sstevel@tonic-gate dlpnrp = (dl_promiscon_req_t *)buf; 7967c478bd9Sstevel@tonic-gate dlpnrp->dl_primitive = DL_PROMISCON_REQ; 7977c478bd9Sstevel@tonic-gate dlpnrp->dl_level = level; 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)dlpnrp, opsize, 0) == -1) 8007c478bd9Sstevel@tonic-gate goto done; 8017c478bd9Sstevel@tonic-gate } else { 8027c478bd9Sstevel@tonic-gate dlpfrp = (dl_promiscoff_req_t *)buf; 8037c478bd9Sstevel@tonic-gate dlpfrp->dl_primitive = DL_PROMISCOFF_REQ; 8047c478bd9Sstevel@tonic-gate dlpfrp->dl_level = level; 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)dlpfrp, opsize, 0) == -1) 8077c478bd9Sstevel@tonic-gate goto done; 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 8117c478bd9Sstevel@tonic-gate goto done; 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 8147c478bd9Sstevel@tonic-gate errno = EBADMSG; 8157c478bd9Sstevel@tonic-gate goto done; 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 8197c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 8207c478bd9Sstevel@tonic-gate case DL_OK_ACK: 8217c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 8227c478bd9Sstevel@tonic-gate errno = EBADMSG; 8237c478bd9Sstevel@tonic-gate goto done; 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate break; 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 8287c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 8297c478bd9Sstevel@tonic-gate errno = EBADMSG; 8307c478bd9Sstevel@tonic-gate goto done; 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 8347c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 8357c478bd9Sstevel@tonic-gate case DL_NOTSUPPORTED: 8367c478bd9Sstevel@tonic-gate case DL_UNSUPPORTED: 8377c478bd9Sstevel@tonic-gate errno = ENOTSUP; 8387c478bd9Sstevel@tonic-gate break; 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate case DL_NOTENAB: 8417c478bd9Sstevel@tonic-gate errno = EINVAL; 8427c478bd9Sstevel@tonic-gate break; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate case DL_SYSERR: 8457c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 8467c478bd9Sstevel@tonic-gate break; 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate default: 8497c478bd9Sstevel@tonic-gate errno = EPROTO; 8507c478bd9Sstevel@tonic-gate break; 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate goto done; 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate default: 8557c478bd9Sstevel@tonic-gate errno = EBADMSG; 8567c478bd9Sstevel@tonic-gate goto done; 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate rc = 0; /* success */ 8607c478bd9Sstevel@tonic-gate done: 8617c478bd9Sstevel@tonic-gate free(buf); 8627c478bd9Sstevel@tonic-gate return (rc); 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate int 8667c478bd9Sstevel@tonic-gate dlpi_promiscon(int fd, int timeout, uint_t level) 8677c478bd9Sstevel@tonic-gate { 8687c478bd9Sstevel@tonic-gate return (i_dlpi_promisc(fd, timeout, DLPI_PROMISC_ON, level)); 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate int 8727c478bd9Sstevel@tonic-gate dlpi_promiscoff(int fd, int timeout, uint_t level) 8737c478bd9Sstevel@tonic-gate { 8747c478bd9Sstevel@tonic-gate return (i_dlpi_promisc(fd, timeout, DLPI_PROMISC_OFF, level)); 8757c478bd9Sstevel@tonic-gate } 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate int 8787c478bd9Sstevel@tonic-gate dlpi_phys_addr(int fd, int timeout, uint_t type, uint8_t *addrp, 8797c478bd9Sstevel@tonic-gate size_t *addrlenp) 8807c478bd9Sstevel@tonic-gate { 8817c478bd9Sstevel@tonic-gate int rc = -1; 8827c478bd9Sstevel@tonic-gate size_t size; 8837c478bd9Sstevel@tonic-gate dl_phys_addr_req_t dlpar; 8847c478bd9Sstevel@tonic-gate dl_phys_addr_ack_t *dlpaap; 8857c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 8867c478bd9Sstevel@tonic-gate union DL_primitives *buf; 8877c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate size = 0; 8907c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_phys_addr_ack_t) + MAXADDRLEN, size); 8917c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 8947c478bd9Sstevel@tonic-gate return (-1); 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate dlpar.dl_primitive = DL_PHYS_ADDR_REQ; 8977c478bd9Sstevel@tonic-gate dlpar.dl_addr_type = type; 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlpar, DL_PHYS_ADDR_REQ_SIZE, 0) == -1) 9007c478bd9Sstevel@tonic-gate goto done; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 9037c478bd9Sstevel@tonic-gate goto done; 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 9067c478bd9Sstevel@tonic-gate errno = EBADMSG; 9077c478bd9Sstevel@tonic-gate goto done; 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 9117c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 9127c478bd9Sstevel@tonic-gate case DL_PHYS_ADDR_ACK: 9137c478bd9Sstevel@tonic-gate if (size < DL_PHYS_ADDR_ACK_SIZE) { 9147c478bd9Sstevel@tonic-gate errno = EBADMSG; 9157c478bd9Sstevel@tonic-gate goto done; 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate dlpaap = (dl_phys_addr_ack_t *)buf; 9197c478bd9Sstevel@tonic-gate if (dlpaap->dl_addr_offset != 0) { 9207c478bd9Sstevel@tonic-gate if (dlpaap->dl_addr_length == 0) { 9217c478bd9Sstevel@tonic-gate errno = EPROTO; 9227c478bd9Sstevel@tonic-gate goto done; 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate if (addrlenp != NULL) 9267c478bd9Sstevel@tonic-gate *addrlenp = dlpaap->dl_addr_length; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate if (addrp != NULL) 9297c478bd9Sstevel@tonic-gate (void) memcpy(addrp, 9307c478bd9Sstevel@tonic-gate (char *)buf + dlpaap->dl_addr_offset, 9317c478bd9Sstevel@tonic-gate dlpaap->dl_addr_length); 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate break; 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 9367c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 9377c478bd9Sstevel@tonic-gate errno = EBADMSG; 9387c478bd9Sstevel@tonic-gate goto done; 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 9427c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 9437c478bd9Sstevel@tonic-gate case DL_SYSERR: 9447c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 9457c478bd9Sstevel@tonic-gate break; 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate default: 9487c478bd9Sstevel@tonic-gate errno = EPROTO; 9497c478bd9Sstevel@tonic-gate break; 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate goto done; 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate default: 9547c478bd9Sstevel@tonic-gate errno = EBADMSG; 9557c478bd9Sstevel@tonic-gate goto done; 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate rc = 0; /* success */ 9597c478bd9Sstevel@tonic-gate done: 9607c478bd9Sstevel@tonic-gate free(buf); 9617c478bd9Sstevel@tonic-gate return (rc); 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate int 9657c478bd9Sstevel@tonic-gate dlpi_set_phys_addr(int fd, int timeout, uint8_t *addrp, 9667c478bd9Sstevel@tonic-gate size_t addr_length) 9677c478bd9Sstevel@tonic-gate { 9687c478bd9Sstevel@tonic-gate int rc = -1; 9697c478bd9Sstevel@tonic-gate size_t opsize; 9707c478bd9Sstevel@tonic-gate size_t size; 9717c478bd9Sstevel@tonic-gate dl_set_phys_addr_req_t *dlspap; 9727c478bd9Sstevel@tonic-gate dl_error_ack_t *dleap; 9737c478bd9Sstevel@tonic-gate union DL_primitives *buf; 9747c478bd9Sstevel@tonic-gate union DL_primitives *udlp; 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate opsize = sizeof (dl_set_phys_addr_req_t) + addr_length; 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate size = 0; 9797c478bd9Sstevel@tonic-gate size = MAX(opsize, size); 9807c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), size); 9817c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_error_ack_t), size); 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 9847c478bd9Sstevel@tonic-gate return (-1); 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate dlspap = (dl_set_phys_addr_req_t *)buf; 9877c478bd9Sstevel@tonic-gate dlspap->dl_primitive = DL_SET_PHYS_ADDR_REQ; 9887c478bd9Sstevel@tonic-gate dlspap->dl_addr_length = addr_length; 9897c478bd9Sstevel@tonic-gate dlspap->dl_addr_offset = sizeof (dl_set_phys_addr_req_t); 9907c478bd9Sstevel@tonic-gate (void) memcpy(&dlspap[1], addrp, addr_length); 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)dlspap, opsize, 0) == -1) 9937c478bd9Sstevel@tonic-gate goto done; 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate if (strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL) == -1) 9967c478bd9Sstevel@tonic-gate goto done; 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate if (size < sizeof (t_uscalar_t)) { 9997c478bd9Sstevel@tonic-gate errno = EBADMSG; 10007c478bd9Sstevel@tonic-gate goto done; 10017c478bd9Sstevel@tonic-gate } 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate udlp = (union DL_primitives *)buf; 10047c478bd9Sstevel@tonic-gate switch (udlp->dl_primitive) { 10057c478bd9Sstevel@tonic-gate case DL_OK_ACK: 10067c478bd9Sstevel@tonic-gate if (size < DL_OK_ACK_SIZE) { 10077c478bd9Sstevel@tonic-gate errno = EBADMSG; 10087c478bd9Sstevel@tonic-gate goto done; 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate break; 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate case DL_ERROR_ACK: 10137c478bd9Sstevel@tonic-gate if (size < DL_ERROR_ACK_SIZE) { 10147c478bd9Sstevel@tonic-gate errno = EBADMSG; 10157c478bd9Sstevel@tonic-gate goto done; 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate dleap = (dl_error_ack_t *)buf; 10197c478bd9Sstevel@tonic-gate switch (dleap->dl_errno) { 10207c478bd9Sstevel@tonic-gate case DL_BADADDR: 10217c478bd9Sstevel@tonic-gate errno = EINVAL; 10227c478bd9Sstevel@tonic-gate break; 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate case DL_NOTSUPPORTED: 10257c478bd9Sstevel@tonic-gate errno = ENOTSUP; 10267c478bd9Sstevel@tonic-gate break; 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate case DL_SYSERR: 10297c478bd9Sstevel@tonic-gate errno = dleap->dl_unix_errno; 10307c478bd9Sstevel@tonic-gate break; 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate default: 10337c478bd9Sstevel@tonic-gate errno = EPROTO; 10347c478bd9Sstevel@tonic-gate break; 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate goto done; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate default: 10397c478bd9Sstevel@tonic-gate errno = EBADMSG; 10407c478bd9Sstevel@tonic-gate goto done; 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate rc = 0; /* success */ 10447c478bd9Sstevel@tonic-gate done: 10457c478bd9Sstevel@tonic-gate free(buf); 10467c478bd9Sstevel@tonic-gate return (rc); 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate void 10507c478bd9Sstevel@tonic-gate dlpi_passive(int fd, int timeout) 10517c478bd9Sstevel@tonic-gate { 10527c478bd9Sstevel@tonic-gate size_t size; 10537c478bd9Sstevel@tonic-gate dl_passive_req_t dlpr; 10547c478bd9Sstevel@tonic-gate union DL_primitives *buf; 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate size = MAX(sizeof (dl_ok_ack_t), sizeof (dl_error_ack_t)); 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate if ((buf = malloc(size)) == NULL) 10597c478bd9Sstevel@tonic-gate return; 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate dlpr.dl_primitive = DL_PASSIVE_REQ; 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate /* 10647c478bd9Sstevel@tonic-gate * We don't care about the outcome of this operation. We at least 10657c478bd9Sstevel@tonic-gate * don't want to return until the operation completes or the 10667c478bd9Sstevel@tonic-gate * timeout expires. 10677c478bd9Sstevel@tonic-gate */ 10687c478bd9Sstevel@tonic-gate if (strputmsg(fd, (uint8_t *)&dlpr, DL_PASSIVE_REQ_SIZE, 0) == 0) 10697c478bd9Sstevel@tonic-gate (void) strgetmsg(fd, timeout, (char *)buf, &size, NULL, NULL); 10707c478bd9Sstevel@tonic-gate free(buf); 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate static int 10747c478bd9Sstevel@tonic-gate i_dlpi_style1_open(dlpi_if_attr_t *diap) 10757c478bd9Sstevel@tonic-gate { 10767c478bd9Sstevel@tonic-gate int fd; 10777c478bd9Sstevel@tonic-gate int cnt; 10787c478bd9Sstevel@tonic-gate dl_info_ack_t dlia; 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate /* Open device */ 10817c478bd9Sstevel@tonic-gate if ((fd = dlpi_open(diap->devname)) == -1) { 10827c478bd9Sstevel@tonic-gate diap->style1_failed = B_TRUE; 10837c478bd9Sstevel@tonic-gate diap->mod_pushed = 0; 10847c478bd9Sstevel@tonic-gate return (-1); 10857c478bd9Sstevel@tonic-gate } else { 10867c478bd9Sstevel@tonic-gate diap->style1_fd = fd; 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate /* 10907c478bd9Sstevel@tonic-gate * Try to push modules (if any) onto the device stream 10917c478bd9Sstevel@tonic-gate */ 10927c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < diap->mod_cnt; cnt++) { 10937c478bd9Sstevel@tonic-gate if (ioctl(fd, I_PUSH, diap->modlist[cnt]) == -1) { 10947c478bd9Sstevel@tonic-gate diap->mod_pushed = cnt+1; 10957c478bd9Sstevel@tonic-gate return (-1); 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) == -1) 11007c478bd9Sstevel@tonic-gate goto failed; 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate if (dlia.dl_provider_style != DL_STYLE1) 11037c478bd9Sstevel@tonic-gate goto failed; 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate diap->style = DL_STYLE1; 1106*5e1c24c3Sss150715 diap->style1_failed = B_FALSE; 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate return (fd); 11097c478bd9Sstevel@tonic-gate failed: 1110*5e1c24c3Sss150715 diap->style1_failed = B_TRUE; 11117c478bd9Sstevel@tonic-gate (void) dlpi_close(fd); 11127c478bd9Sstevel@tonic-gate return (-1); 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate static int 11167c478bd9Sstevel@tonic-gate i_dlpi_style2_open(dlpi_if_attr_t *diap) 11177c478bd9Sstevel@tonic-gate { 11187c478bd9Sstevel@tonic-gate int fd; 11197c478bd9Sstevel@tonic-gate uint_t ppa; 11207c478bd9Sstevel@tonic-gate dl_info_ack_t dlia; 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate /* 11237c478bd9Sstevel@tonic-gate * If style 1 open failed, we need to determine how far it got and 11247c478bd9Sstevel@tonic-gate * finish up the open() call as a style 2 open 11257c478bd9Sstevel@tonic-gate * 11267c478bd9Sstevel@tonic-gate * If no modules were pushed (mod_pushed == 0), then we need to 11277c478bd9Sstevel@tonic-gate * strip off the ppa off the device name and open it as a style 2 11287c478bd9Sstevel@tonic-gate * device 11297c478bd9Sstevel@tonic-gate * 11307c478bd9Sstevel@tonic-gate * If the pushing of the last module failed, we need to strip off the 11317c478bd9Sstevel@tonic-gate * ppa from that module and try pushing it as a style 2 module 11327c478bd9Sstevel@tonic-gate * 11337c478bd9Sstevel@tonic-gate * Otherwise we failed during the push of an intermediate module and 11347c478bd9Sstevel@tonic-gate * must fail out and close the device. 11357c478bd9Sstevel@tonic-gate * 11367c478bd9Sstevel@tonic-gate * And if style1 did not fail (i.e. we called style2 open directly), 11377c478bd9Sstevel@tonic-gate * just open the device 11387c478bd9Sstevel@tonic-gate */ 11397c478bd9Sstevel@tonic-gate if (diap->style1_failed) { 11407c478bd9Sstevel@tonic-gate if (!diap->mod_pushed) { 11417c478bd9Sstevel@tonic-gate if (i_dlpi_ifrm_num(diap->devname, &ppa) < 0) 11427c478bd9Sstevel@tonic-gate return (-1); 11437c478bd9Sstevel@tonic-gate if ((fd = dlpi_open(diap->devname)) == -1) 11447c478bd9Sstevel@tonic-gate return (-1); 11457c478bd9Sstevel@tonic-gate } else if (diap->mod_pushed == diap->mod_cnt) { 11467c478bd9Sstevel@tonic-gate if (i_dlpi_ifrm_num( 11477c478bd9Sstevel@tonic-gate diap->modlist[diap->mod_cnt - 1], &ppa) < 0) 11487c478bd9Sstevel@tonic-gate return (-1); 11497c478bd9Sstevel@tonic-gate diap->mod_pushed--; 11507c478bd9Sstevel@tonic-gate fd = diap->style1_fd; 11517c478bd9Sstevel@tonic-gate } else { 11527c478bd9Sstevel@tonic-gate return (-1); 11537c478bd9Sstevel@tonic-gate } 11547c478bd9Sstevel@tonic-gate } else { 11557c478bd9Sstevel@tonic-gate if ((fd = dlpi_open(diap->devname)) == -1) 11567c478bd9Sstevel@tonic-gate return (-1); 11577c478bd9Sstevel@tonic-gate } 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate /* 11607c478bd9Sstevel@tonic-gate * Try and push modules (if any) onto the device stream 11617c478bd9Sstevel@tonic-gate */ 11627c478bd9Sstevel@tonic-gate for (; diap->mod_pushed < diap->mod_cnt; diap->mod_pushed++) { 11637c478bd9Sstevel@tonic-gate if (ioctl(fd, I_PUSH, 11647c478bd9Sstevel@tonic-gate diap->modlist[diap->mod_pushed]) == -1) 11657c478bd9Sstevel@tonic-gate goto failed; 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, 11697c478bd9Sstevel@tonic-gate NULL) == -1) 11707c478bd9Sstevel@tonic-gate goto failed; 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate if (dlia.dl_provider_style != DL_STYLE2) 11737c478bd9Sstevel@tonic-gate goto failed; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate diap->style = DL_STYLE2; 11767c478bd9Sstevel@tonic-gate 11777c478bd9Sstevel@tonic-gate if (dlpi_attach(fd, -1, diap->ppa) < 0) 11787c478bd9Sstevel@tonic-gate goto failed; 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate return (fd); 11817c478bd9Sstevel@tonic-gate failed: 11827c478bd9Sstevel@tonic-gate (void) dlpi_close(fd); 11837c478bd9Sstevel@tonic-gate return (-1); 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate static int 11877c478bd9Sstevel@tonic-gate i_dlpi_ifname_parse(const char *ifname, dlpi_if_attr_t *diap) 11887c478bd9Sstevel@tonic-gate { 11897c478bd9Sstevel@tonic-gate char *modlist = NULL; /* list of modules to push */ 11907c478bd9Sstevel@tonic-gate int cnt = 0; /* number of modules to push */ 11917c478bd9Sstevel@tonic-gate char modbuf[LIFNAMSIZ + 32]; 11927c478bd9Sstevel@tonic-gate char *nxtmod; 11937c478bd9Sstevel@tonic-gate char *p; 11947c478bd9Sstevel@tonic-gate int len; 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate /* if lun is specified fail (backwards compat) */ 11977c478bd9Sstevel@tonic-gate if (strchr(ifname, ':') != NULL) 11987c478bd9Sstevel@tonic-gate return (-1); 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate /* save copy of original device name */ 12017c478bd9Sstevel@tonic-gate if (strlcpy(diap->ifname, ifname, sizeof (diap->ifname)) >= 12027c478bd9Sstevel@tonic-gate sizeof (diap->ifname)) 12037c478bd9Sstevel@tonic-gate return (-1); 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate /* initialize ppa */ 12067c478bd9Sstevel@tonic-gate diap->ppa = -1; 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate /* get provider name and ppa from ifname */ 12097c478bd9Sstevel@tonic-gate len = strlen(ifname); 12107c478bd9Sstevel@tonic-gate for (p = (char *)ifname + len; --p != ifname; len--) { 12117c478bd9Sstevel@tonic-gate if (!isdigit(*p)) { 12127c478bd9Sstevel@tonic-gate (void) strlcpy(diap->provider, ifname, len + 1); 12137c478bd9Sstevel@tonic-gate diap->ppa = atoi(p + 1); 12147c478bd9Sstevel@tonic-gate break; 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate } 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate if (strlcpy(modbuf, diap->ifname, sizeof (modbuf)) >= 12197c478bd9Sstevel@tonic-gate sizeof (modbuf)) 12207c478bd9Sstevel@tonic-gate return (-1); 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate /* parse '.' delimited module list */ 12237c478bd9Sstevel@tonic-gate modlist = strchr(modbuf, '.'); 12247c478bd9Sstevel@tonic-gate if (modlist != NULL) { 12257c478bd9Sstevel@tonic-gate /* null-terminate interface name (device) */ 12267c478bd9Sstevel@tonic-gate *modlist = '\0'; 12277c478bd9Sstevel@tonic-gate modlist++; 12287c478bd9Sstevel@tonic-gate while (modlist && cnt < MAX_MODS) { 12297c478bd9Sstevel@tonic-gate if (*modlist == '\0') 12307c478bd9Sstevel@tonic-gate return (-1); 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate nxtmod = strchr(modlist, '.'); 12337c478bd9Sstevel@tonic-gate if (nxtmod) { 12347c478bd9Sstevel@tonic-gate *nxtmod = '\0'; 12357c478bd9Sstevel@tonic-gate nxtmod++; 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate if (strlcpy(diap->modlist[cnt], modlist, 12387c478bd9Sstevel@tonic-gate sizeof (diap->modlist[cnt])) >= 12397c478bd9Sstevel@tonic-gate sizeof (diap->modlist[cnt])) 12407c478bd9Sstevel@tonic-gate return (-1); 12417c478bd9Sstevel@tonic-gate cnt++; 12427c478bd9Sstevel@tonic-gate modlist = nxtmod; 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate diap->mod_cnt = cnt; 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate if (strlcpy(diap->devname, modbuf, sizeof (diap->devname)) >= 12487c478bd9Sstevel@tonic-gate sizeof (diap->devname)) 12497c478bd9Sstevel@tonic-gate return (-1); 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate return (0); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate int 12557c478bd9Sstevel@tonic-gate dlpi_if_open(const char *ifname, dlpi_if_attr_t *diap, 12567c478bd9Sstevel@tonic-gate boolean_t force_style2) 12577c478bd9Sstevel@tonic-gate { 12587c478bd9Sstevel@tonic-gate int fd; 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate if (i_dlpi_ifname_parse(ifname, diap) == -1) { 12617c478bd9Sstevel@tonic-gate errno = EINVAL; 12627c478bd9Sstevel@tonic-gate return (-1); 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate 1265*5e1c24c3Sss150715 diap->style1_failed = B_TRUE; 1266*5e1c24c3Sss150715 12677c478bd9Sstevel@tonic-gate if (!force_style2) { 12687c478bd9Sstevel@tonic-gate if ((fd = i_dlpi_style1_open(diap)) != -1) 12697c478bd9Sstevel@tonic-gate return (fd); 12707c478bd9Sstevel@tonic-gate } 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate if ((fd = i_dlpi_style2_open(diap)) == -1) 12737c478bd9Sstevel@tonic-gate return (-1); 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate return (fd); 12767c478bd9Sstevel@tonic-gate } 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate int 12797c478bd9Sstevel@tonic-gate dlpi_if_parse(const char *ifname, char *provider, int *ppap) 12807c478bd9Sstevel@tonic-gate { 12817c478bd9Sstevel@tonic-gate dlpi_if_attr_t diap; 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate if (i_dlpi_ifname_parse(ifname, &diap) == -1) { 12847c478bd9Sstevel@tonic-gate errno = EINVAL; 12857c478bd9Sstevel@tonic-gate return (-1); 12867c478bd9Sstevel@tonic-gate } 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate if (strlcpy(provider, diap.provider, LIFNAMSIZ) > LIFNAMSIZ) 12897c478bd9Sstevel@tonic-gate return (-1); 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate if (ppap != NULL) 12927c478bd9Sstevel@tonic-gate *ppap = diap.ppa; 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate return (0); 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate /* 12987c478bd9Sstevel@tonic-gate * attempt to remove ppa from end of file name 12997c478bd9Sstevel@tonic-gate * return -1 if none found 13007c478bd9Sstevel@tonic-gate * return ppa if found and remove the ppa from the filename 13017c478bd9Sstevel@tonic-gate */ 13027c478bd9Sstevel@tonic-gate static int 13037c478bd9Sstevel@tonic-gate i_dlpi_ifrm_num(char *fname, unsigned int *ppa) 13047c478bd9Sstevel@tonic-gate { 13057c478bd9Sstevel@tonic-gate int i; 13067c478bd9Sstevel@tonic-gate uint_t p = 0; 13077c478bd9Sstevel@tonic-gate unsigned int m = 1; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate i = strlen(fname) - 1; 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate while (i >= 0 && isdigit(fname[i])) { 13127c478bd9Sstevel@tonic-gate p += (fname[i] - '0')*m; 13137c478bd9Sstevel@tonic-gate m *= 10; 13147c478bd9Sstevel@tonic-gate i--; 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate if (m == 1) { 13187c478bd9Sstevel@tonic-gate return (-1); 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate fname[i + 1] = '\0'; 13227c478bd9Sstevel@tonic-gate *ppa = p; 13237c478bd9Sstevel@tonic-gate return (0); 13247c478bd9Sstevel@tonic-gate } 1325