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 55e1c24c3Sss150715 * Common Development and Distribution License (the "License"). 65e1c24c3Sss150715 * 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 /* 22c7e4935fSss150715 * Copyright 2007 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 #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <unistd.h> 387c478bd9Sstevel@tonic-gate #include <poll.h> 397c478bd9Sstevel@tonic-gate #include <stropts.h> 407c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 417c478bd9Sstevel@tonic-gate #include <errno.h> 42c7e4935fSss150715 #include <alloca.h> 437c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 447c478bd9Sstevel@tonic-gate #include <ctype.h> 45948f2876Sss150715 #include <net/if_types.h> 46948f2876Sss150715 #include <netinet/arp.h> 477c478bd9Sstevel@tonic-gate #include <libdlpi.h> 48c7e4935fSss150715 #include <libintl.h> 49c7e4935fSss150715 #include <libinetutil.h> 507c478bd9Sstevel@tonic-gate 51c7e4935fSss150715 #include "libdlpi_impl.h" 527c478bd9Sstevel@tonic-gate 53c7e4935fSss150715 static int i_dlpi_open(const char *, int *, uint_t); 54c7e4935fSss150715 static int i_dlpi_style1_open(dlpi_impl_t *); 55c7e4935fSss150715 static int i_dlpi_style2_open(dlpi_impl_t *); 56c7e4935fSss150715 static int i_dlpi_checkstyle(dlpi_impl_t *, t_uscalar_t); 57c7e4935fSss150715 static int i_dlpi_remove_ppa(char *); 58c7e4935fSss150715 static int i_dlpi_attach(dlpi_impl_t *); 59c7e4935fSss150715 static void i_dlpi_passive(dlpi_impl_t *); 607c478bd9Sstevel@tonic-gate 61c7e4935fSss150715 static int i_dlpi_strputmsg(int, const dlpi_msg_t *, const void *, size_t, int); 62c7e4935fSss150715 static int i_dlpi_strgetmsg(int, int, dlpi_msg_t *, t_uscalar_t, t_uscalar_t, 63c7e4935fSss150715 size_t, void *, size_t *, size_t *); 64c7e4935fSss150715 static int i_dlpi_msg_common(dlpi_impl_t *, const dlpi_msg_t *, dlpi_msg_t *, 65c7e4935fSss150715 size_t, int); 667c478bd9Sstevel@tonic-gate 67c7e4935fSss150715 static size_t i_dlpi_getprimsize(t_uscalar_t); 68c7e4935fSss150715 static int i_dlpi_multi(dlpi_handle_t, t_uscalar_t, const uint8_t *, size_t); 69c7e4935fSss150715 static int i_dlpi_promisc(dlpi_handle_t, t_uscalar_t, uint_t); 70c7e4935fSss150715 static uint_t i_dlpi_buildsap(uint8_t *, uint_t); 71c7e4935fSss150715 static void i_dlpi_writesap(void *, uint_t, uint_t); 72c7e4935fSss150715 73c7e4935fSss150715 int 74c7e4935fSss150715 dlpi_open(const char *linkname, dlpi_handle_t *dhp, uint_t flags) 75c7e4935fSss150715 { 76c7e4935fSss150715 int retval; 77c7e4935fSss150715 int cnt; 78c7e4935fSss150715 ifspec_t ifsp; 79c7e4935fSss150715 dlpi_impl_t *dip; 80c7e4935fSss150715 81c7e4935fSss150715 /* 82c7e4935fSss150715 * Validate linkname, fail if logical unit number (lun) is specified, 83c7e4935fSss150715 * otherwise decompose the contents into ifsp. 84c7e4935fSss150715 */ 85c7e4935fSss150715 if (linkname == NULL || (strchr(linkname, ':') != NULL) || 86c7e4935fSss150715 !ifparse_ifspec(linkname, &ifsp)) 87c7e4935fSss150715 return (DLPI_ELINKNAMEINVAL); 88c7e4935fSss150715 89c7e4935fSss150715 /* Allocate a new dlpi_impl_t. */ 90c7e4935fSss150715 if ((dip = calloc(1, sizeof (dlpi_impl_t))) == NULL) 91c7e4935fSss150715 return (DL_SYSERR); 92c7e4935fSss150715 93c7e4935fSss150715 /* Fill in known/default libdlpi handle values. */ 94c7e4935fSss150715 dip->dli_timeout = DLPI_DEF_TIMEOUT; 95c7e4935fSss150715 dip->dli_ppa = ifsp.ifsp_ppa; 96c7e4935fSss150715 dip->dli_mod_cnt = ifsp.ifsp_modcnt; 97c7e4935fSss150715 dip->dli_oflags = flags; 98c7e4935fSss150715 99c7e4935fSss150715 for (cnt = 0; cnt != dip->dli_mod_cnt; cnt++) { 100c7e4935fSss150715 (void) strlcpy(dip->dli_modlist[cnt], ifsp.ifsp_mods[cnt], 101c7e4935fSss150715 DLPI_LINKNAME_MAX); 102c7e4935fSss150715 } 103c7e4935fSss150715 104c7e4935fSss150715 /* Copy linkname provided to the function. */ 105c7e4935fSss150715 if (strlcpy(dip->dli_linkname, linkname, sizeof (dip->dli_linkname)) >= 106c7e4935fSss150715 sizeof (dip->dli_linkname)) { 107c7e4935fSss150715 free(dip); 108c7e4935fSss150715 return (DLPI_ELINKNAMEINVAL); 109c7e4935fSss150715 } 110c7e4935fSss150715 111c7e4935fSss150715 /* Copy provider name. */ 112c7e4935fSss150715 (void) strlcpy(dip->dli_provider, ifsp.ifsp_devnm, 113c7e4935fSss150715 sizeof (dip->dli_provider)); 114c7e4935fSss150715 115c7e4935fSss150715 /* 116c7e4935fSss150715 * Special case: DLPI_SERIAL flag is set to indicate a synchronous 117c7e4935fSss150715 * serial line interface (see syncinit(1M), syncstat(1M), 118c7e4935fSss150715 * syncloop(1M)), which is not a DLPI link. 119c7e4935fSss150715 */ 120c7e4935fSss150715 if (dip->dli_oflags & DLPI_SERIAL) { 121c7e4935fSss150715 if ((retval = i_dlpi_style2_open(dip)) != DLPI_SUCCESS) { 122c7e4935fSss150715 free(dip); 123c7e4935fSss150715 return (retval); 124c7e4935fSss150715 } 125c7e4935fSss150715 126c7e4935fSss150715 *dhp = (dlpi_handle_t)dip; 127c7e4935fSss150715 return (retval); 128c7e4935fSss150715 } 129c7e4935fSss150715 130c7e4935fSss150715 if (i_dlpi_style1_open(dip) != DLPI_SUCCESS) { 131c7e4935fSss150715 if ((retval = i_dlpi_style2_open(dip)) != DLPI_SUCCESS) { 132c7e4935fSss150715 free(dip); 133c7e4935fSss150715 return (retval); 134c7e4935fSss150715 } 135c7e4935fSss150715 } 136c7e4935fSss150715 137c7e4935fSss150715 if (dip->dli_oflags & DLPI_PASSIVE) 138c7e4935fSss150715 i_dlpi_passive(dip); 139c7e4935fSss150715 140c7e4935fSss150715 if ((dip->dli_oflags & DLPI_RAW) && 141c7e4935fSss150715 ioctl(dip->dli_fd, DLIOCRAW, 0) < 0) { 142c7e4935fSss150715 dlpi_close((dlpi_handle_t)dip); 143c7e4935fSss150715 return (DLPI_ERAWNOTSUP); 144c7e4935fSss150715 } 145c7e4935fSss150715 146c7e4935fSss150715 /* 147c7e4935fSss150715 * We intentionally do not care if this request fails, as this 148c7e4935fSss150715 * indicates the underlying DLPI device does not support Native mode 149c7e4935fSss150715 * (pre-GLDV3 device drivers). 150c7e4935fSss150715 */ 151c7e4935fSss150715 if (dip->dli_oflags & DLPI_NATIVE) { 152c7e4935fSss150715 if ((retval = ioctl(dip->dli_fd, DLIOCNATIVE, 0)) > 0) 153c7e4935fSss150715 dip->dli_mactype = retval; 154c7e4935fSss150715 } 155c7e4935fSss150715 156c7e4935fSss150715 *dhp = (dlpi_handle_t)dip; 157c7e4935fSss150715 return (DLPI_SUCCESS); 158c7e4935fSss150715 } 159c7e4935fSss150715 160c7e4935fSss150715 void 161c7e4935fSss150715 dlpi_close(dlpi_handle_t dh) 162c7e4935fSss150715 { 163c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 164c7e4935fSss150715 165c7e4935fSss150715 if (dip != NULL) { 166c7e4935fSss150715 (void) close(dip->dli_fd); 167c7e4935fSss150715 free(dip); 168c7e4935fSss150715 } 169c7e4935fSss150715 } 170c7e4935fSss150715 171c7e4935fSss150715 /* 172c7e4935fSss150715 * NOTE: The opt argument must be zero and is reserved for future use to extend 173c7e4935fSss150715 * fields to the dlpi_info_t structure (see dlpi_info(3DLPI)). 174c7e4935fSss150715 */ 175c7e4935fSss150715 int 176c7e4935fSss150715 dlpi_info(dlpi_handle_t dh, dlpi_info_t *infop, uint_t opt) 177c7e4935fSss150715 { 178c7e4935fSss150715 int retval; 179c7e4935fSss150715 dlpi_msg_t req, ack; 180c7e4935fSss150715 dl_info_ack_t *infoackp; 181c7e4935fSss150715 uint8_t *sapp, *addrp; 182c7e4935fSss150715 caddr_t ackendp, datap; 183c7e4935fSss150715 t_uscalar_t dataoff, datalen; 184c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 185c7e4935fSss150715 186c7e4935fSss150715 if (dip == NULL) 187c7e4935fSss150715 return (DLPI_EINHANDLE); 188c7e4935fSss150715 189c7e4935fSss150715 if (infop == NULL || opt != 0) 190c7e4935fSss150715 return (DLPI_EINVAL); 191c7e4935fSss150715 192c7e4935fSss150715 (void) memset(infop, 0, sizeof (dlpi_info_t)); 193c7e4935fSss150715 194c7e4935fSss150715 /* Set QoS range parameters to default unsupported value. */ 195c7e4935fSss150715 infop->di_qos_range.dl_qos_type = (t_uscalar_t)DL_UNKNOWN; 196c7e4935fSss150715 infop->di_qos_range.dl_trans_delay.dl_target_value = DL_UNKNOWN; 197c7e4935fSss150715 infop->di_qos_range.dl_trans_delay.dl_accept_value = DL_UNKNOWN; 198c7e4935fSss150715 infop->di_qos_range.dl_priority.dl_min = DL_UNKNOWN; 199c7e4935fSss150715 infop->di_qos_range.dl_priority.dl_max = DL_UNKNOWN; 200c7e4935fSss150715 infop->di_qos_range.dl_protection.dl_min = DL_UNKNOWN; 201c7e4935fSss150715 infop->di_qos_range.dl_protection.dl_max = DL_UNKNOWN; 202c7e4935fSss150715 infop->di_qos_range.dl_residual_error = DL_UNKNOWN; 203c7e4935fSss150715 204c7e4935fSss150715 /* Set QoS parameters to default unsupported value. */ 205c7e4935fSss150715 infop->di_qos_sel.dl_qos_type = (t_uscalar_t)DL_UNKNOWN; 206c7e4935fSss150715 infop->di_qos_sel.dl_trans_delay = DL_UNKNOWN; 207c7e4935fSss150715 infop->di_qos_sel.dl_priority = DL_UNKNOWN; 208c7e4935fSss150715 infop->di_qos_sel.dl_protection = DL_UNKNOWN; 209c7e4935fSss150715 infop->di_qos_sel.dl_residual_error = DL_UNKNOWN; 210c7e4935fSss150715 211c7e4935fSss150715 DLPI_MSG_CREATE(req, DL_INFO_REQ); 212c7e4935fSss150715 DLPI_MSG_CREATE(ack, DL_INFO_ACK); 213c7e4935fSss150715 214c7e4935fSss150715 retval = i_dlpi_msg_common(dip, &req, &ack, DL_INFO_ACK_SIZE, RS_HIPRI); 215c7e4935fSss150715 if (retval != DLPI_SUCCESS) 216c7e4935fSss150715 return (retval); 217c7e4935fSss150715 218c7e4935fSss150715 infoackp = &(ack.dlm_msg->info_ack); 219c7e4935fSss150715 if (infoackp->dl_version != DL_VERSION_2) 220c7e4935fSss150715 return (DLPI_EVERNOTSUP); 221c7e4935fSss150715 222c7e4935fSss150715 if (infoackp->dl_service_mode != DL_CLDLS) 223c7e4935fSss150715 return (DLPI_EMODENOTSUP); 224c7e4935fSss150715 225c7e4935fSss150715 dip->dli_style = infoackp->dl_provider_style; 226c7e4935fSss150715 dip->dli_mactype = infoackp->dl_mac_type; 227c7e4935fSss150715 228c7e4935fSss150715 ackendp = (caddr_t)ack.dlm_msg + ack.dlm_msgsz; 229c7e4935fSss150715 230c7e4935fSss150715 /* Check and save QoS selection information, if any. */ 231c7e4935fSss150715 datalen = infoackp->dl_qos_length; 232c7e4935fSss150715 dataoff = infoackp->dl_qos_offset; 233c7e4935fSss150715 if (dataoff != 0 && datalen != 0) { 234c7e4935fSss150715 datap = (caddr_t)infoackp + dataoff; 235c7e4935fSss150715 if (datalen > sizeof (dl_qos_cl_sel1_t) || 236c7e4935fSss150715 dataoff < DL_INFO_ACK_SIZE || datap + datalen > ackendp) 237c7e4935fSss150715 return (DLPI_EBADMSG); 238c7e4935fSss150715 239c7e4935fSss150715 (void) memcpy(&infop->di_qos_sel, datap, datalen); 240c7e4935fSss150715 if (infop->di_qos_sel.dl_qos_type != DL_QOS_CL_SEL1) 241c7e4935fSss150715 return (DLPI_EMODENOTSUP); 242c7e4935fSss150715 } 243c7e4935fSss150715 244c7e4935fSss150715 /* Check and save QoS range information, if any. */ 245c7e4935fSss150715 datalen = infoackp->dl_qos_range_length; 246c7e4935fSss150715 dataoff = infoackp->dl_qos_range_offset; 247c7e4935fSss150715 if (dataoff != 0 && datalen != 0) { 248c7e4935fSss150715 datap = (caddr_t)infoackp + dataoff; 249c7e4935fSss150715 if (datalen > sizeof (dl_qos_cl_range1_t) || 250c7e4935fSss150715 dataoff < DL_INFO_ACK_SIZE || datap + datalen > ackendp) 251c7e4935fSss150715 return (DLPI_EBADMSG); 252c7e4935fSss150715 253c7e4935fSss150715 (void) memcpy(&infop->di_qos_range, datap, datalen); 254c7e4935fSss150715 if (infop->di_qos_range.dl_qos_type != DL_QOS_CL_RANGE1) 255c7e4935fSss150715 return (DLPI_EMODENOTSUP); 256c7e4935fSss150715 } 257c7e4935fSss150715 258c7e4935fSss150715 /* Check and save physical address and SAP information. */ 259c7e4935fSss150715 dip->dli_saplen = abs(infoackp->dl_sap_length); 260c7e4935fSss150715 dip->dli_sapbefore = (infoackp->dl_sap_length > 0); 261c7e4935fSss150715 infop->di_physaddrlen = infoackp->dl_addr_length - dip->dli_saplen; 262c7e4935fSss150715 263c7e4935fSss150715 if (infop->di_physaddrlen > DLPI_PHYSADDR_MAX || 264c7e4935fSss150715 dip->dli_saplen > DLPI_SAPLEN_MAX) 265c7e4935fSss150715 return (DL_BADADDR); 266c7e4935fSss150715 267c7e4935fSss150715 dataoff = infoackp->dl_addr_offset; 268c7e4935fSss150715 datalen = infoackp->dl_addr_length; 269c7e4935fSss150715 if (dataoff != 0 && datalen != 0) { 270c7e4935fSss150715 datap = (caddr_t)infoackp + dataoff; 271c7e4935fSss150715 if (dataoff < DL_INFO_ACK_SIZE || datap + datalen > ackendp) 272c7e4935fSss150715 return (DLPI_EBADMSG); 273c7e4935fSss150715 274c7e4935fSss150715 sapp = addrp = (uint8_t *)datap; 275c7e4935fSss150715 if (dip->dli_sapbefore) 276c7e4935fSss150715 addrp += dip->dli_saplen; 277c7e4935fSss150715 else 278c7e4935fSss150715 sapp += infop->di_physaddrlen; 279c7e4935fSss150715 280c7e4935fSss150715 (void) memcpy(infop->di_physaddr, addrp, infop->di_physaddrlen); 281c7e4935fSss150715 infop->di_sap = i_dlpi_buildsap(sapp, dip->dli_saplen); 282c7e4935fSss150715 } 283c7e4935fSss150715 284c7e4935fSss150715 /* Check and save broadcast address information, if any. */ 285c7e4935fSss150715 datalen = infoackp->dl_brdcst_addr_length; 286c7e4935fSss150715 dataoff = infoackp->dl_brdcst_addr_offset; 287c7e4935fSss150715 if (dataoff != 0 && datalen != 0) { 288c7e4935fSss150715 datap = (caddr_t)infoackp + dataoff; 289c7e4935fSss150715 if (dataoff < DL_INFO_ACK_SIZE || datap + datalen > ackendp) 290c7e4935fSss150715 return (DLPI_EBADMSG); 291c7e4935fSss150715 if (datalen != infop->di_physaddrlen) 292c7e4935fSss150715 return (DL_BADADDR); 293c7e4935fSss150715 294c7e4935fSss150715 infop->di_bcastaddrlen = datalen; 295c7e4935fSss150715 (void) memcpy(infop->di_bcastaddr, datap, datalen); 296c7e4935fSss150715 } 297c7e4935fSss150715 298c7e4935fSss150715 infop->di_max_sdu = infoackp->dl_max_sdu; 299c7e4935fSss150715 infop->di_min_sdu = infoackp->dl_min_sdu; 300c7e4935fSss150715 infop->di_state = infoackp->dl_current_state; 301c7e4935fSss150715 infop->di_mactype = infoackp->dl_mac_type; 302c7e4935fSss150715 303c7e4935fSss150715 /* Information retrieved from the handle. */ 304c7e4935fSss150715 (void) strlcpy(infop->di_linkname, dip->dli_linkname, 305c7e4935fSss150715 sizeof (infop->di_linkname)); 306c7e4935fSss150715 infop->di_timeout = dip->dli_timeout; 307c7e4935fSss150715 308c7e4935fSss150715 return (DLPI_SUCCESS); 309c7e4935fSss150715 } 310c7e4935fSss150715 311c7e4935fSss150715 /* 312c7e4935fSss150715 * This function parses 'linkname' and stores the 'provider' name and 'PPA'. 313c7e4935fSss150715 */ 314c7e4935fSss150715 int 315c7e4935fSss150715 dlpi_parselink(const char *linkname, char *provider, uint_t *ppa) 316c7e4935fSss150715 { 317c7e4935fSss150715 ifspec_t ifsp; 318c7e4935fSss150715 319c7e4935fSss150715 if (linkname == NULL || !ifparse_ifspec(linkname, &ifsp)) 320c7e4935fSss150715 return (DLPI_ELINKNAMEINVAL); 321c7e4935fSss150715 322c7e4935fSss150715 if (provider != NULL) 323c7e4935fSss150715 (void) strlcpy(provider, ifsp.ifsp_devnm, DLPI_LINKNAME_MAX); 324c7e4935fSss150715 325c7e4935fSss150715 if (ppa != NULL) 326c7e4935fSss150715 *ppa = ifsp.ifsp_ppa; 327c7e4935fSss150715 328c7e4935fSss150715 return (DLPI_SUCCESS); 329c7e4935fSss150715 } 330c7e4935fSss150715 331c7e4935fSss150715 /* 332c7e4935fSss150715 * This function takes a provider name and a PPA and stores a full linkname 333c7e4935fSss150715 * as 'linkname'. If 'provider' already is a full linkname 'provider' name 334c7e4935fSss150715 * is stored in 'linkname'. 335c7e4935fSss150715 */ 336c7e4935fSss150715 int 337c7e4935fSss150715 dlpi_makelink(char *linkname, const char *provider, uint_t ppa) 338c7e4935fSss150715 { 339c7e4935fSss150715 int provlen = strlen(provider); 340c7e4935fSss150715 341c7e4935fSss150715 if (linkname == NULL || provlen == 0 || provlen >= DLPI_LINKNAME_MAX) 342c7e4935fSss150715 return (DLPI_ELINKNAMEINVAL); 343c7e4935fSss150715 344c7e4935fSss150715 if (!isdigit(provider[provlen - 1])) { 345c7e4935fSss150715 (void) snprintf(linkname, DLPI_LINKNAME_MAX, "%s%d", provider, 346c7e4935fSss150715 ppa); 347c7e4935fSss150715 } else { 348c7e4935fSss150715 (void) strlcpy(linkname, provider, DLPI_LINKNAME_MAX); 349c7e4935fSss150715 } 350c7e4935fSss150715 351c7e4935fSss150715 return (DLPI_SUCCESS); 352c7e4935fSss150715 } 353c7e4935fSss150715 354c7e4935fSss150715 int 355c7e4935fSss150715 dlpi_bind(dlpi_handle_t dh, uint_t sap, uint_t *boundsap) 356c7e4935fSss150715 { 357c7e4935fSss150715 int retval; 358c7e4935fSss150715 dlpi_msg_t req, ack; 359c7e4935fSss150715 dl_bind_req_t *bindreqp; 360c7e4935fSss150715 dl_bind_ack_t *bindackp; 361c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 362c7e4935fSss150715 363c7e4935fSss150715 if (dip == NULL) 364c7e4935fSss150715 return (DLPI_EINHANDLE); 365c7e4935fSss150715 366c7e4935fSss150715 DLPI_MSG_CREATE(req, DL_BIND_REQ); 367c7e4935fSss150715 DLPI_MSG_CREATE(ack, DL_BIND_ACK); 368c7e4935fSss150715 bindreqp = &(req.dlm_msg->bind_req); 369c7e4935fSss150715 370c7e4935fSss150715 /* 371c7e4935fSss150715 * If 'sap' is DLPI_ANY_SAP, bind to SAP 2 on token ring, else 0 on 372c7e4935fSss150715 * other interface types (SAP 0 has special significance on token ring). 373c7e4935fSss150715 */ 374c7e4935fSss150715 if (sap == DLPI_ANY_SAP) 375c7e4935fSss150715 bindreqp->dl_sap = ((dip->dli_mactype == DL_TPR) ? 2 : 0); 376c7e4935fSss150715 else 377c7e4935fSss150715 bindreqp->dl_sap = sap; 378c7e4935fSss150715 379c7e4935fSss150715 bindreqp->dl_service_mode = DL_CLDLS; 380c7e4935fSss150715 bindreqp->dl_conn_mgmt = 0; 381c7e4935fSss150715 bindreqp->dl_max_conind = 0; 382c7e4935fSss150715 bindreqp->dl_xidtest_flg = 0; 383c7e4935fSss150715 384c7e4935fSss150715 retval = i_dlpi_msg_common(dip, &req, &ack, DL_BIND_ACK_SIZE, 0); 385c7e4935fSss150715 if (retval != DLPI_SUCCESS) 386c7e4935fSss150715 return (retval); 387c7e4935fSss150715 388c7e4935fSss150715 bindackp = &(ack.dlm_msg->bind_ack); 389c7e4935fSss150715 /* 390c7e4935fSss150715 * Received a DLPI_BIND_ACK, now verify that the bound SAP 391c7e4935fSss150715 * is equal to the SAP requested. Some DLPI MAC type may bind 392c7e4935fSss150715 * to a different SAP than requested, in this case 'boundsap' 393c7e4935fSss150715 * returns the actual bound SAP. For the case where 'boundsap' 394c7e4935fSss150715 * is NULL and 'sap' is not DLPI_ANY_SAP, dlpi_bind fails. 395c7e4935fSss150715 */ 396c7e4935fSss150715 if (boundsap != NULL) { 397c7e4935fSss150715 *boundsap = bindackp->dl_sap; 398c7e4935fSss150715 } else if (sap != DLPI_ANY_SAP && bindackp->dl_sap != sap) { 399c7e4935fSss150715 if (dlpi_unbind(dh) != DLPI_SUCCESS) 400c7e4935fSss150715 return (DLPI_FAILURE); 401c7e4935fSss150715 else 402c7e4935fSss150715 return (DLPI_EUNAVAILSAP); 403c7e4935fSss150715 } 404c7e4935fSss150715 405c7e4935fSss150715 dip->dli_sap = bindackp->dl_sap; /* save sap value in handle */ 406c7e4935fSss150715 return (DLPI_SUCCESS); 407c7e4935fSss150715 } 408c7e4935fSss150715 409c7e4935fSss150715 int 410c7e4935fSss150715 dlpi_unbind(dlpi_handle_t dh) 411c7e4935fSss150715 { 412c7e4935fSss150715 dlpi_msg_t req, ack; 413c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 414c7e4935fSss150715 415c7e4935fSss150715 if (dip == NULL) 416c7e4935fSss150715 return (DLPI_EINHANDLE); 417c7e4935fSss150715 418c7e4935fSss150715 DLPI_MSG_CREATE(req, DL_UNBIND_REQ); 419c7e4935fSss150715 DLPI_MSG_CREATE(ack, DL_OK_ACK); 420c7e4935fSss150715 421c7e4935fSss150715 return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); 422c7e4935fSss150715 } 423c7e4935fSss150715 424c7e4935fSss150715 /* 425c7e4935fSss150715 * This function is invoked by dlpi_enabmulti() or dlpi_disabmulti() and 426c7e4935fSss150715 * based on the "op" value, multicast address is enabled/disabled. 427c7e4935fSss150715 */ 428c7e4935fSss150715 static int 429c7e4935fSss150715 i_dlpi_multi(dlpi_handle_t dh, t_uscalar_t op, const uint8_t *addrp, 430c7e4935fSss150715 size_t addrlen) 431c7e4935fSss150715 { 432c7e4935fSss150715 dlpi_msg_t req, ack; 433c7e4935fSss150715 dl_enabmulti_req_t *multireqp; 434c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 435c7e4935fSss150715 436c7e4935fSss150715 if (dip == NULL) 437c7e4935fSss150715 return (DLPI_EINHANDLE); 438c7e4935fSss150715 439c7e4935fSss150715 if (addrlen > DLPI_PHYSADDR_MAX) 440c7e4935fSss150715 return (DLPI_EINVAL); 441c7e4935fSss150715 442c7e4935fSss150715 DLPI_MSG_CREATE(req, op); 443c7e4935fSss150715 DLPI_MSG_CREATE(ack, DL_OK_ACK); 444c7e4935fSss150715 445c7e4935fSss150715 multireqp = &(req.dlm_msg->enabmulti_req); 446c7e4935fSss150715 multireqp->dl_addr_length = addrlen; 447c7e4935fSss150715 multireqp->dl_addr_offset = sizeof (dl_enabmulti_req_t); 448c7e4935fSss150715 (void) memcpy(&multireqp[1], addrp, addrlen); 449c7e4935fSss150715 450c7e4935fSss150715 return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); 451c7e4935fSss150715 } 452c7e4935fSss150715 453c7e4935fSss150715 int 454c7e4935fSss150715 dlpi_enabmulti(dlpi_handle_t dh, const void *addrp, size_t addrlen) 455c7e4935fSss150715 { 456c7e4935fSss150715 return (i_dlpi_multi(dh, DL_ENABMULTI_REQ, addrp, addrlen)); 457c7e4935fSss150715 } 458c7e4935fSss150715 459c7e4935fSss150715 int 460c7e4935fSss150715 dlpi_disabmulti(dlpi_handle_t dh, const void *addrp, size_t addrlen) 461c7e4935fSss150715 { 462c7e4935fSss150715 return (i_dlpi_multi(dh, DL_DISABMULTI_REQ, addrp, addrlen)); 463c7e4935fSss150715 } 464c7e4935fSss150715 465c7e4935fSss150715 /* 466c7e4935fSss150715 * This function is invoked by dlpi_promiscon() or dlpi_promiscoff(). Based 467c7e4935fSss150715 * on the value of 'op', promiscuous mode is turned on/off at the specified 468c7e4935fSss150715 * 'level'. 469c7e4935fSss150715 */ 470c7e4935fSss150715 static int 471c7e4935fSss150715 i_dlpi_promisc(dlpi_handle_t dh, t_uscalar_t op, uint_t level) 472c7e4935fSss150715 { 473c7e4935fSss150715 dlpi_msg_t req, ack; 474c7e4935fSss150715 dl_promiscon_req_t *promiscreqp; 475c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 476c7e4935fSss150715 477c7e4935fSss150715 if (dip == NULL) 478c7e4935fSss150715 return (DLPI_EINHANDLE); 479c7e4935fSss150715 480c7e4935fSss150715 DLPI_MSG_CREATE(req, op); 481c7e4935fSss150715 DLPI_MSG_CREATE(ack, DL_OK_ACK); 482c7e4935fSss150715 483c7e4935fSss150715 promiscreqp = &(req.dlm_msg->promiscon_req); 484c7e4935fSss150715 promiscreqp->dl_level = level; 485c7e4935fSss150715 486c7e4935fSss150715 return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); 487c7e4935fSss150715 } 488c7e4935fSss150715 489c7e4935fSss150715 int 490c7e4935fSss150715 dlpi_promiscon(dlpi_handle_t dh, uint_t level) 491c7e4935fSss150715 { 492c7e4935fSss150715 return (i_dlpi_promisc(dh, DL_PROMISCON_REQ, level)); 493c7e4935fSss150715 } 494c7e4935fSss150715 495c7e4935fSss150715 int 496c7e4935fSss150715 dlpi_promiscoff(dlpi_handle_t dh, uint_t level) 497c7e4935fSss150715 { 498c7e4935fSss150715 return (i_dlpi_promisc(dh, DL_PROMISCOFF_REQ, level)); 499c7e4935fSss150715 } 500c7e4935fSss150715 501c7e4935fSss150715 int 502c7e4935fSss150715 dlpi_get_physaddr(dlpi_handle_t dh, uint_t type, void *addrp, size_t *addrlenp) 503c7e4935fSss150715 { 504c7e4935fSss150715 int retval; 505c7e4935fSss150715 dlpi_msg_t req, ack; 506c7e4935fSss150715 dl_phys_addr_req_t *physreqp; 507c7e4935fSss150715 dl_phys_addr_ack_t *physackp; 508c7e4935fSss150715 t_uscalar_t dataoff, datalen; 509c7e4935fSss150715 caddr_t datap, physackendp; 510c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 511c7e4935fSss150715 512c7e4935fSss150715 if (dip == NULL) 513c7e4935fSss150715 return (DLPI_EINHANDLE); 514c7e4935fSss150715 515c7e4935fSss150715 if (addrlenp == NULL || addrp == NULL || *addrlenp < DLPI_PHYSADDR_MAX) 516c7e4935fSss150715 return (DLPI_EINVAL); 517c7e4935fSss150715 518c7e4935fSss150715 DLPI_MSG_CREATE(req, DL_PHYS_ADDR_REQ); 519c7e4935fSss150715 DLPI_MSG_CREATE(ack, DL_PHYS_ADDR_ACK); 520c7e4935fSss150715 521c7e4935fSss150715 physreqp = &(req.dlm_msg->physaddr_req); 522c7e4935fSss150715 physreqp->dl_addr_type = type; 523c7e4935fSss150715 524c7e4935fSss150715 retval = i_dlpi_msg_common(dip, &req, &ack, DL_PHYS_ADDR_ACK_SIZE, 0); 525c7e4935fSss150715 if (retval != DLPI_SUCCESS) 526c7e4935fSss150715 return (retval); 527c7e4935fSss150715 528c7e4935fSss150715 /* Received DL_PHYS_ADDR_ACK, store the physical address and length. */ 529c7e4935fSss150715 physackp = &(ack.dlm_msg->physaddr_ack); 530c7e4935fSss150715 physackendp = (caddr_t)ack.dlm_msg + ack.dlm_msgsz; 531c7e4935fSss150715 dataoff = physackp->dl_addr_offset; 532c7e4935fSss150715 datalen = physackp->dl_addr_length; 533c7e4935fSss150715 if (dataoff != 0 && datalen != 0) { 534c7e4935fSss150715 datap = (caddr_t)physackp + dataoff; 535c7e4935fSss150715 if (datalen > DLPI_PHYSADDR_MAX) 536c7e4935fSss150715 return (DL_BADADDR); 537c7e4935fSss150715 if (dataoff < DL_PHYS_ADDR_ACK_SIZE || 538c7e4935fSss150715 datap + datalen > physackendp) 539c7e4935fSss150715 return (DLPI_EBADMSG); 540c7e4935fSss150715 541c7e4935fSss150715 *addrlenp = physackp->dl_addr_length; 542c7e4935fSss150715 (void) memcpy(addrp, datap, datalen); 543c7e4935fSss150715 } else { 544c7e4935fSss150715 *addrlenp = datalen; 545c7e4935fSss150715 } 546c7e4935fSss150715 547c7e4935fSss150715 return (DLPI_SUCCESS); 548c7e4935fSss150715 } 549c7e4935fSss150715 550c7e4935fSss150715 int 551c7e4935fSss150715 dlpi_set_physaddr(dlpi_handle_t dh, uint_t type, const void *addrp, 552c7e4935fSss150715 size_t addrlen) 553c7e4935fSss150715 { 554c7e4935fSss150715 dlpi_msg_t req, ack; 555c7e4935fSss150715 dl_set_phys_addr_req_t *setphysreqp; 556c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 557c7e4935fSss150715 558c7e4935fSss150715 if (dip == NULL) 559c7e4935fSss150715 return (DLPI_EINHANDLE); 560c7e4935fSss150715 561c7e4935fSss150715 if (addrp == NULL || type != DL_CURR_PHYS_ADDR || 562c7e4935fSss150715 addrlen > DLPI_PHYSADDR_MAX) 563c7e4935fSss150715 return (DLPI_EINVAL); 564c7e4935fSss150715 565c7e4935fSss150715 DLPI_MSG_CREATE(req, DL_SET_PHYS_ADDR_REQ); 566c7e4935fSss150715 DLPI_MSG_CREATE(ack, DL_OK_ACK); 567c7e4935fSss150715 568c7e4935fSss150715 setphysreqp = &(req.dlm_msg->set_physaddr_req); 569c7e4935fSss150715 setphysreqp->dl_addr_length = addrlen; 570c7e4935fSss150715 setphysreqp->dl_addr_offset = sizeof (dl_set_phys_addr_req_t); 571c7e4935fSss150715 (void) memcpy(&setphysreqp[1], addrp, addrlen); 572c7e4935fSss150715 573c7e4935fSss150715 return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); 574c7e4935fSss150715 } 575c7e4935fSss150715 576c7e4935fSss150715 int 577c7e4935fSss150715 dlpi_send(dlpi_handle_t dh, const void *daddrp, size_t daddrlen, 578c7e4935fSss150715 const void *msgbuf, size_t msglen, const dlpi_sendinfo_t *sendp) 579c7e4935fSss150715 { 580c7e4935fSss150715 dlpi_msg_t req; 581c7e4935fSss150715 dl_unitdata_req_t *udatareqp; 582c7e4935fSss150715 uint_t sap; 583c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 584c7e4935fSss150715 585c7e4935fSss150715 if (dip == NULL) 586c7e4935fSss150715 return (DLPI_EINHANDLE); 587c7e4935fSss150715 588c7e4935fSss150715 if (dip->dli_oflags & DLPI_RAW) 589c7e4935fSss150715 return (i_dlpi_strputmsg(dip->dli_fd, NULL, msgbuf, msglen, 0)); 590c7e4935fSss150715 591948f2876Sss150715 if ((daddrlen > 0 && daddrp == NULL) || daddrlen > DLPI_PHYSADDR_MAX) 592c7e4935fSss150715 return (DLPI_EINVAL); 593c7e4935fSss150715 594c7e4935fSss150715 DLPI_MSG_CREATE(req, DL_UNITDATA_REQ); 595c7e4935fSss150715 udatareqp = &(req.dlm_msg->unitdata_req); 596c7e4935fSss150715 597c7e4935fSss150715 /* Set priority to default priority range. */ 598c7e4935fSss150715 udatareqp->dl_priority.dl_min = 0; 599c7e4935fSss150715 udatareqp->dl_priority.dl_max = 0; 600c7e4935fSss150715 601c7e4935fSss150715 /* Use SAP value if specified otherwise use bound SAP value. */ 602c7e4935fSss150715 if (sendp != NULL) { 603c7e4935fSss150715 sap = sendp->dsi_sap; 604c7e4935fSss150715 if (sendp->dsi_prio.dl_min != DL_QOS_DONT_CARE) 605c7e4935fSss150715 udatareqp->dl_priority.dl_min = sendp->dsi_prio.dl_min; 606c7e4935fSss150715 if (sendp->dsi_prio.dl_max != DL_QOS_DONT_CARE) 607c7e4935fSss150715 udatareqp->dl_priority.dl_max = sendp->dsi_prio.dl_max; 608c7e4935fSss150715 } else { 609c7e4935fSss150715 sap = dip->dli_sap; 610c7e4935fSss150715 } 611c7e4935fSss150715 612c7e4935fSss150715 udatareqp->dl_dest_addr_length = daddrlen + dip->dli_saplen; 613c7e4935fSss150715 udatareqp->dl_dest_addr_offset = DL_UNITDATA_REQ_SIZE; 614c7e4935fSss150715 615c7e4935fSss150715 /* 616c7e4935fSss150715 * Since `daddrp' only has the link-layer destination address, 617c7e4935fSss150715 * we must prepend or append the SAP (according to dli_sapbefore) 618c7e4935fSss150715 * to make a full DLPI address. 619c7e4935fSss150715 */ 620c7e4935fSss150715 if (dip->dli_sapbefore) { 621c7e4935fSss150715 i_dlpi_writesap(&udatareqp[1], sap, dip->dli_saplen); 622c7e4935fSss150715 (void) memcpy((caddr_t)&udatareqp[1] + dip->dli_saplen, 623c7e4935fSss150715 daddrp, daddrlen); 624c7e4935fSss150715 } else { 625c7e4935fSss150715 (void) memcpy(&udatareqp[1], daddrp, daddrlen); 626c7e4935fSss150715 i_dlpi_writesap((caddr_t)&udatareqp[1] + daddrlen, sap, 627c7e4935fSss150715 dip->dli_saplen); 628c7e4935fSss150715 } 629c7e4935fSss150715 630c7e4935fSss150715 return (i_dlpi_strputmsg(dip->dli_fd, &req, msgbuf, msglen, 0)); 631c7e4935fSss150715 } 632c7e4935fSss150715 633c7e4935fSss150715 int 634c7e4935fSss150715 dlpi_recv(dlpi_handle_t dh, void *saddrp, size_t *saddrlenp, void *msgbuf, 635c7e4935fSss150715 size_t *msglenp, int msec, dlpi_recvinfo_t *recvp) 636c7e4935fSss150715 { 637c7e4935fSss150715 int retval; 638c7e4935fSss150715 dlpi_msg_t ind; 639c7e4935fSss150715 size_t totmsglen; 640c7e4935fSss150715 dl_unitdata_ind_t *udatap; 641c7e4935fSss150715 t_uscalar_t dataoff, datalen; 642c7e4935fSss150715 caddr_t datap, indendp; 643c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 644c7e4935fSss150715 645c7e4935fSss150715 if (dip == NULL) 646c7e4935fSss150715 return (DLPI_EINHANDLE); 647c7e4935fSss150715 /* 648c7e4935fSss150715 * If handle is in raw mode ignore everything except total message 649c7e4935fSss150715 * length. 650c7e4935fSss150715 */ 651c7e4935fSss150715 if (dip->dli_oflags & DLPI_RAW) { 652c7e4935fSss150715 retval = i_dlpi_strgetmsg(dip->dli_fd, msec, NULL, 0, 0, 0, 653c7e4935fSss150715 msgbuf, msglenp, &totmsglen); 654c7e4935fSss150715 655c7e4935fSss150715 if (retval == DLPI_SUCCESS && recvp != NULL) 656c7e4935fSss150715 recvp->dri_totmsglen = totmsglen; 657c7e4935fSss150715 return (retval); 658c7e4935fSss150715 } 659c7e4935fSss150715 660c7e4935fSss150715 DLPI_MSG_CREATE(ind, DL_UNITDATA_IND); 661c7e4935fSss150715 udatap = &(ind.dlm_msg->unitdata_ind); 662c7e4935fSss150715 indendp = (caddr_t)ind.dlm_msg + ind.dlm_msgsz; 663c7e4935fSss150715 664c7e4935fSss150715 if ((retval = i_dlpi_strgetmsg(dip->dli_fd, msec, &ind, 665c7e4935fSss150715 DL_UNITDATA_IND, DL_UNITDATA_IND, DL_UNITDATA_IND_SIZE, 666c7e4935fSss150715 msgbuf, msglenp, &totmsglen)) != DLPI_SUCCESS) 667c7e4935fSss150715 return (retval); 668c7e4935fSss150715 669c7e4935fSss150715 /* 670c7e4935fSss150715 * If DLPI link provides source address, store source address in 671c7e4935fSss150715 * 'saddrp' and source length in 'saddrlenp', else set saddrlenp to 0. 672c7e4935fSss150715 */ 673c7e4935fSss150715 if (saddrp != NULL && saddrlenp != NULL) { 674c7e4935fSss150715 if (*saddrlenp < DLPI_PHYSADDR_MAX) 675c7e4935fSss150715 return (DLPI_EINVAL); 676c7e4935fSss150715 677c7e4935fSss150715 dataoff = udatap->dl_src_addr_offset; 678c7e4935fSss150715 datalen = udatap->dl_src_addr_length; 679c7e4935fSss150715 if (dataoff != 0 && datalen != 0) { 680c7e4935fSss150715 datap = (caddr_t)udatap + dataoff; 681c7e4935fSss150715 if (dataoff < DL_UNITDATA_IND_SIZE || 682c7e4935fSss150715 datap + datalen > indendp) 683c7e4935fSss150715 return (DLPI_EBADMSG); 684c7e4935fSss150715 685c7e4935fSss150715 *saddrlenp = datalen - dip->dli_saplen; 686c7e4935fSss150715 if (*saddrlenp > DLPI_PHYSADDR_MAX) 687c7e4935fSss150715 return (DL_BADADDR); 688c7e4935fSss150715 689c7e4935fSss150715 if (dip->dli_sapbefore) 690c7e4935fSss150715 datap += dip->dli_saplen; 691c7e4935fSss150715 (void) memcpy(saddrp, datap, *saddrlenp); 692c7e4935fSss150715 } else { 693c7e4935fSss150715 *saddrlenp = 0; 694c7e4935fSss150715 } 695c7e4935fSss150715 } 696c7e4935fSss150715 697c7e4935fSss150715 /* 698c7e4935fSss150715 * If destination address requested, check and save destination 699c7e4935fSss150715 * address, if any. 700c7e4935fSss150715 */ 701c7e4935fSss150715 if (recvp != NULL) { 702c7e4935fSss150715 dataoff = udatap->dl_dest_addr_offset; 703c7e4935fSss150715 datalen = udatap->dl_dest_addr_length; 704c7e4935fSss150715 if (dataoff != 0 && datalen != 0) { 705c7e4935fSss150715 datap = (caddr_t)udatap + dataoff; 706c7e4935fSss150715 if (dataoff < DL_UNITDATA_IND_SIZE || 707c7e4935fSss150715 datap + datalen > indendp) 708c7e4935fSss150715 return (DLPI_EBADMSG); 709c7e4935fSss150715 710c7e4935fSss150715 recvp->dri_destaddrlen = datalen - dip->dli_saplen; 711c7e4935fSss150715 if (recvp->dri_destaddrlen > DLPI_PHYSADDR_MAX) 712c7e4935fSss150715 return (DL_BADADDR); 713c7e4935fSss150715 714c7e4935fSss150715 if (dip->dli_sapbefore) 715c7e4935fSss150715 datap += dip->dli_saplen; 716c7e4935fSss150715 (void) memcpy(recvp->dri_destaddr, datap, 717c7e4935fSss150715 recvp->dri_destaddrlen); 718c7e4935fSss150715 } else { 719c7e4935fSss150715 recvp->dri_destaddrlen = 0; 720c7e4935fSss150715 } 721c7e4935fSss150715 722*5494fa53Sss150715 recvp->dri_destaddrtype = udatap->dl_group_address; 723c7e4935fSss150715 recvp->dri_totmsglen = totmsglen; 724c7e4935fSss150715 } 725c7e4935fSss150715 726c7e4935fSss150715 return (DLPI_SUCCESS); 727c7e4935fSss150715 } 728c7e4935fSss150715 729c7e4935fSss150715 int 730c7e4935fSss150715 dlpi_fd(dlpi_handle_t dh) 731c7e4935fSss150715 { 732c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 733c7e4935fSss150715 734c7e4935fSss150715 return (dip != NULL ? dip->dli_fd : -1); 735c7e4935fSss150715 } 736c7e4935fSss150715 737c7e4935fSss150715 int 738c7e4935fSss150715 dlpi_set_timeout(dlpi_handle_t dh, int sec) 739c7e4935fSss150715 { 740c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 741c7e4935fSss150715 742c7e4935fSss150715 if (dip == NULL) 743c7e4935fSss150715 return (DLPI_EINHANDLE); 744c7e4935fSss150715 745c7e4935fSss150715 dip->dli_timeout = sec; 746c7e4935fSss150715 return (DLPI_SUCCESS); 747c7e4935fSss150715 } 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate const char * 750c7e4935fSss150715 dlpi_linkname(dlpi_handle_t dh) 7517c478bd9Sstevel@tonic-gate { 752c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 7537c478bd9Sstevel@tonic-gate 754c7e4935fSss150715 return (dip != NULL ? dip->dli_linkname : NULL); 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate 757c7e4935fSss150715 /* 758c7e4935fSss150715 * Returns DLPI style stored in the handle. 759c7e4935fSss150715 * Note: This function is used for test purposes only. Do not remove without 760c7e4935fSss150715 * fixing the DLPI testsuite. 761c7e4935fSss150715 */ 762c7e4935fSss150715 uint_t 763c7e4935fSss150715 dlpi_style(dlpi_handle_t dh) 7647c478bd9Sstevel@tonic-gate { 765c7e4935fSss150715 dlpi_impl_t *dip = (dlpi_impl_t *)dh; 7667c478bd9Sstevel@tonic-gate 767c7e4935fSss150715 return (dip->dli_style); 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate 770948f2876Sss150715 uint_t 771948f2876Sss150715 dlpi_arptype(uint_t dlpitype) 772948f2876Sss150715 { 773948f2876Sss150715 switch (dlpitype) { 774948f2876Sss150715 775948f2876Sss150715 case DL_ETHER: 776948f2876Sss150715 return (ARPHRD_ETHER); 777948f2876Sss150715 778948f2876Sss150715 case DL_FRAME: 779948f2876Sss150715 return (ARPHRD_FRAME); 780948f2876Sss150715 781948f2876Sss150715 case DL_ATM: 782948f2876Sss150715 return (ARPHRD_ATM); 783948f2876Sss150715 784948f2876Sss150715 case DL_IPATM: 785948f2876Sss150715 return (ARPHRD_IPATM); 786948f2876Sss150715 787948f2876Sss150715 case DL_HDLC: 788948f2876Sss150715 return (ARPHRD_HDLC); 789948f2876Sss150715 790948f2876Sss150715 case DL_FC: 791948f2876Sss150715 return (ARPHRD_FC); 792948f2876Sss150715 793948f2876Sss150715 case DL_CSMACD: /* ieee 802 networks */ 794948f2876Sss150715 case DL_TPB: 795948f2876Sss150715 case DL_TPR: 796948f2876Sss150715 case DL_METRO: 797948f2876Sss150715 case DL_FDDI: 798948f2876Sss150715 return (ARPHRD_IEEE802); 799948f2876Sss150715 800948f2876Sss150715 case DL_IB: 801948f2876Sss150715 return (ARPHRD_IB); 802948f2876Sss150715 803948f2876Sss150715 case DL_IPV4: 804948f2876Sss150715 case DL_IPV6: 805948f2876Sss150715 return (ARPHRD_TUNNEL); 806948f2876Sss150715 } 807948f2876Sss150715 808948f2876Sss150715 return (0); 809948f2876Sss150715 } 810948f2876Sss150715 811948f2876Sss150715 uint_t 812948f2876Sss150715 dlpi_iftype(uint_t dlpitype) 813948f2876Sss150715 { 814948f2876Sss150715 switch (dlpitype) { 815948f2876Sss150715 816948f2876Sss150715 case DL_ETHER: 817948f2876Sss150715 return (IFT_ETHER); 818948f2876Sss150715 819948f2876Sss150715 case DL_ATM: 820948f2876Sss150715 return (IFT_ATM); 821948f2876Sss150715 822948f2876Sss150715 case DL_CSMACD: 823948f2876Sss150715 return (IFT_ISO88023); 824948f2876Sss150715 825948f2876Sss150715 case DL_TPB: 826948f2876Sss150715 return (IFT_ISO88024); 827948f2876Sss150715 828948f2876Sss150715 case DL_TPR: 829948f2876Sss150715 return (IFT_ISO88025); 830948f2876Sss150715 831948f2876Sss150715 case DL_FDDI: 832948f2876Sss150715 return (IFT_FDDI); 833948f2876Sss150715 834948f2876Sss150715 case DL_IB: 835948f2876Sss150715 return (IFT_IB); 836948f2876Sss150715 837948f2876Sss150715 case DL_OTHER: 838948f2876Sss150715 return (IFT_OTHER); 839948f2876Sss150715 } 840948f2876Sss150715 841948f2876Sss150715 return (0); 842948f2876Sss150715 } 843948f2876Sss150715 844c7e4935fSss150715 /* 845c7e4935fSss150715 * This function attempts to open linkname under the following namespaces: 846c7e4935fSss150715 * - /dev 847c7e4935fSss150715 * - /devices 848c7e4935fSss150715 * If open doesn't succeed and link doesn't exist (ENOENT), this function 849c7e4935fSss150715 * returns DLPI_ENOLINK, otherwise returns DL_SYSERR. 850c7e4935fSss150715 */ 8517c478bd9Sstevel@tonic-gate static int 852c7e4935fSss150715 i_dlpi_open(const char *provider, int *fd, uint_t flags) 8537c478bd9Sstevel@tonic-gate { 854c7e4935fSss150715 char path[MAXPATHLEN]; 855c7e4935fSss150715 int oflags; 856c7e4935fSss150715 857c7e4935fSss150715 oflags = O_RDWR; 858c7e4935fSss150715 if (flags & DLPI_EXCL) 859c7e4935fSss150715 oflags |= O_EXCL; 860c7e4935fSss150715 861c7e4935fSss150715 (void) snprintf(path, sizeof (path), "/dev/%s", provider); 862c7e4935fSss150715 863c7e4935fSss150715 if ((*fd = open(path, oflags)) != -1) 864c7e4935fSss150715 return (DLPI_SUCCESS); 865c7e4935fSss150715 866c7e4935fSss150715 /* 867c7e4935fSss150715 * On diskless boot, it's possible the /dev links have not yet 868c7e4935fSss150715 * been created; fallback to /devices. When /dev links are 869c7e4935fSss150715 * created on demand, this code can be removed. 870c7e4935fSss150715 */ 871c7e4935fSss150715 (void) snprintf(path, sizeof (path), "/devices/pseudo/clone@0:%s", 872c7e4935fSss150715 provider); 873c7e4935fSss150715 874c7e4935fSss150715 if ((*fd = open(path, oflags)) != -1) 875c7e4935fSss150715 return (DLPI_SUCCESS); 876c7e4935fSss150715 877c7e4935fSss150715 return (errno == ENOENT ? DLPI_ENOLINK : DL_SYSERR); 878c7e4935fSss150715 } 879c7e4935fSss150715 880c7e4935fSss150715 /* 881c7e4935fSss150715 * Open a style 1 link. PPA is implicitly attached. 882c7e4935fSss150715 */ 883c7e4935fSss150715 static int 884c7e4935fSss150715 i_dlpi_style1_open(dlpi_impl_t *dip) 885c7e4935fSss150715 { 886c7e4935fSss150715 int retval, save_errno; 887c7e4935fSss150715 int fd; 888c7e4935fSss150715 889c7e4935fSss150715 /* 890c7e4935fSss150715 * In order to support open of syntax like device[.module[.module...]] 891c7e4935fSss150715 * where modules need to be pushed onto the device stream, open only 892c7e4935fSss150715 * device name, otherwise open the full linkname. 893c7e4935fSss150715 */ 894c7e4935fSss150715 retval = i_dlpi_open((dip->dli_mod_cnt != 0) ? dip->dli_provider : 895c7e4935fSss150715 dip->dli_linkname, &fd, dip->dli_oflags); 896c7e4935fSss150715 897c7e4935fSss150715 if (retval != DLPI_SUCCESS) { 898c7e4935fSss150715 dip->dli_mod_pushed = 0; 899c7e4935fSss150715 return (retval); 900c7e4935fSss150715 } 901c7e4935fSss150715 dip->dli_fd = fd; 902c7e4935fSss150715 903c7e4935fSss150715 /* 904c7e4935fSss150715 * Try to push modules (if any) onto the device stream. If I_PUSH 905c7e4935fSss150715 * fails, we increment count of modules pushed (dli_mod_pushed) 906c7e4935fSss150715 * expecting it is last module to be pushed and thus will be pushed 907c7e4935fSss150715 * in i_dlpi_style2_open(). 908c7e4935fSss150715 */ 909c7e4935fSss150715 for (dip->dli_mod_pushed = 0; dip->dli_mod_pushed < dip->dli_mod_cnt; 910c7e4935fSss150715 dip->dli_mod_pushed++) { 911c7e4935fSss150715 if (ioctl(fd, I_PUSH, 912c7e4935fSss150715 dip->dli_modlist[dip->dli_mod_pushed]) == -1) { 913c7e4935fSss150715 dip->dli_mod_pushed++; 914c7e4935fSss150715 return (DLPI_FAILURE); 915c7e4935fSss150715 } 916c7e4935fSss150715 } 917c7e4935fSss150715 918c7e4935fSss150715 if ((retval = i_dlpi_checkstyle(dip, DL_STYLE1)) != DLPI_SUCCESS) { 919c7e4935fSss150715 save_errno = errno; 920c7e4935fSss150715 (void) close(dip->dli_fd); 921c7e4935fSss150715 errno = save_errno; 922c7e4935fSss150715 dip->dli_mod_pushed = 0; 923c7e4935fSss150715 return (retval); 924c7e4935fSss150715 } 925c7e4935fSss150715 926c7e4935fSss150715 return (DLPI_SUCCESS); 927c7e4935fSss150715 } 928c7e4935fSss150715 929c7e4935fSss150715 /* 930c7e4935fSss150715 * Open a style 2 link. PPA must be explicitly attached. 931c7e4935fSss150715 */ 932c7e4935fSss150715 static int 933c7e4935fSss150715 i_dlpi_style2_open(dlpi_impl_t *dip) 934c7e4935fSss150715 { 935c7e4935fSss150715 int fd; 936c7e4935fSss150715 int retval, save_errno; 937c7e4935fSss150715 938c7e4935fSss150715 /* 939c7e4935fSss150715 * If style 1 open failed, we need to determine how far it got and 940c7e4935fSss150715 * finish up the open() call as a style 2 open. 941c7e4935fSss150715 * 942c7e4935fSss150715 * If no modules were pushed (mod_pushed == 0), then we need to 943c7e4935fSss150715 * open it as a style 2 link. 944c7e4935fSss150715 * 945c7e4935fSss150715 * If the pushing of the last module failed, we need to 946c7e4935fSss150715 * try pushing it as a style 2 module. Decrement dli_mod_pushed 947c7e4935fSss150715 * count so it can be pushed onto the stream. 948c7e4935fSss150715 * 949c7e4935fSss150715 * Otherwise we failed during the push of an intermediate module and 950c7e4935fSss150715 * must fail out and close the link. 951c7e4935fSss150715 */ 952c7e4935fSss150715 if (dip->dli_mod_pushed == 0) { 953c7e4935fSss150715 if ((retval = i_dlpi_open(dip->dli_provider, &fd, 954c7e4935fSss150715 dip->dli_oflags)) != DLPI_SUCCESS) 955c7e4935fSss150715 return (retval); 956c7e4935fSss150715 957c7e4935fSss150715 dip->dli_fd = fd; 958c7e4935fSss150715 } else if (dip->dli_mod_pushed == dip->dli_mod_cnt) { 959c7e4935fSss150715 if (i_dlpi_remove_ppa(dip->dli_modlist[dip->dli_mod_cnt - 1]) 960c7e4935fSss150715 != DLPI_SUCCESS) 961c7e4935fSss150715 return (DLPI_ELINKNAMEINVAL); 962c7e4935fSss150715 963c7e4935fSss150715 dip->dli_mod_pushed--; 964c7e4935fSss150715 fd = dip->dli_fd; 965c7e4935fSss150715 } else { 966c7e4935fSss150715 return (DLPI_ELINKNAMEINVAL); 967c7e4935fSss150715 } 968c7e4935fSss150715 969c7e4935fSss150715 /* Try and push modules (if any) onto the device stream. */ 970c7e4935fSss150715 for (; dip->dli_mod_pushed < dip->dli_mod_cnt; dip->dli_mod_pushed++) { 971c7e4935fSss150715 if (ioctl(fd, I_PUSH, 972c7e4935fSss150715 dip->dli_modlist[dip->dli_mod_pushed]) == -1) { 973c7e4935fSss150715 retval = DL_SYSERR; 974c7e4935fSss150715 goto failure; 975c7e4935fSss150715 } 976c7e4935fSss150715 } 977c7e4935fSss150715 978c7e4935fSss150715 /* 979c7e4935fSss150715 * Special case: DLPI_SERIAL flag (synchronous serial lines) is not a 980c7e4935fSss150715 * DLPI link so attach and ignore rest. 981c7e4935fSss150715 */ 982c7e4935fSss150715 if (dip->dli_oflags & DLPI_SERIAL) 983c7e4935fSss150715 goto attach; 984c7e4935fSss150715 985c7e4935fSss150715 if ((retval = i_dlpi_checkstyle(dip, DL_STYLE2)) != DLPI_SUCCESS) 986c7e4935fSss150715 goto failure; 987c7e4935fSss150715 988c7e4935fSss150715 /* 989c7e4935fSss150715 * Succeeded opening the link and verified it is style2. Now attach to 990c7e4935fSss150715 * PPA only if DLPI_NOATTACH is not set. 991c7e4935fSss150715 */ 992c7e4935fSss150715 if (dip->dli_oflags & DLPI_NOATTACH) 993c7e4935fSss150715 return (DLPI_SUCCESS); 994c7e4935fSss150715 995c7e4935fSss150715 attach: 996c7e4935fSss150715 if ((retval = i_dlpi_attach(dip)) != DLPI_SUCCESS) 997c7e4935fSss150715 goto failure; 998c7e4935fSss150715 999c7e4935fSss150715 return (DLPI_SUCCESS); 1000c7e4935fSss150715 1001c7e4935fSss150715 failure: 1002c7e4935fSss150715 save_errno = errno; 1003c7e4935fSss150715 (void) close(dip->dli_fd); 1004c7e4935fSss150715 errno = save_errno; 1005c7e4935fSss150715 return (retval); 1006c7e4935fSss150715 } 1007c7e4935fSss150715 1008c7e4935fSss150715 /* 1009c7e4935fSss150715 * Verify with DLPI that the link is the expected DLPI 'style' device, 1010c7e4935fSss150715 * dlpi_info sets the DLPI style in the DLPI handle. 1011c7e4935fSss150715 */ 1012c7e4935fSss150715 static int 1013c7e4935fSss150715 i_dlpi_checkstyle(dlpi_impl_t *dip, t_uscalar_t style) 1014c7e4935fSss150715 { 1015c7e4935fSss150715 int retval; 1016c7e4935fSss150715 dlpi_info_t dlinfo; 1017c7e4935fSss150715 1018c7e4935fSss150715 retval = dlpi_info((dlpi_handle_t)dip, &dlinfo, 0); 1019c7e4935fSss150715 if (retval == DLPI_SUCCESS && dip->dli_style != style) 1020c7e4935fSss150715 retval = DLPI_EBADLINK; 1021c7e4935fSss150715 1022c7e4935fSss150715 return (retval); 1023c7e4935fSss150715 } 1024c7e4935fSss150715 1025c7e4935fSss150715 /* 1026c7e4935fSss150715 * Remove PPA from end of linkname. 1027c7e4935fSss150715 * Return DLPI_SUCCESS if found, else return DLPI_FAILURE. 1028c7e4935fSss150715 */ 1029c7e4935fSss150715 static int 1030c7e4935fSss150715 i_dlpi_remove_ppa(char *linkname) 1031c7e4935fSss150715 { 1032c7e4935fSss150715 int i = strlen(linkname) - 1; 1033c7e4935fSss150715 1034c7e4935fSss150715 if (i == -1 || !isdigit(linkname[i--])) 1035c7e4935fSss150715 return (DLPI_FAILURE); 1036c7e4935fSss150715 1037c7e4935fSss150715 while (i >= 0 && isdigit(linkname[i])) 1038c7e4935fSss150715 i--; 1039c7e4935fSss150715 1040c7e4935fSss150715 linkname[i + 1] = '\0'; 1041c7e4935fSss150715 return (DLPI_SUCCESS); 1042c7e4935fSss150715 } 1043c7e4935fSss150715 1044c7e4935fSss150715 /* 1045c7e4935fSss150715 * For DLPI style 2 providers, an explicit attach of PPA is required. 1046c7e4935fSss150715 */ 1047c7e4935fSss150715 static int 1048c7e4935fSss150715 i_dlpi_attach(dlpi_impl_t *dip) 1049c7e4935fSss150715 { 1050c7e4935fSss150715 dlpi_msg_t req, ack; 1051c7e4935fSss150715 dl_attach_req_t *attachreqp; 1052c7e4935fSss150715 1053c7e4935fSss150715 /* 1054c7e4935fSss150715 * Special case: DLPI_SERIAL flag (synchronous serial lines) 1055c7e4935fSss150715 * is not a DLPI link so ignore DLPI style. 1056c7e4935fSss150715 */ 1057c7e4935fSss150715 if (dip->dli_style != DL_STYLE2 && !(dip->dli_oflags & DLPI_SERIAL)) 1058c7e4935fSss150715 return (DLPI_ENOTSTYLE2); 1059c7e4935fSss150715 1060c7e4935fSss150715 DLPI_MSG_CREATE(req, DL_ATTACH_REQ); 1061c7e4935fSss150715 DLPI_MSG_CREATE(ack, DL_OK_ACK); 1062c7e4935fSss150715 1063c7e4935fSss150715 attachreqp = &(req.dlm_msg->attach_req); 1064c7e4935fSss150715 attachreqp->dl_ppa = dip->dli_ppa; 1065c7e4935fSss150715 1066c7e4935fSss150715 return (i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0)); 1067c7e4935fSss150715 } 1068c7e4935fSss150715 1069c7e4935fSss150715 /* 1070c7e4935fSss150715 * Enable DLPI passive mode on a DLPI handle. We intentionally do not care 1071c7e4935fSss150715 * if this request fails, as this indicates the underlying DLPI device does 1072c7e4935fSss150715 * not support link aggregation (pre-GLDV3 device drivers), and thus will 1073c7e4935fSss150715 * see the expected behavior without failing with DL_SYSERR/EBUSY when issuing 1074c7e4935fSss150715 * DLPI primitives like DL_BIND_REQ. For further info see dlpi(7p). 1075c7e4935fSss150715 */ 1076c7e4935fSss150715 static void 1077c7e4935fSss150715 i_dlpi_passive(dlpi_impl_t *dip) 1078c7e4935fSss150715 { 1079c7e4935fSss150715 dlpi_msg_t req, ack; 1080c7e4935fSss150715 1081c7e4935fSss150715 DLPI_MSG_CREATE(req, DL_PASSIVE_REQ); 1082c7e4935fSss150715 DLPI_MSG_CREATE(ack, DL_OK_ACK); 1083c7e4935fSss150715 1084c7e4935fSss150715 (void) i_dlpi_msg_common(dip, &req, &ack, DL_OK_ACK_SIZE, 0); 1085c7e4935fSss150715 } 1086c7e4935fSss150715 1087c7e4935fSss150715 /* 1088c7e4935fSss150715 * Send a dlpi control message and/or data message on a stream. The inputs 1089c7e4935fSss150715 * for this function are: 1090c7e4935fSss150715 * int fd: file descriptor of open stream to send message 1091c7e4935fSss150715 * const dlpi_msg_t *dlreqp: request message structure 1092c7e4935fSss150715 * void *databuf: data buffer 1093c7e4935fSss150715 * size_t datalen: data buffer len 1094c7e4935fSss150715 * int flags: flags to set for putmsg() 1095c7e4935fSss150715 * Returns DLPI_SUCCESS if putmsg() succeeds, otherwise DL_SYSERR on failure. 1096c7e4935fSss150715 */ 1097c7e4935fSss150715 static int 1098c7e4935fSss150715 i_dlpi_strputmsg(int fd, const dlpi_msg_t *dlreqp, 1099c7e4935fSss150715 const void *databuf, size_t datalen, int flags) 1100c7e4935fSss150715 { 1101c7e4935fSss150715 int retval; 11027c478bd9Sstevel@tonic-gate struct strbuf ctl; 11037c478bd9Sstevel@tonic-gate struct strbuf data; 1104c7e4935fSss150715 1105c7e4935fSss150715 if (dlreqp != NULL) { 1106c7e4935fSss150715 ctl.buf = (void *)dlreqp->dlm_msg; 1107c7e4935fSss150715 ctl.len = dlreqp->dlm_msgsz; 1108c7e4935fSss150715 } 1109c7e4935fSss150715 1110c7e4935fSss150715 data.buf = (void *)databuf; 1111c7e4935fSss150715 data.len = datalen; 1112c7e4935fSss150715 1113c7e4935fSss150715 retval = putmsg(fd, (dlreqp == NULL ? NULL: &ctl), 1114c7e4935fSss150715 (databuf == NULL ? NULL : &data), flags); 1115c7e4935fSss150715 1116c7e4935fSss150715 return ((retval == 0) ? DLPI_SUCCESS : DL_SYSERR); 1117c7e4935fSss150715 } 1118c7e4935fSss150715 1119c7e4935fSss150715 /* 1120c7e4935fSss150715 * Get a DLPI control message and/or data message from a stream. The inputs 1121c7e4935fSss150715 * for this function are: 1122c7e4935fSss150715 * int fd: file descriptor of open stream 1123c7e4935fSss150715 * int msec: timeout to wait for message 1124c7e4935fSss150715 * dlpi_msg_t *dlreplyp: reply message structure, the message size 1125c7e4935fSss150715 * member on return stores actual size received 1126c7e4935fSss150715 * t_uscalar_t dlreqprim: requested primitive 1127c7e4935fSss150715 * t_uscalar_t dlreplyprim:acknowledged primitive in response to request 1128c7e4935fSss150715 * size_t dlreplyminsz: minimum size of acknowledged primitive size 1129c7e4935fSss150715 * void *databuf: data buffer 1130c7e4935fSss150715 * size_t *datalenp: data buffer len 1131c7e4935fSss150715 * size_t *totdatalenp: total data received. Greater than 'datalenp' if 1132c7e4935fSss150715 * actual data received is larger than 'databuf' 1133c7e4935fSss150715 * Function returns DLPI_SUCCESS if requested message is retrieved 1134c7e4935fSss150715 * otherwise returns error code or timeouts. 1135c7e4935fSss150715 */ 1136c7e4935fSss150715 static int 1137c7e4935fSss150715 i_dlpi_strgetmsg(int fd, int msec, dlpi_msg_t *dlreplyp, t_uscalar_t dlreqprim, 1138c7e4935fSss150715 t_uscalar_t dlreplyprim, size_t dlreplyminsz, void *databuf, 1139c7e4935fSss150715 size_t *datalenp, size_t *totdatalenp) 1140c7e4935fSss150715 { 1141c7e4935fSss150715 int retval; 11427c478bd9Sstevel@tonic-gate int flags = 0; 1143c7e4935fSss150715 struct strbuf ctl, data; 1144c7e4935fSss150715 struct pollfd pfd; 1145c7e4935fSss150715 hrtime_t start, current; 1146c7e4935fSss150715 long bufc[DLPI_CHUNKSIZE / sizeof (long)]; 1147c7e4935fSss150715 long bufd[DLPI_CHUNKSIZE / sizeof (long)]; 1148c7e4935fSss150715 union DL_primitives *dlprim; 1149c7e4935fSss150715 boolean_t infinite = (msec < 0); /* infinite timeout */ 1150c7e4935fSss150715 1151c7e4935fSss150715 if ((dlreplyp == NULL && databuf == NULL) || 1152c7e4935fSss150715 (databuf == NULL && datalenp != NULL) || 1153c7e4935fSss150715 (databuf != NULL && datalenp == NULL)) 1154c7e4935fSss150715 return (DLPI_EINVAL); 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate pfd.fd = fd; 11577c478bd9Sstevel@tonic-gate pfd.events = POLLIN | POLLPRI; 11587c478bd9Sstevel@tonic-gate 1159c7e4935fSss150715 ctl.buf = (dlreplyp == NULL) ? bufc : (void *)dlreplyp->dlm_msg; 11607c478bd9Sstevel@tonic-gate ctl.len = 0; 1161c7e4935fSss150715 ctl.maxlen = (dlreplyp == NULL) ? sizeof (bufc) : dlreplyp->dlm_msgsz; 11627c478bd9Sstevel@tonic-gate 1163c7e4935fSss150715 data.buf = (databuf == NULL) ? bufd : databuf; 11647c478bd9Sstevel@tonic-gate data.len = 0; 1165c7e4935fSss150715 data.maxlen = (databuf == NULL) ? sizeof (bufd): *datalenp; 11667c478bd9Sstevel@tonic-gate 1167c7e4935fSss150715 for (;;) { 1168c7e4935fSss150715 if (!infinite) 1169c7e4935fSss150715 start = gethrtime() / (NANOSEC / MILLISEC); 11707c478bd9Sstevel@tonic-gate 1171c7e4935fSss150715 switch (poll(&pfd, 1, msec)) { 1172c7e4935fSss150715 default: 1173948f2876Sss150715 if (pfd.revents & POLLHUP) 1174948f2876Sss150715 return (DL_SYSERR); 11757c478bd9Sstevel@tonic-gate break; 11767c478bd9Sstevel@tonic-gate case 0: 1177c7e4935fSss150715 return (DLPI_ETIMEDOUT); 11787c478bd9Sstevel@tonic-gate case -1: 1179c7e4935fSss150715 return (DL_SYSERR); 11807c478bd9Sstevel@tonic-gate } 11817c478bd9Sstevel@tonic-gate 1182c7e4935fSss150715 if ((retval = getmsg(fd, &ctl, &data, &flags)) < 0) 1183c7e4935fSss150715 return (DL_SYSERR); 11847c478bd9Sstevel@tonic-gate 1185c7e4935fSss150715 if (totdatalenp != NULL) 1186c7e4935fSss150715 *totdatalenp = data.len; 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate /* 1189c7e4935fSss150715 * The supplied DLPI_CHUNKSIZE sized buffers are large enough 1190c7e4935fSss150715 * to retrieve all valid DLPI responses in one iteration. 1191c7e4935fSss150715 * If MORECTL or MOREDATA is set, we are not interested in the 1192c7e4935fSss150715 * remainder of the message. Temporary buffers are used to 1193c7e4935fSss150715 * drain the remainder of this message. 1194c7e4935fSss150715 * The special case we have to account for is if 1195c7e4935fSss150715 * a higher priority messages is enqueued whilst handling 1196c7e4935fSss150715 * this condition. We use a change in the flags parameter 1197c7e4935fSss150715 * returned by getmsg() to indicate the message has changed. 11987c478bd9Sstevel@tonic-gate */ 1199c7e4935fSss150715 while (retval & (MORECTL | MOREDATA)) { 1200c7e4935fSss150715 struct strbuf cscratch, dscratch; 1201c7e4935fSss150715 int oflags = flags; 1202c7e4935fSss150715 1203c7e4935fSss150715 cscratch.buf = (char *)bufc; 1204c7e4935fSss150715 dscratch.buf = (char *)bufd; 1205c7e4935fSss150715 cscratch.len = dscratch.len = 0; 1206c7e4935fSss150715 cscratch.maxlen = dscratch.maxlen = 1207c7e4935fSss150715 sizeof (bufc); 1208c7e4935fSss150715 1209c7e4935fSss150715 if ((retval = getmsg(fd, &cscratch, &dscratch, 1210c7e4935fSss150715 &flags)) < 0) 1211c7e4935fSss150715 return (DL_SYSERR); 1212c7e4935fSss150715 1213c7e4935fSss150715 if (totdatalenp != NULL) 1214c7e4935fSss150715 *totdatalenp += dscratch.len; 1215c7e4935fSss150715 /* 1216c7e4935fSss150715 * In the special case of higher priority 1217c7e4935fSss150715 * message received, the low priority message 1218c7e4935fSss150715 * received earlier is discarded, if no data 1219c7e4935fSss150715 * or control message is left. 1220c7e4935fSss150715 */ 1221c7e4935fSss150715 if ((flags != oflags) && 1222c7e4935fSss150715 !(retval & (MORECTL | MOREDATA)) && 1223c7e4935fSss150715 (cscratch.len != 0)) { 1224c7e4935fSss150715 ctl.len = MIN(cscratch.len, DLPI_CHUNKSIZE); 1225c7e4935fSss150715 if (dlreplyp != NULL) 1226c7e4935fSss150715 (void) memcpy(dlreplyp->dlm_msg, bufc, 1227c7e4935fSss150715 ctl.len); 1228c7e4935fSss150715 break; 12297c478bd9Sstevel@tonic-gate } 12307c478bd9Sstevel@tonic-gate } 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate /* 1233c7e4935fSss150715 * If we were expecting a data message, and we got one, set 1234c7e4935fSss150715 * *datalenp. If we aren't waiting on a control message, then 1235c7e4935fSss150715 * we're done. 12367c478bd9Sstevel@tonic-gate */ 1237c7e4935fSss150715 if (databuf != NULL && data.len >= 0) { 1238c7e4935fSss150715 *datalenp = data.len; 1239c7e4935fSss150715 if (dlreplyp == NULL) 1240c7e4935fSss150715 break; 12417c478bd9Sstevel@tonic-gate } 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate /* 1244c7e4935fSss150715 * If we were expecting a control message, and the message 1245c7e4935fSss150715 * we received is at least big enough to be a DLPI message, 1246c7e4935fSss150715 * then verify it's a reply to something we sent. If it 1247c7e4935fSss150715 * is a reply to something we sent, also verify its size. 12487c478bd9Sstevel@tonic-gate */ 1249c7e4935fSss150715 if (dlreplyp != NULL && ctl.len >= sizeof (t_uscalar_t)) { 1250c7e4935fSss150715 dlprim = dlreplyp->dlm_msg; 1251c7e4935fSss150715 if (dlprim->dl_primitive == dlreplyprim) { 1252c7e4935fSss150715 if (ctl.len < dlreplyminsz) 1253c7e4935fSss150715 return (DLPI_EBADMSG); 1254c7e4935fSss150715 dlreplyp->dlm_msgsz = ctl.len; 1255c7e4935fSss150715 break; 1256c7e4935fSss150715 } else if (dlprim->dl_primitive == DL_ERROR_ACK) { 1257c7e4935fSss150715 if (ctl.len < DL_ERROR_ACK_SIZE) 1258c7e4935fSss150715 return (DLPI_EBADMSG); 12597c478bd9Sstevel@tonic-gate 1260c7e4935fSss150715 /* Is it ours? */ 1261c7e4935fSss150715 if (dlprim->error_ack.dl_error_primitive == 1262c7e4935fSss150715 dlreqprim) 12637c478bd9Sstevel@tonic-gate break; 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate 1267c7e4935fSss150715 if (!infinite) { 1268c7e4935fSss150715 current = gethrtime() / (NANOSEC / MILLISEC); 1269c7e4935fSss150715 msec -= (current - start); 12707c478bd9Sstevel@tonic-gate 1271c7e4935fSss150715 if (msec <= 0) 1272c7e4935fSss150715 return (DLPI_ETIMEDOUT); 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate 1276c7e4935fSss150715 return (DLPI_SUCCESS); 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate 12797c478bd9Sstevel@tonic-gate /* 1280c7e4935fSss150715 * Common routine invoked by all DLPI control routines. The inputs for this 1281c7e4935fSss150715 * function are: 1282c7e4935fSss150715 * dlpi_impl_t *dip: internal dlpi handle 1283c7e4935fSss150715 * const dlpi_msg_t *dlreqp: request message structure 1284c7e4935fSss150715 * dlpi_msg_t *dlreplyp: reply message structure 1285c7e4935fSss150715 * size_t dlreplyminsz: minimum size of reply primitive 1286c7e4935fSss150715 * int flags: flags to be set to send a message 1287c7e4935fSss150715 * This routine succeeds if the message is an expected request/acknowledged 1288c7e4935fSss150715 * message. Unexpected asynchronous messages (e.g. unexpected DL_NOTIFY_IND 1289c7e4935fSss150715 * messages) will be discarded. 12907c478bd9Sstevel@tonic-gate */ 12917c478bd9Sstevel@tonic-gate static int 1292c7e4935fSss150715 i_dlpi_msg_common(dlpi_impl_t *dip, const dlpi_msg_t *dlreqp, 1293c7e4935fSss150715 dlpi_msg_t *dlreplyp, size_t dlreplyminsz, int flags) 1294c7e4935fSss150715 { 1295c7e4935fSss150715 int retval; 1296c7e4935fSss150715 t_uscalar_t dlreqprim = dlreqp->dlm_msg->dl_primitive; 1297c7e4935fSss150715 t_uscalar_t dlreplyprim = dlreplyp->dlm_msg->dl_primitive; 1298c7e4935fSss150715 1299c7e4935fSss150715 /* Put the requested primitive on the stream. */ 1300c7e4935fSss150715 retval = i_dlpi_strputmsg(dip->dli_fd, dlreqp, NULL, 0, flags); 1301c7e4935fSss150715 if (retval != DLPI_SUCCESS) 1302c7e4935fSss150715 return (retval); 1303c7e4935fSss150715 1304c7e4935fSss150715 /* Retrieve acknowledged message for requested primitive. */ 1305c7e4935fSss150715 retval = i_dlpi_strgetmsg(dip->dli_fd, (dip->dli_timeout * MILLISEC), 1306c7e4935fSss150715 dlreplyp, dlreqprim, dlreplyprim, dlreplyminsz, NULL, NULL, NULL); 1307c7e4935fSss150715 if (retval != DLPI_SUCCESS) 1308c7e4935fSss150715 return (retval); 1309c7e4935fSss150715 1310c7e4935fSss150715 /* 1311c7e4935fSss150715 * If primitive is DL_ERROR_ACK, set errno. 1312c7e4935fSss150715 */ 1313c7e4935fSss150715 if (dlreplyp->dlm_msg->dl_primitive == DL_ERROR_ACK) { 1314c7e4935fSss150715 errno = dlreplyp->dlm_msg->error_ack.dl_unix_errno; 1315c7e4935fSss150715 retval = dlreplyp->dlm_msg->error_ack.dl_errno; 1316c7e4935fSss150715 } 1317c7e4935fSss150715 1318c7e4935fSss150715 return (retval); 1319c7e4935fSss150715 } 1320c7e4935fSss150715 1321c7e4935fSss150715 /* 1322c7e4935fSss150715 * DLPI error codes. 1323c7e4935fSss150715 */ 1324c7e4935fSss150715 static const char *dlpi_errlist[] = { 1325c7e4935fSss150715 "bad LSAP selector", /* DL_BADSAP 0x00 */ 1326c7e4935fSss150715 "DLSAP address in improper format or invalid", /* DL_BADADDR 0x01 */ 1327c7e4935fSss150715 "improper permissions for request", /* DL_ACCESS 0x02 */ 1328c7e4935fSss150715 "primitive issued in improper state", /* DL_OUTSTATE 0x03 */ 1329c7e4935fSss150715 NULL, /* DL_SYSERR 0x04 */ 1330c7e4935fSss150715 "sequence number not from outstanding DL_CONN_IND", 1331c7e4935fSss150715 /* DL_BADCORR 0x05 */ 1332c7e4935fSss150715 "user data exceeded provider limit", /* DL_BADDATA 0x06 */ 1333c7e4935fSss150715 "requested service not supplied by provider", 1334c7e4935fSss150715 /* DL_UNSUPPORTED 0x07 */ 1335c7e4935fSss150715 "specified PPA was invalid", /* DL_BADPPA 0x08 */ 1336c7e4935fSss150715 "primitive received not known by provider", /* DL_BADPRIM 0x09 */ 1337c7e4935fSss150715 "QoS parameters contained invalid values", 1338c7e4935fSss150715 /* DL_BADQOSPARAM 0x0a */ 1339c7e4935fSss150715 "QoS structure type is unknown/unsupported", /* DL_BADQOSTYPE 0x0b */ 1340c7e4935fSss150715 "token used not an active stream", /* DL_BADTOKEN 0x0c */ 1341c7e4935fSss150715 "attempted second bind with dl_max_conind", /* DL_BOUND 0x0d */ 1342c7e4935fSss150715 "physical link initialization failed", /* DL_INITFAILED 0x0e */ 1343c7e4935fSss150715 "provider couldn't allocate alternate address", /* DL_NOADDR 0x0f */ 1344c7e4935fSss150715 "physical link not initialized", /* DL_NOTINIT 0x10 */ 1345c7e4935fSss150715 "previous data unit could not be delivered", 1346c7e4935fSss150715 /* DL_UNDELIVERABLE 0x11 */ 1347c7e4935fSss150715 "primitive is known but unsupported", 1348c7e4935fSss150715 /* DL_NOTSUPPORTED 0x12 */ 1349c7e4935fSss150715 "limit exceeded", /* DL_TOOMANY 0x13 */ 1350c7e4935fSss150715 "promiscuous mode not enabled", /* DL_NOTENAB 0x14 */ 1351c7e4935fSss150715 "other streams for PPA in post-attached", /* DL_BUSY 0x15 */ 1352c7e4935fSss150715 "automatic handling XID&TEST unsupported", /* DL_NOAUTO 0x16 */ 1353c7e4935fSss150715 "automatic handling of XID unsupported", /* DL_NOXIDAUTO 0x17 */ 1354c7e4935fSss150715 "automatic handling of TEST unsupported", /* DL_NOTESTAUTO 0x18 */ 1355c7e4935fSss150715 "automatic handling of XID response", /* DL_XIDAUTO 0x19 */ 1356c7e4935fSss150715 "automatic handling of TEST response", /* DL_TESTAUTO 0x1a */ 1357c7e4935fSss150715 "pending outstanding connect indications" /* DL_PENDING 0x1b */ 1358c7e4935fSss150715 }; 1359c7e4935fSss150715 1360c7e4935fSss150715 /* 1361c7e4935fSss150715 * libdlpi error codes. 1362c7e4935fSss150715 */ 1363c7e4935fSss150715 static const char *libdlpi_errlist[] = { 1364c7e4935fSss150715 "DLPI operation succeeded", /* DLPI_SUCCESS */ 1365c7e4935fSss150715 "invalid argument", /* DLPI_EINVAL */ 1366c7e4935fSss150715 "invalid DLPI linkname", /* DLPI_ELINKNAMEINVAL */ 1367c7e4935fSss150715 "DLPI link does not exist", /* DLPI_ENOLINK */ 1368c7e4935fSss150715 "bad DLPI link", /* DLPI_EBADLINK */ 1369c7e4935fSss150715 "invalid DLPI handle", /* DLPI_EINHANDLE */ 1370c7e4935fSss150715 "DLPI operation timed out", /* DLPI_ETIMEDOUT */ 1371c7e4935fSss150715 "unsupported DLPI version", /* DLPI_EVERNOTSUP */ 1372c7e4935fSss150715 "unsupported DLPI connection mode", /* DLPI_EMODENOTSUP */ 1373c7e4935fSss150715 "unavailable DLPI SAP", /* DLPI_EUNAVAILSAP */ 1374c7e4935fSss150715 "DLPI operation failed", /* DLPI_FAILURE */ 1375c7e4935fSss150715 "DLPI style-2 node reports style-1", /* DLPI_ENOTSTYLE2 */ 1376c7e4935fSss150715 "bad DLPI message", /* DLPI_EBADMSG */ 1377c7e4935fSss150715 "DLPI raw mode not supported" /* DLPI_ERAWNOTSUP */ 1378c7e4935fSss150715 }; 1379c7e4935fSss150715 1380c7e4935fSss150715 const char * 1381c7e4935fSss150715 dlpi_strerror(int err) 1382c7e4935fSss150715 { 1383c7e4935fSss150715 if (err == DL_SYSERR) 1384c7e4935fSss150715 return (strerror(errno)); 1385c7e4935fSss150715 else if (err >= 0 && err < NELEMS(dlpi_errlist)) 1386c7e4935fSss150715 return (dgettext(TEXT_DOMAIN, dlpi_errlist[err])); 1387c7e4935fSss150715 else if (err > DLPI_SUCCESS && err < DLPI_ERRMAX) 1388c7e4935fSss150715 return (dgettext(TEXT_DOMAIN, libdlpi_errlist[err - 1389c7e4935fSss150715 DLPI_SUCCESS])); 1390c7e4935fSss150715 else 1391c7e4935fSss150715 return (dgettext(TEXT_DOMAIN, "Unknown DLPI error")); 1392c7e4935fSss150715 } 1393c7e4935fSss150715 1394c7e4935fSss150715 /* 1395c7e4935fSss150715 * Each table entry comprises a DLPI/Private mactype and the description. 1396c7e4935fSss150715 */ 1397c7e4935fSss150715 static const dlpi_mactype_t dlpi_mactypes[] = { 1398c7e4935fSss150715 { DL_CSMACD, "CSMA/CD" }, 1399c7e4935fSss150715 { DL_TPB, "Token Bus" }, 1400c7e4935fSss150715 { DL_TPR, "Token Ring" }, 1401c7e4935fSss150715 { DL_METRO, "Metro Net" }, 1402c7e4935fSss150715 { DL_ETHER, "Ethernet" }, 1403c7e4935fSss150715 { DL_HDLC, "HDLC" }, 1404c7e4935fSss150715 { DL_CHAR, "Sync Character" }, 1405c7e4935fSss150715 { DL_CTCA, "CTCA" }, 1406c7e4935fSss150715 { DL_FDDI, "FDDI" }, 1407c7e4935fSss150715 { DL_FRAME, "Frame Relay (LAPF)" }, 1408c7e4935fSss150715 { DL_MPFRAME, "MP Frame Relay" }, 1409c7e4935fSss150715 { DL_ASYNC, "Async Character" }, 1410c7e4935fSss150715 { DL_IPX25, "X.25 (Classic IP)" }, 1411c7e4935fSss150715 { DL_LOOP, "Software Loopback" }, 1412c7e4935fSss150715 { DL_FC, "Fiber Channel" }, 1413c7e4935fSss150715 { DL_ATM, "ATM" }, 1414c7e4935fSss150715 { DL_IPATM, "ATM (Classic IP)" }, 1415c7e4935fSss150715 { DL_X25, "X.25 (LAPB)" }, 1416c7e4935fSss150715 { DL_ISDN, "ISDN" }, 1417c7e4935fSss150715 { DL_HIPPI, "HIPPI" }, 1418c7e4935fSss150715 { DL_100VG, "100BaseVG Ethernet" }, 1419c7e4935fSss150715 { DL_100VGTPR, "100BaseVG Token Ring" }, 1420c7e4935fSss150715 { DL_ETH_CSMA, "Ethernet/IEEE 802.3" }, 1421c7e4935fSss150715 { DL_100BT, "100BaseT" }, 1422c7e4935fSss150715 { DL_IB, "Infiniband" }, 1423c7e4935fSss150715 { DL_IPV4, "IPv4 Tunnel" }, 1424c7e4935fSss150715 { DL_IPV6, "IPv6 Tunnel" }, 1425c7e4935fSss150715 { DL_WIFI, "IEEE 802.11" } 1426c7e4935fSss150715 }; 1427c7e4935fSss150715 1428c7e4935fSss150715 const char * 1429c7e4935fSss150715 dlpi_mactype(uint_t mactype) 14307c478bd9Sstevel@tonic-gate { 14317c478bd9Sstevel@tonic-gate int i; 14327c478bd9Sstevel@tonic-gate 1433c7e4935fSss150715 for (i = 0; i < NELEMS(dlpi_mactypes); i++) { 1434c7e4935fSss150715 if (dlpi_mactypes[i].dm_mactype == mactype) 1435c7e4935fSss150715 return (dlpi_mactypes[i].dm_desc); 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate 1438c7e4935fSss150715 return ("Unknown MAC Type"); 14397c478bd9Sstevel@tonic-gate } 14407c478bd9Sstevel@tonic-gate 1441c7e4935fSss150715 /* 1442c7e4935fSss150715 * Each table entry comprises a DLPI primitive and the maximum buffer 1443c7e4935fSss150715 * size needed, in bytes, for the DLPI message (see <sys/dlpi.h> for details). 1444c7e4935fSss150715 */ 1445c7e4935fSss150715 static const dlpi_primsz_t dlpi_primsizes[] = { 1446c7e4935fSss150715 { DL_INFO_REQ, DL_INFO_REQ_SIZE }, 1447c7e4935fSss150715 { DL_INFO_ACK, DL_INFO_ACK_SIZE + (2 * DLPI_PHYSADDR_MAX) + 1448c7e4935fSss150715 DLPI_SAPLEN_MAX + (2 * sizeof (union DL_qos_types))}, 1449c7e4935fSss150715 { DL_ATTACH_REQ, DL_ATTACH_REQ_SIZE }, 1450c7e4935fSss150715 { DL_BIND_REQ, DL_BIND_REQ_SIZE }, 1451c7e4935fSss150715 { DL_BIND_ACK, DL_BIND_ACK_SIZE + DLPI_PHYSADDR_MAX + 1452c7e4935fSss150715 DLPI_SAPLEN_MAX }, 1453c7e4935fSss150715 { DL_UNBIND_REQ, DL_UNBIND_REQ_SIZE }, 1454c7e4935fSss150715 { DL_ENABMULTI_REQ, DL_ENABMULTI_REQ_SIZE + DLPI_PHYSADDR_MAX }, 1455c7e4935fSss150715 { DL_DISABMULTI_REQ, DL_DISABMULTI_REQ_SIZE + DLPI_PHYSADDR_MAX }, 1456c7e4935fSss150715 { DL_PROMISCON_REQ, DL_PROMISCON_REQ_SIZE }, 1457c7e4935fSss150715 { DL_PROMISCOFF_REQ, DL_PROMISCOFF_REQ_SIZE }, 1458c7e4935fSss150715 { DL_PASSIVE_REQ, DL_PASSIVE_REQ_SIZE }, 1459c7e4935fSss150715 { DL_UNITDATA_REQ, DL_UNITDATA_REQ_SIZE + DLPI_PHYSADDR_MAX + 1460c7e4935fSss150715 DLPI_SAPLEN_MAX }, 1461c7e4935fSss150715 { DL_UNITDATA_IND, DL_UNITDATA_IND_SIZE + (2 * (DLPI_PHYSADDR_MAX + 1462c7e4935fSss150715 DLPI_SAPLEN_MAX)) }, 1463c7e4935fSss150715 { DL_PHYS_ADDR_REQ, DL_PHYS_ADDR_REQ_SIZE }, 1464c7e4935fSss150715 { DL_PHYS_ADDR_ACK, DL_PHYS_ADDR_ACK_SIZE + DLPI_PHYSADDR_MAX }, 1465c7e4935fSss150715 { DL_SET_PHYS_ADDR_REQ, DL_SET_PHYS_ADDR_REQ_SIZE + DLPI_PHYSADDR_MAX }, 1466c7e4935fSss150715 { DL_OK_ACK, MAX(DL_ERROR_ACK_SIZE, DL_OK_ACK_SIZE) } 1467c7e4935fSss150715 }; 1468c7e4935fSss150715 1469c7e4935fSss150715 /* 1470c7e4935fSss150715 * Refers to the dlpi_primsizes[] table to return corresponding maximum 1471c7e4935fSss150715 * buffer size. 1472c7e4935fSss150715 */ 1473c7e4935fSss150715 static size_t 1474c7e4935fSss150715 i_dlpi_getprimsize(t_uscalar_t prim) 1475c7e4935fSss150715 { 1476c7e4935fSss150715 int i; 1477c7e4935fSss150715 1478c7e4935fSss150715 for (i = 0; i < NELEMS(dlpi_primsizes); i++) { 1479c7e4935fSss150715 if (dlpi_primsizes[i].dp_prim == prim) 1480c7e4935fSss150715 return (dlpi_primsizes[i].dp_primsz); 1481c7e4935fSss150715 } 1482c7e4935fSss150715 1483c7e4935fSss150715 return (sizeof (t_uscalar_t)); 1484c7e4935fSss150715 } 1485c7e4935fSss150715 1486c7e4935fSss150715 /* 1487c7e4935fSss150715 * sap values vary in length and are in host byte order, build sap value 1488c7e4935fSss150715 * by writing saplen bytes, so that the sap value is left aligned. 1489c7e4935fSss150715 */ 1490c7e4935fSss150715 static uint_t 1491c7e4935fSss150715 i_dlpi_buildsap(uint8_t *sapp, uint_t saplen) 1492c7e4935fSss150715 { 1493c7e4935fSss150715 int i; 1494c7e4935fSss150715 uint_t sap = 0; 1495c7e4935fSss150715 1496c7e4935fSss150715 #ifdef _LITTLE_ENDIAN 1497c7e4935fSss150715 for (i = saplen - 1; i >= 0; i--) { 1498c7e4935fSss150715 #else 1499c7e4935fSss150715 for (i = 0; i < saplen; i++) { 1500c7e4935fSss150715 #endif 1501c7e4935fSss150715 sap <<= 8; 1502c7e4935fSss150715 sap |= sapp[i]; 1503c7e4935fSss150715 } 1504c7e4935fSss150715 1505c7e4935fSss150715 return (sap); 1506c7e4935fSss150715 } 1507c7e4935fSss150715 1508c7e4935fSss150715 /* 1509c7e4935fSss150715 * Copy sap value to a buffer in host byte order. saplen is the number of 1510c7e4935fSss150715 * bytes to copy. 1511c7e4935fSss150715 */ 1512c7e4935fSss150715 static void 1513c7e4935fSss150715 i_dlpi_writesap(void *dstbuf, uint_t sap, uint_t saplen) 1514c7e4935fSss150715 { 1515c7e4935fSss150715 uint8_t *sapp; 1516c7e4935fSss150715 1517c7e4935fSss150715 #ifdef _LITTLE_ENDIAN 1518c7e4935fSss150715 sapp = (uint8_t *)&sap; 1519c7e4935fSss150715 #else 1520c7e4935fSss150715 sapp = (uint8_t *)&sap + (sizeof (sap) - saplen); 1521c7e4935fSss150715 #endif 1522c7e4935fSss150715 1523c7e4935fSss150715 (void) memcpy(dstbuf, sapp, saplen); 15247c478bd9Sstevel@tonic-gate } 1525