xref: /titanic_44/usr/src/lib/libuuid/common/etheraddr.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 2000,2002 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 #include "etheraddr.h"
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <stdio.h>
32*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
33*7c478bd9Sstevel@tonic-gate #include <string.h>
34*7c478bd9Sstevel@tonic-gate #include <strings.h>
35*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
36*7c478bd9Sstevel@tonic-gate #include <stropts.h>
37*7c478bd9Sstevel@tonic-gate #include <unistd.h>
38*7c478bd9Sstevel@tonic-gate #include <uuid/uuid.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include <netdb.h>
43*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
44*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #include <sys/dlpi.h>
47*7c478bd9Sstevel@tonic-gate /*
48*7c478bd9Sstevel@tonic-gate  * debugging flag
49*7c478bd9Sstevel@tonic-gate  */
50*7c478bd9Sstevel@tonic-gate static	int	debug = 0;
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate /* Timeout for DLPI acks */
54*7c478bd9Sstevel@tonic-gate static	int	dlpi_timeout = DLPI_TIMEOUT;
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate  * Global functions
58*7c478bd9Sstevel@tonic-gate  */
59*7c478bd9Sstevel@tonic-gate int	dlpi_get_address(char *, struct ether_addr *);
60*7c478bd9Sstevel@tonic-gate int	get_net_if_names(char ***);
61*7c478bd9Sstevel@tonic-gate void	free_net_if_names(char **);
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /*
65*7c478bd9Sstevel@tonic-gate  * local functions
66*7c478bd9Sstevel@tonic-gate  */
67*7c478bd9Sstevel@tonic-gate static	int	dlpi_info_req(int, dl_info_ack_t *);
68*7c478bd9Sstevel@tonic-gate static	int	timed_getmsg(int, struct strbuf *, int *, int, char *, char *);
69*7c478bd9Sstevel@tonic-gate static	int	ifrm_num(char *, unsigned int *);
70*7c478bd9Sstevel@tonic-gate static	int	open_dev(dev_att_t *, int, int *, int);
71*7c478bd9Sstevel@tonic-gate static	void	pf_dev_att(dev_att_t *);
72*7c478bd9Sstevel@tonic-gate static	void	parse_ifname(dev_att_t *);
73*7c478bd9Sstevel@tonic-gate static	int	ifname_open(char *, dev_att_t *);
74*7c478bd9Sstevel@tonic-gate static	int	dlpi_open_attach(char *);
75*7c478bd9Sstevel@tonic-gate static	int	dlpi_attach(int, int, int);
76*7c478bd9Sstevel@tonic-gate static	int	dlpi_get_phys(int, uchar_t *);
77*7c478bd9Sstevel@tonic-gate static	int	dlpi_info_req(int, dl_info_ack_t *);
78*7c478bd9Sstevel@tonic-gate static	int	timed_getmsg(int, struct strbuf *, int *, int, char *, char *);
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate /*
81*7c478bd9Sstevel@tonic-gate  * get an individual arp entry
82*7c478bd9Sstevel@tonic-gate  */
83*7c478bd9Sstevel@tonic-gate int
84*7c478bd9Sstevel@tonic-gate arp_get(uuid_node_t *node)
85*7c478bd9Sstevel@tonic-gate {
86*7c478bd9Sstevel@tonic-gate 	struct utsname name;
87*7c478bd9Sstevel@tonic-gate 	struct arpreq ar;
88*7c478bd9Sstevel@tonic-gate 	struct hostent *hp;
89*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin;
90*7c478bd9Sstevel@tonic-gate 	int s;
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 	if (uname(&name) == -1) {
93*7c478bd9Sstevel@tonic-gate 		return (-1);
94*7c478bd9Sstevel@tonic-gate 	}
95*7c478bd9Sstevel@tonic-gate 	(void) memset(&ar, 0, sizeof (ar));
96*7c478bd9Sstevel@tonic-gate 	ar.arp_pa.sa_family = AF_INET;
97*7c478bd9Sstevel@tonic-gate 	/* LINTED pointer */
98*7c478bd9Sstevel@tonic-gate 	sin = (struct sockaddr_in *)&ar.arp_pa;
99*7c478bd9Sstevel@tonic-gate 	sin->sin_family = AF_INET;
100*7c478bd9Sstevel@tonic-gate 	sin->sin_addr.s_addr = inet_addr(name.nodename);
101*7c478bd9Sstevel@tonic-gate 	if (sin->sin_addr.s_addr == (in_addr_t)-1) {
102*7c478bd9Sstevel@tonic-gate 		hp = gethostbyname(name.nodename);
103*7c478bd9Sstevel@tonic-gate 		if (hp == NULL) {
104*7c478bd9Sstevel@tonic-gate 			return (-1);
105*7c478bd9Sstevel@tonic-gate 		}
106*7c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin->sin_addr, hp->h_addr,
107*7c478bd9Sstevel@tonic-gate 		    sizeof (sin->sin_addr));
108*7c478bd9Sstevel@tonic-gate 	}
109*7c478bd9Sstevel@tonic-gate 	s = socket(AF_INET, SOCK_DGRAM, 0);
110*7c478bd9Sstevel@tonic-gate 	if (s < 0) {
111*7c478bd9Sstevel@tonic-gate 		return (-1);
112*7c478bd9Sstevel@tonic-gate 	}
113*7c478bd9Sstevel@tonic-gate 	if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) {
114*7c478bd9Sstevel@tonic-gate 		(void) close(s);
115*7c478bd9Sstevel@tonic-gate 		return (-1);
116*7c478bd9Sstevel@tonic-gate 	}
117*7c478bd9Sstevel@tonic-gate 	(void) close(s);
118*7c478bd9Sstevel@tonic-gate 	if (ar.arp_flags & ATF_COM) {
119*7c478bd9Sstevel@tonic-gate 		bcopy(&ar.arp_ha.sa_data, node, 6);
120*7c478bd9Sstevel@tonic-gate 	} else
121*7c478bd9Sstevel@tonic-gate 		return (-1);
122*7c478bd9Sstevel@tonic-gate 	return (0);
123*7c478bd9Sstevel@tonic-gate }
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate /* Get all interface names.  This will include IPv6 names. */
127*7c478bd9Sstevel@tonic-gate int
128*7c478bd9Sstevel@tonic-gate get_net_if_names(char ***names)
129*7c478bd9Sstevel@tonic-gate {
130*7c478bd9Sstevel@tonic-gate 	char *buf;		/* buffer for socket info */
131*7c478bd9Sstevel@tonic-gate 	int sd;			/* socket descriptor */
132*7c478bd9Sstevel@tonic-gate 	int ifn;	/* interface count structure */
133*7c478bd9Sstevel@tonic-gate 	struct ifconf ifc;    /* interface config buffer */
134*7c478bd9Sstevel@tonic-gate 	struct ifreq *ifrp;
135*7c478bd9Sstevel@tonic-gate 	int numifs;
136*7c478bd9Sstevel@tonic-gate 	char **tmpnames;
137*7c478bd9Sstevel@tonic-gate 	int n;
138*7c478bd9Sstevel@tonic-gate 	char *tmpname;
139*7c478bd9Sstevel@tonic-gate 	sd = socket(AF_INET, SOCK_DGRAM, 0);
140*7c478bd9Sstevel@tonic-gate 	if (sd < 0)
141*7c478bd9Sstevel@tonic-gate 		return (-1);
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 	if (ioctl(sd, SIOCGIFNUM, &ifn) < 0) {
144*7c478bd9Sstevel@tonic-gate 		(void) close(sd);
145*7c478bd9Sstevel@tonic-gate 		return (-1);
146*7c478bd9Sstevel@tonic-gate 	}
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	if (!(buf = malloc(ifn * sizeof (struct ifreq)))) {
149*7c478bd9Sstevel@tonic-gate 		(void) close(sd);
150*7c478bd9Sstevel@tonic-gate 		return (-1);
151*7c478bd9Sstevel@tonic-gate 	}
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	ifc.ifc_len = ifn * sizeof (struct ifreq);
154*7c478bd9Sstevel@tonic-gate 	ifc.ifc_buf = (caddr_t)buf;
155*7c478bd9Sstevel@tonic-gate 	if (ioctl(sd, SIOCGIFCONF, (char *)&ifc) < 0) {
156*7c478bd9Sstevel@tonic-gate 		free(buf);
157*7c478bd9Sstevel@tonic-gate 		(void) close(sd);
158*7c478bd9Sstevel@tonic-gate 		return (-1);
159*7c478bd9Sstevel@tonic-gate 	}
160*7c478bd9Sstevel@tonic-gate 	(void) close(sd);
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	ifrp = ifc.ifc_req;
163*7c478bd9Sstevel@tonic-gate 	numifs = ifc.ifc_len / sizeof (struct ifreq);
164*7c478bd9Sstevel@tonic-gate 	tmpnames = (char **)calloc((numifs+1), sizeof (char *));
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	if (tmpnames == NULL) {
167*7c478bd9Sstevel@tonic-gate 		free(buf);
168*7c478bd9Sstevel@tonic-gate 		return (-1);
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 	for (n = 0; n < numifs; n++, ifrp++) {
171*7c478bd9Sstevel@tonic-gate 		if ((tmpnames[n] = strdup(ifrp->ifr_name)) == NULL)
172*7c478bd9Sstevel@tonic-gate 			break;
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate 	free(buf);
175*7c478bd9Sstevel@tonic-gate 	*names = tmpnames;
176*7c478bd9Sstevel@tonic-gate 	return (0);
177*7c478bd9Sstevel@tonic-gate }
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate /*
180*7c478bd9Sstevel@tonic-gate  * frees previously-allocated array from get_net_if_names
181*7c478bd9Sstevel@tonic-gate  */
182*7c478bd9Sstevel@tonic-gate void
183*7c478bd9Sstevel@tonic-gate free_net_if_names(char **ifnames)
184*7c478bd9Sstevel@tonic-gate {
185*7c478bd9Sstevel@tonic-gate 	int	i;
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 	i = 0;
188*7c478bd9Sstevel@tonic-gate 	while (ifnames[i] != NULL) {
189*7c478bd9Sstevel@tonic-gate 		free(ifnames[i]);
190*7c478bd9Sstevel@tonic-gate 		i++;
191*7c478bd9Sstevel@tonic-gate 	}
192*7c478bd9Sstevel@tonic-gate 	free(ifnames);
193*7c478bd9Sstevel@tonic-gate }
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate /*
197*7c478bd9Sstevel@tonic-gate  * attempt to remove ppa from end of file name
198*7c478bd9Sstevel@tonic-gate  * return -1 if none found
199*7c478bd9Sstevel@tonic-gate  * return ppa if found and remove the ppa from the filename
200*7c478bd9Sstevel@tonic-gate  */
201*7c478bd9Sstevel@tonic-gate static int
202*7c478bd9Sstevel@tonic-gate ifrm_num(char *fname, unsigned int *ppa)
203*7c478bd9Sstevel@tonic-gate {
204*7c478bd9Sstevel@tonic-gate 	int	i;
205*7c478bd9Sstevel@tonic-gate 	uint_t	p = 0;
206*7c478bd9Sstevel@tonic-gate 	unsigned int	m = 1;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	i = strlen(fname) - 1;
209*7c478bd9Sstevel@tonic-gate 	while (i >= 0 && '0' <= fname[i] && fname[i] <= '9') {
210*7c478bd9Sstevel@tonic-gate 		p += (fname[i] - '0')*m;
211*7c478bd9Sstevel@tonic-gate 		m *= 10;
212*7c478bd9Sstevel@tonic-gate 		i--;
213*7c478bd9Sstevel@tonic-gate 	}
214*7c478bd9Sstevel@tonic-gate 	if (m == 1) {
215*7c478bd9Sstevel@tonic-gate 		return (-1);
216*7c478bd9Sstevel@tonic-gate 	}
217*7c478bd9Sstevel@tonic-gate 	fname[i + 1] = '\0';
218*7c478bd9Sstevel@tonic-gate 	*ppa = p;
219*7c478bd9Sstevel@tonic-gate 	return (0);
220*7c478bd9Sstevel@tonic-gate }
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate /*
223*7c478bd9Sstevel@tonic-gate  * Open the device defined in dev_att with the given mode starting with
224*7c478bd9Sstevel@tonic-gate  * the module indicated by mod_cnt (1 indexed).  If mod_cnt > 0, fd must
225*7c478bd9Sstevel@tonic-gate  * contain the file descriptor that modules are to be pushed on.
226*7c478bd9Sstevel@tonic-gate  * Returns -1 if device could not be opened, the index of
227*7c478bd9Sstevel@tonic-gate  * the module that could not be pushed or 0 on success.
228*7c478bd9Sstevel@tonic-gate  */
229*7c478bd9Sstevel@tonic-gate static int
230*7c478bd9Sstevel@tonic-gate open_dev(dev_att_t *dev_att, int mode, int *fd, int mod_cnt)
231*7c478bd9Sstevel@tonic-gate {
232*7c478bd9Sstevel@tonic-gate 	int	cnt;
233*7c478bd9Sstevel@tonic-gate 	int	local_fd;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	if (debug)
236*7c478bd9Sstevel@tonic-gate 		(void) printf("open_dev: ifname: %s : dev %s fd %d "
237*7c478bd9Sstevel@tonic-gate 		    " mod_cnt %d\n",
238*7c478bd9Sstevel@tonic-gate 		    dev_att->ifname, dev_att->devname, *fd, mod_cnt);
239*7c478bd9Sstevel@tonic-gate 	/*
240*7c478bd9Sstevel@tonic-gate 	 * if no module count is given, try and open the device
241*7c478bd9Sstevel@tonic-gate 	 */
242*7c478bd9Sstevel@tonic-gate 	if (mod_cnt == 0) {
243*7c478bd9Sstevel@tonic-gate 		if (debug)
244*7c478bd9Sstevel@tonic-gate 			(void) printf("open_dev: opening %s\n",
245*7c478bd9Sstevel@tonic-gate 			    dev_att->devname);
246*7c478bd9Sstevel@tonic-gate 		if ((local_fd = open(dev_att->devname, mode)) < 0) {
247*7c478bd9Sstevel@tonic-gate 			if (debug) {
248*7c478bd9Sstevel@tonic-gate 				perror("open_dev: device");
249*7c478bd9Sstevel@tonic-gate 				(void) printf("\n");
250*7c478bd9Sstevel@tonic-gate 			}
251*7c478bd9Sstevel@tonic-gate 			*fd = local_fd;
252*7c478bd9Sstevel@tonic-gate 			return (-1);
253*7c478bd9Sstevel@tonic-gate 		}
254*7c478bd9Sstevel@tonic-gate 		*fd = local_fd;
255*7c478bd9Sstevel@tonic-gate 		cnt = 1;
256*7c478bd9Sstevel@tonic-gate 	} else {
257*7c478bd9Sstevel@tonic-gate 		local_fd = *fd;
258*7c478bd9Sstevel@tonic-gate 		cnt = mod_cnt;
259*7c478bd9Sstevel@tonic-gate 	}
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate 	/*
262*7c478bd9Sstevel@tonic-gate 	 * Try and push modules (if any) onto the device stream
263*7c478bd9Sstevel@tonic-gate 	 */
264*7c478bd9Sstevel@tonic-gate 	for (; cnt <= dev_att->mod_cnt; cnt++) {
265*7c478bd9Sstevel@tonic-gate 		if (debug)
266*7c478bd9Sstevel@tonic-gate 			(void) printf(" pushing: mod %s",
267*7c478bd9Sstevel@tonic-gate 			    dev_att->modlist[cnt - 1]);
268*7c478bd9Sstevel@tonic-gate 		if (ioctl(local_fd, I_PUSH, dev_att->modlist[cnt - 1]) == -1) {
269*7c478bd9Sstevel@tonic-gate 			if (debug) {
270*7c478bd9Sstevel@tonic-gate 				perror("open_dev: push");
271*7c478bd9Sstevel@tonic-gate 				(void) printf("\n");
272*7c478bd9Sstevel@tonic-gate 			}
273*7c478bd9Sstevel@tonic-gate 			return (cnt);
274*7c478bd9Sstevel@tonic-gate 		}
275*7c478bd9Sstevel@tonic-gate 	}
276*7c478bd9Sstevel@tonic-gate 	if (debug)
277*7c478bd9Sstevel@tonic-gate 		(void) printf("\n");
278*7c478bd9Sstevel@tonic-gate 	return (0);
279*7c478bd9Sstevel@tonic-gate }
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate /*
282*7c478bd9Sstevel@tonic-gate  * Debug routine to print out dev_att_t structure
283*7c478bd9Sstevel@tonic-gate  */
284*7c478bd9Sstevel@tonic-gate static void
285*7c478bd9Sstevel@tonic-gate pf_dev_att(dev_att_t *dev_att)
286*7c478bd9Sstevel@tonic-gate {
287*7c478bd9Sstevel@tonic-gate 	int cnt;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	(void) printf("\tifname: %s\n", dev_att->ifname);
290*7c478bd9Sstevel@tonic-gate 	(void) printf("\t  style: %d\n", dev_att->style);
291*7c478bd9Sstevel@tonic-gate 	(void) printf("\t  ppa: %d\n", dev_att->ppa);
292*7c478bd9Sstevel@tonic-gate 	(void) printf("\t  mod_cnt: %d\n", dev_att->mod_cnt);
293*7c478bd9Sstevel@tonic-gate 	(void) printf("\t  devname: %s\n", dev_att->devname);
294*7c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < dev_att->mod_cnt; cnt++) {
295*7c478bd9Sstevel@tonic-gate 		(void) printf("\t      module: %s\n", dev_att->modlist[cnt]);
296*7c478bd9Sstevel@tonic-gate 	}
297*7c478bd9Sstevel@tonic-gate }
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate /*
300*7c478bd9Sstevel@tonic-gate  * This function parses a '.' delimited interface name of the form
301*7c478bd9Sstevel@tonic-gate  * dev[.module[.module...]][:lun]
302*7c478bd9Sstevel@tonic-gate  * and places the device and module name into dev_att
303*7c478bd9Sstevel@tonic-gate  */
304*7c478bd9Sstevel@tonic-gate static void
305*7c478bd9Sstevel@tonic-gate parse_ifname(dev_att_t *dev_att)
306*7c478bd9Sstevel@tonic-gate {
307*7c478bd9Sstevel@tonic-gate 	char		*lunstr;
308*7c478bd9Sstevel@tonic-gate 	char		*modlist = NULL; /* list of modules to push */
309*7c478bd9Sstevel@tonic-gate 	int		cnt = 0; /* number of modules to push */
310*7c478bd9Sstevel@tonic-gate 	char		modbuf[LIFNAMSIZ];
311*7c478bd9Sstevel@tonic-gate 	char		*nxtmod;
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	/*
314*7c478bd9Sstevel@tonic-gate 	 * check for specified lun at end of interface and
315*7c478bd9Sstevel@tonic-gate 	 * strip it off.
316*7c478bd9Sstevel@tonic-gate 	 */
317*7c478bd9Sstevel@tonic-gate 	lunstr = strchr(dev_att->ifname, ':');
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	if (lunstr) {
320*7c478bd9Sstevel@tonic-gate 		char *endptr;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 		*lunstr = '\0';
323*7c478bd9Sstevel@tonic-gate 		lunstr++;
324*7c478bd9Sstevel@tonic-gate 		endptr = lunstr;
325*7c478bd9Sstevel@tonic-gate 		dev_att->lun = strtoul(lunstr, &endptr, 10);
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate 		if (endptr == lunstr || *endptr != '\0') {
328*7c478bd9Sstevel@tonic-gate 			(void) printf("Invalid logical unit number:%s", lunstr);
329*7c478bd9Sstevel@tonic-gate 			exit(-1);
330*7c478bd9Sstevel@tonic-gate 		}
331*7c478bd9Sstevel@tonic-gate 	} else {
332*7c478bd9Sstevel@tonic-gate 		dev_att->lun = 0;
333*7c478bd9Sstevel@tonic-gate 	}
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(modbuf, dev_att->ifname, LIFNAMSIZ);
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	/* parse '.' delmited module list */
338*7c478bd9Sstevel@tonic-gate 	modlist = strchr(modbuf, '.');
339*7c478bd9Sstevel@tonic-gate 	if (modlist) {
340*7c478bd9Sstevel@tonic-gate 		/* null-terminate interface name (device) */
341*7c478bd9Sstevel@tonic-gate 		*modlist = '\0';
342*7c478bd9Sstevel@tonic-gate 		modlist++;
343*7c478bd9Sstevel@tonic-gate 		if (strlen(modlist) == 0)
344*7c478bd9Sstevel@tonic-gate 			modlist = NULL;
345*7c478bd9Sstevel@tonic-gate 		while (modlist && cnt < MAX_MODS) {
346*7c478bd9Sstevel@tonic-gate 			nxtmod = strchr(modlist, '.');
347*7c478bd9Sstevel@tonic-gate 			if (nxtmod) {
348*7c478bd9Sstevel@tonic-gate 				*nxtmod = '\0';
349*7c478bd9Sstevel@tonic-gate 				nxtmod++;
350*7c478bd9Sstevel@tonic-gate 			}
351*7c478bd9Sstevel@tonic-gate 			(void) strncpy(dev_att->modlist[cnt], modlist,
352*7c478bd9Sstevel@tonic-gate 			    LIFNAMSIZ);
353*7c478bd9Sstevel@tonic-gate 			cnt++;
354*7c478bd9Sstevel@tonic-gate 			modlist = nxtmod;
355*7c478bd9Sstevel@tonic-gate 		}
356*7c478bd9Sstevel@tonic-gate 	}
357*7c478bd9Sstevel@tonic-gate 	(void) snprintf(dev_att->devname, LIFNAMSIZ, "%s/%s", DEVDIR, modbuf);
358*7c478bd9Sstevel@tonic-gate 	dev_att->mod_cnt = cnt;
359*7c478bd9Sstevel@tonic-gate }
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate /*
362*7c478bd9Sstevel@tonic-gate  * given a interface name (with possible modules to push)
363*7c478bd9Sstevel@tonic-gate  * interface name must have the format of
364*7c478bd9Sstevel@tonic-gate  * dev[ppa][.module[.module...][ppa]][:lun]
365*7c478bd9Sstevel@tonic-gate  * where only one ppa may be specified e.g. ip0.foo.tun or ip.foo.tun0
366*7c478bd9Sstevel@tonic-gate  */
367*7c478bd9Sstevel@tonic-gate static int
368*7c478bd9Sstevel@tonic-gate ifname_open(char *dev_name, dev_att_t *dev_att)
369*7c478bd9Sstevel@tonic-gate {
370*7c478bd9Sstevel@tonic-gate 	int		fd;
371*7c478bd9Sstevel@tonic-gate 	uint_t		ppa;
372*7c478bd9Sstevel@tonic-gate 	int		res;
373*7c478bd9Sstevel@tonic-gate 	int		style;
374*7c478bd9Sstevel@tonic-gate 	dl_info_ack_t	dl_info;
375*7c478bd9Sstevel@tonic-gate 	int		mod_id;
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	if (debug)
378*7c478bd9Sstevel@tonic-gate 		(void) printf("ifname_open: %s\n", dev_name);
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	if (strlen(dev_name) > LIFNAMSIZ - 1) {
381*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
382*7c478bd9Sstevel@tonic-gate 		return (-1);
383*7c478bd9Sstevel@tonic-gate 	}
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate 	/* save copy of original device name */
386*7c478bd9Sstevel@tonic-gate 	(void) strncpy(dev_att->ifname, dev_name, LIFNAMSIZ);
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate 	/* parse modules */
389*7c478bd9Sstevel@tonic-gate 	parse_ifname(dev_att);
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	/* try DLPI style 1 device first */
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	if (debug) {
394*7c478bd9Sstevel@tonic-gate 		pf_dev_att(dev_att);
395*7c478bd9Sstevel@tonic-gate 	}
396*7c478bd9Sstevel@tonic-gate 	mod_id = open_dev(dev_att, O_RDWR, &fd, 0);
397*7c478bd9Sstevel@tonic-gate 	if (mod_id != 0) {
398*7c478bd9Sstevel@tonic-gate 		if (debug) {
399*7c478bd9Sstevel@tonic-gate 			(void) printf("Error on open_dev style 1 mod_id: %d"
400*7c478bd9Sstevel@tonic-gate 			    " attemping style 2\n", mod_id);
401*7c478bd9Sstevel@tonic-gate 			pf_dev_att(dev_att);
402*7c478bd9Sstevel@tonic-gate 		}
403*7c478bd9Sstevel@tonic-gate 		if (mod_id == -1) {
404*7c478bd9Sstevel@tonic-gate 			res = ifrm_num(dev_att->devname, &ppa);
405*7c478bd9Sstevel@tonic-gate 			mod_id = 0;
406*7c478bd9Sstevel@tonic-gate 			if (res < 0) {
407*7c478bd9Sstevel@tonic-gate 				if (debug)
408*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
409*7c478bd9Sstevel@tonic-gate 					    "%s: No such file or directory\n",
410*7c478bd9Sstevel@tonic-gate 					    dev_att->devname);
411*7c478bd9Sstevel@tonic-gate 				(void) close(fd);
412*7c478bd9Sstevel@tonic-gate 				return (-1);
413*7c478bd9Sstevel@tonic-gate 			}
414*7c478bd9Sstevel@tonic-gate 			/*
415*7c478bd9Sstevel@tonic-gate 			 * ensure that it's the last module
416*7c478bd9Sstevel@tonic-gate 			 * in the list to extract
417*7c478bd9Sstevel@tonic-gate 			 * ppa
418*7c478bd9Sstevel@tonic-gate 			 */
419*7c478bd9Sstevel@tonic-gate 		} else if ((mod_id != dev_att->mod_cnt) ||
420*7c478bd9Sstevel@tonic-gate 		    (res = ifrm_num(dev_att->modlist[dev_att->mod_cnt - 1],
421*7c478bd9Sstevel@tonic-gate 			&ppa)) < 0) {
422*7c478bd9Sstevel@tonic-gate 			if (debug) {
423*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
424*7c478bd9Sstevel@tonic-gate 				    "Error on open_dev style 2 mod_id: %d \n",
425*7c478bd9Sstevel@tonic-gate 				    mod_id);
426*7c478bd9Sstevel@tonic-gate 			}
427*7c478bd9Sstevel@tonic-gate 			if (mod_id == dev_att->mod_cnt)
428*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "libuuid: could not "
429*7c478bd9Sstevel@tonic-gate 				    "locate ppa in %s\n",
430*7c478bd9Sstevel@tonic-gate 				    dev_att->ifname);
431*7c478bd9Sstevel@tonic-gate 			(void) close(fd);
432*7c478bd9Sstevel@tonic-gate 			return (-1);
433*7c478bd9Sstevel@tonic-gate 		}
434*7c478bd9Sstevel@tonic-gate 		goto style2;
435*7c478bd9Sstevel@tonic-gate 	}
436*7c478bd9Sstevel@tonic-gate 	dev_att->style = 1;
437*7c478bd9Sstevel@tonic-gate 	dev_att->ppa = 0;
438*7c478bd9Sstevel@tonic-gate 	style = DL_STYLE1;
439*7c478bd9Sstevel@tonic-gate 	goto dl_info_chk;
440*7c478bd9Sstevel@tonic-gate style2:
441*7c478bd9Sstevel@tonic-gate 	dev_att->ppa = ppa;
442*7c478bd9Sstevel@tonic-gate 	mod_id = open_dev(dev_att, O_RDWR, &fd, mod_id);
443*7c478bd9Sstevel@tonic-gate 	if (mod_id != 0) {
444*7c478bd9Sstevel@tonic-gate 		if (debug) {
445*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
446*7c478bd9Sstevel@tonic-gate 			    "Error on open_dev style 2 mod_id: %d \n",
447*7c478bd9Sstevel@tonic-gate 			    mod_id);
448*7c478bd9Sstevel@tonic-gate 			if (mod_id > 0) {
449*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "%s: No such module\n",
450*7c478bd9Sstevel@tonic-gate 				    dev_att->modlist[mod_id - 2]);
451*7c478bd9Sstevel@tonic-gate 			}
452*7c478bd9Sstevel@tonic-gate 			pf_dev_att(dev_att);
453*7c478bd9Sstevel@tonic-gate 		}
454*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
455*7c478bd9Sstevel@tonic-gate 		return (-1);
456*7c478bd9Sstevel@tonic-gate 	}
457*7c478bd9Sstevel@tonic-gate 	dev_att->style = 2;
458*7c478bd9Sstevel@tonic-gate 	style = DL_STYLE2;
459*7c478bd9Sstevel@tonic-gate dl_info_chk:
460*7c478bd9Sstevel@tonic-gate 	if (dlpi_info_req(fd, &dl_info) < 0) {
461*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
462*7c478bd9Sstevel@tonic-gate 		pf_dev_att(dev_att);
463*7c478bd9Sstevel@tonic-gate 		return (-1);
464*7c478bd9Sstevel@tonic-gate 	}
465*7c478bd9Sstevel@tonic-gate 	if (dl_info.dl_provider_style != style) {
466*7c478bd9Sstevel@tonic-gate 		if (debug) {
467*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "DLPI provider style mismatch: "
468*7c478bd9Sstevel@tonic-gate 			    "expected style %s got style %s (0x%lx)\n",
469*7c478bd9Sstevel@tonic-gate 			    style == DL_STYLE1 ? "1" : "2",
470*7c478bd9Sstevel@tonic-gate 			    dl_info.dl_provider_style == DL_STYLE1 ? "1" : "2",
471*7c478bd9Sstevel@tonic-gate 			    dl_info.dl_provider_style);
472*7c478bd9Sstevel@tonic-gate 		}
473*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
474*7c478bd9Sstevel@tonic-gate 		return (-1);
475*7c478bd9Sstevel@tonic-gate 	}
476*7c478bd9Sstevel@tonic-gate 	if (debug) {
477*7c478bd9Sstevel@tonic-gate 		(void) printf("pars_dev_att() success\n");
478*7c478bd9Sstevel@tonic-gate 		pf_dev_att(dev_att);
479*7c478bd9Sstevel@tonic-gate 	}
480*7c478bd9Sstevel@tonic-gate 	return (fd);
481*7c478bd9Sstevel@tonic-gate }
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate static int
484*7c478bd9Sstevel@tonic-gate dlpi_open_attach(char *ifname)
485*7c478bd9Sstevel@tonic-gate {
486*7c478bd9Sstevel@tonic-gate 	int			fd;
487*7c478bd9Sstevel@tonic-gate 	dev_att_t		dev_att;
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	if (debug)
490*7c478bd9Sstevel@tonic-gate 		(void) printf("dlpi_open_attach %s\n", ifname);
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	/* if lun is specified fail (backwards compat) */
493*7c478bd9Sstevel@tonic-gate 	if (strchr(ifname, ':') != NULL) {
494*7c478bd9Sstevel@tonic-gate 		return (-1);
495*7c478bd9Sstevel@tonic-gate 	}
496*7c478bd9Sstevel@tonic-gate 	if ((fd = ifname_open(ifname, &dev_att)) < 0) {
497*7c478bd9Sstevel@tonic-gate 		/* Not found */
498*7c478bd9Sstevel@tonic-gate 		errno = ENXIO;
499*7c478bd9Sstevel@tonic-gate 		return (-1);
500*7c478bd9Sstevel@tonic-gate 	}
501*7c478bd9Sstevel@tonic-gate 	if (dlpi_attach(fd, dev_att.ppa, dev_att.style) < 0) {
502*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
503*7c478bd9Sstevel@tonic-gate 		return (-1);
504*7c478bd9Sstevel@tonic-gate 	}
505*7c478bd9Sstevel@tonic-gate 	return (fd);
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate static int
509*7c478bd9Sstevel@tonic-gate dlpi_attach(int fd, int ppa, int style)
510*7c478bd9Sstevel@tonic-gate {
511*7c478bd9Sstevel@tonic-gate 	union DL_primitives	*dlp;
512*7c478bd9Sstevel@tonic-gate 	char			*buf;
513*7c478bd9Sstevel@tonic-gate 	struct strbuf		ctl;
514*7c478bd9Sstevel@tonic-gate 	int			flags;
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	if (style != 2)
517*7c478bd9Sstevel@tonic-gate 		return (0);
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	/* Allocate required buffers */
520*7c478bd9Sstevel@tonic-gate 	if ((buf = malloc(BUFSIZ)) == NULL) {
521*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "libuuid: malloc() failed\n");
522*7c478bd9Sstevel@tonic-gate 		return (-1);
523*7c478bd9Sstevel@tonic-gate 	}
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	/* Issue DL_ATTACH_REQ */
526*7c478bd9Sstevel@tonic-gate 	/* LINTED: malloc returns a pointer aligned for any use */
527*7c478bd9Sstevel@tonic-gate 	dlp = (union DL_primitives *)buf;
528*7c478bd9Sstevel@tonic-gate 	dlp->attach_req.dl_primitive = DL_ATTACH_REQ;
529*7c478bd9Sstevel@tonic-gate 	dlp->attach_req.dl_ppa = ppa;
530*7c478bd9Sstevel@tonic-gate 	ctl.buf = (char *)dlp;
531*7c478bd9Sstevel@tonic-gate 	ctl.len = DL_ATTACH_REQ_SIZE;
532*7c478bd9Sstevel@tonic-gate 	if (putmsg(fd, &ctl, NULL, 0) < 0) {
533*7c478bd9Sstevel@tonic-gate 		perror("libuuid: putmsg");
534*7c478bd9Sstevel@tonic-gate 		free(buf);
535*7c478bd9Sstevel@tonic-gate 		return (-1);
536*7c478bd9Sstevel@tonic-gate 	}
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 	/* read reply */
539*7c478bd9Sstevel@tonic-gate 	ctl.buf = (char *)dlp;
540*7c478bd9Sstevel@tonic-gate 	ctl.len = 0;
541*7c478bd9Sstevel@tonic-gate 	ctl.maxlen = BUFSIZ;
542*7c478bd9Sstevel@tonic-gate 	flags = 0;
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	/* start timeout for DL_OK_ACK reply */
545*7c478bd9Sstevel@tonic-gate 	if (timed_getmsg(fd, &ctl, &flags, dlpi_timeout,
546*7c478bd9Sstevel@tonic-gate 	    "DL_OK_ACK", "DL_ATTACH_REQ") == 0) {
547*7c478bd9Sstevel@tonic-gate 		free(buf);
548*7c478bd9Sstevel@tonic-gate 		return (-1);
549*7c478bd9Sstevel@tonic-gate 	}
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 	if (debug) {
552*7c478bd9Sstevel@tonic-gate 		(void) printf("ok_ack: ctl.len[%d] flags[%d]\n", ctl.len,
553*7c478bd9Sstevel@tonic-gate 		    flags);
554*7c478bd9Sstevel@tonic-gate 	}
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 	/* Validate DL_OK_ACK reply.  */
557*7c478bd9Sstevel@tonic-gate 	if (ctl.len < sizeof (t_uscalar_t)) {
558*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
559*7c478bd9Sstevel@tonic-gate 		    "libuuid: attach failed: short reply to attach request\n");
560*7c478bd9Sstevel@tonic-gate 		free(buf);
561*7c478bd9Sstevel@tonic-gate 		return (-1);
562*7c478bd9Sstevel@tonic-gate 	}
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate 	if (dlp->dl_primitive == DL_ERROR_ACK) {
565*7c478bd9Sstevel@tonic-gate 		if (debug)
566*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
567*7c478bd9Sstevel@tonic-gate 			    "attach failed:  dl_errno %lu errno %lu\n",
568*7c478bd9Sstevel@tonic-gate 			    dlp->error_ack.dl_errno,
569*7c478bd9Sstevel@tonic-gate 			    dlp->error_ack.dl_unix_errno);
570*7c478bd9Sstevel@tonic-gate 		free(buf);
571*7c478bd9Sstevel@tonic-gate 		errno = ENXIO;
572*7c478bd9Sstevel@tonic-gate 		return (-1);
573*7c478bd9Sstevel@tonic-gate 	}
574*7c478bd9Sstevel@tonic-gate 	if (dlp->dl_primitive != DL_OK_ACK) {
575*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
576*7c478bd9Sstevel@tonic-gate 		    "libuuid: attach failed: "
577*7c478bd9Sstevel@tonic-gate 		    "unrecognizable dl_primitive %lu received",
578*7c478bd9Sstevel@tonic-gate 		    dlp->dl_primitive);
579*7c478bd9Sstevel@tonic-gate 		free(buf);
580*7c478bd9Sstevel@tonic-gate 		return (-1);
581*7c478bd9Sstevel@tonic-gate 	}
582*7c478bd9Sstevel@tonic-gate 	if (ctl.len < DL_OK_ACK_SIZE) {
583*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
584*7c478bd9Sstevel@tonic-gate 		    "libuuid: attach failed: "
585*7c478bd9Sstevel@tonic-gate 		    "short attach acknowledgement received\n");
586*7c478bd9Sstevel@tonic-gate 		free(buf);
587*7c478bd9Sstevel@tonic-gate 		return (-1);
588*7c478bd9Sstevel@tonic-gate 	}
589*7c478bd9Sstevel@tonic-gate 	if (dlp->ok_ack.dl_correct_primitive != DL_ATTACH_REQ) {
590*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
591*7c478bd9Sstevel@tonic-gate 		    "libuuid: attach failed: "
592*7c478bd9Sstevel@tonic-gate 		    "returned prim %lu != requested prim %lu\n",
593*7c478bd9Sstevel@tonic-gate 		    dlp->ok_ack.dl_correct_primitive,
594*7c478bd9Sstevel@tonic-gate 		    (t_uscalar_t)DL_ATTACH_REQ);
595*7c478bd9Sstevel@tonic-gate 		free(buf);
596*7c478bd9Sstevel@tonic-gate 		return (-1);
597*7c478bd9Sstevel@tonic-gate 	}
598*7c478bd9Sstevel@tonic-gate 	if (debug)
599*7c478bd9Sstevel@tonic-gate 		(void) printf("attach done\n");
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 	free(buf);
602*7c478bd9Sstevel@tonic-gate 	return (0);
603*7c478bd9Sstevel@tonic-gate }
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate static int
606*7c478bd9Sstevel@tonic-gate dlpi_get_phys(int fd, uchar_t *eaddr)
607*7c478bd9Sstevel@tonic-gate {
608*7c478bd9Sstevel@tonic-gate 	union DL_primitives	*dlp;
609*7c478bd9Sstevel@tonic-gate 	char			*buf;
610*7c478bd9Sstevel@tonic-gate 	struct strbuf		ctl;
611*7c478bd9Sstevel@tonic-gate 	int			flags;
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate 	/* Allocate required buffers */
614*7c478bd9Sstevel@tonic-gate 	if ((buf = malloc(BUFSIZ)) == NULL) {
615*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "libuuid: malloc() failed\n");
616*7c478bd9Sstevel@tonic-gate 		return (-1);
617*7c478bd9Sstevel@tonic-gate 	}
618*7c478bd9Sstevel@tonic-gate 	/* Issue DL_PHYS_ADDR_REQ */
619*7c478bd9Sstevel@tonic-gate 	/* LINTED: malloc returns a pointer aligned for any use */
620*7c478bd9Sstevel@tonic-gate 	dlp = (union DL_primitives *)buf;
621*7c478bd9Sstevel@tonic-gate 	dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
622*7c478bd9Sstevel@tonic-gate 	dlp->physaddr_req.dl_addr_type = DL_CURR_PHYS_ADDR;
623*7c478bd9Sstevel@tonic-gate 	ctl.buf = (char *)dlp;
624*7c478bd9Sstevel@tonic-gate 	ctl.len = DL_PHYS_ADDR_REQ_SIZE;
625*7c478bd9Sstevel@tonic-gate 	if (putmsg(fd, &ctl, NULL, 0) < 0) {
626*7c478bd9Sstevel@tonic-gate 		perror("libuuid: putmsg");
627*7c478bd9Sstevel@tonic-gate 		free(buf);
628*7c478bd9Sstevel@tonic-gate 		return (-1);
629*7c478bd9Sstevel@tonic-gate 	}
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 	/* read reply */
632*7c478bd9Sstevel@tonic-gate 	ctl.buf = (char *)dlp;
633*7c478bd9Sstevel@tonic-gate 	ctl.len = 0;
634*7c478bd9Sstevel@tonic-gate 	ctl.maxlen = BUFSIZ;
635*7c478bd9Sstevel@tonic-gate 	flags = 0;
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate 	if (timed_getmsg(fd, &ctl, &flags, dlpi_timeout,
638*7c478bd9Sstevel@tonic-gate 	    "DL_PHYS_ADDR_ACK", "DL_PHYS_ADDR_REQ (DL_CURR_PHYS_ADDR)") == 0) {
639*7c478bd9Sstevel@tonic-gate 		free(buf);
640*7c478bd9Sstevel@tonic-gate 		return (-1);
641*7c478bd9Sstevel@tonic-gate 	}
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 	if (debug) {
644*7c478bd9Sstevel@tonic-gate 		(void) printf("phys_addr_ack: ctl.len[%d] flags[%d]\n", ctl.len,
645*7c478bd9Sstevel@tonic-gate 		    flags);
646*7c478bd9Sstevel@tonic-gate 	}
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 	/* Validate DL_PHYS_ADDR_ACK reply.  */
649*7c478bd9Sstevel@tonic-gate 	if (ctl.len < sizeof (t_uscalar_t)) {
650*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "libuuid: phys_addr failed: "
651*7c478bd9Sstevel@tonic-gate 		    "short reply to phys_addr request\n");
652*7c478bd9Sstevel@tonic-gate 		free(buf);
653*7c478bd9Sstevel@tonic-gate 		return (-1);
654*7c478bd9Sstevel@tonic-gate 	}
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 	if (dlp->dl_primitive == DL_ERROR_ACK) {
657*7c478bd9Sstevel@tonic-gate 		/*
658*7c478bd9Sstevel@tonic-gate 		 * Do not print errors for DL_UNSUPPORTED and DL_NOTSUPPORTED
659*7c478bd9Sstevel@tonic-gate 		 */
660*7c478bd9Sstevel@tonic-gate 		if (dlp->error_ack.dl_errno != DL_UNSUPPORTED &&
661*7c478bd9Sstevel@tonic-gate 		    dlp->error_ack.dl_errno != DL_NOTSUPPORTED) {
662*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "libuuid: phys_addr failed: "
663*7c478bd9Sstevel@tonic-gate 			    "dl_errno %lu errno %lu\n",
664*7c478bd9Sstevel@tonic-gate 			    dlp->error_ack.dl_errno,
665*7c478bd9Sstevel@tonic-gate 			    dlp->error_ack.dl_unix_errno);
666*7c478bd9Sstevel@tonic-gate 		}
667*7c478bd9Sstevel@tonic-gate 		free(buf);
668*7c478bd9Sstevel@tonic-gate 		return (-1);
669*7c478bd9Sstevel@tonic-gate 	}
670*7c478bd9Sstevel@tonic-gate 	if (dlp->dl_primitive != DL_PHYS_ADDR_ACK) {
671*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "libuuid: phys_addr failed: "
672*7c478bd9Sstevel@tonic-gate 		    "unrecognizable dl_primitive %lu received\n",
673*7c478bd9Sstevel@tonic-gate 		    dlp->dl_primitive);
674*7c478bd9Sstevel@tonic-gate 		free(buf);
675*7c478bd9Sstevel@tonic-gate 		return (-1);
676*7c478bd9Sstevel@tonic-gate 	}
677*7c478bd9Sstevel@tonic-gate 	if (ctl.len < DL_PHYS_ADDR_ACK_SIZE) {
678*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "libuuid: phys_addr failed: "
679*7c478bd9Sstevel@tonic-gate 		    "short phys_addr acknowledgement received\n");
680*7c478bd9Sstevel@tonic-gate 		free(buf);
681*7c478bd9Sstevel@tonic-gate 		return (-1);
682*7c478bd9Sstevel@tonic-gate 	}
683*7c478bd9Sstevel@tonic-gate 	/* Check length of address. */
684*7c478bd9Sstevel@tonic-gate 	if (dlp->physaddr_ack.dl_addr_length != ETHERADDRL) {
685*7c478bd9Sstevel@tonic-gate 		free(buf);
686*7c478bd9Sstevel@tonic-gate 		return (-1);
687*7c478bd9Sstevel@tonic-gate 	}
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 	/* copy Ethernet address */
690*7c478bd9Sstevel@tonic-gate 	(void) memcpy(eaddr, &buf[dlp->physaddr_ack.dl_addr_offset],
691*7c478bd9Sstevel@tonic-gate 	    ETHERADDRL);
692*7c478bd9Sstevel@tonic-gate 
693*7c478bd9Sstevel@tonic-gate 	free(buf);
694*7c478bd9Sstevel@tonic-gate 	return (0);
695*7c478bd9Sstevel@tonic-gate }
696*7c478bd9Sstevel@tonic-gate 
697*7c478bd9Sstevel@tonic-gate 
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate static int
700*7c478bd9Sstevel@tonic-gate dlpi_info_req(int fd, dl_info_ack_t *info_ack)
701*7c478bd9Sstevel@tonic-gate {
702*7c478bd9Sstevel@tonic-gate 	dl_info_req_t   info_req;
703*7c478bd9Sstevel@tonic-gate 	int	buf[BUFSIZ/sizeof (int)];
704*7c478bd9Sstevel@tonic-gate 	union DL_primitives	*dlp = (union DL_primitives *)buf;
705*7c478bd9Sstevel@tonic-gate 	struct  strbuf  ctl;
706*7c478bd9Sstevel@tonic-gate 	int	flags;
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate 	info_req.dl_primitive = DL_INFO_REQ;
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate 	ctl.len = DL_INFO_REQ_SIZE;
711*7c478bd9Sstevel@tonic-gate 	ctl.buf = (char *)&info_req;
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	flags = RS_HIPRI;
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 	if (putmsg(fd, &ctl, (struct strbuf *)NULL, flags) < 0) {
716*7c478bd9Sstevel@tonic-gate 		perror("libuuid: putmsg");
717*7c478bd9Sstevel@tonic-gate 		return (-1);
718*7c478bd9Sstevel@tonic-gate 	}
719*7c478bd9Sstevel@tonic-gate 
720*7c478bd9Sstevel@tonic-gate 	/* read reply */
721*7c478bd9Sstevel@tonic-gate 	ctl.buf = (char *)dlp;
722*7c478bd9Sstevel@tonic-gate 	ctl.len = 0;
723*7c478bd9Sstevel@tonic-gate 	ctl.maxlen = BUFSIZ;
724*7c478bd9Sstevel@tonic-gate 	flags = 0;
725*7c478bd9Sstevel@tonic-gate 	/* start timeout for DL_BIND_ACK reply */
726*7c478bd9Sstevel@tonic-gate 	if (timed_getmsg(fd, &ctl, &flags, dlpi_timeout, "DL_INFO_ACK",
727*7c478bd9Sstevel@tonic-gate 	    "DL_INFO_ACK") == 0) {
728*7c478bd9Sstevel@tonic-gate 		return (-1);
729*7c478bd9Sstevel@tonic-gate 	}
730*7c478bd9Sstevel@tonic-gate 
731*7c478bd9Sstevel@tonic-gate 	if (debug) {
732*7c478bd9Sstevel@tonic-gate 		(void) printf("info_ack: ctl.len[%d] flags[%d]\n", ctl.len,
733*7c478bd9Sstevel@tonic-gate 		    flags);
734*7c478bd9Sstevel@tonic-gate 	}
735*7c478bd9Sstevel@tonic-gate 
736*7c478bd9Sstevel@tonic-gate 	/* Validate DL_BIND_ACK reply.  */
737*7c478bd9Sstevel@tonic-gate 	if (ctl.len < sizeof (t_uscalar_t)) {
738*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
739*7c478bd9Sstevel@tonic-gate 		    "libuuid: info req failed: short reply to info request\n");
740*7c478bd9Sstevel@tonic-gate 		return (-1);
741*7c478bd9Sstevel@tonic-gate 	}
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 	if (dlp->dl_primitive == DL_ERROR_ACK) {
744*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
745*7c478bd9Sstevel@tonic-gate 		    "libuuid: info req failed:  dl_errno %lu errno %lu\n",
746*7c478bd9Sstevel@tonic-gate 		    dlp->error_ack.dl_errno, dlp->error_ack.dl_unix_errno);
747*7c478bd9Sstevel@tonic-gate 		return (-1);
748*7c478bd9Sstevel@tonic-gate 	}
749*7c478bd9Sstevel@tonic-gate 	if (dlp->dl_primitive != DL_INFO_ACK) {
750*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
751*7c478bd9Sstevel@tonic-gate 		    "libuuid: info req failed: "
752*7c478bd9Sstevel@tonic-gate 		    "unrecognizable dl_primitive %lu received\n",
753*7c478bd9Sstevel@tonic-gate 		    dlp->dl_primitive);
754*7c478bd9Sstevel@tonic-gate 		return (-1);
755*7c478bd9Sstevel@tonic-gate 	}
756*7c478bd9Sstevel@tonic-gate 	if (ctl.len < DL_INFO_ACK_SIZE) {
757*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
758*7c478bd9Sstevel@tonic-gate 		    "libuuid: info req failed: "
759*7c478bd9Sstevel@tonic-gate 		    "short info acknowledgement received\n");
760*7c478bd9Sstevel@tonic-gate 		return (-1);
761*7c478bd9Sstevel@tonic-gate 	}
762*7c478bd9Sstevel@tonic-gate 	*info_ack = *(dl_info_ack_t *)dlp;
763*7c478bd9Sstevel@tonic-gate 	return (0);
764*7c478bd9Sstevel@tonic-gate }
765*7c478bd9Sstevel@tonic-gate 
766*7c478bd9Sstevel@tonic-gate 
767*7c478bd9Sstevel@tonic-gate /*
768*7c478bd9Sstevel@tonic-gate  * interface called from libuuid to get the ethernet address - jhf
769*7c478bd9Sstevel@tonic-gate  */
770*7c478bd9Sstevel@tonic-gate int
771*7c478bd9Sstevel@tonic-gate dlpi_get_address(char *ifname, struct ether_addr *ea)
772*7c478bd9Sstevel@tonic-gate {
773*7c478bd9Sstevel@tonic-gate 	int 	fd;
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate 	if (debug)
776*7c478bd9Sstevel@tonic-gate 		(void) printf("dlpi_get_address: dlpi_open_attach\t");
777*7c478bd9Sstevel@tonic-gate 	fd = dlpi_open_attach(ifname);
778*7c478bd9Sstevel@tonic-gate 	if (fd < 0) {
779*7c478bd9Sstevel@tonic-gate 		/* Do not report an error */
780*7c478bd9Sstevel@tonic-gate 		return (-1);
781*7c478bd9Sstevel@tonic-gate 	}
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 	if (debug)
784*7c478bd9Sstevel@tonic-gate 		(void) printf("dlpi_get_address: dlpi_get_phys %s\n", ifname);
785*7c478bd9Sstevel@tonic-gate 	if (dlpi_get_phys(fd, (uchar_t *)ea) < 0) {
786*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
787*7c478bd9Sstevel@tonic-gate 		return (-1);
788*7c478bd9Sstevel@tonic-gate 	}
789*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
790*7c478bd9Sstevel@tonic-gate 	return (0);
791*7c478bd9Sstevel@tonic-gate }
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate static int
794*7c478bd9Sstevel@tonic-gate timed_getmsg(int fd, struct strbuf *ctlp, int *flagsp, int timeout, char *kind,
795*7c478bd9Sstevel@tonic-gate     char *request)
796*7c478bd9Sstevel@tonic-gate {
797*7c478bd9Sstevel@tonic-gate 	char		perrorbuf[BUFSIZ];
798*7c478bd9Sstevel@tonic-gate 	struct pollfd	pfd;
799*7c478bd9Sstevel@tonic-gate 	int		ret;
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate 	pfd.fd = fd;
802*7c478bd9Sstevel@tonic-gate 
803*7c478bd9Sstevel@tonic-gate 	pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
804*7c478bd9Sstevel@tonic-gate 	if ((ret = poll(&pfd, 1, timeout * 1000)) == 0) {
805*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "libuuid: %s timed out\n", kind);
806*7c478bd9Sstevel@tonic-gate 		return (0);
807*7c478bd9Sstevel@tonic-gate 	} else if (ret == -1) {
808*7c478bd9Sstevel@tonic-gate 		(void) snprintf(perrorbuf, sizeof (perrorbuf),
809*7c478bd9Sstevel@tonic-gate 		    "libuuid: poll for %s from %s", kind, request);
810*7c478bd9Sstevel@tonic-gate 		perror(perrorbuf);
811*7c478bd9Sstevel@tonic-gate 		return (0);
812*7c478bd9Sstevel@tonic-gate 	}
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 	/* poll returned > 0 for this fd so getmsg should not block */
815*7c478bd9Sstevel@tonic-gate 	if ((ret = getmsg(fd, ctlp, NULL, flagsp)) < 0) {
816*7c478bd9Sstevel@tonic-gate 		(void) snprintf(perrorbuf, sizeof (perrorbuf),
817*7c478bd9Sstevel@tonic-gate 		    "libuuid: getmsg expecting %s for %s", kind, request);
818*7c478bd9Sstevel@tonic-gate 		perror(perrorbuf);
819*7c478bd9Sstevel@tonic-gate 		return (0);
820*7c478bd9Sstevel@tonic-gate 	}
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate 	return (1);
823*7c478bd9Sstevel@tonic-gate }
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate /*
826*7c478bd9Sstevel@tonic-gate  * Name:	get_ethernet_address
827*7c478bd9Sstevel@tonic-gate  *
828*7c478bd9Sstevel@tonic-gate  * Description:	Obtains the system ethernet address.
829*7c478bd9Sstevel@tonic-gate  *
830*7c478bd9Sstevel@tonic-gate  * Returns:	0 on success, non-zero otherwise.  The system ethernet
831*7c478bd9Sstevel@tonic-gate  *		address is copied into the passed-in variable.
832*7c478bd9Sstevel@tonic-gate  */
833*7c478bd9Sstevel@tonic-gate int
834*7c478bd9Sstevel@tonic-gate get_ethernet_address(uuid_node_t *node)
835*7c478bd9Sstevel@tonic-gate {
836*7c478bd9Sstevel@tonic-gate 	char			**ifnames;
837*7c478bd9Sstevel@tonic-gate 	char			*ifname;
838*7c478bd9Sstevel@tonic-gate 	int			i;
839*7c478bd9Sstevel@tonic-gate 	struct ether_addr	addr;
840*7c478bd9Sstevel@tonic-gate 	int			found;
841*7c478bd9Sstevel@tonic-gate 
842*7c478bd9Sstevel@tonic-gate 	if (arp_get(node) == 0)
843*7c478bd9Sstevel@tonic-gate 		return (0);
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate 	/*
846*7c478bd9Sstevel@tonic-gate 	 * go get all interface names
847*7c478bd9Sstevel@tonic-gate 	 */
848*7c478bd9Sstevel@tonic-gate 	if (get_net_if_names(&ifnames) == 0) {
849*7c478bd9Sstevel@tonic-gate 		return (0);
850*7c478bd9Sstevel@tonic-gate 	}
851*7c478bd9Sstevel@tonic-gate 
852*7c478bd9Sstevel@tonic-gate 	/*
853*7c478bd9Sstevel@tonic-gate 	 * Assume failure
854*7c478bd9Sstevel@tonic-gate 	 */
855*7c478bd9Sstevel@tonic-gate 	found = -1;
856*7c478bd9Sstevel@tonic-gate 
857*7c478bd9Sstevel@tonic-gate 	/*
858*7c478bd9Sstevel@tonic-gate 	 * for each interface, query it through dlpi to get its physical
859*7c478bd9Sstevel@tonic-gate 	 * (ethernet) address
860*7c478bd9Sstevel@tonic-gate 	 */
861*7c478bd9Sstevel@tonic-gate 	if (ifnames != NULL) {
862*7c478bd9Sstevel@tonic-gate 		i = 0;
863*7c478bd9Sstevel@tonic-gate 		while ((ifnames[i] != NULL) && found) {
864*7c478bd9Sstevel@tonic-gate 			ifname = ifnames[i];
865*7c478bd9Sstevel@tonic-gate 			/* Gross hack to avoid getting errors from /dev/lo0 */
866*7c478bd9Sstevel@tonic-gate 			if (strcmp(ifname, LOOPBACK_IF) != 0) {
867*7c478bd9Sstevel@tonic-gate 			    if (dlpi_get_address(ifname, &addr) == 0) {
868*7c478bd9Sstevel@tonic-gate 				bcopy(&addr, node, 6);
869*7c478bd9Sstevel@tonic-gate 				/*
870*7c478bd9Sstevel@tonic-gate 				 * found one, set result to successful
871*7c478bd9Sstevel@tonic-gate 				 */
872*7c478bd9Sstevel@tonic-gate 				found = 0;
873*7c478bd9Sstevel@tonic-gate 				continue;
874*7c478bd9Sstevel@tonic-gate 			    }
875*7c478bd9Sstevel@tonic-gate 			}
876*7c478bd9Sstevel@tonic-gate 			i++;
877*7c478bd9Sstevel@tonic-gate 		}
878*7c478bd9Sstevel@tonic-gate 		free_net_if_names(ifnames);
879*7c478bd9Sstevel@tonic-gate 	}
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate 	/*
882*7c478bd9Sstevel@tonic-gate 	 * Couldn't get ethernet address from any interfaces...
883*7c478bd9Sstevel@tonic-gate 	 */
884*7c478bd9Sstevel@tonic-gate 	return (found);
885*7c478bd9Sstevel@tonic-gate }
886