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