1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <stdio.h>
30*0Sstevel@tonic-gate #include <sys/types.h>
31*0Sstevel@tonic-gate #include <sys/stat.h>
32*0Sstevel@tonic-gate #include <string.h>
33*0Sstevel@tonic-gate #include <fcntl.h>
34*0Sstevel@tonic-gate #include <unistd.h>
35*0Sstevel@tonic-gate #include <stropts.h>
36*0Sstevel@tonic-gate #include <stdlib.h>
37*0Sstevel@tonic-gate #include <errno.h>
38*0Sstevel@tonic-gate #include <libdevinfo.h>
39*0Sstevel@tonic-gate #include <libdlpi.h>
40*0Sstevel@tonic-gate #include <libdladm.h>
41*0Sstevel@tonic-gate #include <libintl.h>
42*0Sstevel@tonic-gate #include <sys/dld.h>
43*0Sstevel@tonic-gate #include <net/if.h>
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate #define	DLADM_DB	"/etc/datalink.conf"
46*0Sstevel@tonic-gate #define	DLADM_DB_TMP	"/etc/datalink.conf.new"
47*0Sstevel@tonic-gate #define	DLADM_DB_LOCK	"/tmp/datalink.conf.lock"
48*0Sstevel@tonic-gate #define	DLADM_DB_PERMS	S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate #define	MAXLINELEN	1024
51*0Sstevel@tonic-gate #define	LISTSZ		1024
52*0Sstevel@tonic-gate #define	MAXPATHLEN	1024
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate #define	BLANK_LINE(s)	((s[0] == '\0') || (s[0] == '#') || (s[0] == '\n'))
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate typedef	struct i_dladm_walk {
57*0Sstevel@tonic-gate 	int		fd;
58*0Sstevel@tonic-gate 	boolean_t	found;
59*0Sstevel@tonic-gate 	const char	*name;
60*0Sstevel@tonic-gate } i_dladm_walk_t;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate /*
63*0Sstevel@tonic-gate  * Open and lock the aggregation configuration file lock. The lock is
64*0Sstevel@tonic-gate  * acquired as a reader (F_RDLCK) or writer (F_WRLCK).
65*0Sstevel@tonic-gate  */
66*0Sstevel@tonic-gate static int
67*0Sstevel@tonic-gate i_dladm_lock_db(short type)
68*0Sstevel@tonic-gate {
69*0Sstevel@tonic-gate 	int lock_fd;
70*0Sstevel@tonic-gate 	struct flock lock;
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate 	if ((lock_fd = open(DLADM_DB_LOCK, O_RDWR | O_CREAT | O_TRUNC,
73*0Sstevel@tonic-gate 	    DLADM_DB_PERMS)) < 0)
74*0Sstevel@tonic-gate 		return (-1);
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	lock.l_type = type;
77*0Sstevel@tonic-gate 	lock.l_whence = SEEK_SET;
78*0Sstevel@tonic-gate 	lock.l_start = 0;
79*0Sstevel@tonic-gate 	lock.l_len = 0;
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 	if (fcntl(lock_fd, F_SETLKW, &lock) < 0) {
82*0Sstevel@tonic-gate 		(void) close(lock_fd);
83*0Sstevel@tonic-gate 		(void) unlink(DLADM_DB_LOCK);
84*0Sstevel@tonic-gate 		return (-1);
85*0Sstevel@tonic-gate 	}
86*0Sstevel@tonic-gate 	return (lock_fd);
87*0Sstevel@tonic-gate }
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate /*
90*0Sstevel@tonic-gate  * Unlock and close the specified file.
91*0Sstevel@tonic-gate  */
92*0Sstevel@tonic-gate static void
93*0Sstevel@tonic-gate i_dladm_unlock_db(int fd)
94*0Sstevel@tonic-gate {
95*0Sstevel@tonic-gate 	struct flock lock;
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	if (fd < 0)
98*0Sstevel@tonic-gate 		return;
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 	lock.l_type = F_UNLCK;
101*0Sstevel@tonic-gate 	lock.l_whence = SEEK_SET;
102*0Sstevel@tonic-gate 	lock.l_start = 0;
103*0Sstevel@tonic-gate 	lock.l_len = 0;
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate 	(void) fcntl(fd, F_SETLKW, &lock);
106*0Sstevel@tonic-gate 	(void) close(fd);
107*0Sstevel@tonic-gate 	(void) unlink(DLADM_DB_LOCK);
108*0Sstevel@tonic-gate }
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate /*
111*0Sstevel@tonic-gate  * Parse a line of the configuration file, returns -1 if an error
112*0Sstevel@tonic-gate  * occured.
113*0Sstevel@tonic-gate  */
114*0Sstevel@tonic-gate static int
115*0Sstevel@tonic-gate i_dladm_db_decode(char *buf, char *name, dladm_attr_t *dap)
116*0Sstevel@tonic-gate {
117*0Sstevel@tonic-gate 	char		*attr[DLADM_NATTR + 1];
118*0Sstevel@tonic-gate 	char		*endp = NULL;
119*0Sstevel@tonic-gate 	char		*lasts = NULL;
120*0Sstevel@tonic-gate 	uint_t		i;
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	attr[0] = strtok_r(buf, " \t\n", &lasts);
123*0Sstevel@tonic-gate 	for (i = 1; i < DLADM_NATTR + 1; i++) {
124*0Sstevel@tonic-gate 		if ((attr[i] = strtok_r(NULL, " \t\n", &lasts)) == NULL)
125*0Sstevel@tonic-gate 			return (-1);
126*0Sstevel@tonic-gate 	}
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 	if (i != DLADM_NATTR + 1) {
129*0Sstevel@tonic-gate 		errno = EINVAL;
130*0Sstevel@tonic-gate 		return (-1);
131*0Sstevel@tonic-gate 	}
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	(void) strlcpy(name, attr[0], IFNAMSIZ);
134*0Sstevel@tonic-gate 	(void) strlcpy(dap->da_dev, attr[1], MAXNAMELEN);
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate 	errno = 0;
137*0Sstevel@tonic-gate 	dap->da_port = (int)strtol(attr[2], &endp, 10);
138*0Sstevel@tonic-gate 	if (errno != 0 || *endp != '\0') {
139*0Sstevel@tonic-gate 		return (-1);
140*0Sstevel@tonic-gate 	}
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	errno = 0;
143*0Sstevel@tonic-gate 	dap->da_vid = (int)strtol(attr[3], &endp, 10);
144*0Sstevel@tonic-gate 	if (errno != 0 || *endp != '\0') {
145*0Sstevel@tonic-gate 		return (-1);
146*0Sstevel@tonic-gate 	}
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 	return (0);
149*0Sstevel@tonic-gate }
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate /*
152*0Sstevel@tonic-gate  * Add a datalink of the specified name and attributes to
153*0Sstevel@tonic-gate  * the configuration repository.
154*0Sstevel@tonic-gate  */
155*0Sstevel@tonic-gate static int
156*0Sstevel@tonic-gate i_dladm_db_add(const char *name, dladm_attr_t *dap, const char *root,
157*0Sstevel@tonic-gate     dladm_diag_t *diag)
158*0Sstevel@tonic-gate {
159*0Sstevel@tonic-gate 	FILE		*fp;
160*0Sstevel@tonic-gate 	int		lock_fd, retval = -1;
161*0Sstevel@tonic-gate 	char		line[MAXLINELEN];
162*0Sstevel@tonic-gate 	char		dl_name[IFNAMSIZ];
163*0Sstevel@tonic-gate 	dladm_attr_t	da;
164*0Sstevel@tonic-gate 	char		*db_file;
165*0Sstevel@tonic-gate 	char		db_file_buf[MAXPATHLEN];
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 	if (root == NULL) {
168*0Sstevel@tonic-gate 		db_file = DLADM_DB;
169*0Sstevel@tonic-gate 	} else {
170*0Sstevel@tonic-gate 		(void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
171*0Sstevel@tonic-gate 		    DLADM_DB);
172*0Sstevel@tonic-gate 		db_file = db_file_buf;
173*0Sstevel@tonic-gate 	}
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	if ((lock_fd = i_dladm_lock_db(F_WRLCK)) < 0)
176*0Sstevel@tonic-gate 		return (-1);
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 	if ((fp = fopen(db_file, "r+")) == NULL &&
179*0Sstevel@tonic-gate 	    (fp = fopen(db_file, "w")) == NULL) {
180*0Sstevel@tonic-gate 		*diag = DLADM_DIAG_REPOSITORY_OPENFAIL;
181*0Sstevel@tonic-gate 		i_dladm_unlock_db(lock_fd);
182*0Sstevel@tonic-gate 		return (-1);
183*0Sstevel@tonic-gate 	}
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	while (fgets(line, MAXLINELEN, fp) != NULL) {
186*0Sstevel@tonic-gate 		/* skip comments and blank lines */
187*0Sstevel@tonic-gate 		if (BLANK_LINE(line))
188*0Sstevel@tonic-gate 			continue;
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 		/* skip corrupted lines */
191*0Sstevel@tonic-gate 		if (i_dladm_db_decode(line, dl_name, &da) < 0)
192*0Sstevel@tonic-gate 			continue;
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 		if (strcmp(dl_name, name) == 0) {
195*0Sstevel@tonic-gate 			errno = EEXIST;
196*0Sstevel@tonic-gate 			goto failed;
197*0Sstevel@tonic-gate 		}
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 		if (strcmp(da.da_dev, dap->da_dev) == 0 &&
200*0Sstevel@tonic-gate 		    da.da_port == dap->da_port &&
201*0Sstevel@tonic-gate 		    da.da_vid == dap->da_vid) {
202*0Sstevel@tonic-gate 			errno = EEXIST;
203*0Sstevel@tonic-gate 			goto failed;
204*0Sstevel@tonic-gate 		}
205*0Sstevel@tonic-gate 	}
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 	(void) snprintf(line, MAXPATHLEN, "%s\t%s\t%u\t%u\n",
208*0Sstevel@tonic-gate 	    name, dap->da_dev, dap->da_port, dap->da_vid);
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 	if (fputs(line, fp) == EOF) {
211*0Sstevel@tonic-gate 		*diag = DLADM_DIAG_REPOSITORY_WRITEFAIL;
212*0Sstevel@tonic-gate 		goto failed;
213*0Sstevel@tonic-gate 	}
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	if (fflush(fp) == EOF)
216*0Sstevel@tonic-gate 		goto failed;
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 	retval = 0;
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate failed:
221*0Sstevel@tonic-gate 	(void) fclose(fp);
222*0Sstevel@tonic-gate 	i_dladm_unlock_db(lock_fd);
223*0Sstevel@tonic-gate 	return (retval);
224*0Sstevel@tonic-gate }
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate /*
227*0Sstevel@tonic-gate  * Remove the datalink of the specified name from the configuration repository.
228*0Sstevel@tonic-gate  */
229*0Sstevel@tonic-gate static int
230*0Sstevel@tonic-gate i_dladm_db_remove(const char *name, const char *root)
231*0Sstevel@tonic-gate {
232*0Sstevel@tonic-gate 	FILE		*fp;
233*0Sstevel@tonic-gate 	FILE		*nfp;
234*0Sstevel@tonic-gate 	int		nfd, lock_fd;
235*0Sstevel@tonic-gate 	char		line[MAXLINELEN];
236*0Sstevel@tonic-gate 	char		copy[MAXLINELEN];
237*0Sstevel@tonic-gate 	char		dl_name[IFNAMSIZ];
238*0Sstevel@tonic-gate 	dladm_attr_t	da;
239*0Sstevel@tonic-gate 	boolean_t	found = B_FALSE;
240*0Sstevel@tonic-gate 	char		*db_file, *tmp_db_file;
241*0Sstevel@tonic-gate 	char		db_file_buf[MAXPATHLEN];
242*0Sstevel@tonic-gate 	char		tmp_db_file_buf[MAXPATHLEN];
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate 	if (root == NULL) {
245*0Sstevel@tonic-gate 		db_file = DLADM_DB;
246*0Sstevel@tonic-gate 		tmp_db_file = DLADM_DB_TMP;
247*0Sstevel@tonic-gate 	} else {
248*0Sstevel@tonic-gate 		(void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
249*0Sstevel@tonic-gate 		    DLADM_DB);
250*0Sstevel@tonic-gate 		(void) snprintf(tmp_db_file_buf, MAXPATHLEN, "%s%s", root,
251*0Sstevel@tonic-gate 		    DLADM_DB_TMP);
252*0Sstevel@tonic-gate 		db_file = db_file_buf;
253*0Sstevel@tonic-gate 		tmp_db_file = tmp_db_file_buf;
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	if ((lock_fd = i_dladm_lock_db(F_WRLCK)) < 0)
257*0Sstevel@tonic-gate 		return (-1);
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 	if ((fp = fopen(db_file, "r")) == NULL) {
260*0Sstevel@tonic-gate 		i_dladm_unlock_db(lock_fd);
261*0Sstevel@tonic-gate 		return (-1);
262*0Sstevel@tonic-gate 	}
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate 	if ((nfd = open(tmp_db_file, O_WRONLY | O_CREAT | O_TRUNC,
265*0Sstevel@tonic-gate 	    DLADM_DB_PERMS)) < 0) {
266*0Sstevel@tonic-gate 		(void) fclose(fp);
267*0Sstevel@tonic-gate 		i_dladm_unlock_db(lock_fd);
268*0Sstevel@tonic-gate 		return (-1);
269*0Sstevel@tonic-gate 	}
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 	if ((nfp = fdopen(nfd, "w")) == NULL) {
272*0Sstevel@tonic-gate 		(void) close(nfd);
273*0Sstevel@tonic-gate 		(void) fclose(fp);
274*0Sstevel@tonic-gate 		(void) unlink(tmp_db_file);
275*0Sstevel@tonic-gate 		i_dladm_unlock_db(lock_fd);
276*0Sstevel@tonic-gate 		return (-1);
277*0Sstevel@tonic-gate 	}
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 	while (fgets(line, MAXLINELEN, fp) != NULL) {
280*0Sstevel@tonic-gate 		(void) strlcpy(copy, line, MAXLINELEN);
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 		/* skip comments */
283*0Sstevel@tonic-gate 		if (!BLANK_LINE(line)) {
284*0Sstevel@tonic-gate 			if (i_dladm_db_decode(line, dl_name, &da) < 0) {
285*0Sstevel@tonic-gate 				continue;
286*0Sstevel@tonic-gate 			}
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate 			if (strcmp(dl_name, name) == 0) {
289*0Sstevel@tonic-gate 				found = B_TRUE;
290*0Sstevel@tonic-gate 				continue;
291*0Sstevel@tonic-gate 			}
292*0Sstevel@tonic-gate 		}
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 		if (fputs(copy, nfp) == EOF)
295*0Sstevel@tonic-gate 			goto failed;
296*0Sstevel@tonic-gate 	}
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 	if (!found) {
299*0Sstevel@tonic-gate 		errno = ENOENT;
300*0Sstevel@tonic-gate 		goto failed;
301*0Sstevel@tonic-gate 	}
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 	if (fflush(nfp) == EOF)
304*0Sstevel@tonic-gate 		goto failed;
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 	(void) fclose(fp);
307*0Sstevel@tonic-gate 	(void) fclose(nfp);
308*0Sstevel@tonic-gate 	if (rename(tmp_db_file, db_file) < 0) {
309*0Sstevel@tonic-gate 		(void) unlink(tmp_db_file);
310*0Sstevel@tonic-gate 		i_dladm_unlock_db(lock_fd);
311*0Sstevel@tonic-gate 		return (-1);
312*0Sstevel@tonic-gate 	}
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 	i_dladm_unlock_db(lock_fd);
315*0Sstevel@tonic-gate 	return (0);
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate failed:
318*0Sstevel@tonic-gate 	(void) fclose(fp);
319*0Sstevel@tonic-gate 	(void) fclose(nfp);
320*0Sstevel@tonic-gate 	(void) unlink(tmp_db_file);
321*0Sstevel@tonic-gate 	i_dladm_unlock_db(lock_fd);
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 	return (-1);
324*0Sstevel@tonic-gate }
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate /*
327*0Sstevel@tonic-gate  * For each datalink in the configuration repository, invoke the specified
328*0Sstevel@tonic-gate  * callback. If the datalink name is specified, the callback is invoked
329*0Sstevel@tonic-gate  * only for datalink of the matching name.
330*0Sstevel@tonic-gate  */
331*0Sstevel@tonic-gate static void
332*0Sstevel@tonic-gate i_dladm_db_walk(void (*fn)(void *, const char *, dladm_attr_t *),
333*0Sstevel@tonic-gate     const char *name, void *arg)
334*0Sstevel@tonic-gate {
335*0Sstevel@tonic-gate 	FILE		*fp;
336*0Sstevel@tonic-gate 	int		lock_fd;
337*0Sstevel@tonic-gate 	char		line[MAXLINELEN];
338*0Sstevel@tonic-gate 	char		dl_name[IFNAMSIZ];
339*0Sstevel@tonic-gate 	dladm_attr_t	da;
340*0Sstevel@tonic-gate 
341*0Sstevel@tonic-gate 	lock_fd = i_dladm_lock_db(F_RDLCK);
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	if ((fp = fopen(DLADM_DB, "r")) == NULL) {
344*0Sstevel@tonic-gate 		i_dladm_unlock_db(lock_fd);
345*0Sstevel@tonic-gate 		return;
346*0Sstevel@tonic-gate 	}
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	while (fgets(line, MAXLINELEN, fp) != NULL) {
349*0Sstevel@tonic-gate 		/* skip comments */
350*0Sstevel@tonic-gate 		if (BLANK_LINE(line))
351*0Sstevel@tonic-gate 			continue;
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate 		if (i_dladm_db_decode(line, dl_name, &da) < 0)
354*0Sstevel@tonic-gate 			continue;
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 		if (name != NULL && strcmp(name, dl_name) != 0)
357*0Sstevel@tonic-gate 			continue;
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 		fn(arg, dl_name, &da);
360*0Sstevel@tonic-gate 	}
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 	(void) fclose(fp);
363*0Sstevel@tonic-gate 	i_dladm_unlock_db(lock_fd);
364*0Sstevel@tonic-gate }
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate /*
367*0Sstevel@tonic-gate  * For each datalink in the configuration repository, invoke the
368*0Sstevel@tonic-gate  * specified callback.
369*0Sstevel@tonic-gate  */
370*0Sstevel@tonic-gate void
371*0Sstevel@tonic-gate dladm_db_walk(void (*fn)(void *, const char *, dladm_attr_t *),
372*0Sstevel@tonic-gate     void *arg)
373*0Sstevel@tonic-gate {
374*0Sstevel@tonic-gate 	i_dladm_db_walk(fn, NULL, arg);
375*0Sstevel@tonic-gate }
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate /*
378*0Sstevel@tonic-gate  * Issue an ioctl to the specified file descriptor attached to the
379*0Sstevel@tonic-gate  * DLD control driver interface.
380*0Sstevel@tonic-gate  */
381*0Sstevel@tonic-gate static int
382*0Sstevel@tonic-gate i_dladm_ioctl(int fd, char *ic_dp, int ic_cmd, int ic_len)
383*0Sstevel@tonic-gate {
384*0Sstevel@tonic-gate 	struct strioctl	iocb;
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 	iocb.ic_cmd = ic_cmd;
387*0Sstevel@tonic-gate 	iocb.ic_timout = 0;
388*0Sstevel@tonic-gate 	iocb.ic_len = ic_len;
389*0Sstevel@tonic-gate 	iocb.ic_dp = ic_dp;
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 	return (ioctl(fd, I_STR, &iocb));
392*0Sstevel@tonic-gate }
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate /*
395*0Sstevel@tonic-gate  * Issue a DLDIOCCREATE ioctl command.
396*0Sstevel@tonic-gate  */
397*0Sstevel@tonic-gate static int
398*0Sstevel@tonic-gate i_dladm_create(int fd, const char *name, dladm_attr_t *dap)
399*0Sstevel@tonic-gate {
400*0Sstevel@tonic-gate 	dld_ioc_create_t	dic;
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 	if (strlen(name) >= IFNAMSIZ) {
403*0Sstevel@tonic-gate 		errno = EINVAL;
404*0Sstevel@tonic-gate 		return (-1);
405*0Sstevel@tonic-gate 	}
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate 	(void) strlcpy(dic.dic_name, name, IFNAMSIZ);
408*0Sstevel@tonic-gate 	(void) strlcpy(dic.dic_dev, dap->da_dev, MAXNAMELEN);
409*0Sstevel@tonic-gate 	dic.dic_port = dap->da_port;
410*0Sstevel@tonic-gate 	dic.dic_vid = dap->da_vid;
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	return (i_dladm_ioctl(fd, (char *)&dic, DLDIOCCREATE, sizeof (dic)));
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate /*
416*0Sstevel@tonic-gate  * Datalink bringup callback. Brings up the specified datalink.
417*0Sstevel@tonic-gate  */
418*0Sstevel@tonic-gate static void
419*0Sstevel@tonic-gate i_dladm_up(void *arg, const char *name, dladm_attr_t *dap)
420*0Sstevel@tonic-gate {
421*0Sstevel@tonic-gate 	i_dladm_walk_t	*wp = arg;
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 	wp->found = B_TRUE;
424*0Sstevel@tonic-gate 	(void) i_dladm_create(wp->fd, name, dap);
425*0Sstevel@tonic-gate }
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate /*
428*0Sstevel@tonic-gate  * Bring down the datalink of the specified name.
429*0Sstevel@tonic-gate  */
430*0Sstevel@tonic-gate static int
431*0Sstevel@tonic-gate i_dladm_destroy(int fd, const char *name)
432*0Sstevel@tonic-gate {
433*0Sstevel@tonic-gate 	dld_ioc_destroy_t	did;
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 	if (strlen(name) >= IFNAMSIZ) {
436*0Sstevel@tonic-gate 		errno = EINVAL;
437*0Sstevel@tonic-gate 		return (-1);
438*0Sstevel@tonic-gate 	}
439*0Sstevel@tonic-gate 
440*0Sstevel@tonic-gate 	(void) strlcpy(did.did_name, name, IFNAMSIZ);
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate 	return (i_dladm_ioctl(fd, (char *)&did, DLDIOCDESTROY, sizeof (did)));
443*0Sstevel@tonic-gate }
444*0Sstevel@tonic-gate 
445*0Sstevel@tonic-gate /*
446*0Sstevel@tonic-gate  * Bring down one or all currently active datalinks.
447*0Sstevel@tonic-gate  */
448*0Sstevel@tonic-gate /*ARGSUSED*/
449*0Sstevel@tonic-gate static void
450*0Sstevel@tonic-gate i_dladm_down(void *arg, const char *name)
451*0Sstevel@tonic-gate {
452*0Sstevel@tonic-gate 	i_dladm_walk_t	*wp = (i_dladm_walk_t *)arg;
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate 	wp->found = B_TRUE;
455*0Sstevel@tonic-gate 
456*0Sstevel@tonic-gate 	if (wp->name != NULL && strcmp(name, wp->name) != 0)
457*0Sstevel@tonic-gate 		return;
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 	(void) i_dladm_destroy(wp->fd, name);
460*0Sstevel@tonic-gate }
461*0Sstevel@tonic-gate 
462*0Sstevel@tonic-gate /*
463*0Sstevel@tonic-gate  * Return the attributes of the specified datalink from the DLD driver.
464*0Sstevel@tonic-gate  */
465*0Sstevel@tonic-gate static int
466*0Sstevel@tonic-gate i_dladm_info(int fd, const char *name, dladm_attr_t *dap)
467*0Sstevel@tonic-gate {
468*0Sstevel@tonic-gate 	dld_ioc_attr_t	dia;
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate 	if (strlen(name) >= IFNAMSIZ) {
471*0Sstevel@tonic-gate 		errno = EINVAL;
472*0Sstevel@tonic-gate 		return (-1);
473*0Sstevel@tonic-gate 	}
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate 	(void) strlcpy(dia.dia_name, name, IFNAMSIZ);
476*0Sstevel@tonic-gate 
477*0Sstevel@tonic-gate 	if (i_dladm_ioctl(fd, (char *)&dia, DLDIOCATTR, sizeof (dia)) < 0)
478*0Sstevel@tonic-gate 		return (-1);
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 	(void) strlcpy(dap->da_dev, dia.dia_dev, MAXNAMELEN);
481*0Sstevel@tonic-gate 	dap->da_port = dia.dia_port;
482*0Sstevel@tonic-gate 	dap->da_vid = dia.dia_vid;
483*0Sstevel@tonic-gate 
484*0Sstevel@tonic-gate 	return (0);
485*0Sstevel@tonic-gate }
486*0Sstevel@tonic-gate 
487*0Sstevel@tonic-gate /*
488*0Sstevel@tonic-gate  * Callback function used to count the number of DDI_NT_NET.
489*0Sstevel@tonic-gate  */
490*0Sstevel@tonic-gate /* ARGSUSED */
491*0Sstevel@tonic-gate static int
492*0Sstevel@tonic-gate i_dladm_nt_net_count(di_node_t node, di_minor_t minor, void *arg)
493*0Sstevel@tonic-gate {
494*0Sstevel@tonic-gate 	uint_t		*countp = arg;
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate 	(*countp)++;
497*0Sstevel@tonic-gate 	return (DI_WALK_CONTINUE);
498*0Sstevel@tonic-gate }
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate /*
501*0Sstevel@tonic-gate  * Adds a datalink to the array corresponding to arg.
502*0Sstevel@tonic-gate  */
503*0Sstevel@tonic-gate static void
504*0Sstevel@tonic-gate i_dladm_nt_net_add(void *arg, char *name)
505*0Sstevel@tonic-gate {
506*0Sstevel@tonic-gate 	char		**array = arg;
507*0Sstevel@tonic-gate 	char		*elem;
508*0Sstevel@tonic-gate 
509*0Sstevel@tonic-gate 	for (;;) {
510*0Sstevel@tonic-gate 		elem = *(array++);
511*0Sstevel@tonic-gate 		if (elem[0] == '\0')
512*0Sstevel@tonic-gate 			break;
513*0Sstevel@tonic-gate 		if (strcmp(elem, name) == 0)
514*0Sstevel@tonic-gate 			return;
515*0Sstevel@tonic-gate 	}
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate 	(void) strlcpy(elem, name, MAXNAMELEN);
518*0Sstevel@tonic-gate }
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate /*
521*0Sstevel@tonic-gate  * Walker callback invoked for each DDI_NT_NET node.
522*0Sstevel@tonic-gate  */
523*0Sstevel@tonic-gate static int
524*0Sstevel@tonic-gate i_dladm_nt_net_walk(di_node_t node, di_minor_t minor, void *arg)
525*0Sstevel@tonic-gate {
526*0Sstevel@tonic-gate 	dl_info_ack_t	dlia;
527*0Sstevel@tonic-gate 	char		name[IFNAMSIZ];
528*0Sstevel@tonic-gate 	int		fd;
529*0Sstevel@tonic-gate 	char		*provider;
530*0Sstevel@tonic-gate 	uint_t		ppa;
531*0Sstevel@tonic-gate 
532*0Sstevel@tonic-gate 	provider = di_minor_name(minor);
533*0Sstevel@tonic-gate 
534*0Sstevel@tonic-gate 	if ((fd = dlpi_open(provider)) < 0)
535*0Sstevel@tonic-gate 		return (DI_WALK_CONTINUE);
536*0Sstevel@tonic-gate 
537*0Sstevel@tonic-gate 	if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) < 0) {
538*0Sstevel@tonic-gate 		(void) dlpi_close(fd);
539*0Sstevel@tonic-gate 		return (DI_WALK_CONTINUE);
540*0Sstevel@tonic-gate 	}
541*0Sstevel@tonic-gate 
542*0Sstevel@tonic-gate 	if (dlia.dl_provider_style == DL_STYLE1) {
543*0Sstevel@tonic-gate 		i_dladm_nt_net_add(arg, provider);
544*0Sstevel@tonic-gate 		(void) dlpi_close(fd);
545*0Sstevel@tonic-gate 		return (DI_WALK_CONTINUE);
546*0Sstevel@tonic-gate 	}
547*0Sstevel@tonic-gate 
548*0Sstevel@tonic-gate 	ppa = di_instance(node);
549*0Sstevel@tonic-gate 
550*0Sstevel@tonic-gate 	if (dlpi_attach(fd, -1, ppa) < 0) {
551*0Sstevel@tonic-gate 		(void) dlpi_close(fd);
552*0Sstevel@tonic-gate 		return (DI_WALK_CONTINUE);
553*0Sstevel@tonic-gate 	}
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 	(void) snprintf(name, IFNAMSIZ - 1, "%s%d", provider, ppa);
556*0Sstevel@tonic-gate 	i_dladm_nt_net_add(arg, name);
557*0Sstevel@tonic-gate 	(void) dlpi_close(fd);
558*0Sstevel@tonic-gate 	return (DI_WALK_CONTINUE);
559*0Sstevel@tonic-gate }
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate /*
562*0Sstevel@tonic-gate  * Invoke the specified callback function for each active DDI_NT_NET
563*0Sstevel@tonic-gate  * node.
564*0Sstevel@tonic-gate  */
565*0Sstevel@tonic-gate int
566*0Sstevel@tonic-gate dladm_walk(void (*fn)(void *, const char *), void *arg)
567*0Sstevel@tonic-gate {
568*0Sstevel@tonic-gate 	di_node_t	root;
569*0Sstevel@tonic-gate 	uint_t		count;
570*0Sstevel@tonic-gate 	char		**array;
571*0Sstevel@tonic-gate 	char		*elem;
572*0Sstevel@tonic-gate 	int		i;
573*0Sstevel@tonic-gate 
574*0Sstevel@tonic-gate 	if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
575*0Sstevel@tonic-gate 		errno = EFAULT;
576*0Sstevel@tonic-gate 		return (-1);
577*0Sstevel@tonic-gate 	}
578*0Sstevel@tonic-gate 
579*0Sstevel@tonic-gate 	count = 0;
580*0Sstevel@tonic-gate 	(void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, (void *)&count,
581*0Sstevel@tonic-gate 	    i_dladm_nt_net_count);
582*0Sstevel@tonic-gate 
583*0Sstevel@tonic-gate 	if (count == 0)
584*0Sstevel@tonic-gate 		return (0);
585*0Sstevel@tonic-gate 
586*0Sstevel@tonic-gate 	if ((array = malloc(count * sizeof (char *))) == NULL)
587*0Sstevel@tonic-gate 		goto done;
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
590*0Sstevel@tonic-gate 		if ((array[i] = malloc(IFNAMSIZ)) != NULL) {
591*0Sstevel@tonic-gate 			(void) memset(array[i], '\0', IFNAMSIZ);
592*0Sstevel@tonic-gate 			continue;
593*0Sstevel@tonic-gate 		}
594*0Sstevel@tonic-gate 
595*0Sstevel@tonic-gate 		while (--i >= 0)
596*0Sstevel@tonic-gate 			free(array[i]);
597*0Sstevel@tonic-gate 		goto done;
598*0Sstevel@tonic-gate 	}
599*0Sstevel@tonic-gate 
600*0Sstevel@tonic-gate 	(void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, (void *)array,
601*0Sstevel@tonic-gate 	    i_dladm_nt_net_walk);
602*0Sstevel@tonic-gate 	di_fini(root);
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
605*0Sstevel@tonic-gate 		elem = array[i];
606*0Sstevel@tonic-gate 		if (elem[0] != '\0')
607*0Sstevel@tonic-gate 			fn(arg, (const char *)elem);
608*0Sstevel@tonic-gate 		free(elem);
609*0Sstevel@tonic-gate 	}
610*0Sstevel@tonic-gate 
611*0Sstevel@tonic-gate done:
612*0Sstevel@tonic-gate 	free(array);
613*0Sstevel@tonic-gate 	return (0);
614*0Sstevel@tonic-gate }
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate /*
617*0Sstevel@tonic-gate  * Create the link of specified name and attributes. Adds it to the
618*0Sstevel@tonic-gate  * configuration repository if DLADM_LINK_TEMP is not set. Errors
619*0Sstevel@tonic-gate  * will be ignored if DLADM_LINK_FORCED is set.
620*0Sstevel@tonic-gate  */
621*0Sstevel@tonic-gate int
622*0Sstevel@tonic-gate dladm_link(const char *name, dladm_attr_t *dap, int flags,
623*0Sstevel@tonic-gate     const char *root, dladm_diag_t *diag)
624*0Sstevel@tonic-gate {
625*0Sstevel@tonic-gate 	int		fd;
626*0Sstevel@tonic-gate 	boolean_t	tempop = (flags & DLADM_LINK_TEMP);
627*0Sstevel@tonic-gate 	boolean_t	forced = (flags & DLADM_LINK_FORCED);
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
630*0Sstevel@tonic-gate 		*diag = DLADM_DIAG_DEVICE_OPENFAIL;
631*0Sstevel@tonic-gate 		return (-1);
632*0Sstevel@tonic-gate 	}
633*0Sstevel@tonic-gate 
634*0Sstevel@tonic-gate 	if (!tempop) {
635*0Sstevel@tonic-gate 		if (i_dladm_db_add(name, dap, root, diag) < 0 && !forced)
636*0Sstevel@tonic-gate 			goto failed;
637*0Sstevel@tonic-gate 	}
638*0Sstevel@tonic-gate 
639*0Sstevel@tonic-gate 	if (i_dladm_create(fd, name, dap) < 0 && !forced) {
640*0Sstevel@tonic-gate 		if (errno == EINVAL) {
641*0Sstevel@tonic-gate 			*diag = DLADM_DIAG_INVALID_INTFNAME;
642*0Sstevel@tonic-gate 		}
643*0Sstevel@tonic-gate 		if (!tempop)
644*0Sstevel@tonic-gate 			(void) i_dladm_db_remove(name, root);
645*0Sstevel@tonic-gate 		goto failed;
646*0Sstevel@tonic-gate 	}
647*0Sstevel@tonic-gate 
648*0Sstevel@tonic-gate 	(void) close(fd);
649*0Sstevel@tonic-gate 	return (0);
650*0Sstevel@tonic-gate 
651*0Sstevel@tonic-gate failed:
652*0Sstevel@tonic-gate 	(void) close(fd);
653*0Sstevel@tonic-gate 	return (-1);
654*0Sstevel@tonic-gate }
655*0Sstevel@tonic-gate 
656*0Sstevel@tonic-gate /*
657*0Sstevel@tonic-gate  * Instantiate the datalink of specified name. Brings up all datalinks
658*0Sstevel@tonic-gate  * if name is NULL.
659*0Sstevel@tonic-gate  */
660*0Sstevel@tonic-gate int
661*0Sstevel@tonic-gate dladm_up(const char *name, dladm_diag_t *diag)
662*0Sstevel@tonic-gate {
663*0Sstevel@tonic-gate 	i_dladm_walk_t	walk;
664*0Sstevel@tonic-gate 
665*0Sstevel@tonic-gate 	if ((walk.fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
666*0Sstevel@tonic-gate 		*diag =
667*0Sstevel@tonic-gate 		    DLADM_DIAG_DEVICE_OPENFAIL;
668*0Sstevel@tonic-gate 		return (-1);
669*0Sstevel@tonic-gate 	}
670*0Sstevel@tonic-gate 
671*0Sstevel@tonic-gate 	walk.found = B_FALSE;
672*0Sstevel@tonic-gate 	i_dladm_db_walk(i_dladm_up, name, (void *)&walk);
673*0Sstevel@tonic-gate 	if (name != NULL && !walk.found) {
674*0Sstevel@tonic-gate 		(void) close(walk.fd);
675*0Sstevel@tonic-gate 		errno = ENOENT;
676*0Sstevel@tonic-gate 		return (-1);
677*0Sstevel@tonic-gate 	}
678*0Sstevel@tonic-gate 
679*0Sstevel@tonic-gate 	(void) close(walk.fd);
680*0Sstevel@tonic-gate 	return (0);
681*0Sstevel@tonic-gate }
682*0Sstevel@tonic-gate 
683*0Sstevel@tonic-gate /*
684*0Sstevel@tonic-gate  * Deletes the link of specified name.
685*0Sstevel@tonic-gate  */
686*0Sstevel@tonic-gate int
687*0Sstevel@tonic-gate dladm_unlink(const char *name, boolean_t tempop, const char *root,
688*0Sstevel@tonic-gate     dladm_diag_t *diag)
689*0Sstevel@tonic-gate {
690*0Sstevel@tonic-gate 	int		fd;
691*0Sstevel@tonic-gate 
692*0Sstevel@tonic-gate 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
693*0Sstevel@tonic-gate 		*diag = DLADM_DIAG_DEVICE_OPENFAIL;
694*0Sstevel@tonic-gate 		return (-1);
695*0Sstevel@tonic-gate 	}
696*0Sstevel@tonic-gate 
697*0Sstevel@tonic-gate 	if (i_dladm_destroy(fd, name) < 0) {
698*0Sstevel@tonic-gate 		if (errno == EINVAL)
699*0Sstevel@tonic-gate 			*diag = DLADM_DIAG_INVALID_LINKNAME;
700*0Sstevel@tonic-gate 		goto failed;
701*0Sstevel@tonic-gate 	}
702*0Sstevel@tonic-gate 
703*0Sstevel@tonic-gate 	if (!tempop)
704*0Sstevel@tonic-gate 		(void) i_dladm_db_remove(name, root);
705*0Sstevel@tonic-gate 	(void) close(fd);
706*0Sstevel@tonic-gate 	return (0);
707*0Sstevel@tonic-gate 
708*0Sstevel@tonic-gate failed:
709*0Sstevel@tonic-gate 	(void) close(fd);
710*0Sstevel@tonic-gate 	return (-1);
711*0Sstevel@tonic-gate }
712*0Sstevel@tonic-gate 
713*0Sstevel@tonic-gate /*
714*0Sstevel@tonic-gate  * Brings down the datalink of specified name. Brings down all datalinks
715*0Sstevel@tonic-gate  * if name == NULL.
716*0Sstevel@tonic-gate  */
717*0Sstevel@tonic-gate int
718*0Sstevel@tonic-gate dladm_down(const char *name, dladm_diag_t *diag)
719*0Sstevel@tonic-gate {
720*0Sstevel@tonic-gate 	i_dladm_walk_t	walk;
721*0Sstevel@tonic-gate 
722*0Sstevel@tonic-gate 	if ((walk.fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
723*0Sstevel@tonic-gate 		*diag = DLADM_DIAG_DEVICE_OPENFAIL;
724*0Sstevel@tonic-gate 		return (-1);
725*0Sstevel@tonic-gate 	}
726*0Sstevel@tonic-gate 	walk.found = B_FALSE;
727*0Sstevel@tonic-gate 	walk.name = name;
728*0Sstevel@tonic-gate 
729*0Sstevel@tonic-gate 	if (dladm_walk(i_dladm_down, (void *)&walk) < 0) {
730*0Sstevel@tonic-gate 		(void) close(walk.fd);
731*0Sstevel@tonic-gate 		return (-1);
732*0Sstevel@tonic-gate 	}
733*0Sstevel@tonic-gate 
734*0Sstevel@tonic-gate 	if (name != NULL && !walk.found) {
735*0Sstevel@tonic-gate 		(void) close(walk.fd);
736*0Sstevel@tonic-gate 		errno = ENOENT;
737*0Sstevel@tonic-gate 		return (-1);
738*0Sstevel@tonic-gate 	}
739*0Sstevel@tonic-gate 
740*0Sstevel@tonic-gate 	(void) close(walk.fd);
741*0Sstevel@tonic-gate 	return (0);
742*0Sstevel@tonic-gate }
743*0Sstevel@tonic-gate 
744*0Sstevel@tonic-gate /*
745*0Sstevel@tonic-gate  * Returns the current attributes of the specified datalink.
746*0Sstevel@tonic-gate  */
747*0Sstevel@tonic-gate int
748*0Sstevel@tonic-gate dladm_info(const char *name, dladm_attr_t *dap)
749*0Sstevel@tonic-gate {
750*0Sstevel@tonic-gate 	int		fd;
751*0Sstevel@tonic-gate 
752*0Sstevel@tonic-gate 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
753*0Sstevel@tonic-gate 		return (-1);
754*0Sstevel@tonic-gate 
755*0Sstevel@tonic-gate 	if (i_dladm_info(fd, name, dap) < 0)
756*0Sstevel@tonic-gate 		goto failed;
757*0Sstevel@tonic-gate 
758*0Sstevel@tonic-gate 	(void) close(fd);
759*0Sstevel@tonic-gate 	return (0);
760*0Sstevel@tonic-gate 
761*0Sstevel@tonic-gate failed:
762*0Sstevel@tonic-gate 	(void) close(fd);
763*0Sstevel@tonic-gate 	return (-1);
764*0Sstevel@tonic-gate }
765*0Sstevel@tonic-gate 
766*0Sstevel@tonic-gate /*
767*0Sstevel@tonic-gate  * Causes the nodes corresponding to created or deleted datalinks to
768*0Sstevel@tonic-gate  * be created or deleted.
769*0Sstevel@tonic-gate  */
770*0Sstevel@tonic-gate int
771*0Sstevel@tonic-gate dladm_sync(void)
772*0Sstevel@tonic-gate {
773*0Sstevel@tonic-gate 	di_devlink_handle_t	hdl;
774*0Sstevel@tonic-gate 
775*0Sstevel@tonic-gate 	if ((hdl = di_devlink_init(DLD_DRIVER_NAME, DI_MAKE_LINK)) == NULL)
776*0Sstevel@tonic-gate 		return (-1);
777*0Sstevel@tonic-gate 
778*0Sstevel@tonic-gate 	if (di_devlink_fini(&hdl) < 0)
779*0Sstevel@tonic-gate 		return (-1);
780*0Sstevel@tonic-gate 
781*0Sstevel@tonic-gate 	return (0);
782*0Sstevel@tonic-gate }
783*0Sstevel@tonic-gate 
784*0Sstevel@tonic-gate const char *
785*0Sstevel@tonic-gate dladm_diag(dladm_diag_t diag) {
786*0Sstevel@tonic-gate 	switch (diag) {
787*0Sstevel@tonic-gate 	case DLADM_DIAG_INVALID_LINKNAME:
788*0Sstevel@tonic-gate 		return (gettext("invalid datalink name"));
789*0Sstevel@tonic-gate 	case DLADM_DIAG_INVALID_INTFNAME:
790*0Sstevel@tonic-gate 		return (gettext("invalid interface name"));
791*0Sstevel@tonic-gate 	case DLADM_DIAG_CORRUPT_REPOSITORY:
792*0Sstevel@tonic-gate 		return (gettext("configuration repository corrupt"));
793*0Sstevel@tonic-gate 	case DLADM_DIAG_REPOSITORY_OPENFAIL:
794*0Sstevel@tonic-gate 		return (gettext("configuration repository open failed"));
795*0Sstevel@tonic-gate 	case DLADM_DIAG_REPOSITORY_WRITEFAIL:
796*0Sstevel@tonic-gate 		return (gettext("write to configuration repository failed"));
797*0Sstevel@tonic-gate 	case DLADM_DIAG_REPOSITORY_CLOSEFAIL:
798*0Sstevel@tonic-gate 		return (gettext("configuration repository close failed"));
799*0Sstevel@tonic-gate 	case DLADM_DIAG_DEVICE_OPENFAIL:
800*0Sstevel@tonic-gate 		return (gettext("dld device open fail"));
801*0Sstevel@tonic-gate 	default:
802*0Sstevel@tonic-gate 		return (gettext("unknown diagnostic"));
803*0Sstevel@tonic-gate 	}
804*0Sstevel@tonic-gate }
805