xref: /titanic_44/usr/src/lib/libdladm/common/libdlbridge.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
1*4eaa4710SRishi Srivatsavai /*
2*4eaa4710SRishi Srivatsavai  * CDDL HEADER START
3*4eaa4710SRishi Srivatsavai  *
4*4eaa4710SRishi Srivatsavai  * The contents of this file are subject to the terms of the
5*4eaa4710SRishi Srivatsavai  * Common Development and Distribution License (the "License").
6*4eaa4710SRishi Srivatsavai  * You may not use this file except in compliance with the License.
7*4eaa4710SRishi Srivatsavai  *
8*4eaa4710SRishi Srivatsavai  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4eaa4710SRishi Srivatsavai  * or http://www.opensolaris.org/os/licensing.
10*4eaa4710SRishi Srivatsavai  * See the License for the specific language governing permissions
11*4eaa4710SRishi Srivatsavai  * and limitations under the License.
12*4eaa4710SRishi Srivatsavai  *
13*4eaa4710SRishi Srivatsavai  * When distributing Covered Code, include this CDDL HEADER in each
14*4eaa4710SRishi Srivatsavai  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4eaa4710SRishi Srivatsavai  * If applicable, add the following below this CDDL HEADER, with the
16*4eaa4710SRishi Srivatsavai  * fields enclosed by brackets "[]" replaced with your own identifying
17*4eaa4710SRishi Srivatsavai  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4eaa4710SRishi Srivatsavai  *
19*4eaa4710SRishi Srivatsavai  * CDDL HEADER END
20*4eaa4710SRishi Srivatsavai  */
21*4eaa4710SRishi Srivatsavai /*
22*4eaa4710SRishi Srivatsavai  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*4eaa4710SRishi Srivatsavai  * Use is subject to license terms.
24*4eaa4710SRishi Srivatsavai  */
25*4eaa4710SRishi Srivatsavai 
26*4eaa4710SRishi Srivatsavai #include <stdio.h>
27*4eaa4710SRishi Srivatsavai #include <sys/types.h>
28*4eaa4710SRishi Srivatsavai #include <string.h>
29*4eaa4710SRishi Srivatsavai #include <fcntl.h>
30*4eaa4710SRishi Srivatsavai #include <unistd.h>
31*4eaa4710SRishi Srivatsavai #include <stropts.h>
32*4eaa4710SRishi Srivatsavai #include <ctype.h>
33*4eaa4710SRishi Srivatsavai #include <errno.h>
34*4eaa4710SRishi Srivatsavai #include <stdlib.h>
35*4eaa4710SRishi Srivatsavai #include <door.h>
36*4eaa4710SRishi Srivatsavai #include <sys/mman.h>
37*4eaa4710SRishi Srivatsavai #include <libscf.h>
38*4eaa4710SRishi Srivatsavai #include <libscf_priv.h>
39*4eaa4710SRishi Srivatsavai #include <libdllink.h>
40*4eaa4710SRishi Srivatsavai #include <libdlbridge.h>
41*4eaa4710SRishi Srivatsavai #include <libdladm_impl.h>
42*4eaa4710SRishi Srivatsavai #include <stp_in.h>
43*4eaa4710SRishi Srivatsavai #include <net/bridge.h>
44*4eaa4710SRishi Srivatsavai #include <net/trill.h>
45*4eaa4710SRishi Srivatsavai #include <sys/socket.h>
46*4eaa4710SRishi Srivatsavai 
47*4eaa4710SRishi Srivatsavai /*
48*4eaa4710SRishi Srivatsavai  * Bridge Administration Library.
49*4eaa4710SRishi Srivatsavai  *
50*4eaa4710SRishi Srivatsavai  * This library is used by administration tools such as dladm(1M) to configure
51*4eaa4710SRishi Srivatsavai  * bridges, and by the bridge daemon to retrieve configuration information.
52*4eaa4710SRishi Srivatsavai  */
53*4eaa4710SRishi Srivatsavai 
54*4eaa4710SRishi Srivatsavai #define	BRIDGE_SVC_NAME	"network/bridge"
55*4eaa4710SRishi Srivatsavai #define	TRILL_SVC_NAME	"network/routing/trill"
56*4eaa4710SRishi Srivatsavai 
57*4eaa4710SRishi Srivatsavai #define	DEFAULT_TIMEOUT	60000000
58*4eaa4710SRishi Srivatsavai #define	INIT_WAIT_USECS	50000
59*4eaa4710SRishi Srivatsavai #define	MAXPORTS	256
60*4eaa4710SRishi Srivatsavai 
61*4eaa4710SRishi Srivatsavai typedef struct scf_state {
62*4eaa4710SRishi Srivatsavai 	scf_handle_t *ss_handle;
63*4eaa4710SRishi Srivatsavai 	scf_instance_t *ss_inst;
64*4eaa4710SRishi Srivatsavai 	scf_service_t *ss_svc;
65*4eaa4710SRishi Srivatsavai 	scf_snapshot_t *ss_snap;
66*4eaa4710SRishi Srivatsavai 	scf_propertygroup_t *ss_pg;
67*4eaa4710SRishi Srivatsavai 	scf_property_t *ss_prop;
68*4eaa4710SRishi Srivatsavai } scf_state_t;
69*4eaa4710SRishi Srivatsavai 
70*4eaa4710SRishi Srivatsavai static void
71*4eaa4710SRishi Srivatsavai shut_down_scf(scf_state_t *sstate)
72*4eaa4710SRishi Srivatsavai {
73*4eaa4710SRishi Srivatsavai 	scf_instance_destroy(sstate->ss_inst);
74*4eaa4710SRishi Srivatsavai 	(void) scf_handle_unbind(sstate->ss_handle);
75*4eaa4710SRishi Srivatsavai 	scf_handle_destroy(sstate->ss_handle);
76*4eaa4710SRishi Srivatsavai }
77*4eaa4710SRishi Srivatsavai 
78*4eaa4710SRishi Srivatsavai static char *
79*4eaa4710SRishi Srivatsavai alloc_fmri(const char *service, const char *instance_name)
80*4eaa4710SRishi Srivatsavai {
81*4eaa4710SRishi Srivatsavai 	ssize_t max_fmri;
82*4eaa4710SRishi Srivatsavai 	char *fmri;
83*4eaa4710SRishi Srivatsavai 
84*4eaa4710SRishi Srivatsavai 	/* If the limit is unknown, then use an arbitrary value */
85*4eaa4710SRishi Srivatsavai 	if ((max_fmri = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH)) == -1)
86*4eaa4710SRishi Srivatsavai 		max_fmri = 1024;
87*4eaa4710SRishi Srivatsavai 	if ((fmri = malloc(max_fmri)) != NULL) {
88*4eaa4710SRishi Srivatsavai 		(void) snprintf(fmri, max_fmri, "svc:/%s:%s", service,
89*4eaa4710SRishi Srivatsavai 		    instance_name);
90*4eaa4710SRishi Srivatsavai 	}
91*4eaa4710SRishi Srivatsavai 	return (fmri);
92*4eaa4710SRishi Srivatsavai }
93*4eaa4710SRishi Srivatsavai 
94*4eaa4710SRishi Srivatsavai /*
95*4eaa4710SRishi Srivatsavai  * Start up SCF and bind the requested instance alone.
96*4eaa4710SRishi Srivatsavai  */
97*4eaa4710SRishi Srivatsavai static int
98*4eaa4710SRishi Srivatsavai bind_instance(const char *service, const char *instance_name,
99*4eaa4710SRishi Srivatsavai     scf_state_t *sstate)
100*4eaa4710SRishi Srivatsavai {
101*4eaa4710SRishi Srivatsavai 	char *fmri = NULL;
102*4eaa4710SRishi Srivatsavai 
103*4eaa4710SRishi Srivatsavai 	(void) memset(sstate, 0, sizeof (*sstate));
104*4eaa4710SRishi Srivatsavai 
105*4eaa4710SRishi Srivatsavai 	if ((sstate->ss_handle = scf_handle_create(SCF_VERSION)) == NULL)
106*4eaa4710SRishi Srivatsavai 		return (-1);
107*4eaa4710SRishi Srivatsavai 
108*4eaa4710SRishi Srivatsavai 	if (scf_handle_bind(sstate->ss_handle) != 0)
109*4eaa4710SRishi Srivatsavai 		goto failure;
110*4eaa4710SRishi Srivatsavai 	sstate->ss_inst = scf_instance_create(sstate->ss_handle);
111*4eaa4710SRishi Srivatsavai 	if (sstate->ss_inst == NULL)
112*4eaa4710SRishi Srivatsavai 		goto failure;
113*4eaa4710SRishi Srivatsavai 
114*4eaa4710SRishi Srivatsavai 	fmri = alloc_fmri(service, instance_name);
115*4eaa4710SRishi Srivatsavai 
116*4eaa4710SRishi Srivatsavai 	if (scf_handle_decode_fmri(sstate->ss_handle, fmri, NULL, NULL,
117*4eaa4710SRishi Srivatsavai 	    sstate->ss_inst, NULL, NULL,
118*4eaa4710SRishi Srivatsavai 	    SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0)
119*4eaa4710SRishi Srivatsavai 		goto failure;
120*4eaa4710SRishi Srivatsavai 	free(fmri);
121*4eaa4710SRishi Srivatsavai 	return (0);
122*4eaa4710SRishi Srivatsavai 
123*4eaa4710SRishi Srivatsavai failure:
124*4eaa4710SRishi Srivatsavai 	free(fmri);
125*4eaa4710SRishi Srivatsavai 	shut_down_scf(sstate);
126*4eaa4710SRishi Srivatsavai 	return (-1);
127*4eaa4710SRishi Srivatsavai }
128*4eaa4710SRishi Srivatsavai 
129*4eaa4710SRishi Srivatsavai /*
130*4eaa4710SRishi Srivatsavai  * Start up SCF and an exact FMRI.  This is used for creating new instances and
131*4eaa4710SRishi Srivatsavai  * enable/disable actions.
132*4eaa4710SRishi Srivatsavai  */
133*4eaa4710SRishi Srivatsavai static dladm_status_t
134*4eaa4710SRishi Srivatsavai exact_instance(const char *fmri, scf_state_t *sstate)
135*4eaa4710SRishi Srivatsavai {
136*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
137*4eaa4710SRishi Srivatsavai 
138*4eaa4710SRishi Srivatsavai 	(void) memset(sstate, 0, sizeof (*sstate));
139*4eaa4710SRishi Srivatsavai 
140*4eaa4710SRishi Srivatsavai 	if ((sstate->ss_handle = scf_handle_create(SCF_VERSION)) == NULL)
141*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_NOMEM);
142*4eaa4710SRishi Srivatsavai 
143*4eaa4710SRishi Srivatsavai 	status = DLADM_STATUS_FAILED;
144*4eaa4710SRishi Srivatsavai 	if (scf_handle_bind(sstate->ss_handle) != 0)
145*4eaa4710SRishi Srivatsavai 		goto failure;
146*4eaa4710SRishi Srivatsavai 	sstate->ss_svc = scf_service_create(sstate->ss_handle);
147*4eaa4710SRishi Srivatsavai 	if (sstate->ss_svc == NULL)
148*4eaa4710SRishi Srivatsavai 		goto failure;
149*4eaa4710SRishi Srivatsavai 	if (scf_handle_decode_fmri(sstate->ss_handle, fmri, NULL,
150*4eaa4710SRishi Srivatsavai 	    sstate->ss_svc, NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) {
151*4eaa4710SRishi Srivatsavai 		if (scf_error() == SCF_ERROR_NOT_FOUND)
152*4eaa4710SRishi Srivatsavai 			status = DLADM_STATUS_OPTMISSING;
153*4eaa4710SRishi Srivatsavai 		goto failure;
154*4eaa4710SRishi Srivatsavai 	}
155*4eaa4710SRishi Srivatsavai 	sstate->ss_inst = scf_instance_create(sstate->ss_handle);
156*4eaa4710SRishi Srivatsavai 	if (sstate->ss_inst == NULL)
157*4eaa4710SRishi Srivatsavai 		goto failure;
158*4eaa4710SRishi Srivatsavai 	return (DLADM_STATUS_OK);
159*4eaa4710SRishi Srivatsavai 
160*4eaa4710SRishi Srivatsavai failure:
161*4eaa4710SRishi Srivatsavai 	shut_down_scf(sstate);
162*4eaa4710SRishi Srivatsavai 	return (status);
163*4eaa4710SRishi Srivatsavai }
164*4eaa4710SRishi Srivatsavai 
165*4eaa4710SRishi Srivatsavai static void
166*4eaa4710SRishi Srivatsavai drop_composed(scf_state_t *sstate)
167*4eaa4710SRishi Srivatsavai {
168*4eaa4710SRishi Srivatsavai 	scf_property_destroy(sstate->ss_prop);
169*4eaa4710SRishi Srivatsavai 	scf_pg_destroy(sstate->ss_pg);
170*4eaa4710SRishi Srivatsavai 	scf_snapshot_destroy(sstate->ss_snap);
171*4eaa4710SRishi Srivatsavai }
172*4eaa4710SRishi Srivatsavai 
173*4eaa4710SRishi Srivatsavai /*
174*4eaa4710SRishi Srivatsavai  * This function sets up a composed view of the configuration information for
175*4eaa4710SRishi Srivatsavai  * the specified instance.  When this is done, the get_property() function
176*4eaa4710SRishi Srivatsavai  * should be able to return individual parameters.
177*4eaa4710SRishi Srivatsavai  */
178*4eaa4710SRishi Srivatsavai static int
179*4eaa4710SRishi Srivatsavai get_composed_properties(const char *lpg, boolean_t snap, scf_state_t *sstate)
180*4eaa4710SRishi Srivatsavai {
181*4eaa4710SRishi Srivatsavai 	sstate->ss_snap = NULL;
182*4eaa4710SRishi Srivatsavai 	sstate->ss_pg = NULL;
183*4eaa4710SRishi Srivatsavai 	sstate->ss_prop = NULL;
184*4eaa4710SRishi Srivatsavai 
185*4eaa4710SRishi Srivatsavai 	if (snap) {
186*4eaa4710SRishi Srivatsavai 		sstate->ss_snap = scf_snapshot_create(sstate->ss_handle);
187*4eaa4710SRishi Srivatsavai 		if (sstate->ss_snap == NULL)
188*4eaa4710SRishi Srivatsavai 			goto failure;
189*4eaa4710SRishi Srivatsavai 		if (scf_instance_get_snapshot(sstate->ss_inst, "running",
190*4eaa4710SRishi Srivatsavai 		    sstate->ss_snap) != 0)
191*4eaa4710SRishi Srivatsavai 			goto failure;
192*4eaa4710SRishi Srivatsavai 	}
193*4eaa4710SRishi Srivatsavai 	if ((sstate->ss_pg = scf_pg_create(sstate->ss_handle)) == NULL)
194*4eaa4710SRishi Srivatsavai 		goto failure;
195*4eaa4710SRishi Srivatsavai 	if (scf_instance_get_pg_composed(sstate->ss_inst, sstate->ss_snap, lpg,
196*4eaa4710SRishi Srivatsavai 	    sstate->ss_pg) != 0)
197*4eaa4710SRishi Srivatsavai 		goto failure;
198*4eaa4710SRishi Srivatsavai 	if ((sstate->ss_prop = scf_property_create(sstate->ss_handle)) ==
199*4eaa4710SRishi Srivatsavai 	    NULL)
200*4eaa4710SRishi Srivatsavai 		goto failure;
201*4eaa4710SRishi Srivatsavai 	return (0);
202*4eaa4710SRishi Srivatsavai 
203*4eaa4710SRishi Srivatsavai failure:
204*4eaa4710SRishi Srivatsavai 	drop_composed(sstate);
205*4eaa4710SRishi Srivatsavai 	return (-1);
206*4eaa4710SRishi Srivatsavai }
207*4eaa4710SRishi Srivatsavai 
208*4eaa4710SRishi Srivatsavai static int
209*4eaa4710SRishi Srivatsavai get_count(const char *lprop, scf_state_t *sstate, uint64_t *answer)
210*4eaa4710SRishi Srivatsavai {
211*4eaa4710SRishi Srivatsavai 	scf_value_t *val;
212*4eaa4710SRishi Srivatsavai 	int retv;
213*4eaa4710SRishi Srivatsavai 
214*4eaa4710SRishi Srivatsavai 	if (scf_pg_get_property(sstate->ss_pg, lprop, sstate->ss_prop) != 0)
215*4eaa4710SRishi Srivatsavai 		return (-1);
216*4eaa4710SRishi Srivatsavai 	if ((val = scf_value_create(sstate->ss_handle)) == NULL)
217*4eaa4710SRishi Srivatsavai 		return (-1);
218*4eaa4710SRishi Srivatsavai 
219*4eaa4710SRishi Srivatsavai 	if (scf_property_get_value(sstate->ss_prop, val) == 0 &&
220*4eaa4710SRishi Srivatsavai 	    scf_value_get_count(val, answer) == 0)
221*4eaa4710SRishi Srivatsavai 		retv = 0;
222*4eaa4710SRishi Srivatsavai 	else
223*4eaa4710SRishi Srivatsavai 		retv = -1;
224*4eaa4710SRishi Srivatsavai 	scf_value_destroy(val);
225*4eaa4710SRishi Srivatsavai 	return (retv);
226*4eaa4710SRishi Srivatsavai }
227*4eaa4710SRishi Srivatsavai 
228*4eaa4710SRishi Srivatsavai static int
229*4eaa4710SRishi Srivatsavai get_boolean(const char *lprop, scf_state_t *sstate, boolean_t *answer)
230*4eaa4710SRishi Srivatsavai {
231*4eaa4710SRishi Srivatsavai 	scf_value_t *val;
232*4eaa4710SRishi Srivatsavai 	int retv;
233*4eaa4710SRishi Srivatsavai 	uint8_t bval;
234*4eaa4710SRishi Srivatsavai 
235*4eaa4710SRishi Srivatsavai 	if (scf_pg_get_property(sstate->ss_pg, lprop, sstate->ss_prop) != 0)
236*4eaa4710SRishi Srivatsavai 		return (-1);
237*4eaa4710SRishi Srivatsavai 	if ((val = scf_value_create(sstate->ss_handle)) == NULL)
238*4eaa4710SRishi Srivatsavai 		return (-1);
239*4eaa4710SRishi Srivatsavai 
240*4eaa4710SRishi Srivatsavai 	if (scf_property_get_value(sstate->ss_prop, val) == 0 &&
241*4eaa4710SRishi Srivatsavai 	    scf_value_get_boolean(val, &bval) == 0) {
242*4eaa4710SRishi Srivatsavai 		retv = 0;
243*4eaa4710SRishi Srivatsavai 		*answer = bval != 0;
244*4eaa4710SRishi Srivatsavai 	} else {
245*4eaa4710SRishi Srivatsavai 		retv = -1;
246*4eaa4710SRishi Srivatsavai 	}
247*4eaa4710SRishi Srivatsavai 	scf_value_destroy(val);
248*4eaa4710SRishi Srivatsavai 	return (retv);
249*4eaa4710SRishi Srivatsavai }
250*4eaa4710SRishi Srivatsavai 
251*4eaa4710SRishi Srivatsavai static dladm_status_t
252*4eaa4710SRishi Srivatsavai bridge_door_call(const char *instname, bridge_door_type_t dtype,
253*4eaa4710SRishi Srivatsavai     datalink_id_t linkid, void **bufp, size_t inlen, size_t *buflenp,
254*4eaa4710SRishi Srivatsavai     boolean_t is_list)
255*4eaa4710SRishi Srivatsavai {
256*4eaa4710SRishi Srivatsavai 	char doorname[MAXPATHLEN];
257*4eaa4710SRishi Srivatsavai 	int did, retv, etmp;
258*4eaa4710SRishi Srivatsavai 	bridge_door_cmd_t *bdc;
259*4eaa4710SRishi Srivatsavai 	door_arg_t arg;
260*4eaa4710SRishi Srivatsavai 
261*4eaa4710SRishi Srivatsavai 	(void) snprintf(doorname, sizeof (doorname), "%s/%s", DOOR_DIRNAME,
262*4eaa4710SRishi Srivatsavai 	    instname);
263*4eaa4710SRishi Srivatsavai 
264*4eaa4710SRishi Srivatsavai 	/* Knock on the door */
265*4eaa4710SRishi Srivatsavai 	did = open(doorname, O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
266*4eaa4710SRishi Srivatsavai 	if (did == -1)
267*4eaa4710SRishi Srivatsavai 		return (dladm_errno2status(errno));
268*4eaa4710SRishi Srivatsavai 
269*4eaa4710SRishi Srivatsavai 	if ((bdc = malloc(sizeof (*bdc) + inlen)) == NULL) {
270*4eaa4710SRishi Srivatsavai 		(void) close(did);
271*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_NOMEM);
272*4eaa4710SRishi Srivatsavai 	}
273*4eaa4710SRishi Srivatsavai 	bdc->bdc_type = dtype;
274*4eaa4710SRishi Srivatsavai 	bdc->bdc_linkid = linkid;
275*4eaa4710SRishi Srivatsavai 	if (inlen != 0)
276*4eaa4710SRishi Srivatsavai 		(void) memcpy(bdc + 1, *bufp, inlen);
277*4eaa4710SRishi Srivatsavai 
278*4eaa4710SRishi Srivatsavai 	(void) memset(&arg, 0, sizeof (arg));
279*4eaa4710SRishi Srivatsavai 	arg.data_ptr = (char *)bdc;
280*4eaa4710SRishi Srivatsavai 	arg.data_size = sizeof (*bdc) + inlen;
281*4eaa4710SRishi Srivatsavai 	arg.rbuf = *bufp;
282*4eaa4710SRishi Srivatsavai 	arg.rsize = *buflenp;
283*4eaa4710SRishi Srivatsavai 
284*4eaa4710SRishi Srivatsavai 	/* The door_call function doesn't restart, so take care of that */
285*4eaa4710SRishi Srivatsavai 	do {
286*4eaa4710SRishi Srivatsavai 		errno = 0;
287*4eaa4710SRishi Srivatsavai 		if ((retv = door_call(did, &arg)) == 0)
288*4eaa4710SRishi Srivatsavai 			break;
289*4eaa4710SRishi Srivatsavai 	} while (errno == EINTR);
290*4eaa4710SRishi Srivatsavai 
291*4eaa4710SRishi Srivatsavai 	/* If we get an unexpected response, then return an error */
292*4eaa4710SRishi Srivatsavai 	if (retv == 0) {
293*4eaa4710SRishi Srivatsavai 		/* The daemon returns a single int for errors */
294*4eaa4710SRishi Srivatsavai 		/* LINTED: pointer alignment */
295*4eaa4710SRishi Srivatsavai 		if (arg.data_size == sizeof (int) && *(int *)arg.rbuf != 0) {
296*4eaa4710SRishi Srivatsavai 			retv = -1;
297*4eaa4710SRishi Srivatsavai 			/* LINTED: pointer alignment */
298*4eaa4710SRishi Srivatsavai 			errno = *(int *)arg.rbuf;
299*4eaa4710SRishi Srivatsavai 		}
300*4eaa4710SRishi Srivatsavai 		/* Terminated daemon returns with zero data */
301*4eaa4710SRishi Srivatsavai 		if (arg.data_size == 0) {
302*4eaa4710SRishi Srivatsavai 			retv = -1;
303*4eaa4710SRishi Srivatsavai 			errno = EBADF;
304*4eaa4710SRishi Srivatsavai 		}
305*4eaa4710SRishi Srivatsavai 	}
306*4eaa4710SRishi Srivatsavai 
307*4eaa4710SRishi Srivatsavai 	if (retv == 0) {
308*4eaa4710SRishi Srivatsavai 		if (arg.rbuf != *bufp) {
309*4eaa4710SRishi Srivatsavai 			if (is_list) {
310*4eaa4710SRishi Srivatsavai 				void *newp;
311*4eaa4710SRishi Srivatsavai 
312*4eaa4710SRishi Srivatsavai 				newp = realloc(*bufp, arg.data_size);
313*4eaa4710SRishi Srivatsavai 				if (newp == NULL) {
314*4eaa4710SRishi Srivatsavai 					retv = -1;
315*4eaa4710SRishi Srivatsavai 				} else {
316*4eaa4710SRishi Srivatsavai 					*bufp = newp;
317*4eaa4710SRishi Srivatsavai 					(void) memcpy(*bufp, arg.rbuf,
318*4eaa4710SRishi Srivatsavai 					    arg.data_size);
319*4eaa4710SRishi Srivatsavai 				}
320*4eaa4710SRishi Srivatsavai 			}
321*4eaa4710SRishi Srivatsavai 			(void) munmap(arg.rbuf, arg.rsize);
322*4eaa4710SRishi Srivatsavai 		}
323*4eaa4710SRishi Srivatsavai 		if (is_list) {
324*4eaa4710SRishi Srivatsavai 			*buflenp = arg.data_size;
325*4eaa4710SRishi Srivatsavai 		} else if (arg.data_size != *buflenp || arg.rbuf != *bufp) {
326*4eaa4710SRishi Srivatsavai 			errno = EINVAL;
327*4eaa4710SRishi Srivatsavai 			retv = -1;
328*4eaa4710SRishi Srivatsavai 		}
329*4eaa4710SRishi Srivatsavai 	}
330*4eaa4710SRishi Srivatsavai 
331*4eaa4710SRishi Srivatsavai 	etmp = errno;
332*4eaa4710SRishi Srivatsavai 	(void) close(did);
333*4eaa4710SRishi Srivatsavai 
334*4eaa4710SRishi Srivatsavai 	/* Revoked door is the same as no door at all */
335*4eaa4710SRishi Srivatsavai 	if (etmp == EBADF)
336*4eaa4710SRishi Srivatsavai 		etmp = ENOENT;
337*4eaa4710SRishi Srivatsavai 
338*4eaa4710SRishi Srivatsavai 	return (retv == 0 ? DLADM_STATUS_OK : dladm_errno2status(etmp));
339*4eaa4710SRishi Srivatsavai }
340*4eaa4710SRishi Srivatsavai 
341*4eaa4710SRishi Srivatsavai /*
342*4eaa4710SRishi Srivatsavai  * Wrapper function for making per-port calls.
343*4eaa4710SRishi Srivatsavai  */
344*4eaa4710SRishi Srivatsavai static dladm_status_t
345*4eaa4710SRishi Srivatsavai port_door_call(dladm_handle_t handle, datalink_id_t linkid,
346*4eaa4710SRishi Srivatsavai     bridge_door_type_t dtype, void *buf, size_t inlen, size_t buflen)
347*4eaa4710SRishi Srivatsavai {
348*4eaa4710SRishi Srivatsavai 	char bridge[MAXLINKNAMELEN];
349*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
350*4eaa4710SRishi Srivatsavai 
351*4eaa4710SRishi Srivatsavai 	status = dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge));
352*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
353*4eaa4710SRishi Srivatsavai 		return (status);
354*4eaa4710SRishi Srivatsavai 	return (bridge_door_call(bridge, dtype, linkid, &buf, inlen, &buflen,
355*4eaa4710SRishi Srivatsavai 	    B_FALSE));
356*4eaa4710SRishi Srivatsavai }
357*4eaa4710SRishi Srivatsavai 
358*4eaa4710SRishi Srivatsavai static dladm_status_t
359*4eaa4710SRishi Srivatsavai bridge_refresh(const char *bridge)
360*4eaa4710SRishi Srivatsavai {
361*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
362*4eaa4710SRishi Srivatsavai 	int twoints[2];
363*4eaa4710SRishi Srivatsavai 	void *bdptr;
364*4eaa4710SRishi Srivatsavai 	size_t buflen;
365*4eaa4710SRishi Srivatsavai 	char *fmri;
366*4eaa4710SRishi Srivatsavai 	int refresh_count;
367*4eaa4710SRishi Srivatsavai 
368*4eaa4710SRishi Srivatsavai 	buflen = sizeof (twoints);
369*4eaa4710SRishi Srivatsavai 	bdptr = twoints;
370*4eaa4710SRishi Srivatsavai 	status = bridge_door_call(bridge, bdcBridgeGetRefreshCount,
371*4eaa4710SRishi Srivatsavai 	    DATALINK_INVALID_LINKID, &bdptr, 0, &buflen, B_FALSE);
372*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_NOTFOUND)
373*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_OK);
374*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
375*4eaa4710SRishi Srivatsavai 		return (status);
376*4eaa4710SRishi Srivatsavai 	refresh_count = twoints[0];
377*4eaa4710SRishi Srivatsavai 	if ((fmri = alloc_fmri(BRIDGE_SVC_NAME, bridge)) == NULL)
378*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_NOMEM);
379*4eaa4710SRishi Srivatsavai 	status = smf_refresh_instance(fmri) == 0 ?
380*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK : DLADM_STATUS_FAILED;
381*4eaa4710SRishi Srivatsavai 	free(fmri);
382*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK) {
383*4eaa4710SRishi Srivatsavai 		int i = 0;
384*4eaa4710SRishi Srivatsavai 
385*4eaa4710SRishi Srivatsavai 		/*
386*4eaa4710SRishi Srivatsavai 		 * SMF doesn't give any synchronous behavior or dependency
387*4eaa4710SRishi Srivatsavai 		 * ordering for refresh operations, so we have to invent our
388*4eaa4710SRishi Srivatsavai 		 * own mechanism here.  Get the refresh counter from the
389*4eaa4710SRishi Srivatsavai 		 * daemon, and wait for it to change.  It's not pretty, but
390*4eaa4710SRishi Srivatsavai 		 * it's sufficient.
391*4eaa4710SRishi Srivatsavai 		 */
392*4eaa4710SRishi Srivatsavai 		while (++i <= 10) {
393*4eaa4710SRishi Srivatsavai 			buflen = sizeof (twoints);
394*4eaa4710SRishi Srivatsavai 			bdptr = twoints;
395*4eaa4710SRishi Srivatsavai 			status = bridge_door_call(bridge,
396*4eaa4710SRishi Srivatsavai 			    bdcBridgeGetRefreshCount, DATALINK_INVALID_LINKID,
397*4eaa4710SRishi Srivatsavai 			    &bdptr, 0, &buflen, B_FALSE);
398*4eaa4710SRishi Srivatsavai 			if (status != DLADM_STATUS_OK)
399*4eaa4710SRishi Srivatsavai 				break;
400*4eaa4710SRishi Srivatsavai 			if (twoints[0] != refresh_count)
401*4eaa4710SRishi Srivatsavai 				break;
402*4eaa4710SRishi Srivatsavai 			(void) usleep(100000);
403*4eaa4710SRishi Srivatsavai 		}
404*4eaa4710SRishi Srivatsavai 		fmri = alloc_fmri(TRILL_SVC_NAME, bridge);
405*4eaa4710SRishi Srivatsavai 		if (fmri == NULL)
406*4eaa4710SRishi Srivatsavai 			return (DLADM_STATUS_NOMEM);
407*4eaa4710SRishi Srivatsavai 		status = smf_refresh_instance(fmri) == 0 ||
408*4eaa4710SRishi Srivatsavai 		    scf_error() == SCF_ERROR_NOT_FOUND ?
409*4eaa4710SRishi Srivatsavai 		    DLADM_STATUS_OK : DLADM_STATUS_FAILED;
410*4eaa4710SRishi Srivatsavai 		free(fmri);
411*4eaa4710SRishi Srivatsavai 	}
412*4eaa4710SRishi Srivatsavai 	return (status);
413*4eaa4710SRishi Srivatsavai }
414*4eaa4710SRishi Srivatsavai 
415*4eaa4710SRishi Srivatsavai /*
416*4eaa4710SRishi Srivatsavai  * Look up bridge property values from SCF and return them.
417*4eaa4710SRishi Srivatsavai  */
418*4eaa4710SRishi Srivatsavai dladm_status_t
419*4eaa4710SRishi Srivatsavai dladm_bridge_get_properties(const char *instance_name, UID_STP_CFG_T *cfg,
420*4eaa4710SRishi Srivatsavai     dladm_bridge_prot_t *brprotp)
421*4eaa4710SRishi Srivatsavai {
422*4eaa4710SRishi Srivatsavai 	scf_state_t sstate;
423*4eaa4710SRishi Srivatsavai 	uint64_t value;
424*4eaa4710SRishi Srivatsavai 	boolean_t trill_enabled;
425*4eaa4710SRishi Srivatsavai 
426*4eaa4710SRishi Srivatsavai 	cfg->field_mask = 0;
427*4eaa4710SRishi Srivatsavai 	cfg->bridge_priority = DEF_BR_PRIO;
428*4eaa4710SRishi Srivatsavai 	cfg->max_age = DEF_BR_MAXAGE;
429*4eaa4710SRishi Srivatsavai 	cfg->hello_time = DEF_BR_HELLOT;
430*4eaa4710SRishi Srivatsavai 	cfg->forward_delay = DEF_BR_FWDELAY;
431*4eaa4710SRishi Srivatsavai 	cfg->force_version = DEF_FORCE_VERS;
432*4eaa4710SRishi Srivatsavai 
433*4eaa4710SRishi Srivatsavai 	(void) strlcpy(cfg->vlan_name, instance_name, sizeof (cfg->vlan_name));
434*4eaa4710SRishi Srivatsavai 
435*4eaa4710SRishi Srivatsavai 	*brprotp = DLADM_BRIDGE_PROT_STP;
436*4eaa4710SRishi Srivatsavai 
437*4eaa4710SRishi Srivatsavai 	/* It's ok for this to be missing; it's installed separately */
438*4eaa4710SRishi Srivatsavai 	if (bind_instance(TRILL_SVC_NAME, instance_name, &sstate) == 0) {
439*4eaa4710SRishi Srivatsavai 		trill_enabled = B_FALSE;
440*4eaa4710SRishi Srivatsavai 		if (get_composed_properties(SCF_PG_GENERAL, B_FALSE, &sstate) ==
441*4eaa4710SRishi Srivatsavai 		    0) {
442*4eaa4710SRishi Srivatsavai 			(void) get_boolean(SCF_PROPERTY_ENABLED, &sstate,
443*4eaa4710SRishi Srivatsavai 			    &trill_enabled);
444*4eaa4710SRishi Srivatsavai 			if (trill_enabled)
445*4eaa4710SRishi Srivatsavai 				*brprotp = DLADM_BRIDGE_PROT_TRILL;
446*4eaa4710SRishi Srivatsavai 			drop_composed(&sstate);
447*4eaa4710SRishi Srivatsavai 		}
448*4eaa4710SRishi Srivatsavai 		if (get_composed_properties(SCF_PG_GENERAL_OVR, B_FALSE,
449*4eaa4710SRishi Srivatsavai 		    &sstate) == 0) {
450*4eaa4710SRishi Srivatsavai 			(void) get_boolean(SCF_PROPERTY_ENABLED, &sstate,
451*4eaa4710SRishi Srivatsavai 			    &trill_enabled);
452*4eaa4710SRishi Srivatsavai 			if (trill_enabled)
453*4eaa4710SRishi Srivatsavai 				*brprotp = DLADM_BRIDGE_PROT_TRILL;
454*4eaa4710SRishi Srivatsavai 			drop_composed(&sstate);
455*4eaa4710SRishi Srivatsavai 		}
456*4eaa4710SRishi Srivatsavai 		shut_down_scf(&sstate);
457*4eaa4710SRishi Srivatsavai 	}
458*4eaa4710SRishi Srivatsavai 
459*4eaa4710SRishi Srivatsavai 	cfg->stp_enabled = (*brprotp == DLADM_BRIDGE_PROT_STP) ?
460*4eaa4710SRishi Srivatsavai 	    STP_ENABLED : STP_DISABLED;
461*4eaa4710SRishi Srivatsavai 	cfg->field_mask |= BR_CFG_STATE;
462*4eaa4710SRishi Srivatsavai 
463*4eaa4710SRishi Srivatsavai 	if (bind_instance(BRIDGE_SVC_NAME, instance_name, &sstate) != 0)
464*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_REPOSITORYINVAL);
465*4eaa4710SRishi Srivatsavai 
466*4eaa4710SRishi Srivatsavai 	if (get_composed_properties("config", B_TRUE, &sstate) != 0) {
467*4eaa4710SRishi Srivatsavai 		shut_down_scf(&sstate);
468*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_REPOSITORYINVAL);
469*4eaa4710SRishi Srivatsavai 	}
470*4eaa4710SRishi Srivatsavai 
471*4eaa4710SRishi Srivatsavai 	if (get_count("priority", &sstate, &value) == 0) {
472*4eaa4710SRishi Srivatsavai 		cfg->bridge_priority = value;
473*4eaa4710SRishi Srivatsavai 		cfg->field_mask |= BR_CFG_PRIO;
474*4eaa4710SRishi Srivatsavai 	}
475*4eaa4710SRishi Srivatsavai 	if (get_count("max-age", &sstate, &value) == 0) {
476*4eaa4710SRishi Srivatsavai 		cfg->max_age = value / IEEE_TIMER_SCALE;
477*4eaa4710SRishi Srivatsavai 		cfg->field_mask |= BR_CFG_AGE;
478*4eaa4710SRishi Srivatsavai 	}
479*4eaa4710SRishi Srivatsavai 	if (get_count("hello-time", &sstate, &value) == 0) {
480*4eaa4710SRishi Srivatsavai 		cfg->hello_time = value / IEEE_TIMER_SCALE;
481*4eaa4710SRishi Srivatsavai 		cfg->field_mask |= BR_CFG_HELLO;
482*4eaa4710SRishi Srivatsavai 	}
483*4eaa4710SRishi Srivatsavai 	if (get_count("forward-delay", &sstate, &value) == 0) {
484*4eaa4710SRishi Srivatsavai 		cfg->forward_delay = value / IEEE_TIMER_SCALE;
485*4eaa4710SRishi Srivatsavai 		cfg->field_mask |= BR_CFG_DELAY;
486*4eaa4710SRishi Srivatsavai 	}
487*4eaa4710SRishi Srivatsavai 	if (get_count("force-protocol", &sstate, &value) == 0) {
488*4eaa4710SRishi Srivatsavai 		cfg->force_version = value;
489*4eaa4710SRishi Srivatsavai 		cfg->field_mask |= BR_CFG_FORCE_VER;
490*4eaa4710SRishi Srivatsavai 	}
491*4eaa4710SRishi Srivatsavai 
492*4eaa4710SRishi Srivatsavai 	drop_composed(&sstate);
493*4eaa4710SRishi Srivatsavai 	shut_down_scf(&sstate);
494*4eaa4710SRishi Srivatsavai 	return (DLADM_STATUS_OK);
495*4eaa4710SRishi Srivatsavai }
496*4eaa4710SRishi Srivatsavai 
497*4eaa4710SRishi Srivatsavai /*
498*4eaa4710SRishi Srivatsavai  * Retrieve special non-settable and undocumented parameters.
499*4eaa4710SRishi Srivatsavai  */
500*4eaa4710SRishi Srivatsavai dladm_status_t
501*4eaa4710SRishi Srivatsavai dladm_bridge_get_privprop(const char *instance_name, boolean_t *debugp,
502*4eaa4710SRishi Srivatsavai     uint32_t *tablemaxp)
503*4eaa4710SRishi Srivatsavai {
504*4eaa4710SRishi Srivatsavai 	scf_state_t sstate;
505*4eaa4710SRishi Srivatsavai 	uint64_t value;
506*4eaa4710SRishi Srivatsavai 
507*4eaa4710SRishi Srivatsavai 	*debugp = B_FALSE;
508*4eaa4710SRishi Srivatsavai 	*tablemaxp = 10000;
509*4eaa4710SRishi Srivatsavai 
510*4eaa4710SRishi Srivatsavai 	if (bind_instance(BRIDGE_SVC_NAME, instance_name, &sstate) != 0)
511*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_REPOSITORYINVAL);
512*4eaa4710SRishi Srivatsavai 
513*4eaa4710SRishi Srivatsavai 	if (get_composed_properties("config", B_TRUE, &sstate) != 0) {
514*4eaa4710SRishi Srivatsavai 		shut_down_scf(&sstate);
515*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_REPOSITORYINVAL);
516*4eaa4710SRishi Srivatsavai 	}
517*4eaa4710SRishi Srivatsavai 
518*4eaa4710SRishi Srivatsavai 	(void) get_boolean("debug", &sstate, debugp);
519*4eaa4710SRishi Srivatsavai 	if (get_count("table-maximum", &sstate, &value) == 0)
520*4eaa4710SRishi Srivatsavai 		*tablemaxp = (uint32_t)value;
521*4eaa4710SRishi Srivatsavai 
522*4eaa4710SRishi Srivatsavai 	drop_composed(&sstate);
523*4eaa4710SRishi Srivatsavai 	shut_down_scf(&sstate);
524*4eaa4710SRishi Srivatsavai 	return (DLADM_STATUS_OK);
525*4eaa4710SRishi Srivatsavai }
526*4eaa4710SRishi Srivatsavai 
527*4eaa4710SRishi Srivatsavai static boolean_t
528*4eaa4710SRishi Srivatsavai set_count_property(scf_handle_t *handle, scf_transaction_t *tran,
529*4eaa4710SRishi Srivatsavai     const char *propname, uint64_t propval)
530*4eaa4710SRishi Srivatsavai {
531*4eaa4710SRishi Srivatsavai 	scf_transaction_entry_t *entry;
532*4eaa4710SRishi Srivatsavai 	scf_value_t *value = NULL;
533*4eaa4710SRishi Srivatsavai 
534*4eaa4710SRishi Srivatsavai 	if ((entry = scf_entry_create(handle)) == NULL)
535*4eaa4710SRishi Srivatsavai 		return (B_FALSE);
536*4eaa4710SRishi Srivatsavai 
537*4eaa4710SRishi Srivatsavai 	if ((value = scf_value_create(handle)) == NULL)
538*4eaa4710SRishi Srivatsavai 		goto out;
539*4eaa4710SRishi Srivatsavai 	if (scf_transaction_property_new(tran, entry, propname,
540*4eaa4710SRishi Srivatsavai 	    SCF_TYPE_COUNT) != 0 &&
541*4eaa4710SRishi Srivatsavai 	    scf_transaction_property_change(tran, entry, propname,
542*4eaa4710SRishi Srivatsavai 	    SCF_TYPE_COUNT) != 0)
543*4eaa4710SRishi Srivatsavai 		goto out;
544*4eaa4710SRishi Srivatsavai 	scf_value_set_count(value, propval);
545*4eaa4710SRishi Srivatsavai 	if (scf_entry_add_value(entry, value) == 0)
546*4eaa4710SRishi Srivatsavai 		return (B_TRUE);
547*4eaa4710SRishi Srivatsavai 
548*4eaa4710SRishi Srivatsavai out:
549*4eaa4710SRishi Srivatsavai 	if (value != NULL)
550*4eaa4710SRishi Srivatsavai 		scf_value_destroy(value);
551*4eaa4710SRishi Srivatsavai 
552*4eaa4710SRishi Srivatsavai 	scf_entry_destroy_children(entry);
553*4eaa4710SRishi Srivatsavai 	scf_entry_destroy(entry);
554*4eaa4710SRishi Srivatsavai 
555*4eaa4710SRishi Srivatsavai 	return (B_FALSE);
556*4eaa4710SRishi Srivatsavai }
557*4eaa4710SRishi Srivatsavai 
558*4eaa4710SRishi Srivatsavai static boolean_t
559*4eaa4710SRishi Srivatsavai set_string_property(scf_handle_t *handle, scf_transaction_t *tran,
560*4eaa4710SRishi Srivatsavai     const char *propname, const char *propval)
561*4eaa4710SRishi Srivatsavai {
562*4eaa4710SRishi Srivatsavai 	scf_transaction_entry_t *entry;
563*4eaa4710SRishi Srivatsavai 	scf_value_t *value = NULL;
564*4eaa4710SRishi Srivatsavai 
565*4eaa4710SRishi Srivatsavai 	if ((entry = scf_entry_create(handle)) == NULL)
566*4eaa4710SRishi Srivatsavai 		return (B_FALSE);
567*4eaa4710SRishi Srivatsavai 
568*4eaa4710SRishi Srivatsavai 	if ((value = scf_value_create(handle)) == NULL)
569*4eaa4710SRishi Srivatsavai 		goto out;
570*4eaa4710SRishi Srivatsavai 	if (scf_transaction_property_new(tran, entry, propname,
571*4eaa4710SRishi Srivatsavai 	    SCF_TYPE_ASTRING) != 0 &&
572*4eaa4710SRishi Srivatsavai 	    scf_transaction_property_change(tran, entry, propname,
573*4eaa4710SRishi Srivatsavai 	    SCF_TYPE_ASTRING) != 0)
574*4eaa4710SRishi Srivatsavai 		goto out;
575*4eaa4710SRishi Srivatsavai 	if (scf_value_set_astring(value, propval) != 0)
576*4eaa4710SRishi Srivatsavai 		goto out;
577*4eaa4710SRishi Srivatsavai 	if (scf_entry_add_value(entry, value) == 0)
578*4eaa4710SRishi Srivatsavai 		return (B_TRUE);
579*4eaa4710SRishi Srivatsavai 
580*4eaa4710SRishi Srivatsavai out:
581*4eaa4710SRishi Srivatsavai 	if (value != NULL)
582*4eaa4710SRishi Srivatsavai 		scf_value_destroy(value);
583*4eaa4710SRishi Srivatsavai 
584*4eaa4710SRishi Srivatsavai 	scf_entry_destroy_children(entry);
585*4eaa4710SRishi Srivatsavai 	scf_entry_destroy(entry);
586*4eaa4710SRishi Srivatsavai 
587*4eaa4710SRishi Srivatsavai 	return (B_FALSE);
588*4eaa4710SRishi Srivatsavai }
589*4eaa4710SRishi Srivatsavai 
590*4eaa4710SRishi Srivatsavai static boolean_t
591*4eaa4710SRishi Srivatsavai set_fmri_property(scf_handle_t *handle, scf_transaction_t *tran,
592*4eaa4710SRishi Srivatsavai     const char *propname, const char *propval)
593*4eaa4710SRishi Srivatsavai {
594*4eaa4710SRishi Srivatsavai 	scf_transaction_entry_t *entry;
595*4eaa4710SRishi Srivatsavai 	scf_value_t *value = NULL;
596*4eaa4710SRishi Srivatsavai 
597*4eaa4710SRishi Srivatsavai 	if ((entry = scf_entry_create(handle)) == NULL)
598*4eaa4710SRishi Srivatsavai 		return (B_FALSE);
599*4eaa4710SRishi Srivatsavai 
600*4eaa4710SRishi Srivatsavai 	if ((value = scf_value_create(handle)) == NULL)
601*4eaa4710SRishi Srivatsavai 		goto out;
602*4eaa4710SRishi Srivatsavai 	if (scf_transaction_property_new(tran, entry, propname,
603*4eaa4710SRishi Srivatsavai 	    SCF_TYPE_FMRI) != 0 &&
604*4eaa4710SRishi Srivatsavai 	    scf_transaction_property_change(tran, entry, propname,
605*4eaa4710SRishi Srivatsavai 	    SCF_TYPE_FMRI) != 0)
606*4eaa4710SRishi Srivatsavai 		goto out;
607*4eaa4710SRishi Srivatsavai 	if (scf_value_set_from_string(value, SCF_TYPE_FMRI, propval) != 0)
608*4eaa4710SRishi Srivatsavai 		goto out;
609*4eaa4710SRishi Srivatsavai 	if (scf_entry_add_value(entry, value) == 0)
610*4eaa4710SRishi Srivatsavai 		return (B_TRUE);
611*4eaa4710SRishi Srivatsavai 
612*4eaa4710SRishi Srivatsavai out:
613*4eaa4710SRishi Srivatsavai 	if (value != NULL)
614*4eaa4710SRishi Srivatsavai 		scf_value_destroy(value);
615*4eaa4710SRishi Srivatsavai 
616*4eaa4710SRishi Srivatsavai 	scf_entry_destroy_children(entry);
617*4eaa4710SRishi Srivatsavai 	scf_entry_destroy(entry);
618*4eaa4710SRishi Srivatsavai 
619*4eaa4710SRishi Srivatsavai 	return (B_FALSE);
620*4eaa4710SRishi Srivatsavai }
621*4eaa4710SRishi Srivatsavai 
622*4eaa4710SRishi Srivatsavai static dladm_status_t
623*4eaa4710SRishi Srivatsavai dladm_bridge_persist_conf(dladm_handle_t handle, const char *link,
624*4eaa4710SRishi Srivatsavai     datalink_id_t linkid)
625*4eaa4710SRishi Srivatsavai {
626*4eaa4710SRishi Srivatsavai 	dladm_conf_t conf = DLADM_INVALID_CONF;
627*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
628*4eaa4710SRishi Srivatsavai 
629*4eaa4710SRishi Srivatsavai 	status = dladm_create_conf(handle, link, linkid, DATALINK_CLASS_BRIDGE,
630*4eaa4710SRishi Srivatsavai 	    DL_ETHER, &conf);
631*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK) {
632*4eaa4710SRishi Srivatsavai 		/*
633*4eaa4710SRishi Srivatsavai 		 * Create the datalink entry for the bridge.  Note that all of
634*4eaa4710SRishi Srivatsavai 		 * the real configuration information is in SMF.
635*4eaa4710SRishi Srivatsavai 		 */
636*4eaa4710SRishi Srivatsavai 		status = dladm_write_conf(handle, conf);
637*4eaa4710SRishi Srivatsavai 		dladm_destroy_conf(handle, conf);
638*4eaa4710SRishi Srivatsavai 	}
639*4eaa4710SRishi Srivatsavai 	return (status);
640*4eaa4710SRishi Srivatsavai }
641*4eaa4710SRishi Srivatsavai 
642*4eaa4710SRishi Srivatsavai /* Convert bridge protection option string to dladm_bridge_prot_t */
643*4eaa4710SRishi Srivatsavai dladm_status_t
644*4eaa4710SRishi Srivatsavai dladm_bridge_str2prot(const char *str, dladm_bridge_prot_t *brprotp)
645*4eaa4710SRishi Srivatsavai {
646*4eaa4710SRishi Srivatsavai 	if (strcmp(str, "stp") == 0)
647*4eaa4710SRishi Srivatsavai 		*brprotp = DLADM_BRIDGE_PROT_STP;
648*4eaa4710SRishi Srivatsavai 	else if (strcmp(str, "trill") == 0)
649*4eaa4710SRishi Srivatsavai 		*brprotp = DLADM_BRIDGE_PROT_TRILL;
650*4eaa4710SRishi Srivatsavai 	else
651*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_BADARG);
652*4eaa4710SRishi Srivatsavai 	return (DLADM_STATUS_OK);
653*4eaa4710SRishi Srivatsavai }
654*4eaa4710SRishi Srivatsavai 
655*4eaa4710SRishi Srivatsavai /* Convert bridge protection option from dladm_bridge_prot_t to string */
656*4eaa4710SRishi Srivatsavai const char *
657*4eaa4710SRishi Srivatsavai dladm_bridge_prot2str(dladm_bridge_prot_t brprot)
658*4eaa4710SRishi Srivatsavai {
659*4eaa4710SRishi Srivatsavai 	switch (brprot) {
660*4eaa4710SRishi Srivatsavai 	case DLADM_BRIDGE_PROT_STP:
661*4eaa4710SRishi Srivatsavai 		return ("stp");
662*4eaa4710SRishi Srivatsavai 	case DLADM_BRIDGE_PROT_TRILL:
663*4eaa4710SRishi Srivatsavai 		return ("trill");
664*4eaa4710SRishi Srivatsavai 	default:
665*4eaa4710SRishi Srivatsavai 		return ("unknown");
666*4eaa4710SRishi Srivatsavai 	}
667*4eaa4710SRishi Srivatsavai }
668*4eaa4710SRishi Srivatsavai 
669*4eaa4710SRishi Srivatsavai static dladm_status_t
670*4eaa4710SRishi Srivatsavai enable_instance(const char *service_name, const char *instance)
671*4eaa4710SRishi Srivatsavai {
672*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
673*4eaa4710SRishi Srivatsavai 	char *fmri = alloc_fmri(service_name, instance);
674*4eaa4710SRishi Srivatsavai 
675*4eaa4710SRishi Srivatsavai 	if (fmri == NULL)
676*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_NOMEM);
677*4eaa4710SRishi Srivatsavai 	status = smf_enable_instance(fmri, 0) == 0 ?
678*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK : DLADM_STATUS_FAILED;
679*4eaa4710SRishi Srivatsavai 	free(fmri);
680*4eaa4710SRishi Srivatsavai 	return (status);
681*4eaa4710SRishi Srivatsavai }
682*4eaa4710SRishi Srivatsavai 
683*4eaa4710SRishi Srivatsavai /*
684*4eaa4710SRishi Srivatsavai  * Shut down a possibly-running service instance.  If this is a permanent
685*4eaa4710SRishi Srivatsavai  * change, then delete it from the system.
686*4eaa4710SRishi Srivatsavai  */
687*4eaa4710SRishi Srivatsavai static dladm_status_t
688*4eaa4710SRishi Srivatsavai shut_down_instance(const char *service_name, const char *instance,
689*4eaa4710SRishi Srivatsavai     uint32_t flags)
690*4eaa4710SRishi Srivatsavai {
691*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
692*4eaa4710SRishi Srivatsavai 	char *fmri = alloc_fmri(service_name, instance);
693*4eaa4710SRishi Srivatsavai 	char *state;
694*4eaa4710SRishi Srivatsavai 	scf_state_t sstate;
695*4eaa4710SRishi Srivatsavai 
696*4eaa4710SRishi Srivatsavai 	if (fmri == NULL)
697*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_NOMEM);
698*4eaa4710SRishi Srivatsavai 
699*4eaa4710SRishi Srivatsavai 	if (smf_disable_instance(fmri,
700*4eaa4710SRishi Srivatsavai 	    flags & DLADM_OPT_PERSIST ? 0 : SMF_TEMPORARY) == 0) {
701*4eaa4710SRishi Srivatsavai 		useconds_t usecs, umax;
702*4eaa4710SRishi Srivatsavai 
703*4eaa4710SRishi Srivatsavai 		/* If we can disable, then wait for it to happen. */
704*4eaa4710SRishi Srivatsavai 		umax = DEFAULT_TIMEOUT;
705*4eaa4710SRishi Srivatsavai 		for (usecs = INIT_WAIT_USECS; umax != 0; umax -= usecs) {
706*4eaa4710SRishi Srivatsavai 			state = smf_get_state(fmri);
707*4eaa4710SRishi Srivatsavai 			if (state != NULL &&
708*4eaa4710SRishi Srivatsavai 			    strcmp(state, SCF_STATE_STRING_DISABLED) == 0)
709*4eaa4710SRishi Srivatsavai 				break;
710*4eaa4710SRishi Srivatsavai 			free(state);
711*4eaa4710SRishi Srivatsavai 			usecs *= 2;
712*4eaa4710SRishi Srivatsavai 			if (usecs > umax)
713*4eaa4710SRishi Srivatsavai 				usecs = umax;
714*4eaa4710SRishi Srivatsavai 			(void) usleep(usecs);
715*4eaa4710SRishi Srivatsavai 		}
716*4eaa4710SRishi Srivatsavai 		if (umax == 0) {
717*4eaa4710SRishi Srivatsavai 			state = smf_get_state(fmri);
718*4eaa4710SRishi Srivatsavai 			if (state != NULL &&
719*4eaa4710SRishi Srivatsavai 			    strcmp(state, SCF_STATE_STRING_DISABLED) == 0)
720*4eaa4710SRishi Srivatsavai 				umax = 1;
721*4eaa4710SRishi Srivatsavai 		}
722*4eaa4710SRishi Srivatsavai 		free(state);
723*4eaa4710SRishi Srivatsavai 		status = umax != 0 ? DLADM_STATUS_OK : DLADM_STATUS_FAILED;
724*4eaa4710SRishi Srivatsavai 	} else if (scf_error() == SCF_ERROR_NOT_FOUND) {
725*4eaa4710SRishi Srivatsavai 		free(fmri);
726*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_OK);
727*4eaa4710SRishi Srivatsavai 	} else {
728*4eaa4710SRishi Srivatsavai 		status = DLADM_STATUS_FAILED;
729*4eaa4710SRishi Srivatsavai 	}
730*4eaa4710SRishi Srivatsavai 
731*4eaa4710SRishi Srivatsavai 	free(fmri);
732*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_PERSIST) &&
733*4eaa4710SRishi Srivatsavai 	    bind_instance(service_name, instance, &sstate) == 0) {
734*4eaa4710SRishi Srivatsavai 		(void) scf_instance_delete(sstate.ss_inst);
735*4eaa4710SRishi Srivatsavai 		shut_down_scf(&sstate);
736*4eaa4710SRishi Srivatsavai 	}
737*4eaa4710SRishi Srivatsavai 
738*4eaa4710SRishi Srivatsavai 	return (status);
739*4eaa4710SRishi Srivatsavai }
740*4eaa4710SRishi Srivatsavai 
741*4eaa4710SRishi Srivatsavai static dladm_status_t
742*4eaa4710SRishi Srivatsavai disable_trill(const char *instance, uint32_t flags)
743*4eaa4710SRishi Srivatsavai {
744*4eaa4710SRishi Srivatsavai 	return (shut_down_instance(TRILL_SVC_NAME, instance, flags));
745*4eaa4710SRishi Srivatsavai }
746*4eaa4710SRishi Srivatsavai 
747*4eaa4710SRishi Srivatsavai /*
748*4eaa4710SRishi Srivatsavai  * To enable TRILL, we must create a new instance of the TRILL service, then
749*4eaa4710SRishi Srivatsavai  * add proper dependencies to it, and finally mark it as enabled.  The
750*4eaa4710SRishi Srivatsavai  * dependencies will keep it from going on-line until the bridge is running.
751*4eaa4710SRishi Srivatsavai  */
752*4eaa4710SRishi Srivatsavai static dladm_status_t
753*4eaa4710SRishi Srivatsavai enable_trill(const char *instance)
754*4eaa4710SRishi Srivatsavai {
755*4eaa4710SRishi Srivatsavai 	dladm_status_t status = DLADM_STATUS_FAILED;
756*4eaa4710SRishi Srivatsavai 	char *fmri = NULL;
757*4eaa4710SRishi Srivatsavai 	scf_state_t sstate;
758*4eaa4710SRishi Srivatsavai 	scf_transaction_t *tran = NULL;
759*4eaa4710SRishi Srivatsavai 	boolean_t new_instance = B_FALSE;
760*4eaa4710SRishi Srivatsavai 	boolean_t new_pg = B_FALSE;
761*4eaa4710SRishi Srivatsavai 	int rv;
762*4eaa4710SRishi Srivatsavai 
763*4eaa4710SRishi Srivatsavai 	/*
764*4eaa4710SRishi Srivatsavai 	 * This check is here in case the user has installed and then removed
765*4eaa4710SRishi Srivatsavai 	 * the package.  SMF should remove the manifest, but currently does
766*4eaa4710SRishi Srivatsavai 	 * not.
767*4eaa4710SRishi Srivatsavai 	 */
768*4eaa4710SRishi Srivatsavai 	if (access("/usr/sbin/trilld", F_OK) != 0)
769*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_OPTMISSING);
770*4eaa4710SRishi Srivatsavai 
771*4eaa4710SRishi Srivatsavai 	if ((status = exact_instance(TRILL_SVC_NAME, &sstate)) !=
772*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK)
773*4eaa4710SRishi Srivatsavai 		goto out;
774*4eaa4710SRishi Srivatsavai 
775*4eaa4710SRishi Srivatsavai 	status = DLADM_STATUS_FAILED;
776*4eaa4710SRishi Srivatsavai 	if (scf_service_get_instance(sstate.ss_svc, instance, sstate.ss_inst) !=
777*4eaa4710SRishi Srivatsavai 	    0) {
778*4eaa4710SRishi Srivatsavai 		if (scf_service_add_instance(sstate.ss_svc, instance,
779*4eaa4710SRishi Srivatsavai 		    sstate.ss_inst) != 0)
780*4eaa4710SRishi Srivatsavai 			goto out;
781*4eaa4710SRishi Srivatsavai 		new_instance = B_TRUE;
782*4eaa4710SRishi Srivatsavai 	}
783*4eaa4710SRishi Srivatsavai 
784*4eaa4710SRishi Srivatsavai 	if ((tran = scf_transaction_create(sstate.ss_handle)) == NULL)
785*4eaa4710SRishi Srivatsavai 		goto out;
786*4eaa4710SRishi Srivatsavai 
787*4eaa4710SRishi Srivatsavai 	if ((sstate.ss_pg = scf_pg_create(sstate.ss_handle)) == NULL)
788*4eaa4710SRishi Srivatsavai 		goto out;
789*4eaa4710SRishi Srivatsavai 
790*4eaa4710SRishi Srivatsavai 	if (scf_instance_get_pg(sstate.ss_inst, "bridging",
791*4eaa4710SRishi Srivatsavai 	    sstate.ss_pg) == 0) {
792*4eaa4710SRishi Srivatsavai 		status = DLADM_STATUS_OK;
793*4eaa4710SRishi Srivatsavai 		goto out;
794*4eaa4710SRishi Srivatsavai 	}
795*4eaa4710SRishi Srivatsavai 
796*4eaa4710SRishi Srivatsavai 	if ((fmri = alloc_fmri(BRIDGE_SVC_NAME, instance)) == NULL)
797*4eaa4710SRishi Srivatsavai 		goto out;
798*4eaa4710SRishi Srivatsavai 
799*4eaa4710SRishi Srivatsavai 	if (scf_instance_add_pg(sstate.ss_inst, "bridging",
800*4eaa4710SRishi Srivatsavai 	    SCF_GROUP_DEPENDENCY, 0, sstate.ss_pg) != 0)
801*4eaa4710SRishi Srivatsavai 		goto out;
802*4eaa4710SRishi Srivatsavai 
803*4eaa4710SRishi Srivatsavai 	new_pg = B_TRUE;
804*4eaa4710SRishi Srivatsavai 	do {
805*4eaa4710SRishi Srivatsavai 		if (scf_transaction_start(tran, sstate.ss_pg) != 0)
806*4eaa4710SRishi Srivatsavai 			goto out;
807*4eaa4710SRishi Srivatsavai 
808*4eaa4710SRishi Srivatsavai 		if (!set_string_property(sstate.ss_handle, tran,
809*4eaa4710SRishi Srivatsavai 		    SCF_PROPERTY_GROUPING, SCF_DEP_REQUIRE_ALL))
810*4eaa4710SRishi Srivatsavai 			goto out;
811*4eaa4710SRishi Srivatsavai 		if (!set_string_property(sstate.ss_handle, tran,
812*4eaa4710SRishi Srivatsavai 		    SCF_PROPERTY_RESTART_ON, SCF_DEP_RESET_ON_RESTART))
813*4eaa4710SRishi Srivatsavai 			goto out;
814*4eaa4710SRishi Srivatsavai 		if (!set_string_property(sstate.ss_handle, tran,
815*4eaa4710SRishi Srivatsavai 		    SCF_PROPERTY_TYPE, "service"))
816*4eaa4710SRishi Srivatsavai 			goto out;
817*4eaa4710SRishi Srivatsavai 		if (!set_fmri_property(sstate.ss_handle, tran,
818*4eaa4710SRishi Srivatsavai 		    SCF_PROPERTY_ENTITIES, fmri))
819*4eaa4710SRishi Srivatsavai 			goto out;
820*4eaa4710SRishi Srivatsavai 
821*4eaa4710SRishi Srivatsavai 		rv = scf_transaction_commit(tran);
822*4eaa4710SRishi Srivatsavai 		scf_transaction_reset(tran);
823*4eaa4710SRishi Srivatsavai 		if (rv == 0 && scf_pg_update(sstate.ss_pg) == -1)
824*4eaa4710SRishi Srivatsavai 			goto out;
825*4eaa4710SRishi Srivatsavai 	} while (rv == 0);
826*4eaa4710SRishi Srivatsavai 	if (rv != 1)
827*4eaa4710SRishi Srivatsavai 		goto out;
828*4eaa4710SRishi Srivatsavai 
829*4eaa4710SRishi Srivatsavai 	status = DLADM_STATUS_OK;
830*4eaa4710SRishi Srivatsavai 
831*4eaa4710SRishi Srivatsavai out:
832*4eaa4710SRishi Srivatsavai 	free(fmri);
833*4eaa4710SRishi Srivatsavai 	if (tran != NULL) {
834*4eaa4710SRishi Srivatsavai 		scf_transaction_destroy_children(tran);
835*4eaa4710SRishi Srivatsavai 		scf_transaction_destroy(tran);
836*4eaa4710SRishi Srivatsavai 	}
837*4eaa4710SRishi Srivatsavai 
838*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK && new_pg)
839*4eaa4710SRishi Srivatsavai 		(void) scf_pg_delete(sstate.ss_pg);
840*4eaa4710SRishi Srivatsavai 
841*4eaa4710SRishi Srivatsavai 	drop_composed(&sstate);
842*4eaa4710SRishi Srivatsavai 
843*4eaa4710SRishi Srivatsavai 	/*
844*4eaa4710SRishi Srivatsavai 	 * If we created an instance and then failed, then remove the instance
845*4eaa4710SRishi Srivatsavai 	 * from the system.
846*4eaa4710SRishi Srivatsavai 	 */
847*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK && new_instance)
848*4eaa4710SRishi Srivatsavai 		(void) scf_instance_delete(sstate.ss_inst);
849*4eaa4710SRishi Srivatsavai 
850*4eaa4710SRishi Srivatsavai 	shut_down_scf(&sstate);
851*4eaa4710SRishi Srivatsavai 
852*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK)
853*4eaa4710SRishi Srivatsavai 		status = enable_instance(TRILL_SVC_NAME, instance);
854*4eaa4710SRishi Srivatsavai 
855*4eaa4710SRishi Srivatsavai 	return (status);
856*4eaa4710SRishi Srivatsavai }
857*4eaa4710SRishi Srivatsavai 
858*4eaa4710SRishi Srivatsavai /*
859*4eaa4710SRishi Srivatsavai  * Create a new bridge or modify an existing one.  Update the SMF configuration
860*4eaa4710SRishi Srivatsavai  * and add links.
861*4eaa4710SRishi Srivatsavai  *
862*4eaa4710SRishi Srivatsavai  * Input timer values are in IEEE scaled (* 256) format.
863*4eaa4710SRishi Srivatsavai  */
864*4eaa4710SRishi Srivatsavai dladm_status_t
865*4eaa4710SRishi Srivatsavai dladm_bridge_configure(dladm_handle_t handle, const char *name,
866*4eaa4710SRishi Srivatsavai     const UID_STP_CFG_T *cfg, dladm_bridge_prot_t brprot, uint32_t flags)
867*4eaa4710SRishi Srivatsavai {
868*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
869*4eaa4710SRishi Srivatsavai 	scf_state_t sstate;
870*4eaa4710SRishi Srivatsavai 	scf_transaction_t *tran = NULL;
871*4eaa4710SRishi Srivatsavai 	boolean_t new_instance = B_FALSE;
872*4eaa4710SRishi Srivatsavai 	boolean_t new_pg = B_FALSE;
873*4eaa4710SRishi Srivatsavai 	datalink_id_t linkid = DATALINK_INVALID_LINKID;
874*4eaa4710SRishi Srivatsavai 	char linkname[MAXLINKNAMELEN];
875*4eaa4710SRishi Srivatsavai 	int rv;
876*4eaa4710SRishi Srivatsavai 
877*4eaa4710SRishi Srivatsavai 	if (!dladm_valid_bridgename(name))
878*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_FAILED);
879*4eaa4710SRishi Srivatsavai 
880*4eaa4710SRishi Srivatsavai 	if (flags & DLADM_OPT_CREATE) {
881*4eaa4710SRishi Srivatsavai 		/*
882*4eaa4710SRishi Srivatsavai 		 * This check is here in case the user has installed and then
883*4eaa4710SRishi Srivatsavai 		 * removed the package.  SMF should remove the manifest, but
884*4eaa4710SRishi Srivatsavai 		 * currently does not.
885*4eaa4710SRishi Srivatsavai 		 */
886*4eaa4710SRishi Srivatsavai 		if (access("/usr/lib/bridged", F_OK) != 0)
887*4eaa4710SRishi Srivatsavai 			return (DLADM_STATUS_OPTMISSING);
888*4eaa4710SRishi Srivatsavai 
889*4eaa4710SRishi Srivatsavai 		(void) snprintf(linkname, sizeof (linkname), "%s0", name);
890*4eaa4710SRishi Srivatsavai 		status = dladm_create_datalink_id(handle, linkname,
891*4eaa4710SRishi Srivatsavai 		    DATALINK_CLASS_BRIDGE, DL_ETHER,
892*4eaa4710SRishi Srivatsavai 		    flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST), &linkid);
893*4eaa4710SRishi Srivatsavai 		if (status != DLADM_STATUS_OK)
894*4eaa4710SRishi Srivatsavai 			return (status);
895*4eaa4710SRishi Srivatsavai 
896*4eaa4710SRishi Srivatsavai 		if ((flags & DLADM_OPT_PERSIST) &&
897*4eaa4710SRishi Srivatsavai 		    (status = dladm_bridge_persist_conf(handle, linkname,
898*4eaa4710SRishi Srivatsavai 		    linkid) != DLADM_STATUS_OK))
899*4eaa4710SRishi Srivatsavai 			goto dladm_fail;
900*4eaa4710SRishi Srivatsavai 	}
901*4eaa4710SRishi Srivatsavai 
902*4eaa4710SRishi Srivatsavai 	if (brprot == DLADM_BRIDGE_PROT_TRILL)
903*4eaa4710SRishi Srivatsavai 		status = enable_trill(name);
904*4eaa4710SRishi Srivatsavai 	else
905*4eaa4710SRishi Srivatsavai 		status = disable_trill(name, flags);
906*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
907*4eaa4710SRishi Srivatsavai 		goto dladm_fail;
908*4eaa4710SRishi Srivatsavai 
909*4eaa4710SRishi Srivatsavai 	if ((status = exact_instance(BRIDGE_SVC_NAME, &sstate)) !=
910*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK)
911*4eaa4710SRishi Srivatsavai 		goto out;
912*4eaa4710SRishi Srivatsavai 
913*4eaa4710SRishi Srivatsavai 	/* set up for a series of scf calls */
914*4eaa4710SRishi Srivatsavai 	status = DLADM_STATUS_FAILED;
915*4eaa4710SRishi Srivatsavai 
916*4eaa4710SRishi Srivatsavai 	if (scf_service_get_instance(sstate.ss_svc, name, sstate.ss_inst) ==
917*4eaa4710SRishi Srivatsavai 	    0) {
918*4eaa4710SRishi Srivatsavai 		if (flags & DLADM_OPT_CREATE) {
919*4eaa4710SRishi Srivatsavai 			status = DLADM_STATUS_EXIST;
920*4eaa4710SRishi Srivatsavai 			goto out;
921*4eaa4710SRishi Srivatsavai 		}
922*4eaa4710SRishi Srivatsavai 	} else {
923*4eaa4710SRishi Srivatsavai 		if (!(flags & DLADM_OPT_CREATE)) {
924*4eaa4710SRishi Srivatsavai 			status = DLADM_STATUS_NOTFOUND;
925*4eaa4710SRishi Srivatsavai 			goto out;
926*4eaa4710SRishi Srivatsavai 		}
927*4eaa4710SRishi Srivatsavai 		if (scf_service_add_instance(sstate.ss_svc, name,
928*4eaa4710SRishi Srivatsavai 		    sstate.ss_inst) != 0)
929*4eaa4710SRishi Srivatsavai 			goto out;
930*4eaa4710SRishi Srivatsavai 		new_instance = B_TRUE;
931*4eaa4710SRishi Srivatsavai 	}
932*4eaa4710SRishi Srivatsavai 
933*4eaa4710SRishi Srivatsavai 	if ((tran = scf_transaction_create(sstate.ss_handle)) == NULL)
934*4eaa4710SRishi Srivatsavai 		goto out;
935*4eaa4710SRishi Srivatsavai 
936*4eaa4710SRishi Srivatsavai 	if (cfg->field_mask & BR_CFG_ALL) {
937*4eaa4710SRishi Srivatsavai 		if ((sstate.ss_pg = scf_pg_create(sstate.ss_handle)) == NULL)
938*4eaa4710SRishi Srivatsavai 			goto out;
939*4eaa4710SRishi Srivatsavai 		if (scf_instance_add_pg(sstate.ss_inst, "config",
940*4eaa4710SRishi Srivatsavai 		    SCF_GROUP_APPLICATION, 0, sstate.ss_pg) == 0) {
941*4eaa4710SRishi Srivatsavai 			new_pg = B_TRUE;
942*4eaa4710SRishi Srivatsavai 		} else if (scf_instance_get_pg(sstate.ss_inst, "config",
943*4eaa4710SRishi Srivatsavai 		    sstate.ss_pg) != 0) {
944*4eaa4710SRishi Srivatsavai 			goto out;
945*4eaa4710SRishi Srivatsavai 		}
946*4eaa4710SRishi Srivatsavai 		do {
947*4eaa4710SRishi Srivatsavai 			if (scf_transaction_start(tran, sstate.ss_pg) != 0)
948*4eaa4710SRishi Srivatsavai 				goto out;
949*4eaa4710SRishi Srivatsavai 
950*4eaa4710SRishi Srivatsavai 			if ((cfg->field_mask & BR_CFG_PRIO) &&
951*4eaa4710SRishi Srivatsavai 			    !set_count_property(sstate.ss_handle, tran,
952*4eaa4710SRishi Srivatsavai 			    "priority", cfg->bridge_priority))
953*4eaa4710SRishi Srivatsavai 				goto out;
954*4eaa4710SRishi Srivatsavai 			if ((cfg->field_mask & BR_CFG_AGE) &&
955*4eaa4710SRishi Srivatsavai 			    !set_count_property(sstate.ss_handle, tran,
956*4eaa4710SRishi Srivatsavai 			    "max-age", cfg->max_age * IEEE_TIMER_SCALE))
957*4eaa4710SRishi Srivatsavai 				goto out;
958*4eaa4710SRishi Srivatsavai 			if ((cfg->field_mask & BR_CFG_HELLO) &&
959*4eaa4710SRishi Srivatsavai 			    !set_count_property(sstate.ss_handle, tran,
960*4eaa4710SRishi Srivatsavai 			    "hello-time", cfg->hello_time * IEEE_TIMER_SCALE))
961*4eaa4710SRishi Srivatsavai 				goto out;
962*4eaa4710SRishi Srivatsavai 			if ((cfg->field_mask & BR_CFG_DELAY) &&
963*4eaa4710SRishi Srivatsavai 			    !set_count_property(sstate.ss_handle, tran,
964*4eaa4710SRishi Srivatsavai 			    "forward-delay",
965*4eaa4710SRishi Srivatsavai 			    cfg->forward_delay * IEEE_TIMER_SCALE))
966*4eaa4710SRishi Srivatsavai 				goto out;
967*4eaa4710SRishi Srivatsavai 			if ((cfg->field_mask & BR_CFG_FORCE_VER) &&
968*4eaa4710SRishi Srivatsavai 			    !set_count_property(sstate.ss_handle, tran,
969*4eaa4710SRishi Srivatsavai 			    "force-protocol", cfg->force_version))
970*4eaa4710SRishi Srivatsavai 				goto out;
971*4eaa4710SRishi Srivatsavai 
972*4eaa4710SRishi Srivatsavai 			rv = scf_transaction_commit(tran);
973*4eaa4710SRishi Srivatsavai 			scf_transaction_reset(tran);
974*4eaa4710SRishi Srivatsavai 			if (rv == 0 && scf_pg_update(sstate.ss_pg) == -1)
975*4eaa4710SRishi Srivatsavai 				goto out;
976*4eaa4710SRishi Srivatsavai 		} while (rv == 0);
977*4eaa4710SRishi Srivatsavai 		if (rv != 1)
978*4eaa4710SRishi Srivatsavai 			goto out;
979*4eaa4710SRishi Srivatsavai 	}
980*4eaa4710SRishi Srivatsavai 
981*4eaa4710SRishi Srivatsavai 	/*
982*4eaa4710SRishi Srivatsavai 	 * If we're modifying an existing and running bridge, then tell the
983*4eaa4710SRishi Srivatsavai 	 * daemon to update the requested values.
984*4eaa4710SRishi Srivatsavai 	 */
985*4eaa4710SRishi Srivatsavai 	if ((flags & DLADM_OPT_ACTIVE) && !(flags & DLADM_OPT_CREATE))
986*4eaa4710SRishi Srivatsavai 		status = bridge_refresh(name);
987*4eaa4710SRishi Srivatsavai 	else
988*4eaa4710SRishi Srivatsavai 		status = DLADM_STATUS_OK;
989*4eaa4710SRishi Srivatsavai 
990*4eaa4710SRishi Srivatsavai out:
991*4eaa4710SRishi Srivatsavai 	if (tran != NULL) {
992*4eaa4710SRishi Srivatsavai 		scf_transaction_destroy_children(tran);
993*4eaa4710SRishi Srivatsavai 		scf_transaction_destroy(tran);
994*4eaa4710SRishi Srivatsavai 	}
995*4eaa4710SRishi Srivatsavai 
996*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK && new_pg)
997*4eaa4710SRishi Srivatsavai 		(void) scf_pg_delete(sstate.ss_pg);
998*4eaa4710SRishi Srivatsavai 
999*4eaa4710SRishi Srivatsavai 	drop_composed(&sstate);
1000*4eaa4710SRishi Srivatsavai 
1001*4eaa4710SRishi Srivatsavai 	/*
1002*4eaa4710SRishi Srivatsavai 	 * If we created an instance and then failed, then remove the instance
1003*4eaa4710SRishi Srivatsavai 	 * from the system.
1004*4eaa4710SRishi Srivatsavai 	 */
1005*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK && new_instance)
1006*4eaa4710SRishi Srivatsavai 		(void) scf_instance_delete(sstate.ss_inst);
1007*4eaa4710SRishi Srivatsavai 
1008*4eaa4710SRishi Srivatsavai 	shut_down_scf(&sstate);
1009*4eaa4710SRishi Srivatsavai 
1010*4eaa4710SRishi Srivatsavai 	/*
1011*4eaa4710SRishi Srivatsavai 	 * Remove the bridge linkid if we've allocated one in this function but
1012*4eaa4710SRishi Srivatsavai 	 * we've failed to set up the SMF properties.
1013*4eaa4710SRishi Srivatsavai 	 */
1014*4eaa4710SRishi Srivatsavai dladm_fail:
1015*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK && linkid != DATALINK_INVALID_LINKID) {
1016*4eaa4710SRishi Srivatsavai 		(void) dladm_remove_conf(handle, linkid);
1017*4eaa4710SRishi Srivatsavai 		(void) dladm_destroy_datalink_id(handle, linkid, flags);
1018*4eaa4710SRishi Srivatsavai 	}
1019*4eaa4710SRishi Srivatsavai 
1020*4eaa4710SRishi Srivatsavai 	return (status);
1021*4eaa4710SRishi Srivatsavai }
1022*4eaa4710SRishi Srivatsavai 
1023*4eaa4710SRishi Srivatsavai /*
1024*4eaa4710SRishi Srivatsavai  * Enable a newly-created bridge in SMF by creating "general/enabled" and
1025*4eaa4710SRishi Srivatsavai  * deleting any "general_ovr/enabled" (used for temporary services).
1026*4eaa4710SRishi Srivatsavai  */
1027*4eaa4710SRishi Srivatsavai dladm_status_t
1028*4eaa4710SRishi Srivatsavai dladm_bridge_enable(const char *name)
1029*4eaa4710SRishi Srivatsavai {
1030*4eaa4710SRishi Srivatsavai 	return (enable_instance(BRIDGE_SVC_NAME, name));
1031*4eaa4710SRishi Srivatsavai }
1032*4eaa4710SRishi Srivatsavai 
1033*4eaa4710SRishi Srivatsavai /*
1034*4eaa4710SRishi Srivatsavai  * Set a link as a member of a bridge, or remove bridge membership.  If the
1035*4eaa4710SRishi Srivatsavai  * DLADM_OPT_CREATE flag is set, then we assume that the daemon isn't running.
1036*4eaa4710SRishi Srivatsavai  * In all other cases, we must tell the daemon to add or delete the link in
1037*4eaa4710SRishi Srivatsavai  * order to stay in sync.
1038*4eaa4710SRishi Srivatsavai  */
1039*4eaa4710SRishi Srivatsavai dladm_status_t
1040*4eaa4710SRishi Srivatsavai dladm_bridge_setlink(dladm_handle_t handle, datalink_id_t linkid,
1041*4eaa4710SRishi Srivatsavai     const char *bridge)
1042*4eaa4710SRishi Srivatsavai {
1043*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
1044*4eaa4710SRishi Srivatsavai 	dladm_conf_t conf;
1045*4eaa4710SRishi Srivatsavai 	char oldbridge[MAXLINKNAMELEN];
1046*4eaa4710SRishi Srivatsavai 	boolean_t has_oldbridge;
1047*4eaa4710SRishi Srivatsavai 	boolean_t changed = B_FALSE;
1048*4eaa4710SRishi Srivatsavai 
1049*4eaa4710SRishi Srivatsavai 	if (*bridge != '\0' && !dladm_valid_bridgename(bridge))
1050*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_FAILED);
1051*4eaa4710SRishi Srivatsavai 
1052*4eaa4710SRishi Srivatsavai 	if ((status = dladm_read_conf(handle, linkid, &conf)) !=
1053*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK)
1054*4eaa4710SRishi Srivatsavai 		return (status);
1055*4eaa4710SRishi Srivatsavai 
1056*4eaa4710SRishi Srivatsavai 	has_oldbridge = B_FALSE;
1057*4eaa4710SRishi Srivatsavai 	status = dladm_get_conf_field(handle, conf, FBRIDGE, oldbridge,
1058*4eaa4710SRishi Srivatsavai 	    sizeof (oldbridge));
1059*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK) {
1060*4eaa4710SRishi Srivatsavai 		/*
1061*4eaa4710SRishi Srivatsavai 		 * Don't allow a link to be reassigned directly from one bridge
1062*4eaa4710SRishi Srivatsavai 		 * to another.  It must be removed first.
1063*4eaa4710SRishi Srivatsavai 		 */
1064*4eaa4710SRishi Srivatsavai 		if (*oldbridge != '\0' && *bridge != '\0') {
1065*4eaa4710SRishi Srivatsavai 			status = DLADM_STATUS_EXIST;
1066*4eaa4710SRishi Srivatsavai 			goto out;
1067*4eaa4710SRishi Srivatsavai 		}
1068*4eaa4710SRishi Srivatsavai 		has_oldbridge = B_TRUE;
1069*4eaa4710SRishi Srivatsavai 	} else if (status != DLADM_STATUS_NOTFOUND) {
1070*4eaa4710SRishi Srivatsavai 		goto out;
1071*4eaa4710SRishi Srivatsavai 	}
1072*4eaa4710SRishi Srivatsavai 
1073*4eaa4710SRishi Srivatsavai 	if (*bridge != '\0') {
1074*4eaa4710SRishi Srivatsavai 		status = dladm_set_conf_field(handle, conf, FBRIDGE,
1075*4eaa4710SRishi Srivatsavai 		    DLADM_TYPE_STR, bridge);
1076*4eaa4710SRishi Srivatsavai 		changed = B_TRUE;
1077*4eaa4710SRishi Srivatsavai 	} else if (has_oldbridge) {
1078*4eaa4710SRishi Srivatsavai 		status = dladm_unset_conf_field(handle, conf, FBRIDGE);
1079*4eaa4710SRishi Srivatsavai 		changed = B_TRUE;
1080*4eaa4710SRishi Srivatsavai 	} else {
1081*4eaa4710SRishi Srivatsavai 		status = DLADM_STATUS_OK;
1082*4eaa4710SRishi Srivatsavai 		goto out;
1083*4eaa4710SRishi Srivatsavai 	}
1084*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK)
1085*4eaa4710SRishi Srivatsavai 		status = dladm_write_conf(handle, conf);
1086*4eaa4710SRishi Srivatsavai 
1087*4eaa4710SRishi Srivatsavai out:
1088*4eaa4710SRishi Srivatsavai 	dladm_destroy_conf(handle, conf);
1089*4eaa4710SRishi Srivatsavai 	if (changed && status == DLADM_STATUS_OK) {
1090*4eaa4710SRishi Srivatsavai 		if (bridge[0] == '\0')
1091*4eaa4710SRishi Srivatsavai 			bridge = oldbridge;
1092*4eaa4710SRishi Srivatsavai 		status = bridge_refresh(bridge);
1093*4eaa4710SRishi Srivatsavai 	}
1094*4eaa4710SRishi Srivatsavai 	return (status);
1095*4eaa4710SRishi Srivatsavai }
1096*4eaa4710SRishi Srivatsavai 
1097*4eaa4710SRishi Srivatsavai /*
1098*4eaa4710SRishi Srivatsavai  * Get the name of the bridge of which the given linkid is a member.
1099*4eaa4710SRishi Srivatsavai  */
1100*4eaa4710SRishi Srivatsavai dladm_status_t
1101*4eaa4710SRishi Srivatsavai dladm_bridge_getlink(dladm_handle_t handle, datalink_id_t linkid, char *bridge,
1102*4eaa4710SRishi Srivatsavai     size_t bridgelen)
1103*4eaa4710SRishi Srivatsavai {
1104*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
1105*4eaa4710SRishi Srivatsavai 	dladm_conf_t conf;
1106*4eaa4710SRishi Srivatsavai 
1107*4eaa4710SRishi Srivatsavai 	if ((status = dladm_read_conf(handle, linkid, &conf)) !=
1108*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK)
1109*4eaa4710SRishi Srivatsavai 		return (status);
1110*4eaa4710SRishi Srivatsavai 
1111*4eaa4710SRishi Srivatsavai 	*bridge = '\0';
1112*4eaa4710SRishi Srivatsavai 	status = dladm_get_conf_field(handle, conf, FBRIDGE, bridge, bridgelen);
1113*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK && *bridge == '\0')
1114*4eaa4710SRishi Srivatsavai 		status = DLADM_STATUS_NOTFOUND;
1115*4eaa4710SRishi Srivatsavai 
1116*4eaa4710SRishi Srivatsavai 	dladm_destroy_conf(handle, conf);
1117*4eaa4710SRishi Srivatsavai 	return (status);
1118*4eaa4710SRishi Srivatsavai }
1119*4eaa4710SRishi Srivatsavai 
1120*4eaa4710SRishi Srivatsavai dladm_status_t
1121*4eaa4710SRishi Srivatsavai dladm_bridge_refresh(dladm_handle_t handle, datalink_id_t linkid)
1122*4eaa4710SRishi Srivatsavai {
1123*4eaa4710SRishi Srivatsavai 	char bridge[MAXLINKNAMELEN];
1124*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
1125*4eaa4710SRishi Srivatsavai 
1126*4eaa4710SRishi Srivatsavai 	status = dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge));
1127*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_NOTFOUND)
1128*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_OK);
1129*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK)
1130*4eaa4710SRishi Srivatsavai 		status = bridge_refresh(bridge);
1131*4eaa4710SRishi Srivatsavai 	return (status);
1132*4eaa4710SRishi Srivatsavai }
1133*4eaa4710SRishi Srivatsavai 
1134*4eaa4710SRishi Srivatsavai typedef struct bridge_held_arg_s {
1135*4eaa4710SRishi Srivatsavai 	const char	*bha_bridge;
1136*4eaa4710SRishi Srivatsavai 	boolean_t	bha_isheld;
1137*4eaa4710SRishi Srivatsavai } bridge_held_arg_t;
1138*4eaa4710SRishi Srivatsavai 
1139*4eaa4710SRishi Srivatsavai static int
1140*4eaa4710SRishi Srivatsavai i_dladm_bridge_is_held(dladm_handle_t handle, datalink_id_t linkid, void *arg)
1141*4eaa4710SRishi Srivatsavai {
1142*4eaa4710SRishi Srivatsavai 	dladm_status_t status = DLADM_STATUS_FAILED;
1143*4eaa4710SRishi Srivatsavai 	dladm_conf_t conf;
1144*4eaa4710SRishi Srivatsavai 	char bridge[MAXLINKNAMELEN];
1145*4eaa4710SRishi Srivatsavai 	bridge_held_arg_t	*bha = arg;
1146*4eaa4710SRishi Srivatsavai 
1147*4eaa4710SRishi Srivatsavai 	if ((status = dladm_read_conf(handle, linkid, &conf)) !=
1148*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK)
1149*4eaa4710SRishi Srivatsavai 		return (DLADM_WALK_CONTINUE);
1150*4eaa4710SRishi Srivatsavai 	status = dladm_get_conf_field(handle, conf, FBRIDGE, bridge,
1151*4eaa4710SRishi Srivatsavai 	    sizeof (bridge));
1152*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK && strcmp(bha->bha_bridge, bridge) == 0) {
1153*4eaa4710SRishi Srivatsavai 		bha->bha_isheld = B_TRUE;
1154*4eaa4710SRishi Srivatsavai 		dladm_destroy_conf(handle, conf);
1155*4eaa4710SRishi Srivatsavai 		return (DLADM_WALK_TERMINATE);
1156*4eaa4710SRishi Srivatsavai 	} else {
1157*4eaa4710SRishi Srivatsavai 		dladm_destroy_conf(handle, conf);
1158*4eaa4710SRishi Srivatsavai 		return (DLADM_WALK_CONTINUE);
1159*4eaa4710SRishi Srivatsavai 	}
1160*4eaa4710SRishi Srivatsavai }
1161*4eaa4710SRishi Srivatsavai 
1162*4eaa4710SRishi Srivatsavai /*
1163*4eaa4710SRishi Srivatsavai  * Delete a previously created bridge.
1164*4eaa4710SRishi Srivatsavai  */
1165*4eaa4710SRishi Srivatsavai dladm_status_t
1166*4eaa4710SRishi Srivatsavai dladm_bridge_delete(dladm_handle_t handle, const char *bridge, uint32_t flags)
1167*4eaa4710SRishi Srivatsavai {
1168*4eaa4710SRishi Srivatsavai 	datalink_id_t linkid;
1169*4eaa4710SRishi Srivatsavai 	datalink_class_t class;
1170*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
1171*4eaa4710SRishi Srivatsavai 	char linkname[MAXLINKNAMELEN];
1172*4eaa4710SRishi Srivatsavai 
1173*4eaa4710SRishi Srivatsavai 	if (!dladm_valid_bridgename(bridge))
1174*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_LINKINVAL);
1175*4eaa4710SRishi Srivatsavai 
1176*4eaa4710SRishi Srivatsavai 	/* Get the datalink ID for this bridge */
1177*4eaa4710SRishi Srivatsavai 	(void) snprintf(linkname, sizeof (linkname), "%s0", bridge);
1178*4eaa4710SRishi Srivatsavai 	if (dladm_name2info(handle, linkname, &linkid, NULL, NULL, NULL) !=
1179*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK)
1180*4eaa4710SRishi Srivatsavai 		linkid = DATALINK_INVALID_LINKID;
1181*4eaa4710SRishi Srivatsavai 	else if (dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
1182*4eaa4710SRishi Srivatsavai 	    NULL, 0) != DLADM_STATUS_OK)
1183*4eaa4710SRishi Srivatsavai 		linkid = DATALINK_INVALID_LINKID;
1184*4eaa4710SRishi Srivatsavai 	else if (class != DATALINK_CLASS_BRIDGE)
1185*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_BADARG);
1186*4eaa4710SRishi Srivatsavai 
1187*4eaa4710SRishi Srivatsavai 	if ((flags & DLADM_OPT_ACTIVE) && linkid == DATALINK_INVALID_LINKID)
1188*4eaa4710SRishi Srivatsavai 		return (DLADM_STATUS_BADARG);
1189*4eaa4710SRishi Srivatsavai 
1190*4eaa4710SRishi Srivatsavai 	if (flags & DLADM_OPT_PERSIST) {
1191*4eaa4710SRishi Srivatsavai 		bridge_held_arg_t arg;
1192*4eaa4710SRishi Srivatsavai 
1193*4eaa4710SRishi Srivatsavai 		arg.bha_bridge = bridge;
1194*4eaa4710SRishi Srivatsavai 		arg.bha_isheld = B_FALSE;
1195*4eaa4710SRishi Srivatsavai 
1196*4eaa4710SRishi Srivatsavai 		/*
1197*4eaa4710SRishi Srivatsavai 		 * See whether there are any persistent links using this
1198*4eaa4710SRishi Srivatsavai 		 * bridge.  If so, we fail the operation.
1199*4eaa4710SRishi Srivatsavai 		 */
1200*4eaa4710SRishi Srivatsavai 		(void) dladm_walk_datalink_id(i_dladm_bridge_is_held, handle,
1201*4eaa4710SRishi Srivatsavai 		    &arg, DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR |
1202*4eaa4710SRishi Srivatsavai 		    DATALINK_CLASS_ETHERSTUB | DATALINK_CLASS_SIMNET,
1203*4eaa4710SRishi Srivatsavai 		    DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
1204*4eaa4710SRishi Srivatsavai 		if (arg.bha_isheld)
1205*4eaa4710SRishi Srivatsavai 			return (DLADM_STATUS_LINKBUSY);
1206*4eaa4710SRishi Srivatsavai 	}
1207*4eaa4710SRishi Srivatsavai 
1208*4eaa4710SRishi Srivatsavai 	if ((status = disable_trill(bridge, flags)) != DLADM_STATUS_OK)
1209*4eaa4710SRishi Srivatsavai 		goto out;
1210*4eaa4710SRishi Srivatsavai 
1211*4eaa4710SRishi Srivatsavai 	/* Disable or remove the SMF instance */
1212*4eaa4710SRishi Srivatsavai 	status = shut_down_instance(BRIDGE_SVC_NAME, bridge, flags);
1213*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
1214*4eaa4710SRishi Srivatsavai 		goto out;
1215*4eaa4710SRishi Srivatsavai 
1216*4eaa4710SRishi Srivatsavai 	if (flags & DLADM_OPT_ACTIVE) {
1217*4eaa4710SRishi Srivatsavai 		/*
1218*4eaa4710SRishi Srivatsavai 		 * Delete ACTIVE linkprop now that daemon is gone.
1219*4eaa4710SRishi Srivatsavai 		 */
1220*4eaa4710SRishi Srivatsavai 		(void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0,
1221*4eaa4710SRishi Srivatsavai 		    DLADM_OPT_ACTIVE);
1222*4eaa4710SRishi Srivatsavai 		(void) dladm_destroy_datalink_id(handle, linkid,
1223*4eaa4710SRishi Srivatsavai 		    DLADM_OPT_ACTIVE);
1224*4eaa4710SRishi Srivatsavai 	}
1225*4eaa4710SRishi Srivatsavai 
1226*4eaa4710SRishi Srivatsavai 	if (flags & DLADM_OPT_PERSIST) {
1227*4eaa4710SRishi Srivatsavai 		(void) dladm_remove_conf(handle, linkid);
1228*4eaa4710SRishi Srivatsavai 		(void) dladm_destroy_datalink_id(handle, linkid,
1229*4eaa4710SRishi Srivatsavai 		    DLADM_OPT_PERSIST);
1230*4eaa4710SRishi Srivatsavai 	}
1231*4eaa4710SRishi Srivatsavai 
1232*4eaa4710SRishi Srivatsavai out:
1233*4eaa4710SRishi Srivatsavai 
1234*4eaa4710SRishi Srivatsavai 	return (status);
1235*4eaa4710SRishi Srivatsavai }
1236*4eaa4710SRishi Srivatsavai 
1237*4eaa4710SRishi Srivatsavai /* Check if given name is valid for bridges */
1238*4eaa4710SRishi Srivatsavai boolean_t
1239*4eaa4710SRishi Srivatsavai dladm_valid_bridgename(const char *bridge)
1240*4eaa4710SRishi Srivatsavai {
1241*4eaa4710SRishi Srivatsavai 	size_t		len = strnlen(bridge, MAXLINKNAMELEN);
1242*4eaa4710SRishi Srivatsavai 	const char	*cp;
1243*4eaa4710SRishi Srivatsavai 
1244*4eaa4710SRishi Srivatsavai 	if (len == MAXLINKNAMELEN)
1245*4eaa4710SRishi Srivatsavai 		return (B_FALSE);
1246*4eaa4710SRishi Srivatsavai 
1247*4eaa4710SRishi Srivatsavai 	/*
1248*4eaa4710SRishi Srivatsavai 	 * The bridge name cannot start or end with a digit.
1249*4eaa4710SRishi Srivatsavai 	 */
1250*4eaa4710SRishi Srivatsavai 	if (isdigit(bridge[0]) || isdigit(bridge[len - 1]))
1251*4eaa4710SRishi Srivatsavai 		return (B_FALSE);
1252*4eaa4710SRishi Srivatsavai 
1253*4eaa4710SRishi Srivatsavai 	/*
1254*4eaa4710SRishi Srivatsavai 	 * The legal characters within a bridge name are:
1255*4eaa4710SRishi Srivatsavai 	 * alphanumeric (a-z,  A-Z,  0-9), and the underscore ('_').
1256*4eaa4710SRishi Srivatsavai 	 */
1257*4eaa4710SRishi Srivatsavai 	for (cp = bridge; *cp != '\0'; cp++) {
1258*4eaa4710SRishi Srivatsavai 		if (!isalnum(*cp) && *cp != '_')
1259*4eaa4710SRishi Srivatsavai 			return (B_FALSE);
1260*4eaa4710SRishi Srivatsavai 	}
1261*4eaa4710SRishi Srivatsavai 
1262*4eaa4710SRishi Srivatsavai 	return (B_TRUE);
1263*4eaa4710SRishi Srivatsavai }
1264*4eaa4710SRishi Srivatsavai 
1265*4eaa4710SRishi Srivatsavai /*
1266*4eaa4710SRishi Srivatsavai  * Convert a bridge-related observability node name back into the name of the
1267*4eaa4710SRishi Srivatsavai  * bridge.  Returns B_FALSE without making changes if the input name is not in
1268*4eaa4710SRishi Srivatsavai  * a legal format.
1269*4eaa4710SRishi Srivatsavai  */
1270*4eaa4710SRishi Srivatsavai boolean_t
1271*4eaa4710SRishi Srivatsavai dladm_observe_to_bridge(char *link)
1272*4eaa4710SRishi Srivatsavai {
1273*4eaa4710SRishi Srivatsavai 	int llen;
1274*4eaa4710SRishi Srivatsavai 
1275*4eaa4710SRishi Srivatsavai 	llen = strnlen(link, MAXLINKNAMELEN);
1276*4eaa4710SRishi Srivatsavai 	if (llen < 2 || link[llen - 1] != '0' || isdigit(link[llen - 2]))
1277*4eaa4710SRishi Srivatsavai 		return (B_FALSE);
1278*4eaa4710SRishi Srivatsavai 	link[llen - 1] = '\0';
1279*4eaa4710SRishi Srivatsavai 	return (B_TRUE);
1280*4eaa4710SRishi Srivatsavai }
1281*4eaa4710SRishi Srivatsavai 
1282*4eaa4710SRishi Srivatsavai /*
1283*4eaa4710SRishi Srivatsavai  * Get bridge property values from the running daemon and return them in a
1284*4eaa4710SRishi Srivatsavai  * common structure.
1285*4eaa4710SRishi Srivatsavai  */
1286*4eaa4710SRishi Srivatsavai dladm_status_t
1287*4eaa4710SRishi Srivatsavai dladm_bridge_run_properties(const char *instname, UID_STP_CFG_T *smcfg,
1288*4eaa4710SRishi Srivatsavai     dladm_bridge_prot_t *brprotp)
1289*4eaa4710SRishi Srivatsavai {
1290*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
1291*4eaa4710SRishi Srivatsavai 	bridge_door_cfg_t bdcf;
1292*4eaa4710SRishi Srivatsavai 	bridge_door_cfg_t *bdcfp = &bdcf;
1293*4eaa4710SRishi Srivatsavai 	size_t buflen = sizeof (bdcf);
1294*4eaa4710SRishi Srivatsavai 
1295*4eaa4710SRishi Srivatsavai 	status = bridge_door_call(instname, bdcBridgeGetConfig,
1296*4eaa4710SRishi Srivatsavai 	    DATALINK_INVALID_LINKID, (void **)&bdcfp, 0, &buflen, B_FALSE);
1297*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK) {
1298*4eaa4710SRishi Srivatsavai 		*smcfg = bdcfp->bdcf_cfg;
1299*4eaa4710SRishi Srivatsavai 		*brprotp = bdcfp->bdcf_prot;
1300*4eaa4710SRishi Srivatsavai 	} else {
1301*4eaa4710SRishi Srivatsavai 		smcfg->field_mask = 0;
1302*4eaa4710SRishi Srivatsavai 		*brprotp = DLADM_BRIDGE_PROT_STP;
1303*4eaa4710SRishi Srivatsavai 	}
1304*4eaa4710SRishi Srivatsavai 	return (status);
1305*4eaa4710SRishi Srivatsavai }
1306*4eaa4710SRishi Srivatsavai 
1307*4eaa4710SRishi Srivatsavai /*
1308*4eaa4710SRishi Srivatsavai  * Get bridge state from the running daemon and return in structure borrowed
1309*4eaa4710SRishi Srivatsavai  * from librstp.
1310*4eaa4710SRishi Srivatsavai  */
1311*4eaa4710SRishi Srivatsavai dladm_status_t
1312*4eaa4710SRishi Srivatsavai dladm_bridge_state(const char *instname, UID_STP_STATE_T *statep)
1313*4eaa4710SRishi Srivatsavai {
1314*4eaa4710SRishi Srivatsavai 	size_t buflen = sizeof (*statep);
1315*4eaa4710SRishi Srivatsavai 
1316*4eaa4710SRishi Srivatsavai 	return (bridge_door_call(instname, bdcBridgeGetState,
1317*4eaa4710SRishi Srivatsavai 	    DATALINK_INVALID_LINKID, (void **)&statep, 0, &buflen, B_FALSE));
1318*4eaa4710SRishi Srivatsavai }
1319*4eaa4710SRishi Srivatsavai 
1320*4eaa4710SRishi Srivatsavai /* Returns list of ports (datalink_id_t values) assigned to a bridge instance */
1321*4eaa4710SRishi Srivatsavai datalink_id_t *
1322*4eaa4710SRishi Srivatsavai dladm_bridge_get_portlist(const char *instname, uint_t *nports)
1323*4eaa4710SRishi Srivatsavai {
1324*4eaa4710SRishi Srivatsavai 	size_t buflen = sizeof (int) + MAXPORTS * sizeof (datalink_id_t);
1325*4eaa4710SRishi Srivatsavai 	int *rbuf;
1326*4eaa4710SRishi Srivatsavai 
1327*4eaa4710SRishi Srivatsavai 	if ((rbuf = malloc(buflen)) == NULL)
1328*4eaa4710SRishi Srivatsavai 		return (NULL);
1329*4eaa4710SRishi Srivatsavai 	if (bridge_door_call(instname, bdcBridgeGetPorts,
1330*4eaa4710SRishi Srivatsavai 	    DATALINK_INVALID_LINKID, (void **)&rbuf, 0, &buflen, B_TRUE) !=
1331*4eaa4710SRishi Srivatsavai 	    DLADM_STATUS_OK) {
1332*4eaa4710SRishi Srivatsavai 		free(rbuf);
1333*4eaa4710SRishi Srivatsavai 		return (NULL);
1334*4eaa4710SRishi Srivatsavai 	} else {
1335*4eaa4710SRishi Srivatsavai 		/*
1336*4eaa4710SRishi Srivatsavai 		 * Returns an array of datalink_id_t values for all the ports
1337*4eaa4710SRishi Srivatsavai 		 * part of the bridge instance. First entry in the array is the
1338*4eaa4710SRishi Srivatsavai 		 * number of ports.
1339*4eaa4710SRishi Srivatsavai 		 */
1340*4eaa4710SRishi Srivatsavai 		*nports = *rbuf;
1341*4eaa4710SRishi Srivatsavai 		return ((datalink_id_t *)(rbuf + 1));
1342*4eaa4710SRishi Srivatsavai 	}
1343*4eaa4710SRishi Srivatsavai }
1344*4eaa4710SRishi Srivatsavai 
1345*4eaa4710SRishi Srivatsavai void
1346*4eaa4710SRishi Srivatsavai dladm_bridge_free_portlist(datalink_id_t *dlp)
1347*4eaa4710SRishi Srivatsavai {
1348*4eaa4710SRishi Srivatsavai 	free((int *)dlp - 1);
1349*4eaa4710SRishi Srivatsavai }
1350*4eaa4710SRishi Srivatsavai 
1351*4eaa4710SRishi Srivatsavai /* Retrieve Bridge port configuration values */
1352*4eaa4710SRishi Srivatsavai dladm_status_t
1353*4eaa4710SRishi Srivatsavai dladm_bridge_get_port_cfg(dladm_handle_t handle, datalink_id_t linkid,
1354*4eaa4710SRishi Srivatsavai     int field, int *valuep)
1355*4eaa4710SRishi Srivatsavai {
1356*4eaa4710SRishi Srivatsavai 	UID_STP_PORT_CFG_T portcfg;
1357*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
1358*4eaa4710SRishi Srivatsavai 
1359*4eaa4710SRishi Srivatsavai 	status = port_door_call(handle, linkid, bdcPortGetConfig, &portcfg,
1360*4eaa4710SRishi Srivatsavai 	    0, sizeof (portcfg));
1361*4eaa4710SRishi Srivatsavai 	if (status != DLADM_STATUS_OK)
1362*4eaa4710SRishi Srivatsavai 		return (status);
1363*4eaa4710SRishi Srivatsavai 
1364*4eaa4710SRishi Srivatsavai 	switch (field) {
1365*4eaa4710SRishi Srivatsavai 	case PT_CFG_COST:
1366*4eaa4710SRishi Srivatsavai 		*valuep = portcfg.admin_port_path_cost;
1367*4eaa4710SRishi Srivatsavai 		break;
1368*4eaa4710SRishi Srivatsavai 	case PT_CFG_PRIO:
1369*4eaa4710SRishi Srivatsavai 		*valuep = portcfg.port_priority;
1370*4eaa4710SRishi Srivatsavai 		break;
1371*4eaa4710SRishi Srivatsavai 	case PT_CFG_P2P:
1372*4eaa4710SRishi Srivatsavai 		*valuep = portcfg.admin_point2point;
1373*4eaa4710SRishi Srivatsavai 		break;
1374*4eaa4710SRishi Srivatsavai 	case PT_CFG_EDGE:
1375*4eaa4710SRishi Srivatsavai 		*valuep = portcfg.admin_edge;
1376*4eaa4710SRishi Srivatsavai 		break;
1377*4eaa4710SRishi Srivatsavai 	case PT_CFG_NON_STP:
1378*4eaa4710SRishi Srivatsavai 		*valuep = !portcfg.admin_non_stp;
1379*4eaa4710SRishi Srivatsavai 		break;
1380*4eaa4710SRishi Srivatsavai 	case PT_CFG_MCHECK:
1381*4eaa4710SRishi Srivatsavai 		*valuep = (portcfg.field_mask & PT_CFG_MCHECK) ? 1 : 0;
1382*4eaa4710SRishi Srivatsavai 		break;
1383*4eaa4710SRishi Srivatsavai 	}
1384*4eaa4710SRishi Srivatsavai 	return (status);
1385*4eaa4710SRishi Srivatsavai }
1386*4eaa4710SRishi Srivatsavai 
1387*4eaa4710SRishi Srivatsavai /* Retreive Bridge port status (disabled, bad SDU etc.) */
1388*4eaa4710SRishi Srivatsavai dladm_status_t
1389*4eaa4710SRishi Srivatsavai dladm_bridge_link_state(dladm_handle_t handle, datalink_id_t linkid,
1390*4eaa4710SRishi Srivatsavai     UID_STP_PORT_STATE_T *spsp)
1391*4eaa4710SRishi Srivatsavai {
1392*4eaa4710SRishi Srivatsavai 	return (port_door_call(handle, linkid, bdcPortGetState, spsp, 0,
1393*4eaa4710SRishi Srivatsavai 	    sizeof (*spsp)));
1394*4eaa4710SRishi Srivatsavai }
1395*4eaa4710SRishi Srivatsavai 
1396*4eaa4710SRishi Srivatsavai /* Retrieve Bridge forwarding status of the given link */
1397*4eaa4710SRishi Srivatsavai dladm_status_t
1398*4eaa4710SRishi Srivatsavai dladm_bridge_get_forwarding(dladm_handle_t handle, datalink_id_t linkid,
1399*4eaa4710SRishi Srivatsavai     uint_t *valuep)
1400*4eaa4710SRishi Srivatsavai {
1401*4eaa4710SRishi Srivatsavai 	int twoints[2];
1402*4eaa4710SRishi Srivatsavai 	dladm_status_t status;
1403*4eaa4710SRishi Srivatsavai 
1404*4eaa4710SRishi Srivatsavai 	status = port_door_call(handle, linkid, bdcPortGetForwarding, twoints,
1405*4eaa4710SRishi Srivatsavai 	    0, sizeof (twoints));
1406*4eaa4710SRishi Srivatsavai 	if (status == DLADM_STATUS_OK)
1407*4eaa4710SRishi Srivatsavai 		*valuep = twoints[0];
1408*4eaa4710SRishi Srivatsavai 	return (status);
1409*4eaa4710SRishi Srivatsavai }
1410*4eaa4710SRishi Srivatsavai 
1411*4eaa4710SRishi Srivatsavai /* Retrieve Bridge forwarding table entries */
1412*4eaa4710SRishi Srivatsavai bridge_listfwd_t *
1413*4eaa4710SRishi Srivatsavai dladm_bridge_get_fwdtable(dladm_handle_t handle, const char *bridge,
1414*4eaa4710SRishi Srivatsavai     uint_t *nfwd)
1415*4eaa4710SRishi Srivatsavai {
1416*4eaa4710SRishi Srivatsavai 	bridge_listfwd_t *blf = NULL, *newblf, blfread;
1417*4eaa4710SRishi Srivatsavai 	uint_t nblf = 0, maxblf = 0;
1418*4eaa4710SRishi Srivatsavai 	static uint8_t zero_addr[ETHERADDRL];
1419*4eaa4710SRishi Srivatsavai 	int rc;
1420*4eaa4710SRishi Srivatsavai 
1421*4eaa4710SRishi Srivatsavai 	(void) memset(&blfread, 0, sizeof (blfread));
1422*4eaa4710SRishi Srivatsavai 	(void) snprintf(blfread.blf_name, sizeof (blfread.blf_name),
1423*4eaa4710SRishi Srivatsavai 	    "%s0", bridge);
1424*4eaa4710SRishi Srivatsavai 	for (;;) {
1425*4eaa4710SRishi Srivatsavai 		if (nblf >= maxblf) {
1426*4eaa4710SRishi Srivatsavai 			maxblf = maxblf == 0 ? 64 : (maxblf << 1);
1427*4eaa4710SRishi Srivatsavai 			newblf = realloc(blf, maxblf * sizeof (*blf));
1428*4eaa4710SRishi Srivatsavai 			if (newblf == NULL) {
1429*4eaa4710SRishi Srivatsavai 				free(blf);
1430*4eaa4710SRishi Srivatsavai 				blf = NULL;
1431*4eaa4710SRishi Srivatsavai 				break;
1432*4eaa4710SRishi Srivatsavai 			}
1433*4eaa4710SRishi Srivatsavai 			blf = newblf;
1434*4eaa4710SRishi Srivatsavai 		}
1435*4eaa4710SRishi Srivatsavai 		rc = ioctl(dladm_dld_fd(handle), BRIDGE_IOC_LISTFWD, &blfread);
1436*4eaa4710SRishi Srivatsavai 		if (rc != 0) {
1437*4eaa4710SRishi Srivatsavai 			free(blf);
1438*4eaa4710SRishi Srivatsavai 			blf = NULL;
1439*4eaa4710SRishi Srivatsavai 			break;
1440*4eaa4710SRishi Srivatsavai 		}
1441*4eaa4710SRishi Srivatsavai 		if (memcmp(blfread.blf_dest, zero_addr, ETHERADDRL) == 0)
1442*4eaa4710SRishi Srivatsavai 			break;
1443*4eaa4710SRishi Srivatsavai 		blf[nblf++] = blfread;
1444*4eaa4710SRishi Srivatsavai 	}
1445*4eaa4710SRishi Srivatsavai 	if (blf != NULL)
1446*4eaa4710SRishi Srivatsavai 		*nfwd = nblf;
1447*4eaa4710SRishi Srivatsavai 	return (blf);
1448*4eaa4710SRishi Srivatsavai }
1449*4eaa4710SRishi Srivatsavai 
1450*4eaa4710SRishi Srivatsavai void
1451*4eaa4710SRishi Srivatsavai dladm_bridge_free_fwdtable(bridge_listfwd_t *blf)
1452*4eaa4710SRishi Srivatsavai {
1453*4eaa4710SRishi Srivatsavai 	free(blf);
1454*4eaa4710SRishi Srivatsavai }
1455*4eaa4710SRishi Srivatsavai 
1456*4eaa4710SRishi Srivatsavai /* Retrieve list of TRILL nicknames from the TRILL module */
1457*4eaa4710SRishi Srivatsavai trill_listnick_t *
1458*4eaa4710SRishi Srivatsavai dladm_bridge_get_trillnick(const char *bridge, uint_t *nnick)
1459*4eaa4710SRishi Srivatsavai {
1460*4eaa4710SRishi Srivatsavai 	int fd;
1461*4eaa4710SRishi Srivatsavai 	char brcopy[MAXLINKNAMELEN];
1462*4eaa4710SRishi Srivatsavai 	trill_listnick_t *tln = NULL, *newtln, tlnread;
1463*4eaa4710SRishi Srivatsavai 	uint_t ntln = 0, maxtln = 0;
1464*4eaa4710SRishi Srivatsavai 
1465*4eaa4710SRishi Srivatsavai 	if ((fd = socket(PF_TRILL, SOCK_DGRAM, 0)) == -1)
1466*4eaa4710SRishi Srivatsavai 		return (NULL);
1467*4eaa4710SRishi Srivatsavai 	(void) strlcpy(brcopy, bridge, sizeof (brcopy));
1468*4eaa4710SRishi Srivatsavai 	if (ioctl(fd, TRILL_GETBRIDGE, &brcopy) < 0) {
1469*4eaa4710SRishi Srivatsavai 		(void) close(fd);
1470*4eaa4710SRishi Srivatsavai 		return (NULL);
1471*4eaa4710SRishi Srivatsavai 	}
1472*4eaa4710SRishi Srivatsavai 	(void) memset(&tlnread, 0, sizeof (tlnread));
1473*4eaa4710SRishi Srivatsavai 	for (;;) {
1474*4eaa4710SRishi Srivatsavai 		if (ntln >= maxtln) {
1475*4eaa4710SRishi Srivatsavai 			maxtln = maxtln == 0 ? 64 : (maxtln << 1);
1476*4eaa4710SRishi Srivatsavai 			newtln = realloc(tln, maxtln * sizeof (*tln));
1477*4eaa4710SRishi Srivatsavai 			if (newtln == NULL) {
1478*4eaa4710SRishi Srivatsavai 				free(tln);
1479*4eaa4710SRishi Srivatsavai 				tln = NULL;
1480*4eaa4710SRishi Srivatsavai 				break;
1481*4eaa4710SRishi Srivatsavai 			}
1482*4eaa4710SRishi Srivatsavai 			tln = newtln;
1483*4eaa4710SRishi Srivatsavai 		}
1484*4eaa4710SRishi Srivatsavai 		if (ioctl(fd, TRILL_LISTNICK, &tlnread) == -1) {
1485*4eaa4710SRishi Srivatsavai 			free(tln);
1486*4eaa4710SRishi Srivatsavai 			tln = NULL;
1487*4eaa4710SRishi Srivatsavai 			break;
1488*4eaa4710SRishi Srivatsavai 		}
1489*4eaa4710SRishi Srivatsavai 		if (tlnread.tln_nick == 0)
1490*4eaa4710SRishi Srivatsavai 			break;
1491*4eaa4710SRishi Srivatsavai 		tln[ntln++] = tlnread;
1492*4eaa4710SRishi Srivatsavai 	}
1493*4eaa4710SRishi Srivatsavai 	(void) close(fd);
1494*4eaa4710SRishi Srivatsavai 	if (tln != NULL)
1495*4eaa4710SRishi Srivatsavai 		*nnick = ntln;
1496*4eaa4710SRishi Srivatsavai 	return (tln);
1497*4eaa4710SRishi Srivatsavai }
1498*4eaa4710SRishi Srivatsavai 
1499*4eaa4710SRishi Srivatsavai void
1500*4eaa4710SRishi Srivatsavai dladm_bridge_free_trillnick(trill_listnick_t *tln)
1501*4eaa4710SRishi Srivatsavai {
1502*4eaa4710SRishi Srivatsavai 	free(tln);
1503*4eaa4710SRishi Srivatsavai }
1504*4eaa4710SRishi Srivatsavai 
1505*4eaa4710SRishi Srivatsavai /* Retrieve any stored TRILL nickname from TRILL SMF service */
1506*4eaa4710SRishi Srivatsavai uint16_t
1507*4eaa4710SRishi Srivatsavai dladm_bridge_get_nick(const char *bridge)
1508*4eaa4710SRishi Srivatsavai {
1509*4eaa4710SRishi Srivatsavai 	scf_state_t sstate;
1510*4eaa4710SRishi Srivatsavai 	uint64_t value;
1511*4eaa4710SRishi Srivatsavai 	uint16_t nickname = RBRIDGE_NICKNAME_NONE;
1512*4eaa4710SRishi Srivatsavai 
1513*4eaa4710SRishi Srivatsavai 	if (bind_instance(TRILL_SVC_NAME, bridge, &sstate) != 0)
1514*4eaa4710SRishi Srivatsavai 		return (nickname);
1515*4eaa4710SRishi Srivatsavai 
1516*4eaa4710SRishi Srivatsavai 	if (get_composed_properties("config", B_TRUE, &sstate) == 0 &&
1517*4eaa4710SRishi Srivatsavai 	    get_count("nickname", &sstate, &value) == 0)
1518*4eaa4710SRishi Srivatsavai 		nickname = value;
1519*4eaa4710SRishi Srivatsavai 	shut_down_scf(&sstate);
1520*4eaa4710SRishi Srivatsavai 	return (nickname);
1521*4eaa4710SRishi Srivatsavai }
1522*4eaa4710SRishi Srivatsavai 
1523*4eaa4710SRishi Srivatsavai /* Stores TRILL nickname in SMF configuraiton for the TRILL service */
1524*4eaa4710SRishi Srivatsavai void
1525*4eaa4710SRishi Srivatsavai dladm_bridge_set_nick(const char *bridge, uint16_t nick)
1526*4eaa4710SRishi Srivatsavai {
1527*4eaa4710SRishi Srivatsavai 	scf_state_t sstate;
1528*4eaa4710SRishi Srivatsavai 	scf_transaction_t *tran = NULL;
1529*4eaa4710SRishi Srivatsavai 	boolean_t new_pg = B_FALSE;
1530*4eaa4710SRishi Srivatsavai 	int rv = 0;
1531*4eaa4710SRishi Srivatsavai 	char *fmri;
1532*4eaa4710SRishi Srivatsavai 
1533*4eaa4710SRishi Srivatsavai 	if (exact_instance(TRILL_SVC_NAME, &sstate) != DLADM_STATUS_OK)
1534*4eaa4710SRishi Srivatsavai 		return;
1535*4eaa4710SRishi Srivatsavai 
1536*4eaa4710SRishi Srivatsavai 	if (scf_service_get_instance(sstate.ss_svc, bridge, sstate.ss_inst) !=
1537*4eaa4710SRishi Srivatsavai 	    0)
1538*4eaa4710SRishi Srivatsavai 		goto out;
1539*4eaa4710SRishi Srivatsavai 	if ((tran = scf_transaction_create(sstate.ss_handle)) == NULL)
1540*4eaa4710SRishi Srivatsavai 		goto out;
1541*4eaa4710SRishi Srivatsavai 	if ((sstate.ss_pg = scf_pg_create(sstate.ss_handle)) == NULL)
1542*4eaa4710SRishi Srivatsavai 		goto out;
1543*4eaa4710SRishi Srivatsavai 	if (scf_instance_add_pg(sstate.ss_inst, "config",
1544*4eaa4710SRishi Srivatsavai 	    SCF_GROUP_APPLICATION, 0, sstate.ss_pg) == 0) {
1545*4eaa4710SRishi Srivatsavai 		new_pg = B_TRUE;
1546*4eaa4710SRishi Srivatsavai 	} else if (scf_instance_get_pg(sstate.ss_inst, "config",
1547*4eaa4710SRishi Srivatsavai 	    sstate.ss_pg) != 0) {
1548*4eaa4710SRishi Srivatsavai 		goto out;
1549*4eaa4710SRishi Srivatsavai 	}
1550*4eaa4710SRishi Srivatsavai 	do {
1551*4eaa4710SRishi Srivatsavai 		if (scf_transaction_start(tran, sstate.ss_pg) != 0)
1552*4eaa4710SRishi Srivatsavai 			goto out;
1553*4eaa4710SRishi Srivatsavai 		if (!set_count_property(sstate.ss_handle, tran, "nickname",
1554*4eaa4710SRishi Srivatsavai 		    nick))
1555*4eaa4710SRishi Srivatsavai 			goto out;
1556*4eaa4710SRishi Srivatsavai 		rv = scf_transaction_commit(tran);
1557*4eaa4710SRishi Srivatsavai 		scf_transaction_reset(tran);
1558*4eaa4710SRishi Srivatsavai 		if (rv == 0 && scf_pg_update(sstate.ss_pg) == -1)
1559*4eaa4710SRishi Srivatsavai 			goto out;
1560*4eaa4710SRishi Srivatsavai 	} while (rv == 0);
1561*4eaa4710SRishi Srivatsavai 
1562*4eaa4710SRishi Srivatsavai out:
1563*4eaa4710SRishi Srivatsavai 	if (tran != NULL) {
1564*4eaa4710SRishi Srivatsavai 		scf_transaction_destroy_children(tran);
1565*4eaa4710SRishi Srivatsavai 		scf_transaction_destroy(tran);
1566*4eaa4710SRishi Srivatsavai 	}
1567*4eaa4710SRishi Srivatsavai 
1568*4eaa4710SRishi Srivatsavai 	if (rv != 1 && new_pg)
1569*4eaa4710SRishi Srivatsavai 		(void) scf_pg_delete(sstate.ss_pg);
1570*4eaa4710SRishi Srivatsavai 
1571*4eaa4710SRishi Srivatsavai 	drop_composed(&sstate);
1572*4eaa4710SRishi Srivatsavai 	shut_down_scf(&sstate);
1573*4eaa4710SRishi Srivatsavai 	if (rv == 1 && (fmri = alloc_fmri(TRILL_SVC_NAME, bridge)) != NULL) {
1574*4eaa4710SRishi Srivatsavai 		(void) smf_refresh_instance(fmri);
1575*4eaa4710SRishi Srivatsavai 		free(fmri);
1576*4eaa4710SRishi Srivatsavai 	}
1577*4eaa4710SRishi Srivatsavai }
1578