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