110491SRishi.Srivatsavai@Sun.COM /*
210491SRishi.Srivatsavai@Sun.COM * CDDL HEADER START
310491SRishi.Srivatsavai@Sun.COM *
410491SRishi.Srivatsavai@Sun.COM * The contents of this file are subject to the terms of the
510491SRishi.Srivatsavai@Sun.COM * Common Development and Distribution License (the "License").
610491SRishi.Srivatsavai@Sun.COM * You may not use this file except in compliance with the License.
710491SRishi.Srivatsavai@Sun.COM *
810491SRishi.Srivatsavai@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910491SRishi.Srivatsavai@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010491SRishi.Srivatsavai@Sun.COM * See the License for the specific language governing permissions
1110491SRishi.Srivatsavai@Sun.COM * and limitations under the License.
1210491SRishi.Srivatsavai@Sun.COM *
1310491SRishi.Srivatsavai@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410491SRishi.Srivatsavai@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510491SRishi.Srivatsavai@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610491SRishi.Srivatsavai@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710491SRishi.Srivatsavai@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810491SRishi.Srivatsavai@Sun.COM *
1910491SRishi.Srivatsavai@Sun.COM * CDDL HEADER END
2010491SRishi.Srivatsavai@Sun.COM */
2110491SRishi.Srivatsavai@Sun.COM /*
22*12824SCathy.Zhou@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2310491SRishi.Srivatsavai@Sun.COM */
2410491SRishi.Srivatsavai@Sun.COM
2510491SRishi.Srivatsavai@Sun.COM #include <stdio.h>
2610491SRishi.Srivatsavai@Sun.COM #include <sys/types.h>
2710491SRishi.Srivatsavai@Sun.COM #include <string.h>
2810491SRishi.Srivatsavai@Sun.COM #include <fcntl.h>
2910491SRishi.Srivatsavai@Sun.COM #include <unistd.h>
3010491SRishi.Srivatsavai@Sun.COM #include <stropts.h>
3110491SRishi.Srivatsavai@Sun.COM #include <ctype.h>
3210491SRishi.Srivatsavai@Sun.COM #include <errno.h>
3310491SRishi.Srivatsavai@Sun.COM #include <stdlib.h>
3410491SRishi.Srivatsavai@Sun.COM #include <door.h>
3510491SRishi.Srivatsavai@Sun.COM #include <sys/mman.h>
3610491SRishi.Srivatsavai@Sun.COM #include <libscf.h>
3710491SRishi.Srivatsavai@Sun.COM #include <libscf_priv.h>
3810491SRishi.Srivatsavai@Sun.COM #include <libdllink.h>
3910491SRishi.Srivatsavai@Sun.COM #include <libdlbridge.h>
4010491SRishi.Srivatsavai@Sun.COM #include <libdladm_impl.h>
4110491SRishi.Srivatsavai@Sun.COM #include <stp_in.h>
4210491SRishi.Srivatsavai@Sun.COM #include <net/bridge.h>
4310491SRishi.Srivatsavai@Sun.COM #include <net/trill.h>
4410491SRishi.Srivatsavai@Sun.COM #include <sys/socket.h>
4510530SRishi.Srivatsavai@Sun.COM #include <sys/dld_ioc.h>
4610491SRishi.Srivatsavai@Sun.COM
4710491SRishi.Srivatsavai@Sun.COM /*
4810491SRishi.Srivatsavai@Sun.COM * Bridge Administration Library.
4910491SRishi.Srivatsavai@Sun.COM *
5010491SRishi.Srivatsavai@Sun.COM * This library is used by administration tools such as dladm(1M) to configure
5110491SRishi.Srivatsavai@Sun.COM * bridges, and by the bridge daemon to retrieve configuration information.
5210491SRishi.Srivatsavai@Sun.COM */
5310491SRishi.Srivatsavai@Sun.COM
5410491SRishi.Srivatsavai@Sun.COM #define BRIDGE_SVC_NAME "network/bridge"
5510491SRishi.Srivatsavai@Sun.COM #define TRILL_SVC_NAME "network/routing/trill"
5610491SRishi.Srivatsavai@Sun.COM
5710491SRishi.Srivatsavai@Sun.COM #define DEFAULT_TIMEOUT 60000000
5810491SRishi.Srivatsavai@Sun.COM #define INIT_WAIT_USECS 50000
5910491SRishi.Srivatsavai@Sun.COM #define MAXPORTS 256
6010491SRishi.Srivatsavai@Sun.COM
6110491SRishi.Srivatsavai@Sun.COM typedef struct scf_state {
6210491SRishi.Srivatsavai@Sun.COM scf_handle_t *ss_handle;
6310491SRishi.Srivatsavai@Sun.COM scf_instance_t *ss_inst;
6410491SRishi.Srivatsavai@Sun.COM scf_service_t *ss_svc;
6510491SRishi.Srivatsavai@Sun.COM scf_snapshot_t *ss_snap;
6610491SRishi.Srivatsavai@Sun.COM scf_propertygroup_t *ss_pg;
6710491SRishi.Srivatsavai@Sun.COM scf_property_t *ss_prop;
6810491SRishi.Srivatsavai@Sun.COM } scf_state_t;
6910491SRishi.Srivatsavai@Sun.COM
7010491SRishi.Srivatsavai@Sun.COM static void
shut_down_scf(scf_state_t * sstate)7110491SRishi.Srivatsavai@Sun.COM shut_down_scf(scf_state_t *sstate)
7210491SRishi.Srivatsavai@Sun.COM {
7310491SRishi.Srivatsavai@Sun.COM scf_instance_destroy(sstate->ss_inst);
7410491SRishi.Srivatsavai@Sun.COM (void) scf_handle_unbind(sstate->ss_handle);
7510491SRishi.Srivatsavai@Sun.COM scf_handle_destroy(sstate->ss_handle);
7610491SRishi.Srivatsavai@Sun.COM }
7710491SRishi.Srivatsavai@Sun.COM
7810491SRishi.Srivatsavai@Sun.COM static char *
alloc_fmri(const char * service,const char * instance_name)7910491SRishi.Srivatsavai@Sun.COM alloc_fmri(const char *service, const char *instance_name)
8010491SRishi.Srivatsavai@Sun.COM {
8110491SRishi.Srivatsavai@Sun.COM ssize_t max_fmri;
8210491SRishi.Srivatsavai@Sun.COM char *fmri;
8310491SRishi.Srivatsavai@Sun.COM
8410491SRishi.Srivatsavai@Sun.COM /* If the limit is unknown, then use an arbitrary value */
8510491SRishi.Srivatsavai@Sun.COM if ((max_fmri = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH)) == -1)
8610491SRishi.Srivatsavai@Sun.COM max_fmri = 1024;
8710491SRishi.Srivatsavai@Sun.COM if ((fmri = malloc(max_fmri)) != NULL) {
8810491SRishi.Srivatsavai@Sun.COM (void) snprintf(fmri, max_fmri, "svc:/%s:%s", service,
8910491SRishi.Srivatsavai@Sun.COM instance_name);
9010491SRishi.Srivatsavai@Sun.COM }
9110491SRishi.Srivatsavai@Sun.COM return (fmri);
9210491SRishi.Srivatsavai@Sun.COM }
9310491SRishi.Srivatsavai@Sun.COM
9410491SRishi.Srivatsavai@Sun.COM /*
9510491SRishi.Srivatsavai@Sun.COM * Start up SCF and bind the requested instance alone.
9610491SRishi.Srivatsavai@Sun.COM */
9710491SRishi.Srivatsavai@Sun.COM static int
bind_instance(const char * service,const char * instance_name,scf_state_t * sstate)9810491SRishi.Srivatsavai@Sun.COM bind_instance(const char *service, const char *instance_name,
9910491SRishi.Srivatsavai@Sun.COM scf_state_t *sstate)
10010491SRishi.Srivatsavai@Sun.COM {
10110491SRishi.Srivatsavai@Sun.COM char *fmri = NULL;
10210491SRishi.Srivatsavai@Sun.COM
10310491SRishi.Srivatsavai@Sun.COM (void) memset(sstate, 0, sizeof (*sstate));
10410491SRishi.Srivatsavai@Sun.COM
10510491SRishi.Srivatsavai@Sun.COM if ((sstate->ss_handle = scf_handle_create(SCF_VERSION)) == NULL)
10610491SRishi.Srivatsavai@Sun.COM return (-1);
10710491SRishi.Srivatsavai@Sun.COM
10810491SRishi.Srivatsavai@Sun.COM if (scf_handle_bind(sstate->ss_handle) != 0)
10910491SRishi.Srivatsavai@Sun.COM goto failure;
11010491SRishi.Srivatsavai@Sun.COM sstate->ss_inst = scf_instance_create(sstate->ss_handle);
11110491SRishi.Srivatsavai@Sun.COM if (sstate->ss_inst == NULL)
11210491SRishi.Srivatsavai@Sun.COM goto failure;
11310491SRishi.Srivatsavai@Sun.COM
11410491SRishi.Srivatsavai@Sun.COM fmri = alloc_fmri(service, instance_name);
11510491SRishi.Srivatsavai@Sun.COM
11610491SRishi.Srivatsavai@Sun.COM if (scf_handle_decode_fmri(sstate->ss_handle, fmri, NULL, NULL,
11710491SRishi.Srivatsavai@Sun.COM sstate->ss_inst, NULL, NULL,
11810491SRishi.Srivatsavai@Sun.COM SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0)
11910491SRishi.Srivatsavai@Sun.COM goto failure;
12010491SRishi.Srivatsavai@Sun.COM free(fmri);
12110491SRishi.Srivatsavai@Sun.COM return (0);
12210491SRishi.Srivatsavai@Sun.COM
12310491SRishi.Srivatsavai@Sun.COM failure:
12410491SRishi.Srivatsavai@Sun.COM free(fmri);
12510491SRishi.Srivatsavai@Sun.COM shut_down_scf(sstate);
12610491SRishi.Srivatsavai@Sun.COM return (-1);
12710491SRishi.Srivatsavai@Sun.COM }
12810491SRishi.Srivatsavai@Sun.COM
12910491SRishi.Srivatsavai@Sun.COM /*
13010491SRishi.Srivatsavai@Sun.COM * Start up SCF and an exact FMRI. This is used for creating new instances and
13110491SRishi.Srivatsavai@Sun.COM * enable/disable actions.
13210491SRishi.Srivatsavai@Sun.COM */
13310491SRishi.Srivatsavai@Sun.COM static dladm_status_t
exact_instance(const char * fmri,scf_state_t * sstate)13410491SRishi.Srivatsavai@Sun.COM exact_instance(const char *fmri, scf_state_t *sstate)
13510491SRishi.Srivatsavai@Sun.COM {
13610491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
13710491SRishi.Srivatsavai@Sun.COM
13810491SRishi.Srivatsavai@Sun.COM (void) memset(sstate, 0, sizeof (*sstate));
13910491SRishi.Srivatsavai@Sun.COM
14010491SRishi.Srivatsavai@Sun.COM if ((sstate->ss_handle = scf_handle_create(SCF_VERSION)) == NULL)
14110491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_NOMEM);
14210491SRishi.Srivatsavai@Sun.COM
14310491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_FAILED;
14410491SRishi.Srivatsavai@Sun.COM if (scf_handle_bind(sstate->ss_handle) != 0)
14510491SRishi.Srivatsavai@Sun.COM goto failure;
14610491SRishi.Srivatsavai@Sun.COM sstate->ss_svc = scf_service_create(sstate->ss_handle);
14710491SRishi.Srivatsavai@Sun.COM if (sstate->ss_svc == NULL)
14810491SRishi.Srivatsavai@Sun.COM goto failure;
14910491SRishi.Srivatsavai@Sun.COM if (scf_handle_decode_fmri(sstate->ss_handle, fmri, NULL,
15010491SRishi.Srivatsavai@Sun.COM sstate->ss_svc, NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) {
15110491SRishi.Srivatsavai@Sun.COM if (scf_error() == SCF_ERROR_NOT_FOUND)
15210491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_OPTMISSING;
15310491SRishi.Srivatsavai@Sun.COM goto failure;
15410491SRishi.Srivatsavai@Sun.COM }
15510491SRishi.Srivatsavai@Sun.COM sstate->ss_inst = scf_instance_create(sstate->ss_handle);
15610491SRishi.Srivatsavai@Sun.COM if (sstate->ss_inst == NULL)
15710491SRishi.Srivatsavai@Sun.COM goto failure;
15810491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OK);
15910491SRishi.Srivatsavai@Sun.COM
16010491SRishi.Srivatsavai@Sun.COM failure:
16110491SRishi.Srivatsavai@Sun.COM shut_down_scf(sstate);
16210491SRishi.Srivatsavai@Sun.COM return (status);
16310491SRishi.Srivatsavai@Sun.COM }
16410491SRishi.Srivatsavai@Sun.COM
16510491SRishi.Srivatsavai@Sun.COM static void
drop_composed(scf_state_t * sstate)16610491SRishi.Srivatsavai@Sun.COM drop_composed(scf_state_t *sstate)
16710491SRishi.Srivatsavai@Sun.COM {
16810491SRishi.Srivatsavai@Sun.COM scf_property_destroy(sstate->ss_prop);
16910491SRishi.Srivatsavai@Sun.COM scf_pg_destroy(sstate->ss_pg);
17010491SRishi.Srivatsavai@Sun.COM scf_snapshot_destroy(sstate->ss_snap);
17110491SRishi.Srivatsavai@Sun.COM }
17210491SRishi.Srivatsavai@Sun.COM
17310491SRishi.Srivatsavai@Sun.COM /*
17410491SRishi.Srivatsavai@Sun.COM * This function sets up a composed view of the configuration information for
17510491SRishi.Srivatsavai@Sun.COM * the specified instance. When this is done, the get_property() function
17610491SRishi.Srivatsavai@Sun.COM * should be able to return individual parameters.
17710491SRishi.Srivatsavai@Sun.COM */
17810491SRishi.Srivatsavai@Sun.COM static int
get_composed_properties(const char * lpg,boolean_t snap,scf_state_t * sstate)17910491SRishi.Srivatsavai@Sun.COM get_composed_properties(const char *lpg, boolean_t snap, scf_state_t *sstate)
18010491SRishi.Srivatsavai@Sun.COM {
18110491SRishi.Srivatsavai@Sun.COM sstate->ss_snap = NULL;
18210491SRishi.Srivatsavai@Sun.COM sstate->ss_pg = NULL;
18310491SRishi.Srivatsavai@Sun.COM sstate->ss_prop = NULL;
18410491SRishi.Srivatsavai@Sun.COM
18510491SRishi.Srivatsavai@Sun.COM if (snap) {
18610491SRishi.Srivatsavai@Sun.COM sstate->ss_snap = scf_snapshot_create(sstate->ss_handle);
18710491SRishi.Srivatsavai@Sun.COM if (sstate->ss_snap == NULL)
18810491SRishi.Srivatsavai@Sun.COM goto failure;
18910491SRishi.Srivatsavai@Sun.COM if (scf_instance_get_snapshot(sstate->ss_inst, "running",
19010491SRishi.Srivatsavai@Sun.COM sstate->ss_snap) != 0)
19110491SRishi.Srivatsavai@Sun.COM goto failure;
19210491SRishi.Srivatsavai@Sun.COM }
19310491SRishi.Srivatsavai@Sun.COM if ((sstate->ss_pg = scf_pg_create(sstate->ss_handle)) == NULL)
19410491SRishi.Srivatsavai@Sun.COM goto failure;
19510491SRishi.Srivatsavai@Sun.COM if (scf_instance_get_pg_composed(sstate->ss_inst, sstate->ss_snap, lpg,
19610491SRishi.Srivatsavai@Sun.COM sstate->ss_pg) != 0)
19710491SRishi.Srivatsavai@Sun.COM goto failure;
19810491SRishi.Srivatsavai@Sun.COM if ((sstate->ss_prop = scf_property_create(sstate->ss_handle)) ==
19910491SRishi.Srivatsavai@Sun.COM NULL)
20010491SRishi.Srivatsavai@Sun.COM goto failure;
20110491SRishi.Srivatsavai@Sun.COM return (0);
20210491SRishi.Srivatsavai@Sun.COM
20310491SRishi.Srivatsavai@Sun.COM failure:
20410491SRishi.Srivatsavai@Sun.COM drop_composed(sstate);
20510491SRishi.Srivatsavai@Sun.COM return (-1);
20610491SRishi.Srivatsavai@Sun.COM }
20710491SRishi.Srivatsavai@Sun.COM
20810491SRishi.Srivatsavai@Sun.COM static int
get_count(const char * lprop,scf_state_t * sstate,uint64_t * answer)20910491SRishi.Srivatsavai@Sun.COM get_count(const char *lprop, scf_state_t *sstate, uint64_t *answer)
21010491SRishi.Srivatsavai@Sun.COM {
21110491SRishi.Srivatsavai@Sun.COM scf_value_t *val;
21210491SRishi.Srivatsavai@Sun.COM int retv;
21310491SRishi.Srivatsavai@Sun.COM
21410491SRishi.Srivatsavai@Sun.COM if (scf_pg_get_property(sstate->ss_pg, lprop, sstate->ss_prop) != 0)
21510491SRishi.Srivatsavai@Sun.COM return (-1);
21610491SRishi.Srivatsavai@Sun.COM if ((val = scf_value_create(sstate->ss_handle)) == NULL)
21710491SRishi.Srivatsavai@Sun.COM return (-1);
21810491SRishi.Srivatsavai@Sun.COM
21910491SRishi.Srivatsavai@Sun.COM if (scf_property_get_value(sstate->ss_prop, val) == 0 &&
22010491SRishi.Srivatsavai@Sun.COM scf_value_get_count(val, answer) == 0)
22110491SRishi.Srivatsavai@Sun.COM retv = 0;
22210491SRishi.Srivatsavai@Sun.COM else
22310491SRishi.Srivatsavai@Sun.COM retv = -1;
22410491SRishi.Srivatsavai@Sun.COM scf_value_destroy(val);
22510491SRishi.Srivatsavai@Sun.COM return (retv);
22610491SRishi.Srivatsavai@Sun.COM }
22710491SRishi.Srivatsavai@Sun.COM
22810491SRishi.Srivatsavai@Sun.COM static int
get_boolean(const char * lprop,scf_state_t * sstate,boolean_t * answer)22910491SRishi.Srivatsavai@Sun.COM get_boolean(const char *lprop, scf_state_t *sstate, boolean_t *answer)
23010491SRishi.Srivatsavai@Sun.COM {
23110491SRishi.Srivatsavai@Sun.COM scf_value_t *val;
23210491SRishi.Srivatsavai@Sun.COM int retv;
23310491SRishi.Srivatsavai@Sun.COM uint8_t bval;
23410491SRishi.Srivatsavai@Sun.COM
23510491SRishi.Srivatsavai@Sun.COM if (scf_pg_get_property(sstate->ss_pg, lprop, sstate->ss_prop) != 0)
23610491SRishi.Srivatsavai@Sun.COM return (-1);
23710491SRishi.Srivatsavai@Sun.COM if ((val = scf_value_create(sstate->ss_handle)) == NULL)
23810491SRishi.Srivatsavai@Sun.COM return (-1);
23910491SRishi.Srivatsavai@Sun.COM
24010491SRishi.Srivatsavai@Sun.COM if (scf_property_get_value(sstate->ss_prop, val) == 0 &&
24110491SRishi.Srivatsavai@Sun.COM scf_value_get_boolean(val, &bval) == 0) {
24210491SRishi.Srivatsavai@Sun.COM retv = 0;
24310491SRishi.Srivatsavai@Sun.COM *answer = bval != 0;
24410491SRishi.Srivatsavai@Sun.COM } else {
24510491SRishi.Srivatsavai@Sun.COM retv = -1;
24610491SRishi.Srivatsavai@Sun.COM }
24710491SRishi.Srivatsavai@Sun.COM scf_value_destroy(val);
24810491SRishi.Srivatsavai@Sun.COM return (retv);
24910491SRishi.Srivatsavai@Sun.COM }
25010491SRishi.Srivatsavai@Sun.COM
25110491SRishi.Srivatsavai@Sun.COM static dladm_status_t
bridge_door_call(const char * instname,bridge_door_type_t dtype,datalink_id_t linkid,void ** bufp,size_t inlen,size_t * buflenp,boolean_t is_list)25210491SRishi.Srivatsavai@Sun.COM bridge_door_call(const char *instname, bridge_door_type_t dtype,
25310491SRishi.Srivatsavai@Sun.COM datalink_id_t linkid, void **bufp, size_t inlen, size_t *buflenp,
25410491SRishi.Srivatsavai@Sun.COM boolean_t is_list)
25510491SRishi.Srivatsavai@Sun.COM {
25610491SRishi.Srivatsavai@Sun.COM char doorname[MAXPATHLEN];
25710491SRishi.Srivatsavai@Sun.COM int did, retv, etmp;
25810491SRishi.Srivatsavai@Sun.COM bridge_door_cmd_t *bdc;
25910491SRishi.Srivatsavai@Sun.COM door_arg_t arg;
26010491SRishi.Srivatsavai@Sun.COM
26110491SRishi.Srivatsavai@Sun.COM (void) snprintf(doorname, sizeof (doorname), "%s/%s", DOOR_DIRNAME,
26210491SRishi.Srivatsavai@Sun.COM instname);
26310491SRishi.Srivatsavai@Sun.COM
26410491SRishi.Srivatsavai@Sun.COM /* Knock on the door */
26510491SRishi.Srivatsavai@Sun.COM did = open(doorname, O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
26610491SRishi.Srivatsavai@Sun.COM if (did == -1)
26710491SRishi.Srivatsavai@Sun.COM return (dladm_errno2status(errno));
26810491SRishi.Srivatsavai@Sun.COM
26910491SRishi.Srivatsavai@Sun.COM if ((bdc = malloc(sizeof (*bdc) + inlen)) == NULL) {
27010491SRishi.Srivatsavai@Sun.COM (void) close(did);
27110491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_NOMEM);
27210491SRishi.Srivatsavai@Sun.COM }
27310491SRishi.Srivatsavai@Sun.COM bdc->bdc_type = dtype;
27410491SRishi.Srivatsavai@Sun.COM bdc->bdc_linkid = linkid;
27510491SRishi.Srivatsavai@Sun.COM if (inlen != 0)
27610491SRishi.Srivatsavai@Sun.COM (void) memcpy(bdc + 1, *bufp, inlen);
27710491SRishi.Srivatsavai@Sun.COM
27810491SRishi.Srivatsavai@Sun.COM (void) memset(&arg, 0, sizeof (arg));
27910491SRishi.Srivatsavai@Sun.COM arg.data_ptr = (char *)bdc;
28010491SRishi.Srivatsavai@Sun.COM arg.data_size = sizeof (*bdc) + inlen;
28110491SRishi.Srivatsavai@Sun.COM arg.rbuf = *bufp;
28210491SRishi.Srivatsavai@Sun.COM arg.rsize = *buflenp;
28310491SRishi.Srivatsavai@Sun.COM
28410491SRishi.Srivatsavai@Sun.COM /* The door_call function doesn't restart, so take care of that */
28510491SRishi.Srivatsavai@Sun.COM do {
28610491SRishi.Srivatsavai@Sun.COM errno = 0;
28710491SRishi.Srivatsavai@Sun.COM if ((retv = door_call(did, &arg)) == 0)
28810491SRishi.Srivatsavai@Sun.COM break;
28910491SRishi.Srivatsavai@Sun.COM } while (errno == EINTR);
29010491SRishi.Srivatsavai@Sun.COM
29110491SRishi.Srivatsavai@Sun.COM /* If we get an unexpected response, then return an error */
29210491SRishi.Srivatsavai@Sun.COM if (retv == 0) {
29310491SRishi.Srivatsavai@Sun.COM /* The daemon returns a single int for errors */
29410491SRishi.Srivatsavai@Sun.COM /* LINTED: pointer alignment */
29510491SRishi.Srivatsavai@Sun.COM if (arg.data_size == sizeof (int) && *(int *)arg.rbuf != 0) {
29610491SRishi.Srivatsavai@Sun.COM retv = -1;
29710491SRishi.Srivatsavai@Sun.COM /* LINTED: pointer alignment */
29810491SRishi.Srivatsavai@Sun.COM errno = *(int *)arg.rbuf;
29910491SRishi.Srivatsavai@Sun.COM }
30010491SRishi.Srivatsavai@Sun.COM /* Terminated daemon returns with zero data */
30110491SRishi.Srivatsavai@Sun.COM if (arg.data_size == 0) {
30210491SRishi.Srivatsavai@Sun.COM retv = -1;
30310491SRishi.Srivatsavai@Sun.COM errno = EBADF;
30410491SRishi.Srivatsavai@Sun.COM }
30510491SRishi.Srivatsavai@Sun.COM }
30610491SRishi.Srivatsavai@Sun.COM
30710491SRishi.Srivatsavai@Sun.COM if (retv == 0) {
30810491SRishi.Srivatsavai@Sun.COM if (arg.rbuf != *bufp) {
30910491SRishi.Srivatsavai@Sun.COM if (is_list) {
31010491SRishi.Srivatsavai@Sun.COM void *newp;
31110491SRishi.Srivatsavai@Sun.COM
31210491SRishi.Srivatsavai@Sun.COM newp = realloc(*bufp, arg.data_size);
31310491SRishi.Srivatsavai@Sun.COM if (newp == NULL) {
31410491SRishi.Srivatsavai@Sun.COM retv = -1;
31510491SRishi.Srivatsavai@Sun.COM } else {
31610491SRishi.Srivatsavai@Sun.COM *bufp = newp;
31710491SRishi.Srivatsavai@Sun.COM (void) memcpy(*bufp, arg.rbuf,
31810491SRishi.Srivatsavai@Sun.COM arg.data_size);
31910491SRishi.Srivatsavai@Sun.COM }
32010491SRishi.Srivatsavai@Sun.COM }
32110491SRishi.Srivatsavai@Sun.COM (void) munmap(arg.rbuf, arg.rsize);
32210491SRishi.Srivatsavai@Sun.COM }
32310491SRishi.Srivatsavai@Sun.COM if (is_list) {
32410491SRishi.Srivatsavai@Sun.COM *buflenp = arg.data_size;
32510491SRishi.Srivatsavai@Sun.COM } else if (arg.data_size != *buflenp || arg.rbuf != *bufp) {
32610491SRishi.Srivatsavai@Sun.COM errno = EINVAL;
32710491SRishi.Srivatsavai@Sun.COM retv = -1;
32810491SRishi.Srivatsavai@Sun.COM }
32910491SRishi.Srivatsavai@Sun.COM }
33010491SRishi.Srivatsavai@Sun.COM
33110491SRishi.Srivatsavai@Sun.COM etmp = errno;
33210491SRishi.Srivatsavai@Sun.COM (void) close(did);
33310491SRishi.Srivatsavai@Sun.COM
33410491SRishi.Srivatsavai@Sun.COM /* Revoked door is the same as no door at all */
33510491SRishi.Srivatsavai@Sun.COM if (etmp == EBADF)
33610491SRishi.Srivatsavai@Sun.COM etmp = ENOENT;
33710491SRishi.Srivatsavai@Sun.COM
33810491SRishi.Srivatsavai@Sun.COM return (retv == 0 ? DLADM_STATUS_OK : dladm_errno2status(etmp));
33910491SRishi.Srivatsavai@Sun.COM }
34010491SRishi.Srivatsavai@Sun.COM
34110491SRishi.Srivatsavai@Sun.COM /*
34210491SRishi.Srivatsavai@Sun.COM * Wrapper function for making per-port calls.
34310491SRishi.Srivatsavai@Sun.COM */
34410491SRishi.Srivatsavai@Sun.COM static dladm_status_t
port_door_call(dladm_handle_t handle,datalink_id_t linkid,bridge_door_type_t dtype,void * buf,size_t inlen,size_t buflen)34510491SRishi.Srivatsavai@Sun.COM port_door_call(dladm_handle_t handle, datalink_id_t linkid,
34610491SRishi.Srivatsavai@Sun.COM bridge_door_type_t dtype, void *buf, size_t inlen, size_t buflen)
34710491SRishi.Srivatsavai@Sun.COM {
34810491SRishi.Srivatsavai@Sun.COM char bridge[MAXLINKNAMELEN];
34910491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
35010491SRishi.Srivatsavai@Sun.COM
35110491SRishi.Srivatsavai@Sun.COM status = dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge));
35210491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK)
35310491SRishi.Srivatsavai@Sun.COM return (status);
35410491SRishi.Srivatsavai@Sun.COM return (bridge_door_call(bridge, dtype, linkid, &buf, inlen, &buflen,
35510491SRishi.Srivatsavai@Sun.COM B_FALSE));
35610491SRishi.Srivatsavai@Sun.COM }
35710491SRishi.Srivatsavai@Sun.COM
35810491SRishi.Srivatsavai@Sun.COM static dladm_status_t
bridge_refresh(const char * bridge)35910491SRishi.Srivatsavai@Sun.COM bridge_refresh(const char *bridge)
36010491SRishi.Srivatsavai@Sun.COM {
36110491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
36210491SRishi.Srivatsavai@Sun.COM int twoints[2];
36310491SRishi.Srivatsavai@Sun.COM void *bdptr;
36410491SRishi.Srivatsavai@Sun.COM size_t buflen;
36510491SRishi.Srivatsavai@Sun.COM char *fmri;
36610491SRishi.Srivatsavai@Sun.COM int refresh_count;
36710491SRishi.Srivatsavai@Sun.COM
36810491SRishi.Srivatsavai@Sun.COM buflen = sizeof (twoints);
36910491SRishi.Srivatsavai@Sun.COM bdptr = twoints;
37010491SRishi.Srivatsavai@Sun.COM status = bridge_door_call(bridge, bdcBridgeGetRefreshCount,
37110491SRishi.Srivatsavai@Sun.COM DATALINK_INVALID_LINKID, &bdptr, 0, &buflen, B_FALSE);
37210491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_NOTFOUND)
37310491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OK);
37410491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK)
37510491SRishi.Srivatsavai@Sun.COM return (status);
37610491SRishi.Srivatsavai@Sun.COM refresh_count = twoints[0];
37710491SRishi.Srivatsavai@Sun.COM if ((fmri = alloc_fmri(BRIDGE_SVC_NAME, bridge)) == NULL)
37810491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_NOMEM);
37910491SRishi.Srivatsavai@Sun.COM status = smf_refresh_instance(fmri) == 0 ?
38010491SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK : DLADM_STATUS_FAILED;
38110491SRishi.Srivatsavai@Sun.COM free(fmri);
38210491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK) {
38310491SRishi.Srivatsavai@Sun.COM int i = 0;
38410491SRishi.Srivatsavai@Sun.COM
38510491SRishi.Srivatsavai@Sun.COM /*
38610491SRishi.Srivatsavai@Sun.COM * SMF doesn't give any synchronous behavior or dependency
38710491SRishi.Srivatsavai@Sun.COM * ordering for refresh operations, so we have to invent our
38810491SRishi.Srivatsavai@Sun.COM * own mechanism here. Get the refresh counter from the
38910491SRishi.Srivatsavai@Sun.COM * daemon, and wait for it to change. It's not pretty, but
39010491SRishi.Srivatsavai@Sun.COM * it's sufficient.
39110491SRishi.Srivatsavai@Sun.COM */
39210491SRishi.Srivatsavai@Sun.COM while (++i <= 10) {
39310491SRishi.Srivatsavai@Sun.COM buflen = sizeof (twoints);
39410491SRishi.Srivatsavai@Sun.COM bdptr = twoints;
39510491SRishi.Srivatsavai@Sun.COM status = bridge_door_call(bridge,
39610491SRishi.Srivatsavai@Sun.COM bdcBridgeGetRefreshCount, DATALINK_INVALID_LINKID,
39710491SRishi.Srivatsavai@Sun.COM &bdptr, 0, &buflen, B_FALSE);
39810491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK)
39910491SRishi.Srivatsavai@Sun.COM break;
40010491SRishi.Srivatsavai@Sun.COM if (twoints[0] != refresh_count)
40110491SRishi.Srivatsavai@Sun.COM break;
40210491SRishi.Srivatsavai@Sun.COM (void) usleep(100000);
40310491SRishi.Srivatsavai@Sun.COM }
40410491SRishi.Srivatsavai@Sun.COM fmri = alloc_fmri(TRILL_SVC_NAME, bridge);
40510491SRishi.Srivatsavai@Sun.COM if (fmri == NULL)
40610491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_NOMEM);
40710491SRishi.Srivatsavai@Sun.COM status = smf_refresh_instance(fmri) == 0 ||
40810491SRishi.Srivatsavai@Sun.COM scf_error() == SCF_ERROR_NOT_FOUND ?
40910491SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK : DLADM_STATUS_FAILED;
41010491SRishi.Srivatsavai@Sun.COM free(fmri);
41110491SRishi.Srivatsavai@Sun.COM }
41210491SRishi.Srivatsavai@Sun.COM return (status);
41310491SRishi.Srivatsavai@Sun.COM }
41410491SRishi.Srivatsavai@Sun.COM
41510491SRishi.Srivatsavai@Sun.COM /*
41610491SRishi.Srivatsavai@Sun.COM * Look up bridge property values from SCF and return them.
41710491SRishi.Srivatsavai@Sun.COM */
41810491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_get_properties(const char * instance_name,UID_STP_CFG_T * cfg,dladm_bridge_prot_t * brprotp)41910491SRishi.Srivatsavai@Sun.COM dladm_bridge_get_properties(const char *instance_name, UID_STP_CFG_T *cfg,
42010491SRishi.Srivatsavai@Sun.COM dladm_bridge_prot_t *brprotp)
42110491SRishi.Srivatsavai@Sun.COM {
42210491SRishi.Srivatsavai@Sun.COM scf_state_t sstate;
42310491SRishi.Srivatsavai@Sun.COM uint64_t value;
42410491SRishi.Srivatsavai@Sun.COM boolean_t trill_enabled;
42510491SRishi.Srivatsavai@Sun.COM
42610491SRishi.Srivatsavai@Sun.COM cfg->field_mask = 0;
42710491SRishi.Srivatsavai@Sun.COM cfg->bridge_priority = DEF_BR_PRIO;
42810491SRishi.Srivatsavai@Sun.COM cfg->max_age = DEF_BR_MAXAGE;
42910491SRishi.Srivatsavai@Sun.COM cfg->hello_time = DEF_BR_HELLOT;
43010491SRishi.Srivatsavai@Sun.COM cfg->forward_delay = DEF_BR_FWDELAY;
43110491SRishi.Srivatsavai@Sun.COM cfg->force_version = DEF_FORCE_VERS;
43210491SRishi.Srivatsavai@Sun.COM
43310491SRishi.Srivatsavai@Sun.COM (void) strlcpy(cfg->vlan_name, instance_name, sizeof (cfg->vlan_name));
43410491SRishi.Srivatsavai@Sun.COM
43510491SRishi.Srivatsavai@Sun.COM *brprotp = DLADM_BRIDGE_PROT_STP;
43610491SRishi.Srivatsavai@Sun.COM
43710491SRishi.Srivatsavai@Sun.COM /* It's ok for this to be missing; it's installed separately */
43810491SRishi.Srivatsavai@Sun.COM if (bind_instance(TRILL_SVC_NAME, instance_name, &sstate) == 0) {
43910491SRishi.Srivatsavai@Sun.COM trill_enabled = B_FALSE;
44010491SRishi.Srivatsavai@Sun.COM if (get_composed_properties(SCF_PG_GENERAL, B_FALSE, &sstate) ==
44110491SRishi.Srivatsavai@Sun.COM 0) {
44210491SRishi.Srivatsavai@Sun.COM (void) get_boolean(SCF_PROPERTY_ENABLED, &sstate,
44310491SRishi.Srivatsavai@Sun.COM &trill_enabled);
44410491SRishi.Srivatsavai@Sun.COM if (trill_enabled)
44510491SRishi.Srivatsavai@Sun.COM *brprotp = DLADM_BRIDGE_PROT_TRILL;
44610491SRishi.Srivatsavai@Sun.COM drop_composed(&sstate);
44710491SRishi.Srivatsavai@Sun.COM }
44810491SRishi.Srivatsavai@Sun.COM if (get_composed_properties(SCF_PG_GENERAL_OVR, B_FALSE,
44910491SRishi.Srivatsavai@Sun.COM &sstate) == 0) {
45010491SRishi.Srivatsavai@Sun.COM (void) get_boolean(SCF_PROPERTY_ENABLED, &sstate,
45110491SRishi.Srivatsavai@Sun.COM &trill_enabled);
45210491SRishi.Srivatsavai@Sun.COM if (trill_enabled)
45310491SRishi.Srivatsavai@Sun.COM *brprotp = DLADM_BRIDGE_PROT_TRILL;
45410491SRishi.Srivatsavai@Sun.COM drop_composed(&sstate);
45510491SRishi.Srivatsavai@Sun.COM }
45610491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
45710491SRishi.Srivatsavai@Sun.COM }
45810491SRishi.Srivatsavai@Sun.COM
45910491SRishi.Srivatsavai@Sun.COM cfg->stp_enabled = (*brprotp == DLADM_BRIDGE_PROT_STP) ?
46010491SRishi.Srivatsavai@Sun.COM STP_ENABLED : STP_DISABLED;
46110491SRishi.Srivatsavai@Sun.COM cfg->field_mask |= BR_CFG_STATE;
46210491SRishi.Srivatsavai@Sun.COM
46310491SRishi.Srivatsavai@Sun.COM if (bind_instance(BRIDGE_SVC_NAME, instance_name, &sstate) != 0)
46410491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_REPOSITORYINVAL);
46510491SRishi.Srivatsavai@Sun.COM
46610491SRishi.Srivatsavai@Sun.COM if (get_composed_properties("config", B_TRUE, &sstate) != 0) {
46710491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
46810491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_REPOSITORYINVAL);
46910491SRishi.Srivatsavai@Sun.COM }
47010491SRishi.Srivatsavai@Sun.COM
47110491SRishi.Srivatsavai@Sun.COM if (get_count("priority", &sstate, &value) == 0) {
47210491SRishi.Srivatsavai@Sun.COM cfg->bridge_priority = value;
47310491SRishi.Srivatsavai@Sun.COM cfg->field_mask |= BR_CFG_PRIO;
47410491SRishi.Srivatsavai@Sun.COM }
47510491SRishi.Srivatsavai@Sun.COM if (get_count("max-age", &sstate, &value) == 0) {
47610491SRishi.Srivatsavai@Sun.COM cfg->max_age = value / IEEE_TIMER_SCALE;
47710491SRishi.Srivatsavai@Sun.COM cfg->field_mask |= BR_CFG_AGE;
47810491SRishi.Srivatsavai@Sun.COM }
47910491SRishi.Srivatsavai@Sun.COM if (get_count("hello-time", &sstate, &value) == 0) {
48010491SRishi.Srivatsavai@Sun.COM cfg->hello_time = value / IEEE_TIMER_SCALE;
48110491SRishi.Srivatsavai@Sun.COM cfg->field_mask |= BR_CFG_HELLO;
48210491SRishi.Srivatsavai@Sun.COM }
48310491SRishi.Srivatsavai@Sun.COM if (get_count("forward-delay", &sstate, &value) == 0) {
48410491SRishi.Srivatsavai@Sun.COM cfg->forward_delay = value / IEEE_TIMER_SCALE;
48510491SRishi.Srivatsavai@Sun.COM cfg->field_mask |= BR_CFG_DELAY;
48610491SRishi.Srivatsavai@Sun.COM }
48710491SRishi.Srivatsavai@Sun.COM if (get_count("force-protocol", &sstate, &value) == 0) {
48810491SRishi.Srivatsavai@Sun.COM cfg->force_version = value;
48910491SRishi.Srivatsavai@Sun.COM cfg->field_mask |= BR_CFG_FORCE_VER;
49010491SRishi.Srivatsavai@Sun.COM }
49110491SRishi.Srivatsavai@Sun.COM
49210491SRishi.Srivatsavai@Sun.COM drop_composed(&sstate);
49310491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
49410491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OK);
49510491SRishi.Srivatsavai@Sun.COM }
49610491SRishi.Srivatsavai@Sun.COM
49710491SRishi.Srivatsavai@Sun.COM /*
49810491SRishi.Srivatsavai@Sun.COM * Retrieve special non-settable and undocumented parameters.
49910491SRishi.Srivatsavai@Sun.COM */
50010491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_get_privprop(const char * instance_name,boolean_t * debugp,uint32_t * tablemaxp)50110491SRishi.Srivatsavai@Sun.COM dladm_bridge_get_privprop(const char *instance_name, boolean_t *debugp,
50210491SRishi.Srivatsavai@Sun.COM uint32_t *tablemaxp)
50310491SRishi.Srivatsavai@Sun.COM {
50410491SRishi.Srivatsavai@Sun.COM scf_state_t sstate;
50510491SRishi.Srivatsavai@Sun.COM uint64_t value;
50610491SRishi.Srivatsavai@Sun.COM
50710491SRishi.Srivatsavai@Sun.COM *debugp = B_FALSE;
50810491SRishi.Srivatsavai@Sun.COM *tablemaxp = 10000;
50910491SRishi.Srivatsavai@Sun.COM
51010491SRishi.Srivatsavai@Sun.COM if (bind_instance(BRIDGE_SVC_NAME, instance_name, &sstate) != 0)
51110491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_REPOSITORYINVAL);
51210491SRishi.Srivatsavai@Sun.COM
51310491SRishi.Srivatsavai@Sun.COM if (get_composed_properties("config", B_TRUE, &sstate) != 0) {
51410491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
51510491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_REPOSITORYINVAL);
51610491SRishi.Srivatsavai@Sun.COM }
51710491SRishi.Srivatsavai@Sun.COM
51810491SRishi.Srivatsavai@Sun.COM (void) get_boolean("debug", &sstate, debugp);
51910491SRishi.Srivatsavai@Sun.COM if (get_count("table-maximum", &sstate, &value) == 0)
52010491SRishi.Srivatsavai@Sun.COM *tablemaxp = (uint32_t)value;
52110491SRishi.Srivatsavai@Sun.COM
52210491SRishi.Srivatsavai@Sun.COM drop_composed(&sstate);
52310491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
52410491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OK);
52510491SRishi.Srivatsavai@Sun.COM }
52610491SRishi.Srivatsavai@Sun.COM
52710491SRishi.Srivatsavai@Sun.COM static boolean_t
set_count_property(scf_handle_t * handle,scf_transaction_t * tran,const char * propname,uint64_t propval)52810491SRishi.Srivatsavai@Sun.COM set_count_property(scf_handle_t *handle, scf_transaction_t *tran,
52910491SRishi.Srivatsavai@Sun.COM const char *propname, uint64_t propval)
53010491SRishi.Srivatsavai@Sun.COM {
53110491SRishi.Srivatsavai@Sun.COM scf_transaction_entry_t *entry;
53210491SRishi.Srivatsavai@Sun.COM scf_value_t *value = NULL;
53310491SRishi.Srivatsavai@Sun.COM
53410491SRishi.Srivatsavai@Sun.COM if ((entry = scf_entry_create(handle)) == NULL)
53510491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
53610491SRishi.Srivatsavai@Sun.COM
53710491SRishi.Srivatsavai@Sun.COM if ((value = scf_value_create(handle)) == NULL)
53810491SRishi.Srivatsavai@Sun.COM goto out;
53910491SRishi.Srivatsavai@Sun.COM if (scf_transaction_property_new(tran, entry, propname,
54010491SRishi.Srivatsavai@Sun.COM SCF_TYPE_COUNT) != 0 &&
54110491SRishi.Srivatsavai@Sun.COM scf_transaction_property_change(tran, entry, propname,
54210491SRishi.Srivatsavai@Sun.COM SCF_TYPE_COUNT) != 0)
54310491SRishi.Srivatsavai@Sun.COM goto out;
54410491SRishi.Srivatsavai@Sun.COM scf_value_set_count(value, propval);
54510491SRishi.Srivatsavai@Sun.COM if (scf_entry_add_value(entry, value) == 0)
54610491SRishi.Srivatsavai@Sun.COM return (B_TRUE);
54710491SRishi.Srivatsavai@Sun.COM
54810491SRishi.Srivatsavai@Sun.COM out:
54910491SRishi.Srivatsavai@Sun.COM if (value != NULL)
55010491SRishi.Srivatsavai@Sun.COM scf_value_destroy(value);
55110491SRishi.Srivatsavai@Sun.COM
55210491SRishi.Srivatsavai@Sun.COM scf_entry_destroy_children(entry);
55310491SRishi.Srivatsavai@Sun.COM scf_entry_destroy(entry);
55410491SRishi.Srivatsavai@Sun.COM
55510491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
55610491SRishi.Srivatsavai@Sun.COM }
55710491SRishi.Srivatsavai@Sun.COM
55810491SRishi.Srivatsavai@Sun.COM static boolean_t
set_string_property(scf_handle_t * handle,scf_transaction_t * tran,const char * propname,const char * propval)55910491SRishi.Srivatsavai@Sun.COM set_string_property(scf_handle_t *handle, scf_transaction_t *tran,
56010491SRishi.Srivatsavai@Sun.COM const char *propname, const char *propval)
56110491SRishi.Srivatsavai@Sun.COM {
56210491SRishi.Srivatsavai@Sun.COM scf_transaction_entry_t *entry;
56310491SRishi.Srivatsavai@Sun.COM scf_value_t *value = NULL;
56410491SRishi.Srivatsavai@Sun.COM
56510491SRishi.Srivatsavai@Sun.COM if ((entry = scf_entry_create(handle)) == NULL)
56610491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
56710491SRishi.Srivatsavai@Sun.COM
56810491SRishi.Srivatsavai@Sun.COM if ((value = scf_value_create(handle)) == NULL)
56910491SRishi.Srivatsavai@Sun.COM goto out;
57010491SRishi.Srivatsavai@Sun.COM if (scf_transaction_property_new(tran, entry, propname,
57110491SRishi.Srivatsavai@Sun.COM SCF_TYPE_ASTRING) != 0 &&
57210491SRishi.Srivatsavai@Sun.COM scf_transaction_property_change(tran, entry, propname,
57310491SRishi.Srivatsavai@Sun.COM SCF_TYPE_ASTRING) != 0)
57410491SRishi.Srivatsavai@Sun.COM goto out;
57510491SRishi.Srivatsavai@Sun.COM if (scf_value_set_astring(value, propval) != 0)
57610491SRishi.Srivatsavai@Sun.COM goto out;
57710491SRishi.Srivatsavai@Sun.COM if (scf_entry_add_value(entry, value) == 0)
57810491SRishi.Srivatsavai@Sun.COM return (B_TRUE);
57910491SRishi.Srivatsavai@Sun.COM
58010491SRishi.Srivatsavai@Sun.COM out:
58110491SRishi.Srivatsavai@Sun.COM if (value != NULL)
58210491SRishi.Srivatsavai@Sun.COM scf_value_destroy(value);
58310491SRishi.Srivatsavai@Sun.COM
58410491SRishi.Srivatsavai@Sun.COM scf_entry_destroy_children(entry);
58510491SRishi.Srivatsavai@Sun.COM scf_entry_destroy(entry);
58610491SRishi.Srivatsavai@Sun.COM
58710491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
58810491SRishi.Srivatsavai@Sun.COM }
58910491SRishi.Srivatsavai@Sun.COM
59010491SRishi.Srivatsavai@Sun.COM static boolean_t
set_fmri_property(scf_handle_t * handle,scf_transaction_t * tran,const char * propname,const char * propval)59110491SRishi.Srivatsavai@Sun.COM set_fmri_property(scf_handle_t *handle, scf_transaction_t *tran,
59210491SRishi.Srivatsavai@Sun.COM const char *propname, const char *propval)
59310491SRishi.Srivatsavai@Sun.COM {
59410491SRishi.Srivatsavai@Sun.COM scf_transaction_entry_t *entry;
59510491SRishi.Srivatsavai@Sun.COM scf_value_t *value = NULL;
59610491SRishi.Srivatsavai@Sun.COM
59710491SRishi.Srivatsavai@Sun.COM if ((entry = scf_entry_create(handle)) == NULL)
59810491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
59910491SRishi.Srivatsavai@Sun.COM
60010491SRishi.Srivatsavai@Sun.COM if ((value = scf_value_create(handle)) == NULL)
60110491SRishi.Srivatsavai@Sun.COM goto out;
60210491SRishi.Srivatsavai@Sun.COM if (scf_transaction_property_new(tran, entry, propname,
60310491SRishi.Srivatsavai@Sun.COM SCF_TYPE_FMRI) != 0 &&
60410491SRishi.Srivatsavai@Sun.COM scf_transaction_property_change(tran, entry, propname,
60510491SRishi.Srivatsavai@Sun.COM SCF_TYPE_FMRI) != 0)
60610491SRishi.Srivatsavai@Sun.COM goto out;
60710491SRishi.Srivatsavai@Sun.COM if (scf_value_set_from_string(value, SCF_TYPE_FMRI, propval) != 0)
60810491SRishi.Srivatsavai@Sun.COM goto out;
60910491SRishi.Srivatsavai@Sun.COM if (scf_entry_add_value(entry, value) == 0)
61010491SRishi.Srivatsavai@Sun.COM return (B_TRUE);
61110491SRishi.Srivatsavai@Sun.COM
61210491SRishi.Srivatsavai@Sun.COM out:
61310491SRishi.Srivatsavai@Sun.COM if (value != NULL)
61410491SRishi.Srivatsavai@Sun.COM scf_value_destroy(value);
61510491SRishi.Srivatsavai@Sun.COM
61610491SRishi.Srivatsavai@Sun.COM scf_entry_destroy_children(entry);
61710491SRishi.Srivatsavai@Sun.COM scf_entry_destroy(entry);
61810491SRishi.Srivatsavai@Sun.COM
61910491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
62010491SRishi.Srivatsavai@Sun.COM }
62110491SRishi.Srivatsavai@Sun.COM
62210491SRishi.Srivatsavai@Sun.COM static dladm_status_t
dladm_bridge_persist_conf(dladm_handle_t handle,const char * link,datalink_id_t linkid)62310491SRishi.Srivatsavai@Sun.COM dladm_bridge_persist_conf(dladm_handle_t handle, const char *link,
62410491SRishi.Srivatsavai@Sun.COM datalink_id_t linkid)
62510491SRishi.Srivatsavai@Sun.COM {
626*12824SCathy.Zhou@Sun.COM dladm_conf_t conf;
62710491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
62810491SRishi.Srivatsavai@Sun.COM
62910491SRishi.Srivatsavai@Sun.COM status = dladm_create_conf(handle, link, linkid, DATALINK_CLASS_BRIDGE,
63010491SRishi.Srivatsavai@Sun.COM DL_ETHER, &conf);
63110491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK) {
63210491SRishi.Srivatsavai@Sun.COM /*
63310491SRishi.Srivatsavai@Sun.COM * Create the datalink entry for the bridge. Note that all of
63410491SRishi.Srivatsavai@Sun.COM * the real configuration information is in SMF.
63510491SRishi.Srivatsavai@Sun.COM */
63610491SRishi.Srivatsavai@Sun.COM status = dladm_write_conf(handle, conf);
63710491SRishi.Srivatsavai@Sun.COM dladm_destroy_conf(handle, conf);
63810491SRishi.Srivatsavai@Sun.COM }
63910491SRishi.Srivatsavai@Sun.COM return (status);
64010491SRishi.Srivatsavai@Sun.COM }
64110491SRishi.Srivatsavai@Sun.COM
64210491SRishi.Srivatsavai@Sun.COM /* Convert bridge protection option string to dladm_bridge_prot_t */
64310491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_str2prot(const char * str,dladm_bridge_prot_t * brprotp)64410491SRishi.Srivatsavai@Sun.COM dladm_bridge_str2prot(const char *str, dladm_bridge_prot_t *brprotp)
64510491SRishi.Srivatsavai@Sun.COM {
64610491SRishi.Srivatsavai@Sun.COM if (strcmp(str, "stp") == 0)
64710491SRishi.Srivatsavai@Sun.COM *brprotp = DLADM_BRIDGE_PROT_STP;
64810491SRishi.Srivatsavai@Sun.COM else if (strcmp(str, "trill") == 0)
64910491SRishi.Srivatsavai@Sun.COM *brprotp = DLADM_BRIDGE_PROT_TRILL;
65010491SRishi.Srivatsavai@Sun.COM else
65110491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG);
65210491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OK);
65310491SRishi.Srivatsavai@Sun.COM }
65410491SRishi.Srivatsavai@Sun.COM
65510491SRishi.Srivatsavai@Sun.COM /* Convert bridge protection option from dladm_bridge_prot_t to string */
65610491SRishi.Srivatsavai@Sun.COM const char *
dladm_bridge_prot2str(dladm_bridge_prot_t brprot)65710491SRishi.Srivatsavai@Sun.COM dladm_bridge_prot2str(dladm_bridge_prot_t brprot)
65810491SRishi.Srivatsavai@Sun.COM {
65910491SRishi.Srivatsavai@Sun.COM switch (brprot) {
66010491SRishi.Srivatsavai@Sun.COM case DLADM_BRIDGE_PROT_STP:
66110491SRishi.Srivatsavai@Sun.COM return ("stp");
66210491SRishi.Srivatsavai@Sun.COM case DLADM_BRIDGE_PROT_TRILL:
66310491SRishi.Srivatsavai@Sun.COM return ("trill");
66410491SRishi.Srivatsavai@Sun.COM default:
66510491SRishi.Srivatsavai@Sun.COM return ("unknown");
66610491SRishi.Srivatsavai@Sun.COM }
66710491SRishi.Srivatsavai@Sun.COM }
66810491SRishi.Srivatsavai@Sun.COM
66910491SRishi.Srivatsavai@Sun.COM static dladm_status_t
enable_instance(const char * service_name,const char * instance)67010491SRishi.Srivatsavai@Sun.COM enable_instance(const char *service_name, const char *instance)
67110491SRishi.Srivatsavai@Sun.COM {
67210491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
67310491SRishi.Srivatsavai@Sun.COM char *fmri = alloc_fmri(service_name, instance);
67410491SRishi.Srivatsavai@Sun.COM
67510491SRishi.Srivatsavai@Sun.COM if (fmri == NULL)
67610491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_NOMEM);
67710491SRishi.Srivatsavai@Sun.COM status = smf_enable_instance(fmri, 0) == 0 ?
67810491SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK : DLADM_STATUS_FAILED;
67910491SRishi.Srivatsavai@Sun.COM free(fmri);
68010491SRishi.Srivatsavai@Sun.COM return (status);
68110491SRishi.Srivatsavai@Sun.COM }
68210491SRishi.Srivatsavai@Sun.COM
68310491SRishi.Srivatsavai@Sun.COM /*
68410491SRishi.Srivatsavai@Sun.COM * Shut down a possibly-running service instance. If this is a permanent
68510491SRishi.Srivatsavai@Sun.COM * change, then delete it from the system.
68610491SRishi.Srivatsavai@Sun.COM */
68710491SRishi.Srivatsavai@Sun.COM static dladm_status_t
shut_down_instance(const char * service_name,const char * instance,uint32_t flags)68810491SRishi.Srivatsavai@Sun.COM shut_down_instance(const char *service_name, const char *instance,
68910491SRishi.Srivatsavai@Sun.COM uint32_t flags)
69010491SRishi.Srivatsavai@Sun.COM {
69110491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
69210491SRishi.Srivatsavai@Sun.COM char *fmri = alloc_fmri(service_name, instance);
69310491SRishi.Srivatsavai@Sun.COM char *state;
69410491SRishi.Srivatsavai@Sun.COM scf_state_t sstate;
69510491SRishi.Srivatsavai@Sun.COM
69610491SRishi.Srivatsavai@Sun.COM if (fmri == NULL)
69710491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_NOMEM);
69810491SRishi.Srivatsavai@Sun.COM
69910491SRishi.Srivatsavai@Sun.COM if (smf_disable_instance(fmri,
70010491SRishi.Srivatsavai@Sun.COM flags & DLADM_OPT_PERSIST ? 0 : SMF_TEMPORARY) == 0) {
70110491SRishi.Srivatsavai@Sun.COM useconds_t usecs, umax;
70210491SRishi.Srivatsavai@Sun.COM
70310491SRishi.Srivatsavai@Sun.COM /* If we can disable, then wait for it to happen. */
70410491SRishi.Srivatsavai@Sun.COM umax = DEFAULT_TIMEOUT;
70510491SRishi.Srivatsavai@Sun.COM for (usecs = INIT_WAIT_USECS; umax != 0; umax -= usecs) {
70610491SRishi.Srivatsavai@Sun.COM state = smf_get_state(fmri);
70710491SRishi.Srivatsavai@Sun.COM if (state != NULL &&
70810491SRishi.Srivatsavai@Sun.COM strcmp(state, SCF_STATE_STRING_DISABLED) == 0)
70910491SRishi.Srivatsavai@Sun.COM break;
71010491SRishi.Srivatsavai@Sun.COM free(state);
71110491SRishi.Srivatsavai@Sun.COM usecs *= 2;
71210491SRishi.Srivatsavai@Sun.COM if (usecs > umax)
71310491SRishi.Srivatsavai@Sun.COM usecs = umax;
71410491SRishi.Srivatsavai@Sun.COM (void) usleep(usecs);
71510491SRishi.Srivatsavai@Sun.COM }
71610491SRishi.Srivatsavai@Sun.COM if (umax == 0) {
71710491SRishi.Srivatsavai@Sun.COM state = smf_get_state(fmri);
71810491SRishi.Srivatsavai@Sun.COM if (state != NULL &&
71910491SRishi.Srivatsavai@Sun.COM strcmp(state, SCF_STATE_STRING_DISABLED) == 0)
72010491SRishi.Srivatsavai@Sun.COM umax = 1;
72110491SRishi.Srivatsavai@Sun.COM }
72210491SRishi.Srivatsavai@Sun.COM free(state);
72310491SRishi.Srivatsavai@Sun.COM status = umax != 0 ? DLADM_STATUS_OK : DLADM_STATUS_FAILED;
72410491SRishi.Srivatsavai@Sun.COM } else if (scf_error() == SCF_ERROR_NOT_FOUND) {
72510491SRishi.Srivatsavai@Sun.COM free(fmri);
72610491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OK);
72710491SRishi.Srivatsavai@Sun.COM } else {
72810491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_FAILED;
72910491SRishi.Srivatsavai@Sun.COM }
73010491SRishi.Srivatsavai@Sun.COM
73110491SRishi.Srivatsavai@Sun.COM free(fmri);
73210491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_PERSIST) &&
73310491SRishi.Srivatsavai@Sun.COM bind_instance(service_name, instance, &sstate) == 0) {
73410491SRishi.Srivatsavai@Sun.COM (void) scf_instance_delete(sstate.ss_inst);
73510491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
73610491SRishi.Srivatsavai@Sun.COM }
73710491SRishi.Srivatsavai@Sun.COM
73810491SRishi.Srivatsavai@Sun.COM return (status);
73910491SRishi.Srivatsavai@Sun.COM }
74010491SRishi.Srivatsavai@Sun.COM
74110491SRishi.Srivatsavai@Sun.COM static dladm_status_t
disable_trill(const char * instance,uint32_t flags)74210491SRishi.Srivatsavai@Sun.COM disable_trill(const char *instance, uint32_t flags)
74310491SRishi.Srivatsavai@Sun.COM {
74410491SRishi.Srivatsavai@Sun.COM return (shut_down_instance(TRILL_SVC_NAME, instance, flags));
74510491SRishi.Srivatsavai@Sun.COM }
74610491SRishi.Srivatsavai@Sun.COM
74710491SRishi.Srivatsavai@Sun.COM /*
74810491SRishi.Srivatsavai@Sun.COM * To enable TRILL, we must create a new instance of the TRILL service, then
74910491SRishi.Srivatsavai@Sun.COM * add proper dependencies to it, and finally mark it as enabled. The
75010491SRishi.Srivatsavai@Sun.COM * dependencies will keep it from going on-line until the bridge is running.
75110491SRishi.Srivatsavai@Sun.COM */
75210491SRishi.Srivatsavai@Sun.COM static dladm_status_t
enable_trill(const char * instance)75310491SRishi.Srivatsavai@Sun.COM enable_trill(const char *instance)
75410491SRishi.Srivatsavai@Sun.COM {
75510491SRishi.Srivatsavai@Sun.COM dladm_status_t status = DLADM_STATUS_FAILED;
75610491SRishi.Srivatsavai@Sun.COM char *fmri = NULL;
75710491SRishi.Srivatsavai@Sun.COM scf_state_t sstate;
75810491SRishi.Srivatsavai@Sun.COM scf_transaction_t *tran = NULL;
75910491SRishi.Srivatsavai@Sun.COM boolean_t new_instance = B_FALSE;
76010491SRishi.Srivatsavai@Sun.COM boolean_t new_pg = B_FALSE;
76110491SRishi.Srivatsavai@Sun.COM int rv;
76210491SRishi.Srivatsavai@Sun.COM
76310491SRishi.Srivatsavai@Sun.COM /*
76410491SRishi.Srivatsavai@Sun.COM * This check is here in case the user has installed and then removed
76510491SRishi.Srivatsavai@Sun.COM * the package. SMF should remove the manifest, but currently does
76610491SRishi.Srivatsavai@Sun.COM * not.
76710491SRishi.Srivatsavai@Sun.COM */
76810491SRishi.Srivatsavai@Sun.COM if (access("/usr/sbin/trilld", F_OK) != 0)
76910491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OPTMISSING);
77010491SRishi.Srivatsavai@Sun.COM
77110491SRishi.Srivatsavai@Sun.COM if ((status = exact_instance(TRILL_SVC_NAME, &sstate)) !=
77210491SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK)
77310491SRishi.Srivatsavai@Sun.COM goto out;
77410491SRishi.Srivatsavai@Sun.COM
77510491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_FAILED;
77610491SRishi.Srivatsavai@Sun.COM if (scf_service_get_instance(sstate.ss_svc, instance, sstate.ss_inst) !=
77710491SRishi.Srivatsavai@Sun.COM 0) {
77810491SRishi.Srivatsavai@Sun.COM if (scf_service_add_instance(sstate.ss_svc, instance,
77910491SRishi.Srivatsavai@Sun.COM sstate.ss_inst) != 0)
78010491SRishi.Srivatsavai@Sun.COM goto out;
78110491SRishi.Srivatsavai@Sun.COM new_instance = B_TRUE;
78210491SRishi.Srivatsavai@Sun.COM }
78310491SRishi.Srivatsavai@Sun.COM
78410491SRishi.Srivatsavai@Sun.COM if ((tran = scf_transaction_create(sstate.ss_handle)) == NULL)
78510491SRishi.Srivatsavai@Sun.COM goto out;
78610491SRishi.Srivatsavai@Sun.COM
78710491SRishi.Srivatsavai@Sun.COM if ((sstate.ss_pg = scf_pg_create(sstate.ss_handle)) == NULL)
78810491SRishi.Srivatsavai@Sun.COM goto out;
78910491SRishi.Srivatsavai@Sun.COM
79010491SRishi.Srivatsavai@Sun.COM if (scf_instance_get_pg(sstate.ss_inst, "bridging",
79110491SRishi.Srivatsavai@Sun.COM sstate.ss_pg) == 0) {
79210491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_OK;
79310491SRishi.Srivatsavai@Sun.COM goto out;
79410491SRishi.Srivatsavai@Sun.COM }
79510491SRishi.Srivatsavai@Sun.COM
79610491SRishi.Srivatsavai@Sun.COM if ((fmri = alloc_fmri(BRIDGE_SVC_NAME, instance)) == NULL)
79710491SRishi.Srivatsavai@Sun.COM goto out;
79810491SRishi.Srivatsavai@Sun.COM
79910491SRishi.Srivatsavai@Sun.COM if (scf_instance_add_pg(sstate.ss_inst, "bridging",
80010491SRishi.Srivatsavai@Sun.COM SCF_GROUP_DEPENDENCY, 0, sstate.ss_pg) != 0)
80110491SRishi.Srivatsavai@Sun.COM goto out;
80210491SRishi.Srivatsavai@Sun.COM
80310491SRishi.Srivatsavai@Sun.COM new_pg = B_TRUE;
80410491SRishi.Srivatsavai@Sun.COM do {
80510491SRishi.Srivatsavai@Sun.COM if (scf_transaction_start(tran, sstate.ss_pg) != 0)
80610491SRishi.Srivatsavai@Sun.COM goto out;
80710491SRishi.Srivatsavai@Sun.COM
80810491SRishi.Srivatsavai@Sun.COM if (!set_string_property(sstate.ss_handle, tran,
80910491SRishi.Srivatsavai@Sun.COM SCF_PROPERTY_GROUPING, SCF_DEP_REQUIRE_ALL))
81010491SRishi.Srivatsavai@Sun.COM goto out;
81110491SRishi.Srivatsavai@Sun.COM if (!set_string_property(sstate.ss_handle, tran,
81210491SRishi.Srivatsavai@Sun.COM SCF_PROPERTY_RESTART_ON, SCF_DEP_RESET_ON_RESTART))
81310491SRishi.Srivatsavai@Sun.COM goto out;
81410491SRishi.Srivatsavai@Sun.COM if (!set_string_property(sstate.ss_handle, tran,
81510491SRishi.Srivatsavai@Sun.COM SCF_PROPERTY_TYPE, "service"))
81610491SRishi.Srivatsavai@Sun.COM goto out;
81710491SRishi.Srivatsavai@Sun.COM if (!set_fmri_property(sstate.ss_handle, tran,
81810491SRishi.Srivatsavai@Sun.COM SCF_PROPERTY_ENTITIES, fmri))
81910491SRishi.Srivatsavai@Sun.COM goto out;
82010491SRishi.Srivatsavai@Sun.COM
82110491SRishi.Srivatsavai@Sun.COM rv = scf_transaction_commit(tran);
82210491SRishi.Srivatsavai@Sun.COM scf_transaction_reset(tran);
82310491SRishi.Srivatsavai@Sun.COM if (rv == 0 && scf_pg_update(sstate.ss_pg) == -1)
82410491SRishi.Srivatsavai@Sun.COM goto out;
82510491SRishi.Srivatsavai@Sun.COM } while (rv == 0);
82610491SRishi.Srivatsavai@Sun.COM if (rv != 1)
82710491SRishi.Srivatsavai@Sun.COM goto out;
82810491SRishi.Srivatsavai@Sun.COM
82910491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_OK;
83010491SRishi.Srivatsavai@Sun.COM
83110491SRishi.Srivatsavai@Sun.COM out:
83210491SRishi.Srivatsavai@Sun.COM free(fmri);
83310491SRishi.Srivatsavai@Sun.COM if (tran != NULL) {
83410491SRishi.Srivatsavai@Sun.COM scf_transaction_destroy_children(tran);
83510491SRishi.Srivatsavai@Sun.COM scf_transaction_destroy(tran);
83610491SRishi.Srivatsavai@Sun.COM }
83710491SRishi.Srivatsavai@Sun.COM
83810491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK && new_pg)
83910491SRishi.Srivatsavai@Sun.COM (void) scf_pg_delete(sstate.ss_pg);
84010491SRishi.Srivatsavai@Sun.COM
84110491SRishi.Srivatsavai@Sun.COM drop_composed(&sstate);
84210491SRishi.Srivatsavai@Sun.COM
84310491SRishi.Srivatsavai@Sun.COM /*
84410491SRishi.Srivatsavai@Sun.COM * If we created an instance and then failed, then remove the instance
84510491SRishi.Srivatsavai@Sun.COM * from the system.
84610491SRishi.Srivatsavai@Sun.COM */
84710491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK && new_instance)
84810491SRishi.Srivatsavai@Sun.COM (void) scf_instance_delete(sstate.ss_inst);
84910491SRishi.Srivatsavai@Sun.COM
85010491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
85110491SRishi.Srivatsavai@Sun.COM
85210491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK)
85310491SRishi.Srivatsavai@Sun.COM status = enable_instance(TRILL_SVC_NAME, instance);
85410491SRishi.Srivatsavai@Sun.COM
85510491SRishi.Srivatsavai@Sun.COM return (status);
85610491SRishi.Srivatsavai@Sun.COM }
85710491SRishi.Srivatsavai@Sun.COM
85810491SRishi.Srivatsavai@Sun.COM /*
85910491SRishi.Srivatsavai@Sun.COM * Create a new bridge or modify an existing one. Update the SMF configuration
86010491SRishi.Srivatsavai@Sun.COM * and add links.
86110491SRishi.Srivatsavai@Sun.COM *
86210491SRishi.Srivatsavai@Sun.COM * Input timer values are in IEEE scaled (* 256) format.
86310491SRishi.Srivatsavai@Sun.COM */
86410491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_configure(dladm_handle_t handle,const char * name,const UID_STP_CFG_T * cfg,dladm_bridge_prot_t brprot,uint32_t flags)86510491SRishi.Srivatsavai@Sun.COM dladm_bridge_configure(dladm_handle_t handle, const char *name,
86610491SRishi.Srivatsavai@Sun.COM const UID_STP_CFG_T *cfg, dladm_bridge_prot_t brprot, uint32_t flags)
86710491SRishi.Srivatsavai@Sun.COM {
86810491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
86910491SRishi.Srivatsavai@Sun.COM scf_state_t sstate;
87010491SRishi.Srivatsavai@Sun.COM scf_transaction_t *tran = NULL;
87110491SRishi.Srivatsavai@Sun.COM boolean_t new_instance = B_FALSE;
87210491SRishi.Srivatsavai@Sun.COM boolean_t new_pg = B_FALSE;
87310491SRishi.Srivatsavai@Sun.COM datalink_id_t linkid = DATALINK_INVALID_LINKID;
87410491SRishi.Srivatsavai@Sun.COM char linkname[MAXLINKNAMELEN];
87510491SRishi.Srivatsavai@Sun.COM int rv;
87610491SRishi.Srivatsavai@Sun.COM
87710491SRishi.Srivatsavai@Sun.COM if (!dladm_valid_bridgename(name))
87810491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_FAILED);
87910491SRishi.Srivatsavai@Sun.COM
88010491SRishi.Srivatsavai@Sun.COM if (flags & DLADM_OPT_CREATE) {
88110491SRishi.Srivatsavai@Sun.COM /*
88210491SRishi.Srivatsavai@Sun.COM * This check is here in case the user has installed and then
88310491SRishi.Srivatsavai@Sun.COM * removed the package. SMF should remove the manifest, but
88410491SRishi.Srivatsavai@Sun.COM * currently does not.
88510491SRishi.Srivatsavai@Sun.COM */
88610491SRishi.Srivatsavai@Sun.COM if (access("/usr/lib/bridged", F_OK) != 0)
88710491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OPTMISSING);
88810491SRishi.Srivatsavai@Sun.COM
88910491SRishi.Srivatsavai@Sun.COM (void) snprintf(linkname, sizeof (linkname), "%s0", name);
89010491SRishi.Srivatsavai@Sun.COM status = dladm_create_datalink_id(handle, linkname,
89110491SRishi.Srivatsavai@Sun.COM DATALINK_CLASS_BRIDGE, DL_ETHER,
89210491SRishi.Srivatsavai@Sun.COM flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST), &linkid);
89310491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK)
89410491SRishi.Srivatsavai@Sun.COM return (status);
89510491SRishi.Srivatsavai@Sun.COM
89610491SRishi.Srivatsavai@Sun.COM if ((flags & DLADM_OPT_PERSIST) &&
89710491SRishi.Srivatsavai@Sun.COM (status = dladm_bridge_persist_conf(handle, linkname,
89810491SRishi.Srivatsavai@Sun.COM linkid) != DLADM_STATUS_OK))
89910491SRishi.Srivatsavai@Sun.COM goto dladm_fail;
90010491SRishi.Srivatsavai@Sun.COM }
90110491SRishi.Srivatsavai@Sun.COM
90210491SRishi.Srivatsavai@Sun.COM if (brprot == DLADM_BRIDGE_PROT_TRILL)
90310491SRishi.Srivatsavai@Sun.COM status = enable_trill(name);
90410491SRishi.Srivatsavai@Sun.COM else
90510491SRishi.Srivatsavai@Sun.COM status = disable_trill(name, flags);
90610491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK)
90710491SRishi.Srivatsavai@Sun.COM goto dladm_fail;
90810491SRishi.Srivatsavai@Sun.COM
90910491SRishi.Srivatsavai@Sun.COM if ((status = exact_instance(BRIDGE_SVC_NAME, &sstate)) !=
91010491SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK)
91110491SRishi.Srivatsavai@Sun.COM goto out;
91210491SRishi.Srivatsavai@Sun.COM
91310491SRishi.Srivatsavai@Sun.COM /* set up for a series of scf calls */
91410491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_FAILED;
91510491SRishi.Srivatsavai@Sun.COM
91610491SRishi.Srivatsavai@Sun.COM if (scf_service_get_instance(sstate.ss_svc, name, sstate.ss_inst) ==
91710491SRishi.Srivatsavai@Sun.COM 0) {
91810491SRishi.Srivatsavai@Sun.COM if (flags & DLADM_OPT_CREATE) {
91910491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_EXIST;
92010491SRishi.Srivatsavai@Sun.COM goto out;
92110491SRishi.Srivatsavai@Sun.COM }
92210491SRishi.Srivatsavai@Sun.COM } else {
92310491SRishi.Srivatsavai@Sun.COM if (!(flags & DLADM_OPT_CREATE)) {
92410491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_NOTFOUND;
92510491SRishi.Srivatsavai@Sun.COM goto out;
92610491SRishi.Srivatsavai@Sun.COM }
92710491SRishi.Srivatsavai@Sun.COM if (scf_service_add_instance(sstate.ss_svc, name,
92810491SRishi.Srivatsavai@Sun.COM sstate.ss_inst) != 0)
92910491SRishi.Srivatsavai@Sun.COM goto out;
93010491SRishi.Srivatsavai@Sun.COM new_instance = B_TRUE;
93110491SRishi.Srivatsavai@Sun.COM }
93210491SRishi.Srivatsavai@Sun.COM
93310491SRishi.Srivatsavai@Sun.COM if ((tran = scf_transaction_create(sstate.ss_handle)) == NULL)
93410491SRishi.Srivatsavai@Sun.COM goto out;
93510491SRishi.Srivatsavai@Sun.COM
93610491SRishi.Srivatsavai@Sun.COM if (cfg->field_mask & BR_CFG_ALL) {
93710491SRishi.Srivatsavai@Sun.COM if ((sstate.ss_pg = scf_pg_create(sstate.ss_handle)) == NULL)
93810491SRishi.Srivatsavai@Sun.COM goto out;
93910491SRishi.Srivatsavai@Sun.COM if (scf_instance_add_pg(sstate.ss_inst, "config",
94010491SRishi.Srivatsavai@Sun.COM SCF_GROUP_APPLICATION, 0, sstate.ss_pg) == 0) {
94110491SRishi.Srivatsavai@Sun.COM new_pg = B_TRUE;
94210491SRishi.Srivatsavai@Sun.COM } else if (scf_instance_get_pg(sstate.ss_inst, "config",
94310491SRishi.Srivatsavai@Sun.COM sstate.ss_pg) != 0) {
94410491SRishi.Srivatsavai@Sun.COM goto out;
94510491SRishi.Srivatsavai@Sun.COM }
94610491SRishi.Srivatsavai@Sun.COM do {
94710491SRishi.Srivatsavai@Sun.COM if (scf_transaction_start(tran, sstate.ss_pg) != 0)
94810491SRishi.Srivatsavai@Sun.COM goto out;
94910491SRishi.Srivatsavai@Sun.COM
95010491SRishi.Srivatsavai@Sun.COM if ((cfg->field_mask & BR_CFG_PRIO) &&
95110491SRishi.Srivatsavai@Sun.COM !set_count_property(sstate.ss_handle, tran,
95210491SRishi.Srivatsavai@Sun.COM "priority", cfg->bridge_priority))
95310491SRishi.Srivatsavai@Sun.COM goto out;
95410491SRishi.Srivatsavai@Sun.COM if ((cfg->field_mask & BR_CFG_AGE) &&
95510491SRishi.Srivatsavai@Sun.COM !set_count_property(sstate.ss_handle, tran,
95610491SRishi.Srivatsavai@Sun.COM "max-age", cfg->max_age * IEEE_TIMER_SCALE))
95710491SRishi.Srivatsavai@Sun.COM goto out;
95810491SRishi.Srivatsavai@Sun.COM if ((cfg->field_mask & BR_CFG_HELLO) &&
95910491SRishi.Srivatsavai@Sun.COM !set_count_property(sstate.ss_handle, tran,
96010491SRishi.Srivatsavai@Sun.COM "hello-time", cfg->hello_time * IEEE_TIMER_SCALE))
96110491SRishi.Srivatsavai@Sun.COM goto out;
96210491SRishi.Srivatsavai@Sun.COM if ((cfg->field_mask & BR_CFG_DELAY) &&
96310491SRishi.Srivatsavai@Sun.COM !set_count_property(sstate.ss_handle, tran,
96410491SRishi.Srivatsavai@Sun.COM "forward-delay",
96510491SRishi.Srivatsavai@Sun.COM cfg->forward_delay * IEEE_TIMER_SCALE))
96610491SRishi.Srivatsavai@Sun.COM goto out;
96710491SRishi.Srivatsavai@Sun.COM if ((cfg->field_mask & BR_CFG_FORCE_VER) &&
96810491SRishi.Srivatsavai@Sun.COM !set_count_property(sstate.ss_handle, tran,
96910491SRishi.Srivatsavai@Sun.COM "force-protocol", cfg->force_version))
97010491SRishi.Srivatsavai@Sun.COM goto out;
97110491SRishi.Srivatsavai@Sun.COM
97210491SRishi.Srivatsavai@Sun.COM rv = scf_transaction_commit(tran);
97310491SRishi.Srivatsavai@Sun.COM scf_transaction_reset(tran);
97410491SRishi.Srivatsavai@Sun.COM if (rv == 0 && scf_pg_update(sstate.ss_pg) == -1)
97510491SRishi.Srivatsavai@Sun.COM goto out;
97610491SRishi.Srivatsavai@Sun.COM } while (rv == 0);
97710491SRishi.Srivatsavai@Sun.COM if (rv != 1)
97810491SRishi.Srivatsavai@Sun.COM goto out;
97910491SRishi.Srivatsavai@Sun.COM }
98010491SRishi.Srivatsavai@Sun.COM
98110491SRishi.Srivatsavai@Sun.COM /*
98210491SRishi.Srivatsavai@Sun.COM * If we're modifying an existing and running bridge, then tell the
98310491SRishi.Srivatsavai@Sun.COM * daemon to update the requested values.
98410491SRishi.Srivatsavai@Sun.COM */
98510491SRishi.Srivatsavai@Sun.COM if ((flags & DLADM_OPT_ACTIVE) && !(flags & DLADM_OPT_CREATE))
98610491SRishi.Srivatsavai@Sun.COM status = bridge_refresh(name);
98710491SRishi.Srivatsavai@Sun.COM else
98810491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_OK;
98910491SRishi.Srivatsavai@Sun.COM
99010491SRishi.Srivatsavai@Sun.COM out:
99110491SRishi.Srivatsavai@Sun.COM if (tran != NULL) {
99210491SRishi.Srivatsavai@Sun.COM scf_transaction_destroy_children(tran);
99310491SRishi.Srivatsavai@Sun.COM scf_transaction_destroy(tran);
99410491SRishi.Srivatsavai@Sun.COM }
99510491SRishi.Srivatsavai@Sun.COM
99610491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK && new_pg)
99710491SRishi.Srivatsavai@Sun.COM (void) scf_pg_delete(sstate.ss_pg);
99810491SRishi.Srivatsavai@Sun.COM
99910491SRishi.Srivatsavai@Sun.COM drop_composed(&sstate);
100010491SRishi.Srivatsavai@Sun.COM
100110491SRishi.Srivatsavai@Sun.COM /*
100210491SRishi.Srivatsavai@Sun.COM * If we created an instance and then failed, then remove the instance
100310491SRishi.Srivatsavai@Sun.COM * from the system.
100410491SRishi.Srivatsavai@Sun.COM */
100510491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK && new_instance)
100610491SRishi.Srivatsavai@Sun.COM (void) scf_instance_delete(sstate.ss_inst);
100710491SRishi.Srivatsavai@Sun.COM
100810491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
100910491SRishi.Srivatsavai@Sun.COM
101010491SRishi.Srivatsavai@Sun.COM /*
101110491SRishi.Srivatsavai@Sun.COM * Remove the bridge linkid if we've allocated one in this function but
101210491SRishi.Srivatsavai@Sun.COM * we've failed to set up the SMF properties.
101310491SRishi.Srivatsavai@Sun.COM */
101410491SRishi.Srivatsavai@Sun.COM dladm_fail:
101510491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK && linkid != DATALINK_INVALID_LINKID) {
101610491SRishi.Srivatsavai@Sun.COM (void) dladm_remove_conf(handle, linkid);
101710491SRishi.Srivatsavai@Sun.COM (void) dladm_destroy_datalink_id(handle, linkid, flags);
101810491SRishi.Srivatsavai@Sun.COM }
101910491SRishi.Srivatsavai@Sun.COM
102010491SRishi.Srivatsavai@Sun.COM return (status);
102110491SRishi.Srivatsavai@Sun.COM }
102210491SRishi.Srivatsavai@Sun.COM
102310491SRishi.Srivatsavai@Sun.COM /*
102410491SRishi.Srivatsavai@Sun.COM * Enable a newly-created bridge in SMF by creating "general/enabled" and
102510491SRishi.Srivatsavai@Sun.COM * deleting any "general_ovr/enabled" (used for temporary services).
102610491SRishi.Srivatsavai@Sun.COM */
102710491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_enable(const char * name)102810491SRishi.Srivatsavai@Sun.COM dladm_bridge_enable(const char *name)
102910491SRishi.Srivatsavai@Sun.COM {
103010491SRishi.Srivatsavai@Sun.COM return (enable_instance(BRIDGE_SVC_NAME, name));
103110491SRishi.Srivatsavai@Sun.COM }
103210491SRishi.Srivatsavai@Sun.COM
103310491SRishi.Srivatsavai@Sun.COM /*
103410491SRishi.Srivatsavai@Sun.COM * Set a link as a member of a bridge, or remove bridge membership. If the
103510491SRishi.Srivatsavai@Sun.COM * DLADM_OPT_CREATE flag is set, then we assume that the daemon isn't running.
103610491SRishi.Srivatsavai@Sun.COM * In all other cases, we must tell the daemon to add or delete the link in
103710491SRishi.Srivatsavai@Sun.COM * order to stay in sync.
103810491SRishi.Srivatsavai@Sun.COM */
103910491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_setlink(dladm_handle_t handle,datalink_id_t linkid,const char * bridge)104010491SRishi.Srivatsavai@Sun.COM dladm_bridge_setlink(dladm_handle_t handle, datalink_id_t linkid,
104110491SRishi.Srivatsavai@Sun.COM const char *bridge)
104210491SRishi.Srivatsavai@Sun.COM {
104310491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
104410491SRishi.Srivatsavai@Sun.COM dladm_conf_t conf;
104510491SRishi.Srivatsavai@Sun.COM char oldbridge[MAXLINKNAMELEN];
104610491SRishi.Srivatsavai@Sun.COM boolean_t has_oldbridge;
104710491SRishi.Srivatsavai@Sun.COM boolean_t changed = B_FALSE;
104810491SRishi.Srivatsavai@Sun.COM
104910491SRishi.Srivatsavai@Sun.COM if (*bridge != '\0' && !dladm_valid_bridgename(bridge))
105010491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_FAILED);
105110491SRishi.Srivatsavai@Sun.COM
1052*12824SCathy.Zhou@Sun.COM status = dladm_open_conf(handle, linkid, &conf);
1053*12824SCathy.Zhou@Sun.COM if (status != DLADM_STATUS_OK)
105410491SRishi.Srivatsavai@Sun.COM return (status);
105510491SRishi.Srivatsavai@Sun.COM
105610491SRishi.Srivatsavai@Sun.COM has_oldbridge = B_FALSE;
105710491SRishi.Srivatsavai@Sun.COM status = dladm_get_conf_field(handle, conf, FBRIDGE, oldbridge,
105810491SRishi.Srivatsavai@Sun.COM sizeof (oldbridge));
105910491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK) {
106010491SRishi.Srivatsavai@Sun.COM /*
106110491SRishi.Srivatsavai@Sun.COM * Don't allow a link to be reassigned directly from one bridge
106210491SRishi.Srivatsavai@Sun.COM * to another. It must be removed first.
106310491SRishi.Srivatsavai@Sun.COM */
106410491SRishi.Srivatsavai@Sun.COM if (*oldbridge != '\0' && *bridge != '\0') {
106510491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_EXIST;
106610491SRishi.Srivatsavai@Sun.COM goto out;
106710491SRishi.Srivatsavai@Sun.COM }
106810491SRishi.Srivatsavai@Sun.COM has_oldbridge = B_TRUE;
106910491SRishi.Srivatsavai@Sun.COM } else if (status != DLADM_STATUS_NOTFOUND) {
107010491SRishi.Srivatsavai@Sun.COM goto out;
107110491SRishi.Srivatsavai@Sun.COM }
107210491SRishi.Srivatsavai@Sun.COM
107310491SRishi.Srivatsavai@Sun.COM if (*bridge != '\0') {
107410491SRishi.Srivatsavai@Sun.COM status = dladm_set_conf_field(handle, conf, FBRIDGE,
107510491SRishi.Srivatsavai@Sun.COM DLADM_TYPE_STR, bridge);
107610491SRishi.Srivatsavai@Sun.COM changed = B_TRUE;
107710491SRishi.Srivatsavai@Sun.COM } else if (has_oldbridge) {
107810491SRishi.Srivatsavai@Sun.COM status = dladm_unset_conf_field(handle, conf, FBRIDGE);
107910491SRishi.Srivatsavai@Sun.COM changed = B_TRUE;
108010491SRishi.Srivatsavai@Sun.COM } else {
108110491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_OK;
108210491SRishi.Srivatsavai@Sun.COM goto out;
108310491SRishi.Srivatsavai@Sun.COM }
108410491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK)
108510491SRishi.Srivatsavai@Sun.COM status = dladm_write_conf(handle, conf);
108610491SRishi.Srivatsavai@Sun.COM
108710491SRishi.Srivatsavai@Sun.COM out:
108810491SRishi.Srivatsavai@Sun.COM dladm_destroy_conf(handle, conf);
108910491SRishi.Srivatsavai@Sun.COM if (changed && status == DLADM_STATUS_OK) {
109010491SRishi.Srivatsavai@Sun.COM if (bridge[0] == '\0')
109110491SRishi.Srivatsavai@Sun.COM bridge = oldbridge;
109210491SRishi.Srivatsavai@Sun.COM status = bridge_refresh(bridge);
109310491SRishi.Srivatsavai@Sun.COM }
109410491SRishi.Srivatsavai@Sun.COM return (status);
109510491SRishi.Srivatsavai@Sun.COM }
109610491SRishi.Srivatsavai@Sun.COM
109710491SRishi.Srivatsavai@Sun.COM /*
109810491SRishi.Srivatsavai@Sun.COM * Get the name of the bridge of which the given linkid is a member.
109910491SRishi.Srivatsavai@Sun.COM */
110010491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_getlink(dladm_handle_t handle,datalink_id_t linkid,char * bridge,size_t bridgelen)110110491SRishi.Srivatsavai@Sun.COM dladm_bridge_getlink(dladm_handle_t handle, datalink_id_t linkid, char *bridge,
110210491SRishi.Srivatsavai@Sun.COM size_t bridgelen)
110310491SRishi.Srivatsavai@Sun.COM {
110410491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
110510491SRishi.Srivatsavai@Sun.COM dladm_conf_t conf;
110610491SRishi.Srivatsavai@Sun.COM
1107*12824SCathy.Zhou@Sun.COM if ((status = dladm_getsnap_conf(handle, linkid, &conf)) !=
110810491SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK)
110910491SRishi.Srivatsavai@Sun.COM return (status);
111010491SRishi.Srivatsavai@Sun.COM
111110491SRishi.Srivatsavai@Sun.COM *bridge = '\0';
111210491SRishi.Srivatsavai@Sun.COM status = dladm_get_conf_field(handle, conf, FBRIDGE, bridge, bridgelen);
111310491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK && *bridge == '\0')
111410491SRishi.Srivatsavai@Sun.COM status = DLADM_STATUS_NOTFOUND;
111510491SRishi.Srivatsavai@Sun.COM
111610491SRishi.Srivatsavai@Sun.COM dladm_destroy_conf(handle, conf);
111710491SRishi.Srivatsavai@Sun.COM return (status);
111810491SRishi.Srivatsavai@Sun.COM }
111910491SRishi.Srivatsavai@Sun.COM
112010491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_refresh(dladm_handle_t handle,datalink_id_t linkid)112110491SRishi.Srivatsavai@Sun.COM dladm_bridge_refresh(dladm_handle_t handle, datalink_id_t linkid)
112210491SRishi.Srivatsavai@Sun.COM {
112310491SRishi.Srivatsavai@Sun.COM char bridge[MAXLINKNAMELEN];
112410491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
112510491SRishi.Srivatsavai@Sun.COM
112610491SRishi.Srivatsavai@Sun.COM status = dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge));
112710491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_NOTFOUND)
112810491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_OK);
112910491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK)
113010491SRishi.Srivatsavai@Sun.COM status = bridge_refresh(bridge);
113110491SRishi.Srivatsavai@Sun.COM return (status);
113210491SRishi.Srivatsavai@Sun.COM }
113310491SRishi.Srivatsavai@Sun.COM
113410491SRishi.Srivatsavai@Sun.COM typedef struct bridge_held_arg_s {
113510491SRishi.Srivatsavai@Sun.COM const char *bha_bridge;
113610491SRishi.Srivatsavai@Sun.COM boolean_t bha_isheld;
113710491SRishi.Srivatsavai@Sun.COM } bridge_held_arg_t;
113810491SRishi.Srivatsavai@Sun.COM
113910491SRishi.Srivatsavai@Sun.COM static int
i_dladm_bridge_is_held(dladm_handle_t handle,datalink_id_t linkid,void * arg)114010491SRishi.Srivatsavai@Sun.COM i_dladm_bridge_is_held(dladm_handle_t handle, datalink_id_t linkid, void *arg)
114110491SRishi.Srivatsavai@Sun.COM {
114210491SRishi.Srivatsavai@Sun.COM dladm_status_t status = DLADM_STATUS_FAILED;
114310491SRishi.Srivatsavai@Sun.COM dladm_conf_t conf;
114410491SRishi.Srivatsavai@Sun.COM char bridge[MAXLINKNAMELEN];
1145*12824SCathy.Zhou@Sun.COM bridge_held_arg_t *bha = arg;
114610491SRishi.Srivatsavai@Sun.COM
1147*12824SCathy.Zhou@Sun.COM if ((status = dladm_getsnap_conf(handle, linkid, &conf)) !=
114810491SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK)
114910491SRishi.Srivatsavai@Sun.COM return (DLADM_WALK_CONTINUE);
115010491SRishi.Srivatsavai@Sun.COM status = dladm_get_conf_field(handle, conf, FBRIDGE, bridge,
115110491SRishi.Srivatsavai@Sun.COM sizeof (bridge));
115210491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK && strcmp(bha->bha_bridge, bridge) == 0) {
115310491SRishi.Srivatsavai@Sun.COM bha->bha_isheld = B_TRUE;
115410491SRishi.Srivatsavai@Sun.COM dladm_destroy_conf(handle, conf);
115510491SRishi.Srivatsavai@Sun.COM return (DLADM_WALK_TERMINATE);
115610491SRishi.Srivatsavai@Sun.COM } else {
115710491SRishi.Srivatsavai@Sun.COM dladm_destroy_conf(handle, conf);
115810491SRishi.Srivatsavai@Sun.COM return (DLADM_WALK_CONTINUE);
115910491SRishi.Srivatsavai@Sun.COM }
116010491SRishi.Srivatsavai@Sun.COM }
116110491SRishi.Srivatsavai@Sun.COM
116210491SRishi.Srivatsavai@Sun.COM /*
116310491SRishi.Srivatsavai@Sun.COM * Delete a previously created bridge.
116410491SRishi.Srivatsavai@Sun.COM */
116510491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_delete(dladm_handle_t handle,const char * bridge,uint32_t flags)116610491SRishi.Srivatsavai@Sun.COM dladm_bridge_delete(dladm_handle_t handle, const char *bridge, uint32_t flags)
116710491SRishi.Srivatsavai@Sun.COM {
116810491SRishi.Srivatsavai@Sun.COM datalink_id_t linkid;
116910491SRishi.Srivatsavai@Sun.COM datalink_class_t class;
117010491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
117110491SRishi.Srivatsavai@Sun.COM char linkname[MAXLINKNAMELEN];
117210491SRishi.Srivatsavai@Sun.COM
117310491SRishi.Srivatsavai@Sun.COM if (!dladm_valid_bridgename(bridge))
117410491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_LINKINVAL);
117510491SRishi.Srivatsavai@Sun.COM
117610491SRishi.Srivatsavai@Sun.COM /* Get the datalink ID for this bridge */
117710491SRishi.Srivatsavai@Sun.COM (void) snprintf(linkname, sizeof (linkname), "%s0", bridge);
117810491SRishi.Srivatsavai@Sun.COM if (dladm_name2info(handle, linkname, &linkid, NULL, NULL, NULL) !=
117910491SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK)
118010491SRishi.Srivatsavai@Sun.COM linkid = DATALINK_INVALID_LINKID;
118110491SRishi.Srivatsavai@Sun.COM else if (dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
118210491SRishi.Srivatsavai@Sun.COM NULL, 0) != DLADM_STATUS_OK)
118310491SRishi.Srivatsavai@Sun.COM linkid = DATALINK_INVALID_LINKID;
118410491SRishi.Srivatsavai@Sun.COM else if (class != DATALINK_CLASS_BRIDGE)
118510491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG);
118610491SRishi.Srivatsavai@Sun.COM
118710491SRishi.Srivatsavai@Sun.COM if ((flags & DLADM_OPT_ACTIVE) && linkid == DATALINK_INVALID_LINKID)
118810491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_BADARG);
118910491SRishi.Srivatsavai@Sun.COM
119010491SRishi.Srivatsavai@Sun.COM if (flags & DLADM_OPT_PERSIST) {
119110491SRishi.Srivatsavai@Sun.COM bridge_held_arg_t arg;
119210491SRishi.Srivatsavai@Sun.COM
119310491SRishi.Srivatsavai@Sun.COM arg.bha_bridge = bridge;
119410491SRishi.Srivatsavai@Sun.COM arg.bha_isheld = B_FALSE;
119510491SRishi.Srivatsavai@Sun.COM
119610491SRishi.Srivatsavai@Sun.COM /*
119710491SRishi.Srivatsavai@Sun.COM * See whether there are any persistent links using this
119810491SRishi.Srivatsavai@Sun.COM * bridge. If so, we fail the operation.
119910491SRishi.Srivatsavai@Sun.COM */
120010491SRishi.Srivatsavai@Sun.COM (void) dladm_walk_datalink_id(i_dladm_bridge_is_held, handle,
120110491SRishi.Srivatsavai@Sun.COM &arg, DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR |
120210491SRishi.Srivatsavai@Sun.COM DATALINK_CLASS_ETHERSTUB | DATALINK_CLASS_SIMNET,
120310491SRishi.Srivatsavai@Sun.COM DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
120410491SRishi.Srivatsavai@Sun.COM if (arg.bha_isheld)
120510491SRishi.Srivatsavai@Sun.COM return (DLADM_STATUS_LINKBUSY);
120610491SRishi.Srivatsavai@Sun.COM }
120710491SRishi.Srivatsavai@Sun.COM
120810491SRishi.Srivatsavai@Sun.COM if ((status = disable_trill(bridge, flags)) != DLADM_STATUS_OK)
120910491SRishi.Srivatsavai@Sun.COM goto out;
121010491SRishi.Srivatsavai@Sun.COM
121110491SRishi.Srivatsavai@Sun.COM /* Disable or remove the SMF instance */
121210491SRishi.Srivatsavai@Sun.COM status = shut_down_instance(BRIDGE_SVC_NAME, bridge, flags);
121310491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK)
121410491SRishi.Srivatsavai@Sun.COM goto out;
121510491SRishi.Srivatsavai@Sun.COM
121610491SRishi.Srivatsavai@Sun.COM if (flags & DLADM_OPT_ACTIVE) {
121710491SRishi.Srivatsavai@Sun.COM /*
121810491SRishi.Srivatsavai@Sun.COM * Delete ACTIVE linkprop now that daemon is gone.
121910491SRishi.Srivatsavai@Sun.COM */
122010491SRishi.Srivatsavai@Sun.COM (void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0,
122110491SRishi.Srivatsavai@Sun.COM DLADM_OPT_ACTIVE);
122210491SRishi.Srivatsavai@Sun.COM (void) dladm_destroy_datalink_id(handle, linkid,
122310491SRishi.Srivatsavai@Sun.COM DLADM_OPT_ACTIVE);
122410491SRishi.Srivatsavai@Sun.COM }
122510491SRishi.Srivatsavai@Sun.COM
122610491SRishi.Srivatsavai@Sun.COM if (flags & DLADM_OPT_PERSIST) {
122710491SRishi.Srivatsavai@Sun.COM (void) dladm_remove_conf(handle, linkid);
122810491SRishi.Srivatsavai@Sun.COM (void) dladm_destroy_datalink_id(handle, linkid,
122910491SRishi.Srivatsavai@Sun.COM DLADM_OPT_PERSIST);
123010491SRishi.Srivatsavai@Sun.COM }
123110491SRishi.Srivatsavai@Sun.COM
123210491SRishi.Srivatsavai@Sun.COM out:
123310491SRishi.Srivatsavai@Sun.COM
123410491SRishi.Srivatsavai@Sun.COM return (status);
123510491SRishi.Srivatsavai@Sun.COM }
123610491SRishi.Srivatsavai@Sun.COM
123710491SRishi.Srivatsavai@Sun.COM /* Check if given name is valid for bridges */
123810491SRishi.Srivatsavai@Sun.COM boolean_t
dladm_valid_bridgename(const char * bridge)123910491SRishi.Srivatsavai@Sun.COM dladm_valid_bridgename(const char *bridge)
124010491SRishi.Srivatsavai@Sun.COM {
124110491SRishi.Srivatsavai@Sun.COM size_t len = strnlen(bridge, MAXLINKNAMELEN);
124210491SRishi.Srivatsavai@Sun.COM const char *cp;
124310491SRishi.Srivatsavai@Sun.COM
124410491SRishi.Srivatsavai@Sun.COM if (len == MAXLINKNAMELEN)
124510491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
124610491SRishi.Srivatsavai@Sun.COM
124710491SRishi.Srivatsavai@Sun.COM /*
124810491SRishi.Srivatsavai@Sun.COM * The bridge name cannot start or end with a digit.
124910491SRishi.Srivatsavai@Sun.COM */
125010491SRishi.Srivatsavai@Sun.COM if (isdigit(bridge[0]) || isdigit(bridge[len - 1]))
125110491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
125210491SRishi.Srivatsavai@Sun.COM
125310491SRishi.Srivatsavai@Sun.COM /*
125410491SRishi.Srivatsavai@Sun.COM * The legal characters within a bridge name are:
125510491SRishi.Srivatsavai@Sun.COM * alphanumeric (a-z, A-Z, 0-9), and the underscore ('_').
125610491SRishi.Srivatsavai@Sun.COM */
125710491SRishi.Srivatsavai@Sun.COM for (cp = bridge; *cp != '\0'; cp++) {
125810491SRishi.Srivatsavai@Sun.COM if (!isalnum(*cp) && *cp != '_')
125910491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
126010491SRishi.Srivatsavai@Sun.COM }
126110491SRishi.Srivatsavai@Sun.COM
126210491SRishi.Srivatsavai@Sun.COM return (B_TRUE);
126310491SRishi.Srivatsavai@Sun.COM }
126410491SRishi.Srivatsavai@Sun.COM
126510491SRishi.Srivatsavai@Sun.COM /*
126610491SRishi.Srivatsavai@Sun.COM * Convert a bridge-related observability node name back into the name of the
126710491SRishi.Srivatsavai@Sun.COM * bridge. Returns B_FALSE without making changes if the input name is not in
126810491SRishi.Srivatsavai@Sun.COM * a legal format.
126910491SRishi.Srivatsavai@Sun.COM */
127010491SRishi.Srivatsavai@Sun.COM boolean_t
dladm_observe_to_bridge(char * link)127110491SRishi.Srivatsavai@Sun.COM dladm_observe_to_bridge(char *link)
127210491SRishi.Srivatsavai@Sun.COM {
127310491SRishi.Srivatsavai@Sun.COM int llen;
127410491SRishi.Srivatsavai@Sun.COM
127510491SRishi.Srivatsavai@Sun.COM llen = strnlen(link, MAXLINKNAMELEN);
127610491SRishi.Srivatsavai@Sun.COM if (llen < 2 || link[llen - 1] != '0' || isdigit(link[llen - 2]))
127710491SRishi.Srivatsavai@Sun.COM return (B_FALSE);
127810491SRishi.Srivatsavai@Sun.COM link[llen - 1] = '\0';
127910491SRishi.Srivatsavai@Sun.COM return (B_TRUE);
128010491SRishi.Srivatsavai@Sun.COM }
128110491SRishi.Srivatsavai@Sun.COM
128210491SRishi.Srivatsavai@Sun.COM /*
128310491SRishi.Srivatsavai@Sun.COM * Get bridge property values from the running daemon and return them in a
128410491SRishi.Srivatsavai@Sun.COM * common structure.
128510491SRishi.Srivatsavai@Sun.COM */
128610491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_run_properties(const char * instname,UID_STP_CFG_T * smcfg,dladm_bridge_prot_t * brprotp)128710491SRishi.Srivatsavai@Sun.COM dladm_bridge_run_properties(const char *instname, UID_STP_CFG_T *smcfg,
128810491SRishi.Srivatsavai@Sun.COM dladm_bridge_prot_t *brprotp)
128910491SRishi.Srivatsavai@Sun.COM {
129010491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
129110491SRishi.Srivatsavai@Sun.COM bridge_door_cfg_t bdcf;
129210491SRishi.Srivatsavai@Sun.COM bridge_door_cfg_t *bdcfp = &bdcf;
129310491SRishi.Srivatsavai@Sun.COM size_t buflen = sizeof (bdcf);
129410491SRishi.Srivatsavai@Sun.COM
129510491SRishi.Srivatsavai@Sun.COM status = bridge_door_call(instname, bdcBridgeGetConfig,
129610491SRishi.Srivatsavai@Sun.COM DATALINK_INVALID_LINKID, (void **)&bdcfp, 0, &buflen, B_FALSE);
129710491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK) {
129810491SRishi.Srivatsavai@Sun.COM *smcfg = bdcfp->bdcf_cfg;
129910491SRishi.Srivatsavai@Sun.COM *brprotp = bdcfp->bdcf_prot;
130010491SRishi.Srivatsavai@Sun.COM } else {
130110491SRishi.Srivatsavai@Sun.COM smcfg->field_mask = 0;
130210491SRishi.Srivatsavai@Sun.COM *brprotp = DLADM_BRIDGE_PROT_STP;
130310491SRishi.Srivatsavai@Sun.COM }
130410491SRishi.Srivatsavai@Sun.COM return (status);
130510491SRishi.Srivatsavai@Sun.COM }
130610491SRishi.Srivatsavai@Sun.COM
130710491SRishi.Srivatsavai@Sun.COM /*
130810491SRishi.Srivatsavai@Sun.COM * Get bridge state from the running daemon and return in structure borrowed
130910491SRishi.Srivatsavai@Sun.COM * from librstp.
131010491SRishi.Srivatsavai@Sun.COM */
131110491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_state(const char * instname,UID_STP_STATE_T * statep)131210491SRishi.Srivatsavai@Sun.COM dladm_bridge_state(const char *instname, UID_STP_STATE_T *statep)
131310491SRishi.Srivatsavai@Sun.COM {
131410491SRishi.Srivatsavai@Sun.COM size_t buflen = sizeof (*statep);
131510491SRishi.Srivatsavai@Sun.COM
131610491SRishi.Srivatsavai@Sun.COM return (bridge_door_call(instname, bdcBridgeGetState,
131710491SRishi.Srivatsavai@Sun.COM DATALINK_INVALID_LINKID, (void **)&statep, 0, &buflen, B_FALSE));
131810491SRishi.Srivatsavai@Sun.COM }
131910491SRishi.Srivatsavai@Sun.COM
132010491SRishi.Srivatsavai@Sun.COM /* Returns list of ports (datalink_id_t values) assigned to a bridge instance */
132110491SRishi.Srivatsavai@Sun.COM datalink_id_t *
dladm_bridge_get_portlist(const char * instname,uint_t * nports)132210491SRishi.Srivatsavai@Sun.COM dladm_bridge_get_portlist(const char *instname, uint_t *nports)
132310491SRishi.Srivatsavai@Sun.COM {
132410491SRishi.Srivatsavai@Sun.COM size_t buflen = sizeof (int) + MAXPORTS * sizeof (datalink_id_t);
132510491SRishi.Srivatsavai@Sun.COM int *rbuf;
132610491SRishi.Srivatsavai@Sun.COM
132710491SRishi.Srivatsavai@Sun.COM if ((rbuf = malloc(buflen)) == NULL)
132810491SRishi.Srivatsavai@Sun.COM return (NULL);
132910491SRishi.Srivatsavai@Sun.COM if (bridge_door_call(instname, bdcBridgeGetPorts,
133010491SRishi.Srivatsavai@Sun.COM DATALINK_INVALID_LINKID, (void **)&rbuf, 0, &buflen, B_TRUE) !=
133110491SRishi.Srivatsavai@Sun.COM DLADM_STATUS_OK) {
133210491SRishi.Srivatsavai@Sun.COM free(rbuf);
133310491SRishi.Srivatsavai@Sun.COM return (NULL);
133410491SRishi.Srivatsavai@Sun.COM } else {
133510491SRishi.Srivatsavai@Sun.COM /*
133610491SRishi.Srivatsavai@Sun.COM * Returns an array of datalink_id_t values for all the ports
133710491SRishi.Srivatsavai@Sun.COM * part of the bridge instance. First entry in the array is the
133810491SRishi.Srivatsavai@Sun.COM * number of ports.
133910491SRishi.Srivatsavai@Sun.COM */
134010491SRishi.Srivatsavai@Sun.COM *nports = *rbuf;
134110491SRishi.Srivatsavai@Sun.COM return ((datalink_id_t *)(rbuf + 1));
134210491SRishi.Srivatsavai@Sun.COM }
134310491SRishi.Srivatsavai@Sun.COM }
134410491SRishi.Srivatsavai@Sun.COM
134510491SRishi.Srivatsavai@Sun.COM void
dladm_bridge_free_portlist(datalink_id_t * dlp)134610491SRishi.Srivatsavai@Sun.COM dladm_bridge_free_portlist(datalink_id_t *dlp)
134710491SRishi.Srivatsavai@Sun.COM {
134810491SRishi.Srivatsavai@Sun.COM free((int *)dlp - 1);
134910491SRishi.Srivatsavai@Sun.COM }
135010491SRishi.Srivatsavai@Sun.COM
135110491SRishi.Srivatsavai@Sun.COM /* Retrieve Bridge port configuration values */
135210491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_get_port_cfg(dladm_handle_t handle,datalink_id_t linkid,int field,int * valuep)135310491SRishi.Srivatsavai@Sun.COM dladm_bridge_get_port_cfg(dladm_handle_t handle, datalink_id_t linkid,
135410491SRishi.Srivatsavai@Sun.COM int field, int *valuep)
135510491SRishi.Srivatsavai@Sun.COM {
135610491SRishi.Srivatsavai@Sun.COM UID_STP_PORT_CFG_T portcfg;
135710491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
135810491SRishi.Srivatsavai@Sun.COM
135910491SRishi.Srivatsavai@Sun.COM status = port_door_call(handle, linkid, bdcPortGetConfig, &portcfg,
136010491SRishi.Srivatsavai@Sun.COM 0, sizeof (portcfg));
136110491SRishi.Srivatsavai@Sun.COM if (status != DLADM_STATUS_OK)
136210491SRishi.Srivatsavai@Sun.COM return (status);
136310491SRishi.Srivatsavai@Sun.COM
136410491SRishi.Srivatsavai@Sun.COM switch (field) {
136510491SRishi.Srivatsavai@Sun.COM case PT_CFG_COST:
136610491SRishi.Srivatsavai@Sun.COM *valuep = portcfg.admin_port_path_cost;
136710491SRishi.Srivatsavai@Sun.COM break;
136810491SRishi.Srivatsavai@Sun.COM case PT_CFG_PRIO:
136910491SRishi.Srivatsavai@Sun.COM *valuep = portcfg.port_priority;
137010491SRishi.Srivatsavai@Sun.COM break;
137110491SRishi.Srivatsavai@Sun.COM case PT_CFG_P2P:
137210491SRishi.Srivatsavai@Sun.COM *valuep = portcfg.admin_point2point;
137310491SRishi.Srivatsavai@Sun.COM break;
137410491SRishi.Srivatsavai@Sun.COM case PT_CFG_EDGE:
137510491SRishi.Srivatsavai@Sun.COM *valuep = portcfg.admin_edge;
137610491SRishi.Srivatsavai@Sun.COM break;
137710491SRishi.Srivatsavai@Sun.COM case PT_CFG_NON_STP:
137810491SRishi.Srivatsavai@Sun.COM *valuep = !portcfg.admin_non_stp;
137910491SRishi.Srivatsavai@Sun.COM break;
138010491SRishi.Srivatsavai@Sun.COM case PT_CFG_MCHECK:
138110491SRishi.Srivatsavai@Sun.COM *valuep = (portcfg.field_mask & PT_CFG_MCHECK) ? 1 : 0;
138210491SRishi.Srivatsavai@Sun.COM break;
138310491SRishi.Srivatsavai@Sun.COM }
138410491SRishi.Srivatsavai@Sun.COM return (status);
138510491SRishi.Srivatsavai@Sun.COM }
138610491SRishi.Srivatsavai@Sun.COM
138710491SRishi.Srivatsavai@Sun.COM /* Retreive Bridge port status (disabled, bad SDU etc.) */
138810491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_link_state(dladm_handle_t handle,datalink_id_t linkid,UID_STP_PORT_STATE_T * spsp)138910491SRishi.Srivatsavai@Sun.COM dladm_bridge_link_state(dladm_handle_t handle, datalink_id_t linkid,
139010491SRishi.Srivatsavai@Sun.COM UID_STP_PORT_STATE_T *spsp)
139110491SRishi.Srivatsavai@Sun.COM {
139210491SRishi.Srivatsavai@Sun.COM return (port_door_call(handle, linkid, bdcPortGetState, spsp, 0,
139310491SRishi.Srivatsavai@Sun.COM sizeof (*spsp)));
139410491SRishi.Srivatsavai@Sun.COM }
139510491SRishi.Srivatsavai@Sun.COM
139610491SRishi.Srivatsavai@Sun.COM /* Retrieve Bridge forwarding status of the given link */
139710491SRishi.Srivatsavai@Sun.COM dladm_status_t
dladm_bridge_get_forwarding(dladm_handle_t handle,datalink_id_t linkid,uint_t * valuep)139810491SRishi.Srivatsavai@Sun.COM dladm_bridge_get_forwarding(dladm_handle_t handle, datalink_id_t linkid,
139910491SRishi.Srivatsavai@Sun.COM uint_t *valuep)
140010491SRishi.Srivatsavai@Sun.COM {
140110491SRishi.Srivatsavai@Sun.COM int twoints[2];
140210491SRishi.Srivatsavai@Sun.COM dladm_status_t status;
140310491SRishi.Srivatsavai@Sun.COM
140410491SRishi.Srivatsavai@Sun.COM status = port_door_call(handle, linkid, bdcPortGetForwarding, twoints,
140510491SRishi.Srivatsavai@Sun.COM 0, sizeof (twoints));
140610491SRishi.Srivatsavai@Sun.COM if (status == DLADM_STATUS_OK)
140710491SRishi.Srivatsavai@Sun.COM *valuep = twoints[0];
140810491SRishi.Srivatsavai@Sun.COM return (status);
140910491SRishi.Srivatsavai@Sun.COM }
141010491SRishi.Srivatsavai@Sun.COM
141110491SRishi.Srivatsavai@Sun.COM /* Retrieve Bridge forwarding table entries */
141210491SRishi.Srivatsavai@Sun.COM bridge_listfwd_t *
dladm_bridge_get_fwdtable(dladm_handle_t handle,const char * bridge,uint_t * nfwd)141310491SRishi.Srivatsavai@Sun.COM dladm_bridge_get_fwdtable(dladm_handle_t handle, const char *bridge,
141410491SRishi.Srivatsavai@Sun.COM uint_t *nfwd)
141510491SRishi.Srivatsavai@Sun.COM {
141610491SRishi.Srivatsavai@Sun.COM bridge_listfwd_t *blf = NULL, *newblf, blfread;
141710491SRishi.Srivatsavai@Sun.COM uint_t nblf = 0, maxblf = 0;
141810491SRishi.Srivatsavai@Sun.COM static uint8_t zero_addr[ETHERADDRL];
141910491SRishi.Srivatsavai@Sun.COM int rc;
142010491SRishi.Srivatsavai@Sun.COM
142110491SRishi.Srivatsavai@Sun.COM (void) memset(&blfread, 0, sizeof (blfread));
142210491SRishi.Srivatsavai@Sun.COM (void) snprintf(blfread.blf_name, sizeof (blfread.blf_name),
142310491SRishi.Srivatsavai@Sun.COM "%s0", bridge);
142410491SRishi.Srivatsavai@Sun.COM for (;;) {
142510491SRishi.Srivatsavai@Sun.COM if (nblf >= maxblf) {
142610491SRishi.Srivatsavai@Sun.COM maxblf = maxblf == 0 ? 64 : (maxblf << 1);
142710491SRishi.Srivatsavai@Sun.COM newblf = realloc(blf, maxblf * sizeof (*blf));
142810491SRishi.Srivatsavai@Sun.COM if (newblf == NULL) {
142910491SRishi.Srivatsavai@Sun.COM free(blf);
143010491SRishi.Srivatsavai@Sun.COM blf = NULL;
143110491SRishi.Srivatsavai@Sun.COM break;
143210491SRishi.Srivatsavai@Sun.COM }
143310491SRishi.Srivatsavai@Sun.COM blf = newblf;
143410491SRishi.Srivatsavai@Sun.COM }
143510491SRishi.Srivatsavai@Sun.COM rc = ioctl(dladm_dld_fd(handle), BRIDGE_IOC_LISTFWD, &blfread);
143610491SRishi.Srivatsavai@Sun.COM if (rc != 0) {
143710491SRishi.Srivatsavai@Sun.COM free(blf);
143810491SRishi.Srivatsavai@Sun.COM blf = NULL;
143910491SRishi.Srivatsavai@Sun.COM break;
144010491SRishi.Srivatsavai@Sun.COM }
144110491SRishi.Srivatsavai@Sun.COM if (memcmp(blfread.blf_dest, zero_addr, ETHERADDRL) == 0)
144210491SRishi.Srivatsavai@Sun.COM break;
144310491SRishi.Srivatsavai@Sun.COM blf[nblf++] = blfread;
144410491SRishi.Srivatsavai@Sun.COM }
144510491SRishi.Srivatsavai@Sun.COM if (blf != NULL)
144610491SRishi.Srivatsavai@Sun.COM *nfwd = nblf;
144710491SRishi.Srivatsavai@Sun.COM return (blf);
144810491SRishi.Srivatsavai@Sun.COM }
144910491SRishi.Srivatsavai@Sun.COM
145010491SRishi.Srivatsavai@Sun.COM void
dladm_bridge_free_fwdtable(bridge_listfwd_t * blf)145110491SRishi.Srivatsavai@Sun.COM dladm_bridge_free_fwdtable(bridge_listfwd_t *blf)
145210491SRishi.Srivatsavai@Sun.COM {
145310491SRishi.Srivatsavai@Sun.COM free(blf);
145410491SRishi.Srivatsavai@Sun.COM }
145510491SRishi.Srivatsavai@Sun.COM
145610491SRishi.Srivatsavai@Sun.COM /* Retrieve list of TRILL nicknames from the TRILL module */
145710491SRishi.Srivatsavai@Sun.COM trill_listnick_t *
dladm_bridge_get_trillnick(const char * bridge,uint_t * nnick)145810491SRishi.Srivatsavai@Sun.COM dladm_bridge_get_trillnick(const char *bridge, uint_t *nnick)
145910491SRishi.Srivatsavai@Sun.COM {
146010491SRishi.Srivatsavai@Sun.COM int fd;
146110491SRishi.Srivatsavai@Sun.COM char brcopy[MAXLINKNAMELEN];
146210491SRishi.Srivatsavai@Sun.COM trill_listnick_t *tln = NULL, *newtln, tlnread;
146310491SRishi.Srivatsavai@Sun.COM uint_t ntln = 0, maxtln = 0;
146410491SRishi.Srivatsavai@Sun.COM
146510491SRishi.Srivatsavai@Sun.COM if ((fd = socket(PF_TRILL, SOCK_DGRAM, 0)) == -1)
146610491SRishi.Srivatsavai@Sun.COM return (NULL);
146710491SRishi.Srivatsavai@Sun.COM (void) strlcpy(brcopy, bridge, sizeof (brcopy));
146810491SRishi.Srivatsavai@Sun.COM if (ioctl(fd, TRILL_GETBRIDGE, &brcopy) < 0) {
146910491SRishi.Srivatsavai@Sun.COM (void) close(fd);
147010491SRishi.Srivatsavai@Sun.COM return (NULL);
147110491SRishi.Srivatsavai@Sun.COM }
147210491SRishi.Srivatsavai@Sun.COM (void) memset(&tlnread, 0, sizeof (tlnread));
147310491SRishi.Srivatsavai@Sun.COM for (;;) {
147410491SRishi.Srivatsavai@Sun.COM if (ntln >= maxtln) {
147510491SRishi.Srivatsavai@Sun.COM maxtln = maxtln == 0 ? 64 : (maxtln << 1);
147610491SRishi.Srivatsavai@Sun.COM newtln = realloc(tln, maxtln * sizeof (*tln));
147710491SRishi.Srivatsavai@Sun.COM if (newtln == NULL) {
147810491SRishi.Srivatsavai@Sun.COM free(tln);
147910491SRishi.Srivatsavai@Sun.COM tln = NULL;
148010491SRishi.Srivatsavai@Sun.COM break;
148110491SRishi.Srivatsavai@Sun.COM }
148210491SRishi.Srivatsavai@Sun.COM tln = newtln;
148310491SRishi.Srivatsavai@Sun.COM }
148410491SRishi.Srivatsavai@Sun.COM if (ioctl(fd, TRILL_LISTNICK, &tlnread) == -1) {
148510491SRishi.Srivatsavai@Sun.COM free(tln);
148610491SRishi.Srivatsavai@Sun.COM tln = NULL;
148710491SRishi.Srivatsavai@Sun.COM break;
148810491SRishi.Srivatsavai@Sun.COM }
148910491SRishi.Srivatsavai@Sun.COM if (tlnread.tln_nick == 0)
149010491SRishi.Srivatsavai@Sun.COM break;
149110491SRishi.Srivatsavai@Sun.COM tln[ntln++] = tlnread;
149210491SRishi.Srivatsavai@Sun.COM }
149310491SRishi.Srivatsavai@Sun.COM (void) close(fd);
149410491SRishi.Srivatsavai@Sun.COM if (tln != NULL)
149510491SRishi.Srivatsavai@Sun.COM *nnick = ntln;
149610491SRishi.Srivatsavai@Sun.COM return (tln);
149710491SRishi.Srivatsavai@Sun.COM }
149810491SRishi.Srivatsavai@Sun.COM
149910491SRishi.Srivatsavai@Sun.COM void
dladm_bridge_free_trillnick(trill_listnick_t * tln)150010491SRishi.Srivatsavai@Sun.COM dladm_bridge_free_trillnick(trill_listnick_t *tln)
150110491SRishi.Srivatsavai@Sun.COM {
150210491SRishi.Srivatsavai@Sun.COM free(tln);
150310491SRishi.Srivatsavai@Sun.COM }
150410491SRishi.Srivatsavai@Sun.COM
150510491SRishi.Srivatsavai@Sun.COM /* Retrieve any stored TRILL nickname from TRILL SMF service */
150610491SRishi.Srivatsavai@Sun.COM uint16_t
dladm_bridge_get_nick(const char * bridge)150710491SRishi.Srivatsavai@Sun.COM dladm_bridge_get_nick(const char *bridge)
150810491SRishi.Srivatsavai@Sun.COM {
150910491SRishi.Srivatsavai@Sun.COM scf_state_t sstate;
151010491SRishi.Srivatsavai@Sun.COM uint64_t value;
151110491SRishi.Srivatsavai@Sun.COM uint16_t nickname = RBRIDGE_NICKNAME_NONE;
151210491SRishi.Srivatsavai@Sun.COM
151310491SRishi.Srivatsavai@Sun.COM if (bind_instance(TRILL_SVC_NAME, bridge, &sstate) != 0)
151410491SRishi.Srivatsavai@Sun.COM return (nickname);
151510491SRishi.Srivatsavai@Sun.COM
151610491SRishi.Srivatsavai@Sun.COM if (get_composed_properties("config", B_TRUE, &sstate) == 0 &&
151710491SRishi.Srivatsavai@Sun.COM get_count("nickname", &sstate, &value) == 0)
151810491SRishi.Srivatsavai@Sun.COM nickname = value;
151910491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
152010491SRishi.Srivatsavai@Sun.COM return (nickname);
152110491SRishi.Srivatsavai@Sun.COM }
152210491SRishi.Srivatsavai@Sun.COM
152310491SRishi.Srivatsavai@Sun.COM /* Stores TRILL nickname in SMF configuraiton for the TRILL service */
152410491SRishi.Srivatsavai@Sun.COM void
dladm_bridge_set_nick(const char * bridge,uint16_t nick)152510491SRishi.Srivatsavai@Sun.COM dladm_bridge_set_nick(const char *bridge, uint16_t nick)
152610491SRishi.Srivatsavai@Sun.COM {
152710491SRishi.Srivatsavai@Sun.COM scf_state_t sstate;
152810491SRishi.Srivatsavai@Sun.COM scf_transaction_t *tran = NULL;
152910491SRishi.Srivatsavai@Sun.COM boolean_t new_pg = B_FALSE;
153010491SRishi.Srivatsavai@Sun.COM int rv = 0;
153110491SRishi.Srivatsavai@Sun.COM char *fmri;
153210491SRishi.Srivatsavai@Sun.COM
153310491SRishi.Srivatsavai@Sun.COM if (exact_instance(TRILL_SVC_NAME, &sstate) != DLADM_STATUS_OK)
153410491SRishi.Srivatsavai@Sun.COM return;
153510491SRishi.Srivatsavai@Sun.COM
153610491SRishi.Srivatsavai@Sun.COM if (scf_service_get_instance(sstate.ss_svc, bridge, sstate.ss_inst) !=
153710491SRishi.Srivatsavai@Sun.COM 0)
153810491SRishi.Srivatsavai@Sun.COM goto out;
153910491SRishi.Srivatsavai@Sun.COM if ((tran = scf_transaction_create(sstate.ss_handle)) == NULL)
154010491SRishi.Srivatsavai@Sun.COM goto out;
154110491SRishi.Srivatsavai@Sun.COM if ((sstate.ss_pg = scf_pg_create(sstate.ss_handle)) == NULL)
154210491SRishi.Srivatsavai@Sun.COM goto out;
154310491SRishi.Srivatsavai@Sun.COM if (scf_instance_add_pg(sstate.ss_inst, "config",
154410491SRishi.Srivatsavai@Sun.COM SCF_GROUP_APPLICATION, 0, sstate.ss_pg) == 0) {
154510491SRishi.Srivatsavai@Sun.COM new_pg = B_TRUE;
154610491SRishi.Srivatsavai@Sun.COM } else if (scf_instance_get_pg(sstate.ss_inst, "config",
154710491SRishi.Srivatsavai@Sun.COM sstate.ss_pg) != 0) {
154810491SRishi.Srivatsavai@Sun.COM goto out;
154910491SRishi.Srivatsavai@Sun.COM }
155010491SRishi.Srivatsavai@Sun.COM do {
155110491SRishi.Srivatsavai@Sun.COM if (scf_transaction_start(tran, sstate.ss_pg) != 0)
155210491SRishi.Srivatsavai@Sun.COM goto out;
155310491SRishi.Srivatsavai@Sun.COM if (!set_count_property(sstate.ss_handle, tran, "nickname",
155410491SRishi.Srivatsavai@Sun.COM nick))
155510491SRishi.Srivatsavai@Sun.COM goto out;
155610491SRishi.Srivatsavai@Sun.COM rv = scf_transaction_commit(tran);
155710491SRishi.Srivatsavai@Sun.COM scf_transaction_reset(tran);
155810491SRishi.Srivatsavai@Sun.COM if (rv == 0 && scf_pg_update(sstate.ss_pg) == -1)
155910491SRishi.Srivatsavai@Sun.COM goto out;
156010491SRishi.Srivatsavai@Sun.COM } while (rv == 0);
156110491SRishi.Srivatsavai@Sun.COM
156210491SRishi.Srivatsavai@Sun.COM out:
156310491SRishi.Srivatsavai@Sun.COM if (tran != NULL) {
156410491SRishi.Srivatsavai@Sun.COM scf_transaction_destroy_children(tran);
156510491SRishi.Srivatsavai@Sun.COM scf_transaction_destroy(tran);
156610491SRishi.Srivatsavai@Sun.COM }
156710491SRishi.Srivatsavai@Sun.COM
156810491SRishi.Srivatsavai@Sun.COM if (rv != 1 && new_pg)
156910491SRishi.Srivatsavai@Sun.COM (void) scf_pg_delete(sstate.ss_pg);
157010491SRishi.Srivatsavai@Sun.COM
157110491SRishi.Srivatsavai@Sun.COM drop_composed(&sstate);
157210491SRishi.Srivatsavai@Sun.COM shut_down_scf(&sstate);
157310491SRishi.Srivatsavai@Sun.COM if (rv == 1 && (fmri = alloc_fmri(TRILL_SVC_NAME, bridge)) != NULL) {
157410491SRishi.Srivatsavai@Sun.COM (void) smf_refresh_instance(fmri);
157510491SRishi.Srivatsavai@Sun.COM free(fmri);
157610491SRishi.Srivatsavai@Sun.COM }
157710491SRishi.Srivatsavai@Sun.COM }
1578