14eaa4710SRishi Srivatsavai /* 24eaa4710SRishi Srivatsavai * CDDL HEADER START 34eaa4710SRishi Srivatsavai * 44eaa4710SRishi Srivatsavai * The contents of this file are subject to the terms of the 54eaa4710SRishi Srivatsavai * Common Development and Distribution License (the "License"). 64eaa4710SRishi Srivatsavai * You may not use this file except in compliance with the License. 74eaa4710SRishi Srivatsavai * 84eaa4710SRishi Srivatsavai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94eaa4710SRishi Srivatsavai * or http://www.opensolaris.org/os/licensing. 104eaa4710SRishi Srivatsavai * See the License for the specific language governing permissions 114eaa4710SRishi Srivatsavai * and limitations under the License. 124eaa4710SRishi Srivatsavai * 134eaa4710SRishi Srivatsavai * When distributing Covered Code, include this CDDL HEADER in each 144eaa4710SRishi Srivatsavai * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154eaa4710SRishi Srivatsavai * If applicable, add the following below this CDDL HEADER, with the 164eaa4710SRishi Srivatsavai * fields enclosed by brackets "[]" replaced with your own identifying 174eaa4710SRishi Srivatsavai * information: Portions Copyright [yyyy] [name of copyright owner] 184eaa4710SRishi Srivatsavai * 194eaa4710SRishi Srivatsavai * CDDL HEADER END 204eaa4710SRishi Srivatsavai */ 214eaa4710SRishi Srivatsavai /* 224eaa4710SRishi Srivatsavai * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 234eaa4710SRishi Srivatsavai * Use is subject to license terms. 244eaa4710SRishi Srivatsavai */ 254eaa4710SRishi Srivatsavai 264eaa4710SRishi Srivatsavai #include <stdio.h> 274eaa4710SRishi Srivatsavai #include <sys/types.h> 284eaa4710SRishi Srivatsavai #include <string.h> 294eaa4710SRishi Srivatsavai #include <fcntl.h> 304eaa4710SRishi Srivatsavai #include <unistd.h> 314eaa4710SRishi Srivatsavai #include <stropts.h> 324eaa4710SRishi Srivatsavai #include <ctype.h> 334eaa4710SRishi Srivatsavai #include <errno.h> 344eaa4710SRishi Srivatsavai #include <stdlib.h> 354eaa4710SRishi Srivatsavai #include <door.h> 364eaa4710SRishi Srivatsavai #include <sys/mman.h> 374eaa4710SRishi Srivatsavai #include <libscf.h> 384eaa4710SRishi Srivatsavai #include <libscf_priv.h> 394eaa4710SRishi Srivatsavai #include <libdllink.h> 404eaa4710SRishi Srivatsavai #include <libdlbridge.h> 414eaa4710SRishi Srivatsavai #include <libdladm_impl.h> 424eaa4710SRishi Srivatsavai #include <stp_in.h> 434eaa4710SRishi Srivatsavai #include <net/bridge.h> 444eaa4710SRishi Srivatsavai #include <net/trill.h> 454eaa4710SRishi Srivatsavai #include <sys/socket.h> 46*56a3cd3dSRishi Srivatsavai #include <sys/dld_ioc.h> 474eaa4710SRishi Srivatsavai 484eaa4710SRishi Srivatsavai /* 494eaa4710SRishi Srivatsavai * Bridge Administration Library. 504eaa4710SRishi Srivatsavai * 514eaa4710SRishi Srivatsavai * This library is used by administration tools such as dladm(1M) to configure 524eaa4710SRishi Srivatsavai * bridges, and by the bridge daemon to retrieve configuration information. 534eaa4710SRishi Srivatsavai */ 544eaa4710SRishi Srivatsavai 554eaa4710SRishi Srivatsavai #define BRIDGE_SVC_NAME "network/bridge" 564eaa4710SRishi Srivatsavai #define TRILL_SVC_NAME "network/routing/trill" 574eaa4710SRishi Srivatsavai 584eaa4710SRishi Srivatsavai #define DEFAULT_TIMEOUT 60000000 594eaa4710SRishi Srivatsavai #define INIT_WAIT_USECS 50000 604eaa4710SRishi Srivatsavai #define MAXPORTS 256 614eaa4710SRishi Srivatsavai 624eaa4710SRishi Srivatsavai typedef struct scf_state { 634eaa4710SRishi Srivatsavai scf_handle_t *ss_handle; 644eaa4710SRishi Srivatsavai scf_instance_t *ss_inst; 654eaa4710SRishi Srivatsavai scf_service_t *ss_svc; 664eaa4710SRishi Srivatsavai scf_snapshot_t *ss_snap; 674eaa4710SRishi Srivatsavai scf_propertygroup_t *ss_pg; 684eaa4710SRishi Srivatsavai scf_property_t *ss_prop; 694eaa4710SRishi Srivatsavai } scf_state_t; 704eaa4710SRishi Srivatsavai 714eaa4710SRishi Srivatsavai static void 724eaa4710SRishi Srivatsavai shut_down_scf(scf_state_t *sstate) 734eaa4710SRishi Srivatsavai { 744eaa4710SRishi Srivatsavai scf_instance_destroy(sstate->ss_inst); 754eaa4710SRishi Srivatsavai (void) scf_handle_unbind(sstate->ss_handle); 764eaa4710SRishi Srivatsavai scf_handle_destroy(sstate->ss_handle); 774eaa4710SRishi Srivatsavai } 784eaa4710SRishi Srivatsavai 794eaa4710SRishi Srivatsavai static char * 804eaa4710SRishi Srivatsavai alloc_fmri(const char *service, const char *instance_name) 814eaa4710SRishi Srivatsavai { 824eaa4710SRishi Srivatsavai ssize_t max_fmri; 834eaa4710SRishi Srivatsavai char *fmri; 844eaa4710SRishi Srivatsavai 854eaa4710SRishi Srivatsavai /* If the limit is unknown, then use an arbitrary value */ 864eaa4710SRishi Srivatsavai if ((max_fmri = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH)) == -1) 874eaa4710SRishi Srivatsavai max_fmri = 1024; 884eaa4710SRishi Srivatsavai if ((fmri = malloc(max_fmri)) != NULL) { 894eaa4710SRishi Srivatsavai (void) snprintf(fmri, max_fmri, "svc:/%s:%s", service, 904eaa4710SRishi Srivatsavai instance_name); 914eaa4710SRishi Srivatsavai } 924eaa4710SRishi Srivatsavai return (fmri); 934eaa4710SRishi Srivatsavai } 944eaa4710SRishi Srivatsavai 954eaa4710SRishi Srivatsavai /* 964eaa4710SRishi Srivatsavai * Start up SCF and bind the requested instance alone. 974eaa4710SRishi Srivatsavai */ 984eaa4710SRishi Srivatsavai static int 994eaa4710SRishi Srivatsavai bind_instance(const char *service, const char *instance_name, 1004eaa4710SRishi Srivatsavai scf_state_t *sstate) 1014eaa4710SRishi Srivatsavai { 1024eaa4710SRishi Srivatsavai char *fmri = NULL; 1034eaa4710SRishi Srivatsavai 1044eaa4710SRishi Srivatsavai (void) memset(sstate, 0, sizeof (*sstate)); 1054eaa4710SRishi Srivatsavai 1064eaa4710SRishi Srivatsavai if ((sstate->ss_handle = scf_handle_create(SCF_VERSION)) == NULL) 1074eaa4710SRishi Srivatsavai return (-1); 1084eaa4710SRishi Srivatsavai 1094eaa4710SRishi Srivatsavai if (scf_handle_bind(sstate->ss_handle) != 0) 1104eaa4710SRishi Srivatsavai goto failure; 1114eaa4710SRishi Srivatsavai sstate->ss_inst = scf_instance_create(sstate->ss_handle); 1124eaa4710SRishi Srivatsavai if (sstate->ss_inst == NULL) 1134eaa4710SRishi Srivatsavai goto failure; 1144eaa4710SRishi Srivatsavai 1154eaa4710SRishi Srivatsavai fmri = alloc_fmri(service, instance_name); 1164eaa4710SRishi Srivatsavai 1174eaa4710SRishi Srivatsavai if (scf_handle_decode_fmri(sstate->ss_handle, fmri, NULL, NULL, 1184eaa4710SRishi Srivatsavai sstate->ss_inst, NULL, NULL, 1194eaa4710SRishi Srivatsavai SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) 1204eaa4710SRishi Srivatsavai goto failure; 1214eaa4710SRishi Srivatsavai free(fmri); 1224eaa4710SRishi Srivatsavai return (0); 1234eaa4710SRishi Srivatsavai 1244eaa4710SRishi Srivatsavai failure: 1254eaa4710SRishi Srivatsavai free(fmri); 1264eaa4710SRishi Srivatsavai shut_down_scf(sstate); 1274eaa4710SRishi Srivatsavai return (-1); 1284eaa4710SRishi Srivatsavai } 1294eaa4710SRishi Srivatsavai 1304eaa4710SRishi Srivatsavai /* 1314eaa4710SRishi Srivatsavai * Start up SCF and an exact FMRI. This is used for creating new instances and 1324eaa4710SRishi Srivatsavai * enable/disable actions. 1334eaa4710SRishi Srivatsavai */ 1344eaa4710SRishi Srivatsavai static dladm_status_t 1354eaa4710SRishi Srivatsavai exact_instance(const char *fmri, scf_state_t *sstate) 1364eaa4710SRishi Srivatsavai { 1374eaa4710SRishi Srivatsavai dladm_status_t status; 1384eaa4710SRishi Srivatsavai 1394eaa4710SRishi Srivatsavai (void) memset(sstate, 0, sizeof (*sstate)); 1404eaa4710SRishi Srivatsavai 1414eaa4710SRishi Srivatsavai if ((sstate->ss_handle = scf_handle_create(SCF_VERSION)) == NULL) 1424eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOMEM); 1434eaa4710SRishi Srivatsavai 1444eaa4710SRishi Srivatsavai status = DLADM_STATUS_FAILED; 1454eaa4710SRishi Srivatsavai if (scf_handle_bind(sstate->ss_handle) != 0) 1464eaa4710SRishi Srivatsavai goto failure; 1474eaa4710SRishi Srivatsavai sstate->ss_svc = scf_service_create(sstate->ss_handle); 1484eaa4710SRishi Srivatsavai if (sstate->ss_svc == NULL) 1494eaa4710SRishi Srivatsavai goto failure; 1504eaa4710SRishi Srivatsavai if (scf_handle_decode_fmri(sstate->ss_handle, fmri, NULL, 1514eaa4710SRishi Srivatsavai sstate->ss_svc, NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0) { 1524eaa4710SRishi Srivatsavai if (scf_error() == SCF_ERROR_NOT_FOUND) 1534eaa4710SRishi Srivatsavai status = DLADM_STATUS_OPTMISSING; 1544eaa4710SRishi Srivatsavai goto failure; 1554eaa4710SRishi Srivatsavai } 1564eaa4710SRishi Srivatsavai sstate->ss_inst = scf_instance_create(sstate->ss_handle); 1574eaa4710SRishi Srivatsavai if (sstate->ss_inst == NULL) 1584eaa4710SRishi Srivatsavai goto failure; 1594eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 1604eaa4710SRishi Srivatsavai 1614eaa4710SRishi Srivatsavai failure: 1624eaa4710SRishi Srivatsavai shut_down_scf(sstate); 1634eaa4710SRishi Srivatsavai return (status); 1644eaa4710SRishi Srivatsavai } 1654eaa4710SRishi Srivatsavai 1664eaa4710SRishi Srivatsavai static void 1674eaa4710SRishi Srivatsavai drop_composed(scf_state_t *sstate) 1684eaa4710SRishi Srivatsavai { 1694eaa4710SRishi Srivatsavai scf_property_destroy(sstate->ss_prop); 1704eaa4710SRishi Srivatsavai scf_pg_destroy(sstate->ss_pg); 1714eaa4710SRishi Srivatsavai scf_snapshot_destroy(sstate->ss_snap); 1724eaa4710SRishi Srivatsavai } 1734eaa4710SRishi Srivatsavai 1744eaa4710SRishi Srivatsavai /* 1754eaa4710SRishi Srivatsavai * This function sets up a composed view of the configuration information for 1764eaa4710SRishi Srivatsavai * the specified instance. When this is done, the get_property() function 1774eaa4710SRishi Srivatsavai * should be able to return individual parameters. 1784eaa4710SRishi Srivatsavai */ 1794eaa4710SRishi Srivatsavai static int 1804eaa4710SRishi Srivatsavai get_composed_properties(const char *lpg, boolean_t snap, scf_state_t *sstate) 1814eaa4710SRishi Srivatsavai { 1824eaa4710SRishi Srivatsavai sstate->ss_snap = NULL; 1834eaa4710SRishi Srivatsavai sstate->ss_pg = NULL; 1844eaa4710SRishi Srivatsavai sstate->ss_prop = NULL; 1854eaa4710SRishi Srivatsavai 1864eaa4710SRishi Srivatsavai if (snap) { 1874eaa4710SRishi Srivatsavai sstate->ss_snap = scf_snapshot_create(sstate->ss_handle); 1884eaa4710SRishi Srivatsavai if (sstate->ss_snap == NULL) 1894eaa4710SRishi Srivatsavai goto failure; 1904eaa4710SRishi Srivatsavai if (scf_instance_get_snapshot(sstate->ss_inst, "running", 1914eaa4710SRishi Srivatsavai sstate->ss_snap) != 0) 1924eaa4710SRishi Srivatsavai goto failure; 1934eaa4710SRishi Srivatsavai } 1944eaa4710SRishi Srivatsavai if ((sstate->ss_pg = scf_pg_create(sstate->ss_handle)) == NULL) 1954eaa4710SRishi Srivatsavai goto failure; 1964eaa4710SRishi Srivatsavai if (scf_instance_get_pg_composed(sstate->ss_inst, sstate->ss_snap, lpg, 1974eaa4710SRishi Srivatsavai sstate->ss_pg) != 0) 1984eaa4710SRishi Srivatsavai goto failure; 1994eaa4710SRishi Srivatsavai if ((sstate->ss_prop = scf_property_create(sstate->ss_handle)) == 2004eaa4710SRishi Srivatsavai NULL) 2014eaa4710SRishi Srivatsavai goto failure; 2024eaa4710SRishi Srivatsavai return (0); 2034eaa4710SRishi Srivatsavai 2044eaa4710SRishi Srivatsavai failure: 2054eaa4710SRishi Srivatsavai drop_composed(sstate); 2064eaa4710SRishi Srivatsavai return (-1); 2074eaa4710SRishi Srivatsavai } 2084eaa4710SRishi Srivatsavai 2094eaa4710SRishi Srivatsavai static int 2104eaa4710SRishi Srivatsavai get_count(const char *lprop, scf_state_t *sstate, uint64_t *answer) 2114eaa4710SRishi Srivatsavai { 2124eaa4710SRishi Srivatsavai scf_value_t *val; 2134eaa4710SRishi Srivatsavai int retv; 2144eaa4710SRishi Srivatsavai 2154eaa4710SRishi Srivatsavai if (scf_pg_get_property(sstate->ss_pg, lprop, sstate->ss_prop) != 0) 2164eaa4710SRishi Srivatsavai return (-1); 2174eaa4710SRishi Srivatsavai if ((val = scf_value_create(sstate->ss_handle)) == NULL) 2184eaa4710SRishi Srivatsavai return (-1); 2194eaa4710SRishi Srivatsavai 2204eaa4710SRishi Srivatsavai if (scf_property_get_value(sstate->ss_prop, val) == 0 && 2214eaa4710SRishi Srivatsavai scf_value_get_count(val, answer) == 0) 2224eaa4710SRishi Srivatsavai retv = 0; 2234eaa4710SRishi Srivatsavai else 2244eaa4710SRishi Srivatsavai retv = -1; 2254eaa4710SRishi Srivatsavai scf_value_destroy(val); 2264eaa4710SRishi Srivatsavai return (retv); 2274eaa4710SRishi Srivatsavai } 2284eaa4710SRishi Srivatsavai 2294eaa4710SRishi Srivatsavai static int 2304eaa4710SRishi Srivatsavai get_boolean(const char *lprop, scf_state_t *sstate, boolean_t *answer) 2314eaa4710SRishi Srivatsavai { 2324eaa4710SRishi Srivatsavai scf_value_t *val; 2334eaa4710SRishi Srivatsavai int retv; 2344eaa4710SRishi Srivatsavai uint8_t bval; 2354eaa4710SRishi Srivatsavai 2364eaa4710SRishi Srivatsavai if (scf_pg_get_property(sstate->ss_pg, lprop, sstate->ss_prop) != 0) 2374eaa4710SRishi Srivatsavai return (-1); 2384eaa4710SRishi Srivatsavai if ((val = scf_value_create(sstate->ss_handle)) == NULL) 2394eaa4710SRishi Srivatsavai return (-1); 2404eaa4710SRishi Srivatsavai 2414eaa4710SRishi Srivatsavai if (scf_property_get_value(sstate->ss_prop, val) == 0 && 2424eaa4710SRishi Srivatsavai scf_value_get_boolean(val, &bval) == 0) { 2434eaa4710SRishi Srivatsavai retv = 0; 2444eaa4710SRishi Srivatsavai *answer = bval != 0; 2454eaa4710SRishi Srivatsavai } else { 2464eaa4710SRishi Srivatsavai retv = -1; 2474eaa4710SRishi Srivatsavai } 2484eaa4710SRishi Srivatsavai scf_value_destroy(val); 2494eaa4710SRishi Srivatsavai return (retv); 2504eaa4710SRishi Srivatsavai } 2514eaa4710SRishi Srivatsavai 2524eaa4710SRishi Srivatsavai static dladm_status_t 2534eaa4710SRishi Srivatsavai bridge_door_call(const char *instname, bridge_door_type_t dtype, 2544eaa4710SRishi Srivatsavai datalink_id_t linkid, void **bufp, size_t inlen, size_t *buflenp, 2554eaa4710SRishi Srivatsavai boolean_t is_list) 2564eaa4710SRishi Srivatsavai { 2574eaa4710SRishi Srivatsavai char doorname[MAXPATHLEN]; 2584eaa4710SRishi Srivatsavai int did, retv, etmp; 2594eaa4710SRishi Srivatsavai bridge_door_cmd_t *bdc; 2604eaa4710SRishi Srivatsavai door_arg_t arg; 2614eaa4710SRishi Srivatsavai 2624eaa4710SRishi Srivatsavai (void) snprintf(doorname, sizeof (doorname), "%s/%s", DOOR_DIRNAME, 2634eaa4710SRishi Srivatsavai instname); 2644eaa4710SRishi Srivatsavai 2654eaa4710SRishi Srivatsavai /* Knock on the door */ 2664eaa4710SRishi Srivatsavai did = open(doorname, O_RDONLY | O_NOFOLLOW | O_NONBLOCK); 2674eaa4710SRishi Srivatsavai if (did == -1) 2684eaa4710SRishi Srivatsavai return (dladm_errno2status(errno)); 2694eaa4710SRishi Srivatsavai 2704eaa4710SRishi Srivatsavai if ((bdc = malloc(sizeof (*bdc) + inlen)) == NULL) { 2714eaa4710SRishi Srivatsavai (void) close(did); 2724eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOMEM); 2734eaa4710SRishi Srivatsavai } 2744eaa4710SRishi Srivatsavai bdc->bdc_type = dtype; 2754eaa4710SRishi Srivatsavai bdc->bdc_linkid = linkid; 2764eaa4710SRishi Srivatsavai if (inlen != 0) 2774eaa4710SRishi Srivatsavai (void) memcpy(bdc + 1, *bufp, inlen); 2784eaa4710SRishi Srivatsavai 2794eaa4710SRishi Srivatsavai (void) memset(&arg, 0, sizeof (arg)); 2804eaa4710SRishi Srivatsavai arg.data_ptr = (char *)bdc; 2814eaa4710SRishi Srivatsavai arg.data_size = sizeof (*bdc) + inlen; 2824eaa4710SRishi Srivatsavai arg.rbuf = *bufp; 2834eaa4710SRishi Srivatsavai arg.rsize = *buflenp; 2844eaa4710SRishi Srivatsavai 2854eaa4710SRishi Srivatsavai /* The door_call function doesn't restart, so take care of that */ 2864eaa4710SRishi Srivatsavai do { 2874eaa4710SRishi Srivatsavai errno = 0; 2884eaa4710SRishi Srivatsavai if ((retv = door_call(did, &arg)) == 0) 2894eaa4710SRishi Srivatsavai break; 2904eaa4710SRishi Srivatsavai } while (errno == EINTR); 2914eaa4710SRishi Srivatsavai 2924eaa4710SRishi Srivatsavai /* If we get an unexpected response, then return an error */ 2934eaa4710SRishi Srivatsavai if (retv == 0) { 2944eaa4710SRishi Srivatsavai /* The daemon returns a single int for errors */ 2954eaa4710SRishi Srivatsavai /* LINTED: pointer alignment */ 2964eaa4710SRishi Srivatsavai if (arg.data_size == sizeof (int) && *(int *)arg.rbuf != 0) { 2974eaa4710SRishi Srivatsavai retv = -1; 2984eaa4710SRishi Srivatsavai /* LINTED: pointer alignment */ 2994eaa4710SRishi Srivatsavai errno = *(int *)arg.rbuf; 3004eaa4710SRishi Srivatsavai } 3014eaa4710SRishi Srivatsavai /* Terminated daemon returns with zero data */ 3024eaa4710SRishi Srivatsavai if (arg.data_size == 0) { 3034eaa4710SRishi Srivatsavai retv = -1; 3044eaa4710SRishi Srivatsavai errno = EBADF; 3054eaa4710SRishi Srivatsavai } 3064eaa4710SRishi Srivatsavai } 3074eaa4710SRishi Srivatsavai 3084eaa4710SRishi Srivatsavai if (retv == 0) { 3094eaa4710SRishi Srivatsavai if (arg.rbuf != *bufp) { 3104eaa4710SRishi Srivatsavai if (is_list) { 3114eaa4710SRishi Srivatsavai void *newp; 3124eaa4710SRishi Srivatsavai 3134eaa4710SRishi Srivatsavai newp = realloc(*bufp, arg.data_size); 3144eaa4710SRishi Srivatsavai if (newp == NULL) { 3154eaa4710SRishi Srivatsavai retv = -1; 3164eaa4710SRishi Srivatsavai } else { 3174eaa4710SRishi Srivatsavai *bufp = newp; 3184eaa4710SRishi Srivatsavai (void) memcpy(*bufp, arg.rbuf, 3194eaa4710SRishi Srivatsavai arg.data_size); 3204eaa4710SRishi Srivatsavai } 3214eaa4710SRishi Srivatsavai } 3224eaa4710SRishi Srivatsavai (void) munmap(arg.rbuf, arg.rsize); 3234eaa4710SRishi Srivatsavai } 3244eaa4710SRishi Srivatsavai if (is_list) { 3254eaa4710SRishi Srivatsavai *buflenp = arg.data_size; 3264eaa4710SRishi Srivatsavai } else if (arg.data_size != *buflenp || arg.rbuf != *bufp) { 3274eaa4710SRishi Srivatsavai errno = EINVAL; 3284eaa4710SRishi Srivatsavai retv = -1; 3294eaa4710SRishi Srivatsavai } 3304eaa4710SRishi Srivatsavai } 3314eaa4710SRishi Srivatsavai 3324eaa4710SRishi Srivatsavai etmp = errno; 3334eaa4710SRishi Srivatsavai (void) close(did); 3344eaa4710SRishi Srivatsavai 3354eaa4710SRishi Srivatsavai /* Revoked door is the same as no door at all */ 3364eaa4710SRishi Srivatsavai if (etmp == EBADF) 3374eaa4710SRishi Srivatsavai etmp = ENOENT; 3384eaa4710SRishi Srivatsavai 3394eaa4710SRishi Srivatsavai return (retv == 0 ? DLADM_STATUS_OK : dladm_errno2status(etmp)); 3404eaa4710SRishi Srivatsavai } 3414eaa4710SRishi Srivatsavai 3424eaa4710SRishi Srivatsavai /* 3434eaa4710SRishi Srivatsavai * Wrapper function for making per-port calls. 3444eaa4710SRishi Srivatsavai */ 3454eaa4710SRishi Srivatsavai static dladm_status_t 3464eaa4710SRishi Srivatsavai port_door_call(dladm_handle_t handle, datalink_id_t linkid, 3474eaa4710SRishi Srivatsavai bridge_door_type_t dtype, void *buf, size_t inlen, size_t buflen) 3484eaa4710SRishi Srivatsavai { 3494eaa4710SRishi Srivatsavai char bridge[MAXLINKNAMELEN]; 3504eaa4710SRishi Srivatsavai dladm_status_t status; 3514eaa4710SRishi Srivatsavai 3524eaa4710SRishi Srivatsavai status = dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge)); 3534eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 3544eaa4710SRishi Srivatsavai return (status); 3554eaa4710SRishi Srivatsavai return (bridge_door_call(bridge, dtype, linkid, &buf, inlen, &buflen, 3564eaa4710SRishi Srivatsavai B_FALSE)); 3574eaa4710SRishi Srivatsavai } 3584eaa4710SRishi Srivatsavai 3594eaa4710SRishi Srivatsavai static dladm_status_t 3604eaa4710SRishi Srivatsavai bridge_refresh(const char *bridge) 3614eaa4710SRishi Srivatsavai { 3624eaa4710SRishi Srivatsavai dladm_status_t status; 3634eaa4710SRishi Srivatsavai int twoints[2]; 3644eaa4710SRishi Srivatsavai void *bdptr; 3654eaa4710SRishi Srivatsavai size_t buflen; 3664eaa4710SRishi Srivatsavai char *fmri; 3674eaa4710SRishi Srivatsavai int refresh_count; 3684eaa4710SRishi Srivatsavai 3694eaa4710SRishi Srivatsavai buflen = sizeof (twoints); 3704eaa4710SRishi Srivatsavai bdptr = twoints; 3714eaa4710SRishi Srivatsavai status = bridge_door_call(bridge, bdcBridgeGetRefreshCount, 3724eaa4710SRishi Srivatsavai DATALINK_INVALID_LINKID, &bdptr, 0, &buflen, B_FALSE); 3734eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_NOTFOUND) 3744eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 3754eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 3764eaa4710SRishi Srivatsavai return (status); 3774eaa4710SRishi Srivatsavai refresh_count = twoints[0]; 3784eaa4710SRishi Srivatsavai if ((fmri = alloc_fmri(BRIDGE_SVC_NAME, bridge)) == NULL) 3794eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOMEM); 3804eaa4710SRishi Srivatsavai status = smf_refresh_instance(fmri) == 0 ? 3814eaa4710SRishi Srivatsavai DLADM_STATUS_OK : DLADM_STATUS_FAILED; 3824eaa4710SRishi Srivatsavai free(fmri); 3834eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK) { 3844eaa4710SRishi Srivatsavai int i = 0; 3854eaa4710SRishi Srivatsavai 3864eaa4710SRishi Srivatsavai /* 3874eaa4710SRishi Srivatsavai * SMF doesn't give any synchronous behavior or dependency 3884eaa4710SRishi Srivatsavai * ordering for refresh operations, so we have to invent our 3894eaa4710SRishi Srivatsavai * own mechanism here. Get the refresh counter from the 3904eaa4710SRishi Srivatsavai * daemon, and wait for it to change. It's not pretty, but 3914eaa4710SRishi Srivatsavai * it's sufficient. 3924eaa4710SRishi Srivatsavai */ 3934eaa4710SRishi Srivatsavai while (++i <= 10) { 3944eaa4710SRishi Srivatsavai buflen = sizeof (twoints); 3954eaa4710SRishi Srivatsavai bdptr = twoints; 3964eaa4710SRishi Srivatsavai status = bridge_door_call(bridge, 3974eaa4710SRishi Srivatsavai bdcBridgeGetRefreshCount, DATALINK_INVALID_LINKID, 3984eaa4710SRishi Srivatsavai &bdptr, 0, &buflen, B_FALSE); 3994eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 4004eaa4710SRishi Srivatsavai break; 4014eaa4710SRishi Srivatsavai if (twoints[0] != refresh_count) 4024eaa4710SRishi Srivatsavai break; 4034eaa4710SRishi Srivatsavai (void) usleep(100000); 4044eaa4710SRishi Srivatsavai } 4054eaa4710SRishi Srivatsavai fmri = alloc_fmri(TRILL_SVC_NAME, bridge); 4064eaa4710SRishi Srivatsavai if (fmri == NULL) 4074eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOMEM); 4084eaa4710SRishi Srivatsavai status = smf_refresh_instance(fmri) == 0 || 4094eaa4710SRishi Srivatsavai scf_error() == SCF_ERROR_NOT_FOUND ? 4104eaa4710SRishi Srivatsavai DLADM_STATUS_OK : DLADM_STATUS_FAILED; 4114eaa4710SRishi Srivatsavai free(fmri); 4124eaa4710SRishi Srivatsavai } 4134eaa4710SRishi Srivatsavai return (status); 4144eaa4710SRishi Srivatsavai } 4154eaa4710SRishi Srivatsavai 4164eaa4710SRishi Srivatsavai /* 4174eaa4710SRishi Srivatsavai * Look up bridge property values from SCF and return them. 4184eaa4710SRishi Srivatsavai */ 4194eaa4710SRishi Srivatsavai dladm_status_t 4204eaa4710SRishi Srivatsavai dladm_bridge_get_properties(const char *instance_name, UID_STP_CFG_T *cfg, 4214eaa4710SRishi Srivatsavai dladm_bridge_prot_t *brprotp) 4224eaa4710SRishi Srivatsavai { 4234eaa4710SRishi Srivatsavai scf_state_t sstate; 4244eaa4710SRishi Srivatsavai uint64_t value; 4254eaa4710SRishi Srivatsavai boolean_t trill_enabled; 4264eaa4710SRishi Srivatsavai 4274eaa4710SRishi Srivatsavai cfg->field_mask = 0; 4284eaa4710SRishi Srivatsavai cfg->bridge_priority = DEF_BR_PRIO; 4294eaa4710SRishi Srivatsavai cfg->max_age = DEF_BR_MAXAGE; 4304eaa4710SRishi Srivatsavai cfg->hello_time = DEF_BR_HELLOT; 4314eaa4710SRishi Srivatsavai cfg->forward_delay = DEF_BR_FWDELAY; 4324eaa4710SRishi Srivatsavai cfg->force_version = DEF_FORCE_VERS; 4334eaa4710SRishi Srivatsavai 4344eaa4710SRishi Srivatsavai (void) strlcpy(cfg->vlan_name, instance_name, sizeof (cfg->vlan_name)); 4354eaa4710SRishi Srivatsavai 4364eaa4710SRishi Srivatsavai *brprotp = DLADM_BRIDGE_PROT_STP; 4374eaa4710SRishi Srivatsavai 4384eaa4710SRishi Srivatsavai /* It's ok for this to be missing; it's installed separately */ 4394eaa4710SRishi Srivatsavai if (bind_instance(TRILL_SVC_NAME, instance_name, &sstate) == 0) { 4404eaa4710SRishi Srivatsavai trill_enabled = B_FALSE; 4414eaa4710SRishi Srivatsavai if (get_composed_properties(SCF_PG_GENERAL, B_FALSE, &sstate) == 4424eaa4710SRishi Srivatsavai 0) { 4434eaa4710SRishi Srivatsavai (void) get_boolean(SCF_PROPERTY_ENABLED, &sstate, 4444eaa4710SRishi Srivatsavai &trill_enabled); 4454eaa4710SRishi Srivatsavai if (trill_enabled) 4464eaa4710SRishi Srivatsavai *brprotp = DLADM_BRIDGE_PROT_TRILL; 4474eaa4710SRishi Srivatsavai drop_composed(&sstate); 4484eaa4710SRishi Srivatsavai } 4494eaa4710SRishi Srivatsavai if (get_composed_properties(SCF_PG_GENERAL_OVR, B_FALSE, 4504eaa4710SRishi Srivatsavai &sstate) == 0) { 4514eaa4710SRishi Srivatsavai (void) get_boolean(SCF_PROPERTY_ENABLED, &sstate, 4524eaa4710SRishi Srivatsavai &trill_enabled); 4534eaa4710SRishi Srivatsavai if (trill_enabled) 4544eaa4710SRishi Srivatsavai *brprotp = DLADM_BRIDGE_PROT_TRILL; 4554eaa4710SRishi Srivatsavai drop_composed(&sstate); 4564eaa4710SRishi Srivatsavai } 4574eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 4584eaa4710SRishi Srivatsavai } 4594eaa4710SRishi Srivatsavai 4604eaa4710SRishi Srivatsavai cfg->stp_enabled = (*brprotp == DLADM_BRIDGE_PROT_STP) ? 4614eaa4710SRishi Srivatsavai STP_ENABLED : STP_DISABLED; 4624eaa4710SRishi Srivatsavai cfg->field_mask |= BR_CFG_STATE; 4634eaa4710SRishi Srivatsavai 4644eaa4710SRishi Srivatsavai if (bind_instance(BRIDGE_SVC_NAME, instance_name, &sstate) != 0) 4654eaa4710SRishi Srivatsavai return (DLADM_STATUS_REPOSITORYINVAL); 4664eaa4710SRishi Srivatsavai 4674eaa4710SRishi Srivatsavai if (get_composed_properties("config", B_TRUE, &sstate) != 0) { 4684eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 4694eaa4710SRishi Srivatsavai return (DLADM_STATUS_REPOSITORYINVAL); 4704eaa4710SRishi Srivatsavai } 4714eaa4710SRishi Srivatsavai 4724eaa4710SRishi Srivatsavai if (get_count("priority", &sstate, &value) == 0) { 4734eaa4710SRishi Srivatsavai cfg->bridge_priority = value; 4744eaa4710SRishi Srivatsavai cfg->field_mask |= BR_CFG_PRIO; 4754eaa4710SRishi Srivatsavai } 4764eaa4710SRishi Srivatsavai if (get_count("max-age", &sstate, &value) == 0) { 4774eaa4710SRishi Srivatsavai cfg->max_age = value / IEEE_TIMER_SCALE; 4784eaa4710SRishi Srivatsavai cfg->field_mask |= BR_CFG_AGE; 4794eaa4710SRishi Srivatsavai } 4804eaa4710SRishi Srivatsavai if (get_count("hello-time", &sstate, &value) == 0) { 4814eaa4710SRishi Srivatsavai cfg->hello_time = value / IEEE_TIMER_SCALE; 4824eaa4710SRishi Srivatsavai cfg->field_mask |= BR_CFG_HELLO; 4834eaa4710SRishi Srivatsavai } 4844eaa4710SRishi Srivatsavai if (get_count("forward-delay", &sstate, &value) == 0) { 4854eaa4710SRishi Srivatsavai cfg->forward_delay = value / IEEE_TIMER_SCALE; 4864eaa4710SRishi Srivatsavai cfg->field_mask |= BR_CFG_DELAY; 4874eaa4710SRishi Srivatsavai } 4884eaa4710SRishi Srivatsavai if (get_count("force-protocol", &sstate, &value) == 0) { 4894eaa4710SRishi Srivatsavai cfg->force_version = value; 4904eaa4710SRishi Srivatsavai cfg->field_mask |= BR_CFG_FORCE_VER; 4914eaa4710SRishi Srivatsavai } 4924eaa4710SRishi Srivatsavai 4934eaa4710SRishi Srivatsavai drop_composed(&sstate); 4944eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 4954eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 4964eaa4710SRishi Srivatsavai } 4974eaa4710SRishi Srivatsavai 4984eaa4710SRishi Srivatsavai /* 4994eaa4710SRishi Srivatsavai * Retrieve special non-settable and undocumented parameters. 5004eaa4710SRishi Srivatsavai */ 5014eaa4710SRishi Srivatsavai dladm_status_t 5024eaa4710SRishi Srivatsavai dladm_bridge_get_privprop(const char *instance_name, boolean_t *debugp, 5034eaa4710SRishi Srivatsavai uint32_t *tablemaxp) 5044eaa4710SRishi Srivatsavai { 5054eaa4710SRishi Srivatsavai scf_state_t sstate; 5064eaa4710SRishi Srivatsavai uint64_t value; 5074eaa4710SRishi Srivatsavai 5084eaa4710SRishi Srivatsavai *debugp = B_FALSE; 5094eaa4710SRishi Srivatsavai *tablemaxp = 10000; 5104eaa4710SRishi Srivatsavai 5114eaa4710SRishi Srivatsavai if (bind_instance(BRIDGE_SVC_NAME, instance_name, &sstate) != 0) 5124eaa4710SRishi Srivatsavai return (DLADM_STATUS_REPOSITORYINVAL); 5134eaa4710SRishi Srivatsavai 5144eaa4710SRishi Srivatsavai if (get_composed_properties("config", B_TRUE, &sstate) != 0) { 5154eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 5164eaa4710SRishi Srivatsavai return (DLADM_STATUS_REPOSITORYINVAL); 5174eaa4710SRishi Srivatsavai } 5184eaa4710SRishi Srivatsavai 5194eaa4710SRishi Srivatsavai (void) get_boolean("debug", &sstate, debugp); 5204eaa4710SRishi Srivatsavai if (get_count("table-maximum", &sstate, &value) == 0) 5214eaa4710SRishi Srivatsavai *tablemaxp = (uint32_t)value; 5224eaa4710SRishi Srivatsavai 5234eaa4710SRishi Srivatsavai drop_composed(&sstate); 5244eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 5254eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 5264eaa4710SRishi Srivatsavai } 5274eaa4710SRishi Srivatsavai 5284eaa4710SRishi Srivatsavai static boolean_t 5294eaa4710SRishi Srivatsavai set_count_property(scf_handle_t *handle, scf_transaction_t *tran, 5304eaa4710SRishi Srivatsavai const char *propname, uint64_t propval) 5314eaa4710SRishi Srivatsavai { 5324eaa4710SRishi Srivatsavai scf_transaction_entry_t *entry; 5334eaa4710SRishi Srivatsavai scf_value_t *value = NULL; 5344eaa4710SRishi Srivatsavai 5354eaa4710SRishi Srivatsavai if ((entry = scf_entry_create(handle)) == NULL) 5364eaa4710SRishi Srivatsavai return (B_FALSE); 5374eaa4710SRishi Srivatsavai 5384eaa4710SRishi Srivatsavai if ((value = scf_value_create(handle)) == NULL) 5394eaa4710SRishi Srivatsavai goto out; 5404eaa4710SRishi Srivatsavai if (scf_transaction_property_new(tran, entry, propname, 5414eaa4710SRishi Srivatsavai SCF_TYPE_COUNT) != 0 && 5424eaa4710SRishi Srivatsavai scf_transaction_property_change(tran, entry, propname, 5434eaa4710SRishi Srivatsavai SCF_TYPE_COUNT) != 0) 5444eaa4710SRishi Srivatsavai goto out; 5454eaa4710SRishi Srivatsavai scf_value_set_count(value, propval); 5464eaa4710SRishi Srivatsavai if (scf_entry_add_value(entry, value) == 0) 5474eaa4710SRishi Srivatsavai return (B_TRUE); 5484eaa4710SRishi Srivatsavai 5494eaa4710SRishi Srivatsavai out: 5504eaa4710SRishi Srivatsavai if (value != NULL) 5514eaa4710SRishi Srivatsavai scf_value_destroy(value); 5524eaa4710SRishi Srivatsavai 5534eaa4710SRishi Srivatsavai scf_entry_destroy_children(entry); 5544eaa4710SRishi Srivatsavai scf_entry_destroy(entry); 5554eaa4710SRishi Srivatsavai 5564eaa4710SRishi Srivatsavai return (B_FALSE); 5574eaa4710SRishi Srivatsavai } 5584eaa4710SRishi Srivatsavai 5594eaa4710SRishi Srivatsavai static boolean_t 5604eaa4710SRishi Srivatsavai set_string_property(scf_handle_t *handle, scf_transaction_t *tran, 5614eaa4710SRishi Srivatsavai const char *propname, const char *propval) 5624eaa4710SRishi Srivatsavai { 5634eaa4710SRishi Srivatsavai scf_transaction_entry_t *entry; 5644eaa4710SRishi Srivatsavai scf_value_t *value = NULL; 5654eaa4710SRishi Srivatsavai 5664eaa4710SRishi Srivatsavai if ((entry = scf_entry_create(handle)) == NULL) 5674eaa4710SRishi Srivatsavai return (B_FALSE); 5684eaa4710SRishi Srivatsavai 5694eaa4710SRishi Srivatsavai if ((value = scf_value_create(handle)) == NULL) 5704eaa4710SRishi Srivatsavai goto out; 5714eaa4710SRishi Srivatsavai if (scf_transaction_property_new(tran, entry, propname, 5724eaa4710SRishi Srivatsavai SCF_TYPE_ASTRING) != 0 && 5734eaa4710SRishi Srivatsavai scf_transaction_property_change(tran, entry, propname, 5744eaa4710SRishi Srivatsavai SCF_TYPE_ASTRING) != 0) 5754eaa4710SRishi Srivatsavai goto out; 5764eaa4710SRishi Srivatsavai if (scf_value_set_astring(value, propval) != 0) 5774eaa4710SRishi Srivatsavai goto out; 5784eaa4710SRishi Srivatsavai if (scf_entry_add_value(entry, value) == 0) 5794eaa4710SRishi Srivatsavai return (B_TRUE); 5804eaa4710SRishi Srivatsavai 5814eaa4710SRishi Srivatsavai out: 5824eaa4710SRishi Srivatsavai if (value != NULL) 5834eaa4710SRishi Srivatsavai scf_value_destroy(value); 5844eaa4710SRishi Srivatsavai 5854eaa4710SRishi Srivatsavai scf_entry_destroy_children(entry); 5864eaa4710SRishi Srivatsavai scf_entry_destroy(entry); 5874eaa4710SRishi Srivatsavai 5884eaa4710SRishi Srivatsavai return (B_FALSE); 5894eaa4710SRishi Srivatsavai } 5904eaa4710SRishi Srivatsavai 5914eaa4710SRishi Srivatsavai static boolean_t 5924eaa4710SRishi Srivatsavai set_fmri_property(scf_handle_t *handle, scf_transaction_t *tran, 5934eaa4710SRishi Srivatsavai const char *propname, const char *propval) 5944eaa4710SRishi Srivatsavai { 5954eaa4710SRishi Srivatsavai scf_transaction_entry_t *entry; 5964eaa4710SRishi Srivatsavai scf_value_t *value = NULL; 5974eaa4710SRishi Srivatsavai 5984eaa4710SRishi Srivatsavai if ((entry = scf_entry_create(handle)) == NULL) 5994eaa4710SRishi Srivatsavai return (B_FALSE); 6004eaa4710SRishi Srivatsavai 6014eaa4710SRishi Srivatsavai if ((value = scf_value_create(handle)) == NULL) 6024eaa4710SRishi Srivatsavai goto out; 6034eaa4710SRishi Srivatsavai if (scf_transaction_property_new(tran, entry, propname, 6044eaa4710SRishi Srivatsavai SCF_TYPE_FMRI) != 0 && 6054eaa4710SRishi Srivatsavai scf_transaction_property_change(tran, entry, propname, 6064eaa4710SRishi Srivatsavai SCF_TYPE_FMRI) != 0) 6074eaa4710SRishi Srivatsavai goto out; 6084eaa4710SRishi Srivatsavai if (scf_value_set_from_string(value, SCF_TYPE_FMRI, propval) != 0) 6094eaa4710SRishi Srivatsavai goto out; 6104eaa4710SRishi Srivatsavai if (scf_entry_add_value(entry, value) == 0) 6114eaa4710SRishi Srivatsavai return (B_TRUE); 6124eaa4710SRishi Srivatsavai 6134eaa4710SRishi Srivatsavai out: 6144eaa4710SRishi Srivatsavai if (value != NULL) 6154eaa4710SRishi Srivatsavai scf_value_destroy(value); 6164eaa4710SRishi Srivatsavai 6174eaa4710SRishi Srivatsavai scf_entry_destroy_children(entry); 6184eaa4710SRishi Srivatsavai scf_entry_destroy(entry); 6194eaa4710SRishi Srivatsavai 6204eaa4710SRishi Srivatsavai return (B_FALSE); 6214eaa4710SRishi Srivatsavai } 6224eaa4710SRishi Srivatsavai 6234eaa4710SRishi Srivatsavai static dladm_status_t 6244eaa4710SRishi Srivatsavai dladm_bridge_persist_conf(dladm_handle_t handle, const char *link, 6254eaa4710SRishi Srivatsavai datalink_id_t linkid) 6264eaa4710SRishi Srivatsavai { 6274eaa4710SRishi Srivatsavai dladm_conf_t conf = DLADM_INVALID_CONF; 6284eaa4710SRishi Srivatsavai dladm_status_t status; 6294eaa4710SRishi Srivatsavai 6304eaa4710SRishi Srivatsavai status = dladm_create_conf(handle, link, linkid, DATALINK_CLASS_BRIDGE, 6314eaa4710SRishi Srivatsavai DL_ETHER, &conf); 6324eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK) { 6334eaa4710SRishi Srivatsavai /* 6344eaa4710SRishi Srivatsavai * Create the datalink entry for the bridge. Note that all of 6354eaa4710SRishi Srivatsavai * the real configuration information is in SMF. 6364eaa4710SRishi Srivatsavai */ 6374eaa4710SRishi Srivatsavai status = dladm_write_conf(handle, conf); 6384eaa4710SRishi Srivatsavai dladm_destroy_conf(handle, conf); 6394eaa4710SRishi Srivatsavai } 6404eaa4710SRishi Srivatsavai return (status); 6414eaa4710SRishi Srivatsavai } 6424eaa4710SRishi Srivatsavai 6434eaa4710SRishi Srivatsavai /* Convert bridge protection option string to dladm_bridge_prot_t */ 6444eaa4710SRishi Srivatsavai dladm_status_t 6454eaa4710SRishi Srivatsavai dladm_bridge_str2prot(const char *str, dladm_bridge_prot_t *brprotp) 6464eaa4710SRishi Srivatsavai { 6474eaa4710SRishi Srivatsavai if (strcmp(str, "stp") == 0) 6484eaa4710SRishi Srivatsavai *brprotp = DLADM_BRIDGE_PROT_STP; 6494eaa4710SRishi Srivatsavai else if (strcmp(str, "trill") == 0) 6504eaa4710SRishi Srivatsavai *brprotp = DLADM_BRIDGE_PROT_TRILL; 6514eaa4710SRishi Srivatsavai else 6524eaa4710SRishi Srivatsavai return (DLADM_STATUS_BADARG); 6534eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 6544eaa4710SRishi Srivatsavai } 6554eaa4710SRishi Srivatsavai 6564eaa4710SRishi Srivatsavai /* Convert bridge protection option from dladm_bridge_prot_t to string */ 6574eaa4710SRishi Srivatsavai const char * 6584eaa4710SRishi Srivatsavai dladm_bridge_prot2str(dladm_bridge_prot_t brprot) 6594eaa4710SRishi Srivatsavai { 6604eaa4710SRishi Srivatsavai switch (brprot) { 6614eaa4710SRishi Srivatsavai case DLADM_BRIDGE_PROT_STP: 6624eaa4710SRishi Srivatsavai return ("stp"); 6634eaa4710SRishi Srivatsavai case DLADM_BRIDGE_PROT_TRILL: 6644eaa4710SRishi Srivatsavai return ("trill"); 6654eaa4710SRishi Srivatsavai default: 6664eaa4710SRishi Srivatsavai return ("unknown"); 6674eaa4710SRishi Srivatsavai } 6684eaa4710SRishi Srivatsavai } 6694eaa4710SRishi Srivatsavai 6704eaa4710SRishi Srivatsavai static dladm_status_t 6714eaa4710SRishi Srivatsavai enable_instance(const char *service_name, const char *instance) 6724eaa4710SRishi Srivatsavai { 6734eaa4710SRishi Srivatsavai dladm_status_t status; 6744eaa4710SRishi Srivatsavai char *fmri = alloc_fmri(service_name, instance); 6754eaa4710SRishi Srivatsavai 6764eaa4710SRishi Srivatsavai if (fmri == NULL) 6774eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOMEM); 6784eaa4710SRishi Srivatsavai status = smf_enable_instance(fmri, 0) == 0 ? 6794eaa4710SRishi Srivatsavai DLADM_STATUS_OK : DLADM_STATUS_FAILED; 6804eaa4710SRishi Srivatsavai free(fmri); 6814eaa4710SRishi Srivatsavai return (status); 6824eaa4710SRishi Srivatsavai } 6834eaa4710SRishi Srivatsavai 6844eaa4710SRishi Srivatsavai /* 6854eaa4710SRishi Srivatsavai * Shut down a possibly-running service instance. If this is a permanent 6864eaa4710SRishi Srivatsavai * change, then delete it from the system. 6874eaa4710SRishi Srivatsavai */ 6884eaa4710SRishi Srivatsavai static dladm_status_t 6894eaa4710SRishi Srivatsavai shut_down_instance(const char *service_name, const char *instance, 6904eaa4710SRishi Srivatsavai uint32_t flags) 6914eaa4710SRishi Srivatsavai { 6924eaa4710SRishi Srivatsavai dladm_status_t status; 6934eaa4710SRishi Srivatsavai char *fmri = alloc_fmri(service_name, instance); 6944eaa4710SRishi Srivatsavai char *state; 6954eaa4710SRishi Srivatsavai scf_state_t sstate; 6964eaa4710SRishi Srivatsavai 6974eaa4710SRishi Srivatsavai if (fmri == NULL) 6984eaa4710SRishi Srivatsavai return (DLADM_STATUS_NOMEM); 6994eaa4710SRishi Srivatsavai 7004eaa4710SRishi Srivatsavai if (smf_disable_instance(fmri, 7014eaa4710SRishi Srivatsavai flags & DLADM_OPT_PERSIST ? 0 : SMF_TEMPORARY) == 0) { 7024eaa4710SRishi Srivatsavai useconds_t usecs, umax; 7034eaa4710SRishi Srivatsavai 7044eaa4710SRishi Srivatsavai /* If we can disable, then wait for it to happen. */ 7054eaa4710SRishi Srivatsavai umax = DEFAULT_TIMEOUT; 7064eaa4710SRishi Srivatsavai for (usecs = INIT_WAIT_USECS; umax != 0; umax -= usecs) { 7074eaa4710SRishi Srivatsavai state = smf_get_state(fmri); 7084eaa4710SRishi Srivatsavai if (state != NULL && 7094eaa4710SRishi Srivatsavai strcmp(state, SCF_STATE_STRING_DISABLED) == 0) 7104eaa4710SRishi Srivatsavai break; 7114eaa4710SRishi Srivatsavai free(state); 7124eaa4710SRishi Srivatsavai usecs *= 2; 7134eaa4710SRishi Srivatsavai if (usecs > umax) 7144eaa4710SRishi Srivatsavai usecs = umax; 7154eaa4710SRishi Srivatsavai (void) usleep(usecs); 7164eaa4710SRishi Srivatsavai } 7174eaa4710SRishi Srivatsavai if (umax == 0) { 7184eaa4710SRishi Srivatsavai state = smf_get_state(fmri); 7194eaa4710SRishi Srivatsavai if (state != NULL && 7204eaa4710SRishi Srivatsavai strcmp(state, SCF_STATE_STRING_DISABLED) == 0) 7214eaa4710SRishi Srivatsavai umax = 1; 7224eaa4710SRishi Srivatsavai } 7234eaa4710SRishi Srivatsavai free(state); 7244eaa4710SRishi Srivatsavai status = umax != 0 ? DLADM_STATUS_OK : DLADM_STATUS_FAILED; 7254eaa4710SRishi Srivatsavai } else if (scf_error() == SCF_ERROR_NOT_FOUND) { 7264eaa4710SRishi Srivatsavai free(fmri); 7274eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 7284eaa4710SRishi Srivatsavai } else { 7294eaa4710SRishi Srivatsavai status = DLADM_STATUS_FAILED; 7304eaa4710SRishi Srivatsavai } 7314eaa4710SRishi Srivatsavai 7324eaa4710SRishi Srivatsavai free(fmri); 7334eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_PERSIST) && 7344eaa4710SRishi Srivatsavai bind_instance(service_name, instance, &sstate) == 0) { 7354eaa4710SRishi Srivatsavai (void) scf_instance_delete(sstate.ss_inst); 7364eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 7374eaa4710SRishi Srivatsavai } 7384eaa4710SRishi Srivatsavai 7394eaa4710SRishi Srivatsavai return (status); 7404eaa4710SRishi Srivatsavai } 7414eaa4710SRishi Srivatsavai 7424eaa4710SRishi Srivatsavai static dladm_status_t 7434eaa4710SRishi Srivatsavai disable_trill(const char *instance, uint32_t flags) 7444eaa4710SRishi Srivatsavai { 7454eaa4710SRishi Srivatsavai return (shut_down_instance(TRILL_SVC_NAME, instance, flags)); 7464eaa4710SRishi Srivatsavai } 7474eaa4710SRishi Srivatsavai 7484eaa4710SRishi Srivatsavai /* 7494eaa4710SRishi Srivatsavai * To enable TRILL, we must create a new instance of the TRILL service, then 7504eaa4710SRishi Srivatsavai * add proper dependencies to it, and finally mark it as enabled. The 7514eaa4710SRishi Srivatsavai * dependencies will keep it from going on-line until the bridge is running. 7524eaa4710SRishi Srivatsavai */ 7534eaa4710SRishi Srivatsavai static dladm_status_t 7544eaa4710SRishi Srivatsavai enable_trill(const char *instance) 7554eaa4710SRishi Srivatsavai { 7564eaa4710SRishi Srivatsavai dladm_status_t status = DLADM_STATUS_FAILED; 7574eaa4710SRishi Srivatsavai char *fmri = NULL; 7584eaa4710SRishi Srivatsavai scf_state_t sstate; 7594eaa4710SRishi Srivatsavai scf_transaction_t *tran = NULL; 7604eaa4710SRishi Srivatsavai boolean_t new_instance = B_FALSE; 7614eaa4710SRishi Srivatsavai boolean_t new_pg = B_FALSE; 7624eaa4710SRishi Srivatsavai int rv; 7634eaa4710SRishi Srivatsavai 7644eaa4710SRishi Srivatsavai /* 7654eaa4710SRishi Srivatsavai * This check is here in case the user has installed and then removed 7664eaa4710SRishi Srivatsavai * the package. SMF should remove the manifest, but currently does 7674eaa4710SRishi Srivatsavai * not. 7684eaa4710SRishi Srivatsavai */ 7694eaa4710SRishi Srivatsavai if (access("/usr/sbin/trilld", F_OK) != 0) 7704eaa4710SRishi Srivatsavai return (DLADM_STATUS_OPTMISSING); 7714eaa4710SRishi Srivatsavai 7724eaa4710SRishi Srivatsavai if ((status = exact_instance(TRILL_SVC_NAME, &sstate)) != 7734eaa4710SRishi Srivatsavai DLADM_STATUS_OK) 7744eaa4710SRishi Srivatsavai goto out; 7754eaa4710SRishi Srivatsavai 7764eaa4710SRishi Srivatsavai status = DLADM_STATUS_FAILED; 7774eaa4710SRishi Srivatsavai if (scf_service_get_instance(sstate.ss_svc, instance, sstate.ss_inst) != 7784eaa4710SRishi Srivatsavai 0) { 7794eaa4710SRishi Srivatsavai if (scf_service_add_instance(sstate.ss_svc, instance, 7804eaa4710SRishi Srivatsavai sstate.ss_inst) != 0) 7814eaa4710SRishi Srivatsavai goto out; 7824eaa4710SRishi Srivatsavai new_instance = B_TRUE; 7834eaa4710SRishi Srivatsavai } 7844eaa4710SRishi Srivatsavai 7854eaa4710SRishi Srivatsavai if ((tran = scf_transaction_create(sstate.ss_handle)) == NULL) 7864eaa4710SRishi Srivatsavai goto out; 7874eaa4710SRishi Srivatsavai 7884eaa4710SRishi Srivatsavai if ((sstate.ss_pg = scf_pg_create(sstate.ss_handle)) == NULL) 7894eaa4710SRishi Srivatsavai goto out; 7904eaa4710SRishi Srivatsavai 7914eaa4710SRishi Srivatsavai if (scf_instance_get_pg(sstate.ss_inst, "bridging", 7924eaa4710SRishi Srivatsavai sstate.ss_pg) == 0) { 7934eaa4710SRishi Srivatsavai status = DLADM_STATUS_OK; 7944eaa4710SRishi Srivatsavai goto out; 7954eaa4710SRishi Srivatsavai } 7964eaa4710SRishi Srivatsavai 7974eaa4710SRishi Srivatsavai if ((fmri = alloc_fmri(BRIDGE_SVC_NAME, instance)) == NULL) 7984eaa4710SRishi Srivatsavai goto out; 7994eaa4710SRishi Srivatsavai 8004eaa4710SRishi Srivatsavai if (scf_instance_add_pg(sstate.ss_inst, "bridging", 8014eaa4710SRishi Srivatsavai SCF_GROUP_DEPENDENCY, 0, sstate.ss_pg) != 0) 8024eaa4710SRishi Srivatsavai goto out; 8034eaa4710SRishi Srivatsavai 8044eaa4710SRishi Srivatsavai new_pg = B_TRUE; 8054eaa4710SRishi Srivatsavai do { 8064eaa4710SRishi Srivatsavai if (scf_transaction_start(tran, sstate.ss_pg) != 0) 8074eaa4710SRishi Srivatsavai goto out; 8084eaa4710SRishi Srivatsavai 8094eaa4710SRishi Srivatsavai if (!set_string_property(sstate.ss_handle, tran, 8104eaa4710SRishi Srivatsavai SCF_PROPERTY_GROUPING, SCF_DEP_REQUIRE_ALL)) 8114eaa4710SRishi Srivatsavai goto out; 8124eaa4710SRishi Srivatsavai if (!set_string_property(sstate.ss_handle, tran, 8134eaa4710SRishi Srivatsavai SCF_PROPERTY_RESTART_ON, SCF_DEP_RESET_ON_RESTART)) 8144eaa4710SRishi Srivatsavai goto out; 8154eaa4710SRishi Srivatsavai if (!set_string_property(sstate.ss_handle, tran, 8164eaa4710SRishi Srivatsavai SCF_PROPERTY_TYPE, "service")) 8174eaa4710SRishi Srivatsavai goto out; 8184eaa4710SRishi Srivatsavai if (!set_fmri_property(sstate.ss_handle, tran, 8194eaa4710SRishi Srivatsavai SCF_PROPERTY_ENTITIES, fmri)) 8204eaa4710SRishi Srivatsavai goto out; 8214eaa4710SRishi Srivatsavai 8224eaa4710SRishi Srivatsavai rv = scf_transaction_commit(tran); 8234eaa4710SRishi Srivatsavai scf_transaction_reset(tran); 8244eaa4710SRishi Srivatsavai if (rv == 0 && scf_pg_update(sstate.ss_pg) == -1) 8254eaa4710SRishi Srivatsavai goto out; 8264eaa4710SRishi Srivatsavai } while (rv == 0); 8274eaa4710SRishi Srivatsavai if (rv != 1) 8284eaa4710SRishi Srivatsavai goto out; 8294eaa4710SRishi Srivatsavai 8304eaa4710SRishi Srivatsavai status = DLADM_STATUS_OK; 8314eaa4710SRishi Srivatsavai 8324eaa4710SRishi Srivatsavai out: 8334eaa4710SRishi Srivatsavai free(fmri); 8344eaa4710SRishi Srivatsavai if (tran != NULL) { 8354eaa4710SRishi Srivatsavai scf_transaction_destroy_children(tran); 8364eaa4710SRishi Srivatsavai scf_transaction_destroy(tran); 8374eaa4710SRishi Srivatsavai } 8384eaa4710SRishi Srivatsavai 8394eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK && new_pg) 8404eaa4710SRishi Srivatsavai (void) scf_pg_delete(sstate.ss_pg); 8414eaa4710SRishi Srivatsavai 8424eaa4710SRishi Srivatsavai drop_composed(&sstate); 8434eaa4710SRishi Srivatsavai 8444eaa4710SRishi Srivatsavai /* 8454eaa4710SRishi Srivatsavai * If we created an instance and then failed, then remove the instance 8464eaa4710SRishi Srivatsavai * from the system. 8474eaa4710SRishi Srivatsavai */ 8484eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK && new_instance) 8494eaa4710SRishi Srivatsavai (void) scf_instance_delete(sstate.ss_inst); 8504eaa4710SRishi Srivatsavai 8514eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 8524eaa4710SRishi Srivatsavai 8534eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK) 8544eaa4710SRishi Srivatsavai status = enable_instance(TRILL_SVC_NAME, instance); 8554eaa4710SRishi Srivatsavai 8564eaa4710SRishi Srivatsavai return (status); 8574eaa4710SRishi Srivatsavai } 8584eaa4710SRishi Srivatsavai 8594eaa4710SRishi Srivatsavai /* 8604eaa4710SRishi Srivatsavai * Create a new bridge or modify an existing one. Update the SMF configuration 8614eaa4710SRishi Srivatsavai * and add links. 8624eaa4710SRishi Srivatsavai * 8634eaa4710SRishi Srivatsavai * Input timer values are in IEEE scaled (* 256) format. 8644eaa4710SRishi Srivatsavai */ 8654eaa4710SRishi Srivatsavai dladm_status_t 8664eaa4710SRishi Srivatsavai dladm_bridge_configure(dladm_handle_t handle, const char *name, 8674eaa4710SRishi Srivatsavai const UID_STP_CFG_T *cfg, dladm_bridge_prot_t brprot, uint32_t flags) 8684eaa4710SRishi Srivatsavai { 8694eaa4710SRishi Srivatsavai dladm_status_t status; 8704eaa4710SRishi Srivatsavai scf_state_t sstate; 8714eaa4710SRishi Srivatsavai scf_transaction_t *tran = NULL; 8724eaa4710SRishi Srivatsavai boolean_t new_instance = B_FALSE; 8734eaa4710SRishi Srivatsavai boolean_t new_pg = B_FALSE; 8744eaa4710SRishi Srivatsavai datalink_id_t linkid = DATALINK_INVALID_LINKID; 8754eaa4710SRishi Srivatsavai char linkname[MAXLINKNAMELEN]; 8764eaa4710SRishi Srivatsavai int rv; 8774eaa4710SRishi Srivatsavai 8784eaa4710SRishi Srivatsavai if (!dladm_valid_bridgename(name)) 8794eaa4710SRishi Srivatsavai return (DLADM_STATUS_FAILED); 8804eaa4710SRishi Srivatsavai 8814eaa4710SRishi Srivatsavai if (flags & DLADM_OPT_CREATE) { 8824eaa4710SRishi Srivatsavai /* 8834eaa4710SRishi Srivatsavai * This check is here in case the user has installed and then 8844eaa4710SRishi Srivatsavai * removed the package. SMF should remove the manifest, but 8854eaa4710SRishi Srivatsavai * currently does not. 8864eaa4710SRishi Srivatsavai */ 8874eaa4710SRishi Srivatsavai if (access("/usr/lib/bridged", F_OK) != 0) 8884eaa4710SRishi Srivatsavai return (DLADM_STATUS_OPTMISSING); 8894eaa4710SRishi Srivatsavai 8904eaa4710SRishi Srivatsavai (void) snprintf(linkname, sizeof (linkname), "%s0", name); 8914eaa4710SRishi Srivatsavai status = dladm_create_datalink_id(handle, linkname, 8924eaa4710SRishi Srivatsavai DATALINK_CLASS_BRIDGE, DL_ETHER, 8934eaa4710SRishi Srivatsavai flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST), &linkid); 8944eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 8954eaa4710SRishi Srivatsavai return (status); 8964eaa4710SRishi Srivatsavai 8974eaa4710SRishi Srivatsavai if ((flags & DLADM_OPT_PERSIST) && 8984eaa4710SRishi Srivatsavai (status = dladm_bridge_persist_conf(handle, linkname, 8994eaa4710SRishi Srivatsavai linkid) != DLADM_STATUS_OK)) 9004eaa4710SRishi Srivatsavai goto dladm_fail; 9014eaa4710SRishi Srivatsavai } 9024eaa4710SRishi Srivatsavai 9034eaa4710SRishi Srivatsavai if (brprot == DLADM_BRIDGE_PROT_TRILL) 9044eaa4710SRishi Srivatsavai status = enable_trill(name); 9054eaa4710SRishi Srivatsavai else 9064eaa4710SRishi Srivatsavai status = disable_trill(name, flags); 9074eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 9084eaa4710SRishi Srivatsavai goto dladm_fail; 9094eaa4710SRishi Srivatsavai 9104eaa4710SRishi Srivatsavai if ((status = exact_instance(BRIDGE_SVC_NAME, &sstate)) != 9114eaa4710SRishi Srivatsavai DLADM_STATUS_OK) 9124eaa4710SRishi Srivatsavai goto out; 9134eaa4710SRishi Srivatsavai 9144eaa4710SRishi Srivatsavai /* set up for a series of scf calls */ 9154eaa4710SRishi Srivatsavai status = DLADM_STATUS_FAILED; 9164eaa4710SRishi Srivatsavai 9174eaa4710SRishi Srivatsavai if (scf_service_get_instance(sstate.ss_svc, name, sstate.ss_inst) == 9184eaa4710SRishi Srivatsavai 0) { 9194eaa4710SRishi Srivatsavai if (flags & DLADM_OPT_CREATE) { 9204eaa4710SRishi Srivatsavai status = DLADM_STATUS_EXIST; 9214eaa4710SRishi Srivatsavai goto out; 9224eaa4710SRishi Srivatsavai } 9234eaa4710SRishi Srivatsavai } else { 9244eaa4710SRishi Srivatsavai if (!(flags & DLADM_OPT_CREATE)) { 9254eaa4710SRishi Srivatsavai status = DLADM_STATUS_NOTFOUND; 9264eaa4710SRishi Srivatsavai goto out; 9274eaa4710SRishi Srivatsavai } 9284eaa4710SRishi Srivatsavai if (scf_service_add_instance(sstate.ss_svc, name, 9294eaa4710SRishi Srivatsavai sstate.ss_inst) != 0) 9304eaa4710SRishi Srivatsavai goto out; 9314eaa4710SRishi Srivatsavai new_instance = B_TRUE; 9324eaa4710SRishi Srivatsavai } 9334eaa4710SRishi Srivatsavai 9344eaa4710SRishi Srivatsavai if ((tran = scf_transaction_create(sstate.ss_handle)) == NULL) 9354eaa4710SRishi Srivatsavai goto out; 9364eaa4710SRishi Srivatsavai 9374eaa4710SRishi Srivatsavai if (cfg->field_mask & BR_CFG_ALL) { 9384eaa4710SRishi Srivatsavai if ((sstate.ss_pg = scf_pg_create(sstate.ss_handle)) == NULL) 9394eaa4710SRishi Srivatsavai goto out; 9404eaa4710SRishi Srivatsavai if (scf_instance_add_pg(sstate.ss_inst, "config", 9414eaa4710SRishi Srivatsavai SCF_GROUP_APPLICATION, 0, sstate.ss_pg) == 0) { 9424eaa4710SRishi Srivatsavai new_pg = B_TRUE; 9434eaa4710SRishi Srivatsavai } else if (scf_instance_get_pg(sstate.ss_inst, "config", 9444eaa4710SRishi Srivatsavai sstate.ss_pg) != 0) { 9454eaa4710SRishi Srivatsavai goto out; 9464eaa4710SRishi Srivatsavai } 9474eaa4710SRishi Srivatsavai do { 9484eaa4710SRishi Srivatsavai if (scf_transaction_start(tran, sstate.ss_pg) != 0) 9494eaa4710SRishi Srivatsavai goto out; 9504eaa4710SRishi Srivatsavai 9514eaa4710SRishi Srivatsavai if ((cfg->field_mask & BR_CFG_PRIO) && 9524eaa4710SRishi Srivatsavai !set_count_property(sstate.ss_handle, tran, 9534eaa4710SRishi Srivatsavai "priority", cfg->bridge_priority)) 9544eaa4710SRishi Srivatsavai goto out; 9554eaa4710SRishi Srivatsavai if ((cfg->field_mask & BR_CFG_AGE) && 9564eaa4710SRishi Srivatsavai !set_count_property(sstate.ss_handle, tran, 9574eaa4710SRishi Srivatsavai "max-age", cfg->max_age * IEEE_TIMER_SCALE)) 9584eaa4710SRishi Srivatsavai goto out; 9594eaa4710SRishi Srivatsavai if ((cfg->field_mask & BR_CFG_HELLO) && 9604eaa4710SRishi Srivatsavai !set_count_property(sstate.ss_handle, tran, 9614eaa4710SRishi Srivatsavai "hello-time", cfg->hello_time * IEEE_TIMER_SCALE)) 9624eaa4710SRishi Srivatsavai goto out; 9634eaa4710SRishi Srivatsavai if ((cfg->field_mask & BR_CFG_DELAY) && 9644eaa4710SRishi Srivatsavai !set_count_property(sstate.ss_handle, tran, 9654eaa4710SRishi Srivatsavai "forward-delay", 9664eaa4710SRishi Srivatsavai cfg->forward_delay * IEEE_TIMER_SCALE)) 9674eaa4710SRishi Srivatsavai goto out; 9684eaa4710SRishi Srivatsavai if ((cfg->field_mask & BR_CFG_FORCE_VER) && 9694eaa4710SRishi Srivatsavai !set_count_property(sstate.ss_handle, tran, 9704eaa4710SRishi Srivatsavai "force-protocol", cfg->force_version)) 9714eaa4710SRishi Srivatsavai goto out; 9724eaa4710SRishi Srivatsavai 9734eaa4710SRishi Srivatsavai rv = scf_transaction_commit(tran); 9744eaa4710SRishi Srivatsavai scf_transaction_reset(tran); 9754eaa4710SRishi Srivatsavai if (rv == 0 && scf_pg_update(sstate.ss_pg) == -1) 9764eaa4710SRishi Srivatsavai goto out; 9774eaa4710SRishi Srivatsavai } while (rv == 0); 9784eaa4710SRishi Srivatsavai if (rv != 1) 9794eaa4710SRishi Srivatsavai goto out; 9804eaa4710SRishi Srivatsavai } 9814eaa4710SRishi Srivatsavai 9824eaa4710SRishi Srivatsavai /* 9834eaa4710SRishi Srivatsavai * If we're modifying an existing and running bridge, then tell the 9844eaa4710SRishi Srivatsavai * daemon to update the requested values. 9854eaa4710SRishi Srivatsavai */ 9864eaa4710SRishi Srivatsavai if ((flags & DLADM_OPT_ACTIVE) && !(flags & DLADM_OPT_CREATE)) 9874eaa4710SRishi Srivatsavai status = bridge_refresh(name); 9884eaa4710SRishi Srivatsavai else 9894eaa4710SRishi Srivatsavai status = DLADM_STATUS_OK; 9904eaa4710SRishi Srivatsavai 9914eaa4710SRishi Srivatsavai out: 9924eaa4710SRishi Srivatsavai if (tran != NULL) { 9934eaa4710SRishi Srivatsavai scf_transaction_destroy_children(tran); 9944eaa4710SRishi Srivatsavai scf_transaction_destroy(tran); 9954eaa4710SRishi Srivatsavai } 9964eaa4710SRishi Srivatsavai 9974eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK && new_pg) 9984eaa4710SRishi Srivatsavai (void) scf_pg_delete(sstate.ss_pg); 9994eaa4710SRishi Srivatsavai 10004eaa4710SRishi Srivatsavai drop_composed(&sstate); 10014eaa4710SRishi Srivatsavai 10024eaa4710SRishi Srivatsavai /* 10034eaa4710SRishi Srivatsavai * If we created an instance and then failed, then remove the instance 10044eaa4710SRishi Srivatsavai * from the system. 10054eaa4710SRishi Srivatsavai */ 10064eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK && new_instance) 10074eaa4710SRishi Srivatsavai (void) scf_instance_delete(sstate.ss_inst); 10084eaa4710SRishi Srivatsavai 10094eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 10104eaa4710SRishi Srivatsavai 10114eaa4710SRishi Srivatsavai /* 10124eaa4710SRishi Srivatsavai * Remove the bridge linkid if we've allocated one in this function but 10134eaa4710SRishi Srivatsavai * we've failed to set up the SMF properties. 10144eaa4710SRishi Srivatsavai */ 10154eaa4710SRishi Srivatsavai dladm_fail: 10164eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK && linkid != DATALINK_INVALID_LINKID) { 10174eaa4710SRishi Srivatsavai (void) dladm_remove_conf(handle, linkid); 10184eaa4710SRishi Srivatsavai (void) dladm_destroy_datalink_id(handle, linkid, flags); 10194eaa4710SRishi Srivatsavai } 10204eaa4710SRishi Srivatsavai 10214eaa4710SRishi Srivatsavai return (status); 10224eaa4710SRishi Srivatsavai } 10234eaa4710SRishi Srivatsavai 10244eaa4710SRishi Srivatsavai /* 10254eaa4710SRishi Srivatsavai * Enable a newly-created bridge in SMF by creating "general/enabled" and 10264eaa4710SRishi Srivatsavai * deleting any "general_ovr/enabled" (used for temporary services). 10274eaa4710SRishi Srivatsavai */ 10284eaa4710SRishi Srivatsavai dladm_status_t 10294eaa4710SRishi Srivatsavai dladm_bridge_enable(const char *name) 10304eaa4710SRishi Srivatsavai { 10314eaa4710SRishi Srivatsavai return (enable_instance(BRIDGE_SVC_NAME, name)); 10324eaa4710SRishi Srivatsavai } 10334eaa4710SRishi Srivatsavai 10344eaa4710SRishi Srivatsavai /* 10354eaa4710SRishi Srivatsavai * Set a link as a member of a bridge, or remove bridge membership. If the 10364eaa4710SRishi Srivatsavai * DLADM_OPT_CREATE flag is set, then we assume that the daemon isn't running. 10374eaa4710SRishi Srivatsavai * In all other cases, we must tell the daemon to add or delete the link in 10384eaa4710SRishi Srivatsavai * order to stay in sync. 10394eaa4710SRishi Srivatsavai */ 10404eaa4710SRishi Srivatsavai dladm_status_t 10414eaa4710SRishi Srivatsavai dladm_bridge_setlink(dladm_handle_t handle, datalink_id_t linkid, 10424eaa4710SRishi Srivatsavai const char *bridge) 10434eaa4710SRishi Srivatsavai { 10444eaa4710SRishi Srivatsavai dladm_status_t status; 10454eaa4710SRishi Srivatsavai dladm_conf_t conf; 10464eaa4710SRishi Srivatsavai char oldbridge[MAXLINKNAMELEN]; 10474eaa4710SRishi Srivatsavai boolean_t has_oldbridge; 10484eaa4710SRishi Srivatsavai boolean_t changed = B_FALSE; 10494eaa4710SRishi Srivatsavai 10504eaa4710SRishi Srivatsavai if (*bridge != '\0' && !dladm_valid_bridgename(bridge)) 10514eaa4710SRishi Srivatsavai return (DLADM_STATUS_FAILED); 10524eaa4710SRishi Srivatsavai 10534eaa4710SRishi Srivatsavai if ((status = dladm_read_conf(handle, linkid, &conf)) != 10544eaa4710SRishi Srivatsavai DLADM_STATUS_OK) 10554eaa4710SRishi Srivatsavai return (status); 10564eaa4710SRishi Srivatsavai 10574eaa4710SRishi Srivatsavai has_oldbridge = B_FALSE; 10584eaa4710SRishi Srivatsavai status = dladm_get_conf_field(handle, conf, FBRIDGE, oldbridge, 10594eaa4710SRishi Srivatsavai sizeof (oldbridge)); 10604eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK) { 10614eaa4710SRishi Srivatsavai /* 10624eaa4710SRishi Srivatsavai * Don't allow a link to be reassigned directly from one bridge 10634eaa4710SRishi Srivatsavai * to another. It must be removed first. 10644eaa4710SRishi Srivatsavai */ 10654eaa4710SRishi Srivatsavai if (*oldbridge != '\0' && *bridge != '\0') { 10664eaa4710SRishi Srivatsavai status = DLADM_STATUS_EXIST; 10674eaa4710SRishi Srivatsavai goto out; 10684eaa4710SRishi Srivatsavai } 10694eaa4710SRishi Srivatsavai has_oldbridge = B_TRUE; 10704eaa4710SRishi Srivatsavai } else if (status != DLADM_STATUS_NOTFOUND) { 10714eaa4710SRishi Srivatsavai goto out; 10724eaa4710SRishi Srivatsavai } 10734eaa4710SRishi Srivatsavai 10744eaa4710SRishi Srivatsavai if (*bridge != '\0') { 10754eaa4710SRishi Srivatsavai status = dladm_set_conf_field(handle, conf, FBRIDGE, 10764eaa4710SRishi Srivatsavai DLADM_TYPE_STR, bridge); 10774eaa4710SRishi Srivatsavai changed = B_TRUE; 10784eaa4710SRishi Srivatsavai } else if (has_oldbridge) { 10794eaa4710SRishi Srivatsavai status = dladm_unset_conf_field(handle, conf, FBRIDGE); 10804eaa4710SRishi Srivatsavai changed = B_TRUE; 10814eaa4710SRishi Srivatsavai } else { 10824eaa4710SRishi Srivatsavai status = DLADM_STATUS_OK; 10834eaa4710SRishi Srivatsavai goto out; 10844eaa4710SRishi Srivatsavai } 10854eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK) 10864eaa4710SRishi Srivatsavai status = dladm_write_conf(handle, conf); 10874eaa4710SRishi Srivatsavai 10884eaa4710SRishi Srivatsavai out: 10894eaa4710SRishi Srivatsavai dladm_destroy_conf(handle, conf); 10904eaa4710SRishi Srivatsavai if (changed && status == DLADM_STATUS_OK) { 10914eaa4710SRishi Srivatsavai if (bridge[0] == '\0') 10924eaa4710SRishi Srivatsavai bridge = oldbridge; 10934eaa4710SRishi Srivatsavai status = bridge_refresh(bridge); 10944eaa4710SRishi Srivatsavai } 10954eaa4710SRishi Srivatsavai return (status); 10964eaa4710SRishi Srivatsavai } 10974eaa4710SRishi Srivatsavai 10984eaa4710SRishi Srivatsavai /* 10994eaa4710SRishi Srivatsavai * Get the name of the bridge of which the given linkid is a member. 11004eaa4710SRishi Srivatsavai */ 11014eaa4710SRishi Srivatsavai dladm_status_t 11024eaa4710SRishi Srivatsavai dladm_bridge_getlink(dladm_handle_t handle, datalink_id_t linkid, char *bridge, 11034eaa4710SRishi Srivatsavai size_t bridgelen) 11044eaa4710SRishi Srivatsavai { 11054eaa4710SRishi Srivatsavai dladm_status_t status; 11064eaa4710SRishi Srivatsavai dladm_conf_t conf; 11074eaa4710SRishi Srivatsavai 11084eaa4710SRishi Srivatsavai if ((status = dladm_read_conf(handle, linkid, &conf)) != 11094eaa4710SRishi Srivatsavai DLADM_STATUS_OK) 11104eaa4710SRishi Srivatsavai return (status); 11114eaa4710SRishi Srivatsavai 11124eaa4710SRishi Srivatsavai *bridge = '\0'; 11134eaa4710SRishi Srivatsavai status = dladm_get_conf_field(handle, conf, FBRIDGE, bridge, bridgelen); 11144eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK && *bridge == '\0') 11154eaa4710SRishi Srivatsavai status = DLADM_STATUS_NOTFOUND; 11164eaa4710SRishi Srivatsavai 11174eaa4710SRishi Srivatsavai dladm_destroy_conf(handle, conf); 11184eaa4710SRishi Srivatsavai return (status); 11194eaa4710SRishi Srivatsavai } 11204eaa4710SRishi Srivatsavai 11214eaa4710SRishi Srivatsavai dladm_status_t 11224eaa4710SRishi Srivatsavai dladm_bridge_refresh(dladm_handle_t handle, datalink_id_t linkid) 11234eaa4710SRishi Srivatsavai { 11244eaa4710SRishi Srivatsavai char bridge[MAXLINKNAMELEN]; 11254eaa4710SRishi Srivatsavai dladm_status_t status; 11264eaa4710SRishi Srivatsavai 11274eaa4710SRishi Srivatsavai status = dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge)); 11284eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_NOTFOUND) 11294eaa4710SRishi Srivatsavai return (DLADM_STATUS_OK); 11304eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK) 11314eaa4710SRishi Srivatsavai status = bridge_refresh(bridge); 11324eaa4710SRishi Srivatsavai return (status); 11334eaa4710SRishi Srivatsavai } 11344eaa4710SRishi Srivatsavai 11354eaa4710SRishi Srivatsavai typedef struct bridge_held_arg_s { 11364eaa4710SRishi Srivatsavai const char *bha_bridge; 11374eaa4710SRishi Srivatsavai boolean_t bha_isheld; 11384eaa4710SRishi Srivatsavai } bridge_held_arg_t; 11394eaa4710SRishi Srivatsavai 11404eaa4710SRishi Srivatsavai static int 11414eaa4710SRishi Srivatsavai i_dladm_bridge_is_held(dladm_handle_t handle, datalink_id_t linkid, void *arg) 11424eaa4710SRishi Srivatsavai { 11434eaa4710SRishi Srivatsavai dladm_status_t status = DLADM_STATUS_FAILED; 11444eaa4710SRishi Srivatsavai dladm_conf_t conf; 11454eaa4710SRishi Srivatsavai char bridge[MAXLINKNAMELEN]; 11464eaa4710SRishi Srivatsavai bridge_held_arg_t *bha = arg; 11474eaa4710SRishi Srivatsavai 11484eaa4710SRishi Srivatsavai if ((status = dladm_read_conf(handle, linkid, &conf)) != 11494eaa4710SRishi Srivatsavai DLADM_STATUS_OK) 11504eaa4710SRishi Srivatsavai return (DLADM_WALK_CONTINUE); 11514eaa4710SRishi Srivatsavai status = dladm_get_conf_field(handle, conf, FBRIDGE, bridge, 11524eaa4710SRishi Srivatsavai sizeof (bridge)); 11534eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK && strcmp(bha->bha_bridge, bridge) == 0) { 11544eaa4710SRishi Srivatsavai bha->bha_isheld = B_TRUE; 11554eaa4710SRishi Srivatsavai dladm_destroy_conf(handle, conf); 11564eaa4710SRishi Srivatsavai return (DLADM_WALK_TERMINATE); 11574eaa4710SRishi Srivatsavai } else { 11584eaa4710SRishi Srivatsavai dladm_destroy_conf(handle, conf); 11594eaa4710SRishi Srivatsavai return (DLADM_WALK_CONTINUE); 11604eaa4710SRishi Srivatsavai } 11614eaa4710SRishi Srivatsavai } 11624eaa4710SRishi Srivatsavai 11634eaa4710SRishi Srivatsavai /* 11644eaa4710SRishi Srivatsavai * Delete a previously created bridge. 11654eaa4710SRishi Srivatsavai */ 11664eaa4710SRishi Srivatsavai dladm_status_t 11674eaa4710SRishi Srivatsavai dladm_bridge_delete(dladm_handle_t handle, const char *bridge, uint32_t flags) 11684eaa4710SRishi Srivatsavai { 11694eaa4710SRishi Srivatsavai datalink_id_t linkid; 11704eaa4710SRishi Srivatsavai datalink_class_t class; 11714eaa4710SRishi Srivatsavai dladm_status_t status; 11724eaa4710SRishi Srivatsavai char linkname[MAXLINKNAMELEN]; 11734eaa4710SRishi Srivatsavai 11744eaa4710SRishi Srivatsavai if (!dladm_valid_bridgename(bridge)) 11754eaa4710SRishi Srivatsavai return (DLADM_STATUS_LINKINVAL); 11764eaa4710SRishi Srivatsavai 11774eaa4710SRishi Srivatsavai /* Get the datalink ID for this bridge */ 11784eaa4710SRishi Srivatsavai (void) snprintf(linkname, sizeof (linkname), "%s0", bridge); 11794eaa4710SRishi Srivatsavai if (dladm_name2info(handle, linkname, &linkid, NULL, NULL, NULL) != 11804eaa4710SRishi Srivatsavai DLADM_STATUS_OK) 11814eaa4710SRishi Srivatsavai linkid = DATALINK_INVALID_LINKID; 11824eaa4710SRishi Srivatsavai else if (dladm_datalink_id2info(handle, linkid, NULL, &class, NULL, 11834eaa4710SRishi Srivatsavai NULL, 0) != DLADM_STATUS_OK) 11844eaa4710SRishi Srivatsavai linkid = DATALINK_INVALID_LINKID; 11854eaa4710SRishi Srivatsavai else if (class != DATALINK_CLASS_BRIDGE) 11864eaa4710SRishi Srivatsavai return (DLADM_STATUS_BADARG); 11874eaa4710SRishi Srivatsavai 11884eaa4710SRishi Srivatsavai if ((flags & DLADM_OPT_ACTIVE) && linkid == DATALINK_INVALID_LINKID) 11894eaa4710SRishi Srivatsavai return (DLADM_STATUS_BADARG); 11904eaa4710SRishi Srivatsavai 11914eaa4710SRishi Srivatsavai if (flags & DLADM_OPT_PERSIST) { 11924eaa4710SRishi Srivatsavai bridge_held_arg_t arg; 11934eaa4710SRishi Srivatsavai 11944eaa4710SRishi Srivatsavai arg.bha_bridge = bridge; 11954eaa4710SRishi Srivatsavai arg.bha_isheld = B_FALSE; 11964eaa4710SRishi Srivatsavai 11974eaa4710SRishi Srivatsavai /* 11984eaa4710SRishi Srivatsavai * See whether there are any persistent links using this 11994eaa4710SRishi Srivatsavai * bridge. If so, we fail the operation. 12004eaa4710SRishi Srivatsavai */ 12014eaa4710SRishi Srivatsavai (void) dladm_walk_datalink_id(i_dladm_bridge_is_held, handle, 12024eaa4710SRishi Srivatsavai &arg, DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | 12034eaa4710SRishi Srivatsavai DATALINK_CLASS_ETHERSTUB | DATALINK_CLASS_SIMNET, 12044eaa4710SRishi Srivatsavai DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); 12054eaa4710SRishi Srivatsavai if (arg.bha_isheld) 12064eaa4710SRishi Srivatsavai return (DLADM_STATUS_LINKBUSY); 12074eaa4710SRishi Srivatsavai } 12084eaa4710SRishi Srivatsavai 12094eaa4710SRishi Srivatsavai if ((status = disable_trill(bridge, flags)) != DLADM_STATUS_OK) 12104eaa4710SRishi Srivatsavai goto out; 12114eaa4710SRishi Srivatsavai 12124eaa4710SRishi Srivatsavai /* Disable or remove the SMF instance */ 12134eaa4710SRishi Srivatsavai status = shut_down_instance(BRIDGE_SVC_NAME, bridge, flags); 12144eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 12154eaa4710SRishi Srivatsavai goto out; 12164eaa4710SRishi Srivatsavai 12174eaa4710SRishi Srivatsavai if (flags & DLADM_OPT_ACTIVE) { 12184eaa4710SRishi Srivatsavai /* 12194eaa4710SRishi Srivatsavai * Delete ACTIVE linkprop now that daemon is gone. 12204eaa4710SRishi Srivatsavai */ 12214eaa4710SRishi Srivatsavai (void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0, 12224eaa4710SRishi Srivatsavai DLADM_OPT_ACTIVE); 12234eaa4710SRishi Srivatsavai (void) dladm_destroy_datalink_id(handle, linkid, 12244eaa4710SRishi Srivatsavai DLADM_OPT_ACTIVE); 12254eaa4710SRishi Srivatsavai } 12264eaa4710SRishi Srivatsavai 12274eaa4710SRishi Srivatsavai if (flags & DLADM_OPT_PERSIST) { 12284eaa4710SRishi Srivatsavai (void) dladm_remove_conf(handle, linkid); 12294eaa4710SRishi Srivatsavai (void) dladm_destroy_datalink_id(handle, linkid, 12304eaa4710SRishi Srivatsavai DLADM_OPT_PERSIST); 12314eaa4710SRishi Srivatsavai } 12324eaa4710SRishi Srivatsavai 12334eaa4710SRishi Srivatsavai out: 12344eaa4710SRishi Srivatsavai 12354eaa4710SRishi Srivatsavai return (status); 12364eaa4710SRishi Srivatsavai } 12374eaa4710SRishi Srivatsavai 12384eaa4710SRishi Srivatsavai /* Check if given name is valid for bridges */ 12394eaa4710SRishi Srivatsavai boolean_t 12404eaa4710SRishi Srivatsavai dladm_valid_bridgename(const char *bridge) 12414eaa4710SRishi Srivatsavai { 12424eaa4710SRishi Srivatsavai size_t len = strnlen(bridge, MAXLINKNAMELEN); 12434eaa4710SRishi Srivatsavai const char *cp; 12444eaa4710SRishi Srivatsavai 12454eaa4710SRishi Srivatsavai if (len == MAXLINKNAMELEN) 12464eaa4710SRishi Srivatsavai return (B_FALSE); 12474eaa4710SRishi Srivatsavai 12484eaa4710SRishi Srivatsavai /* 12494eaa4710SRishi Srivatsavai * The bridge name cannot start or end with a digit. 12504eaa4710SRishi Srivatsavai */ 12514eaa4710SRishi Srivatsavai if (isdigit(bridge[0]) || isdigit(bridge[len - 1])) 12524eaa4710SRishi Srivatsavai return (B_FALSE); 12534eaa4710SRishi Srivatsavai 12544eaa4710SRishi Srivatsavai /* 12554eaa4710SRishi Srivatsavai * The legal characters within a bridge name are: 12564eaa4710SRishi Srivatsavai * alphanumeric (a-z, A-Z, 0-9), and the underscore ('_'). 12574eaa4710SRishi Srivatsavai */ 12584eaa4710SRishi Srivatsavai for (cp = bridge; *cp != '\0'; cp++) { 12594eaa4710SRishi Srivatsavai if (!isalnum(*cp) && *cp != '_') 12604eaa4710SRishi Srivatsavai return (B_FALSE); 12614eaa4710SRishi Srivatsavai } 12624eaa4710SRishi Srivatsavai 12634eaa4710SRishi Srivatsavai return (B_TRUE); 12644eaa4710SRishi Srivatsavai } 12654eaa4710SRishi Srivatsavai 12664eaa4710SRishi Srivatsavai /* 12674eaa4710SRishi Srivatsavai * Convert a bridge-related observability node name back into the name of the 12684eaa4710SRishi Srivatsavai * bridge. Returns B_FALSE without making changes if the input name is not in 12694eaa4710SRishi Srivatsavai * a legal format. 12704eaa4710SRishi Srivatsavai */ 12714eaa4710SRishi Srivatsavai boolean_t 12724eaa4710SRishi Srivatsavai dladm_observe_to_bridge(char *link) 12734eaa4710SRishi Srivatsavai { 12744eaa4710SRishi Srivatsavai int llen; 12754eaa4710SRishi Srivatsavai 12764eaa4710SRishi Srivatsavai llen = strnlen(link, MAXLINKNAMELEN); 12774eaa4710SRishi Srivatsavai if (llen < 2 || link[llen - 1] != '0' || isdigit(link[llen - 2])) 12784eaa4710SRishi Srivatsavai return (B_FALSE); 12794eaa4710SRishi Srivatsavai link[llen - 1] = '\0'; 12804eaa4710SRishi Srivatsavai return (B_TRUE); 12814eaa4710SRishi Srivatsavai } 12824eaa4710SRishi Srivatsavai 12834eaa4710SRishi Srivatsavai /* 12844eaa4710SRishi Srivatsavai * Get bridge property values from the running daemon and return them in a 12854eaa4710SRishi Srivatsavai * common structure. 12864eaa4710SRishi Srivatsavai */ 12874eaa4710SRishi Srivatsavai dladm_status_t 12884eaa4710SRishi Srivatsavai dladm_bridge_run_properties(const char *instname, UID_STP_CFG_T *smcfg, 12894eaa4710SRishi Srivatsavai dladm_bridge_prot_t *brprotp) 12904eaa4710SRishi Srivatsavai { 12914eaa4710SRishi Srivatsavai dladm_status_t status; 12924eaa4710SRishi Srivatsavai bridge_door_cfg_t bdcf; 12934eaa4710SRishi Srivatsavai bridge_door_cfg_t *bdcfp = &bdcf; 12944eaa4710SRishi Srivatsavai size_t buflen = sizeof (bdcf); 12954eaa4710SRishi Srivatsavai 12964eaa4710SRishi Srivatsavai status = bridge_door_call(instname, bdcBridgeGetConfig, 12974eaa4710SRishi Srivatsavai DATALINK_INVALID_LINKID, (void **)&bdcfp, 0, &buflen, B_FALSE); 12984eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK) { 12994eaa4710SRishi Srivatsavai *smcfg = bdcfp->bdcf_cfg; 13004eaa4710SRishi Srivatsavai *brprotp = bdcfp->bdcf_prot; 13014eaa4710SRishi Srivatsavai } else { 13024eaa4710SRishi Srivatsavai smcfg->field_mask = 0; 13034eaa4710SRishi Srivatsavai *brprotp = DLADM_BRIDGE_PROT_STP; 13044eaa4710SRishi Srivatsavai } 13054eaa4710SRishi Srivatsavai return (status); 13064eaa4710SRishi Srivatsavai } 13074eaa4710SRishi Srivatsavai 13084eaa4710SRishi Srivatsavai /* 13094eaa4710SRishi Srivatsavai * Get bridge state from the running daemon and return in structure borrowed 13104eaa4710SRishi Srivatsavai * from librstp. 13114eaa4710SRishi Srivatsavai */ 13124eaa4710SRishi Srivatsavai dladm_status_t 13134eaa4710SRishi Srivatsavai dladm_bridge_state(const char *instname, UID_STP_STATE_T *statep) 13144eaa4710SRishi Srivatsavai { 13154eaa4710SRishi Srivatsavai size_t buflen = sizeof (*statep); 13164eaa4710SRishi Srivatsavai 13174eaa4710SRishi Srivatsavai return (bridge_door_call(instname, bdcBridgeGetState, 13184eaa4710SRishi Srivatsavai DATALINK_INVALID_LINKID, (void **)&statep, 0, &buflen, B_FALSE)); 13194eaa4710SRishi Srivatsavai } 13204eaa4710SRishi Srivatsavai 13214eaa4710SRishi Srivatsavai /* Returns list of ports (datalink_id_t values) assigned to a bridge instance */ 13224eaa4710SRishi Srivatsavai datalink_id_t * 13234eaa4710SRishi Srivatsavai dladm_bridge_get_portlist(const char *instname, uint_t *nports) 13244eaa4710SRishi Srivatsavai { 13254eaa4710SRishi Srivatsavai size_t buflen = sizeof (int) + MAXPORTS * sizeof (datalink_id_t); 13264eaa4710SRishi Srivatsavai int *rbuf; 13274eaa4710SRishi Srivatsavai 13284eaa4710SRishi Srivatsavai if ((rbuf = malloc(buflen)) == NULL) 13294eaa4710SRishi Srivatsavai return (NULL); 13304eaa4710SRishi Srivatsavai if (bridge_door_call(instname, bdcBridgeGetPorts, 13314eaa4710SRishi Srivatsavai DATALINK_INVALID_LINKID, (void **)&rbuf, 0, &buflen, B_TRUE) != 13324eaa4710SRishi Srivatsavai DLADM_STATUS_OK) { 13334eaa4710SRishi Srivatsavai free(rbuf); 13344eaa4710SRishi Srivatsavai return (NULL); 13354eaa4710SRishi Srivatsavai } else { 13364eaa4710SRishi Srivatsavai /* 13374eaa4710SRishi Srivatsavai * Returns an array of datalink_id_t values for all the ports 13384eaa4710SRishi Srivatsavai * part of the bridge instance. First entry in the array is the 13394eaa4710SRishi Srivatsavai * number of ports. 13404eaa4710SRishi Srivatsavai */ 13414eaa4710SRishi Srivatsavai *nports = *rbuf; 13424eaa4710SRishi Srivatsavai return ((datalink_id_t *)(rbuf + 1)); 13434eaa4710SRishi Srivatsavai } 13444eaa4710SRishi Srivatsavai } 13454eaa4710SRishi Srivatsavai 13464eaa4710SRishi Srivatsavai void 13474eaa4710SRishi Srivatsavai dladm_bridge_free_portlist(datalink_id_t *dlp) 13484eaa4710SRishi Srivatsavai { 13494eaa4710SRishi Srivatsavai free((int *)dlp - 1); 13504eaa4710SRishi Srivatsavai } 13514eaa4710SRishi Srivatsavai 13524eaa4710SRishi Srivatsavai /* Retrieve Bridge port configuration values */ 13534eaa4710SRishi Srivatsavai dladm_status_t 13544eaa4710SRishi Srivatsavai dladm_bridge_get_port_cfg(dladm_handle_t handle, datalink_id_t linkid, 13554eaa4710SRishi Srivatsavai int field, int *valuep) 13564eaa4710SRishi Srivatsavai { 13574eaa4710SRishi Srivatsavai UID_STP_PORT_CFG_T portcfg; 13584eaa4710SRishi Srivatsavai dladm_status_t status; 13594eaa4710SRishi Srivatsavai 13604eaa4710SRishi Srivatsavai status = port_door_call(handle, linkid, bdcPortGetConfig, &portcfg, 13614eaa4710SRishi Srivatsavai 0, sizeof (portcfg)); 13624eaa4710SRishi Srivatsavai if (status != DLADM_STATUS_OK) 13634eaa4710SRishi Srivatsavai return (status); 13644eaa4710SRishi Srivatsavai 13654eaa4710SRishi Srivatsavai switch (field) { 13664eaa4710SRishi Srivatsavai case PT_CFG_COST: 13674eaa4710SRishi Srivatsavai *valuep = portcfg.admin_port_path_cost; 13684eaa4710SRishi Srivatsavai break; 13694eaa4710SRishi Srivatsavai case PT_CFG_PRIO: 13704eaa4710SRishi Srivatsavai *valuep = portcfg.port_priority; 13714eaa4710SRishi Srivatsavai break; 13724eaa4710SRishi Srivatsavai case PT_CFG_P2P: 13734eaa4710SRishi Srivatsavai *valuep = portcfg.admin_point2point; 13744eaa4710SRishi Srivatsavai break; 13754eaa4710SRishi Srivatsavai case PT_CFG_EDGE: 13764eaa4710SRishi Srivatsavai *valuep = portcfg.admin_edge; 13774eaa4710SRishi Srivatsavai break; 13784eaa4710SRishi Srivatsavai case PT_CFG_NON_STP: 13794eaa4710SRishi Srivatsavai *valuep = !portcfg.admin_non_stp; 13804eaa4710SRishi Srivatsavai break; 13814eaa4710SRishi Srivatsavai case PT_CFG_MCHECK: 13824eaa4710SRishi Srivatsavai *valuep = (portcfg.field_mask & PT_CFG_MCHECK) ? 1 : 0; 13834eaa4710SRishi Srivatsavai break; 13844eaa4710SRishi Srivatsavai } 13854eaa4710SRishi Srivatsavai return (status); 13864eaa4710SRishi Srivatsavai } 13874eaa4710SRishi Srivatsavai 13884eaa4710SRishi Srivatsavai /* Retreive Bridge port status (disabled, bad SDU etc.) */ 13894eaa4710SRishi Srivatsavai dladm_status_t 13904eaa4710SRishi Srivatsavai dladm_bridge_link_state(dladm_handle_t handle, datalink_id_t linkid, 13914eaa4710SRishi Srivatsavai UID_STP_PORT_STATE_T *spsp) 13924eaa4710SRishi Srivatsavai { 13934eaa4710SRishi Srivatsavai return (port_door_call(handle, linkid, bdcPortGetState, spsp, 0, 13944eaa4710SRishi Srivatsavai sizeof (*spsp))); 13954eaa4710SRishi Srivatsavai } 13964eaa4710SRishi Srivatsavai 13974eaa4710SRishi Srivatsavai /* Retrieve Bridge forwarding status of the given link */ 13984eaa4710SRishi Srivatsavai dladm_status_t 13994eaa4710SRishi Srivatsavai dladm_bridge_get_forwarding(dladm_handle_t handle, datalink_id_t linkid, 14004eaa4710SRishi Srivatsavai uint_t *valuep) 14014eaa4710SRishi Srivatsavai { 14024eaa4710SRishi Srivatsavai int twoints[2]; 14034eaa4710SRishi Srivatsavai dladm_status_t status; 14044eaa4710SRishi Srivatsavai 14054eaa4710SRishi Srivatsavai status = port_door_call(handle, linkid, bdcPortGetForwarding, twoints, 14064eaa4710SRishi Srivatsavai 0, sizeof (twoints)); 14074eaa4710SRishi Srivatsavai if (status == DLADM_STATUS_OK) 14084eaa4710SRishi Srivatsavai *valuep = twoints[0]; 14094eaa4710SRishi Srivatsavai return (status); 14104eaa4710SRishi Srivatsavai } 14114eaa4710SRishi Srivatsavai 14124eaa4710SRishi Srivatsavai /* Retrieve Bridge forwarding table entries */ 14134eaa4710SRishi Srivatsavai bridge_listfwd_t * 14144eaa4710SRishi Srivatsavai dladm_bridge_get_fwdtable(dladm_handle_t handle, const char *bridge, 14154eaa4710SRishi Srivatsavai uint_t *nfwd) 14164eaa4710SRishi Srivatsavai { 14174eaa4710SRishi Srivatsavai bridge_listfwd_t *blf = NULL, *newblf, blfread; 14184eaa4710SRishi Srivatsavai uint_t nblf = 0, maxblf = 0; 14194eaa4710SRishi Srivatsavai static uint8_t zero_addr[ETHERADDRL]; 14204eaa4710SRishi Srivatsavai int rc; 14214eaa4710SRishi Srivatsavai 14224eaa4710SRishi Srivatsavai (void) memset(&blfread, 0, sizeof (blfread)); 14234eaa4710SRishi Srivatsavai (void) snprintf(blfread.blf_name, sizeof (blfread.blf_name), 14244eaa4710SRishi Srivatsavai "%s0", bridge); 14254eaa4710SRishi Srivatsavai for (;;) { 14264eaa4710SRishi Srivatsavai if (nblf >= maxblf) { 14274eaa4710SRishi Srivatsavai maxblf = maxblf == 0 ? 64 : (maxblf << 1); 14284eaa4710SRishi Srivatsavai newblf = realloc(blf, maxblf * sizeof (*blf)); 14294eaa4710SRishi Srivatsavai if (newblf == NULL) { 14304eaa4710SRishi Srivatsavai free(blf); 14314eaa4710SRishi Srivatsavai blf = NULL; 14324eaa4710SRishi Srivatsavai break; 14334eaa4710SRishi Srivatsavai } 14344eaa4710SRishi Srivatsavai blf = newblf; 14354eaa4710SRishi Srivatsavai } 14364eaa4710SRishi Srivatsavai rc = ioctl(dladm_dld_fd(handle), BRIDGE_IOC_LISTFWD, &blfread); 14374eaa4710SRishi Srivatsavai if (rc != 0) { 14384eaa4710SRishi Srivatsavai free(blf); 14394eaa4710SRishi Srivatsavai blf = NULL; 14404eaa4710SRishi Srivatsavai break; 14414eaa4710SRishi Srivatsavai } 14424eaa4710SRishi Srivatsavai if (memcmp(blfread.blf_dest, zero_addr, ETHERADDRL) == 0) 14434eaa4710SRishi Srivatsavai break; 14444eaa4710SRishi Srivatsavai blf[nblf++] = blfread; 14454eaa4710SRishi Srivatsavai } 14464eaa4710SRishi Srivatsavai if (blf != NULL) 14474eaa4710SRishi Srivatsavai *nfwd = nblf; 14484eaa4710SRishi Srivatsavai return (blf); 14494eaa4710SRishi Srivatsavai } 14504eaa4710SRishi Srivatsavai 14514eaa4710SRishi Srivatsavai void 14524eaa4710SRishi Srivatsavai dladm_bridge_free_fwdtable(bridge_listfwd_t *blf) 14534eaa4710SRishi Srivatsavai { 14544eaa4710SRishi Srivatsavai free(blf); 14554eaa4710SRishi Srivatsavai } 14564eaa4710SRishi Srivatsavai 14574eaa4710SRishi Srivatsavai /* Retrieve list of TRILL nicknames from the TRILL module */ 14584eaa4710SRishi Srivatsavai trill_listnick_t * 14594eaa4710SRishi Srivatsavai dladm_bridge_get_trillnick(const char *bridge, uint_t *nnick) 14604eaa4710SRishi Srivatsavai { 14614eaa4710SRishi Srivatsavai int fd; 14624eaa4710SRishi Srivatsavai char brcopy[MAXLINKNAMELEN]; 14634eaa4710SRishi Srivatsavai trill_listnick_t *tln = NULL, *newtln, tlnread; 14644eaa4710SRishi Srivatsavai uint_t ntln = 0, maxtln = 0; 14654eaa4710SRishi Srivatsavai 14664eaa4710SRishi Srivatsavai if ((fd = socket(PF_TRILL, SOCK_DGRAM, 0)) == -1) 14674eaa4710SRishi Srivatsavai return (NULL); 14684eaa4710SRishi Srivatsavai (void) strlcpy(brcopy, bridge, sizeof (brcopy)); 14694eaa4710SRishi Srivatsavai if (ioctl(fd, TRILL_GETBRIDGE, &brcopy) < 0) { 14704eaa4710SRishi Srivatsavai (void) close(fd); 14714eaa4710SRishi Srivatsavai return (NULL); 14724eaa4710SRishi Srivatsavai } 14734eaa4710SRishi Srivatsavai (void) memset(&tlnread, 0, sizeof (tlnread)); 14744eaa4710SRishi Srivatsavai for (;;) { 14754eaa4710SRishi Srivatsavai if (ntln >= maxtln) { 14764eaa4710SRishi Srivatsavai maxtln = maxtln == 0 ? 64 : (maxtln << 1); 14774eaa4710SRishi Srivatsavai newtln = realloc(tln, maxtln * sizeof (*tln)); 14784eaa4710SRishi Srivatsavai if (newtln == NULL) { 14794eaa4710SRishi Srivatsavai free(tln); 14804eaa4710SRishi Srivatsavai tln = NULL; 14814eaa4710SRishi Srivatsavai break; 14824eaa4710SRishi Srivatsavai } 14834eaa4710SRishi Srivatsavai tln = newtln; 14844eaa4710SRishi Srivatsavai } 14854eaa4710SRishi Srivatsavai if (ioctl(fd, TRILL_LISTNICK, &tlnread) == -1) { 14864eaa4710SRishi Srivatsavai free(tln); 14874eaa4710SRishi Srivatsavai tln = NULL; 14884eaa4710SRishi Srivatsavai break; 14894eaa4710SRishi Srivatsavai } 14904eaa4710SRishi Srivatsavai if (tlnread.tln_nick == 0) 14914eaa4710SRishi Srivatsavai break; 14924eaa4710SRishi Srivatsavai tln[ntln++] = tlnread; 14934eaa4710SRishi Srivatsavai } 14944eaa4710SRishi Srivatsavai (void) close(fd); 14954eaa4710SRishi Srivatsavai if (tln != NULL) 14964eaa4710SRishi Srivatsavai *nnick = ntln; 14974eaa4710SRishi Srivatsavai return (tln); 14984eaa4710SRishi Srivatsavai } 14994eaa4710SRishi Srivatsavai 15004eaa4710SRishi Srivatsavai void 15014eaa4710SRishi Srivatsavai dladm_bridge_free_trillnick(trill_listnick_t *tln) 15024eaa4710SRishi Srivatsavai { 15034eaa4710SRishi Srivatsavai free(tln); 15044eaa4710SRishi Srivatsavai } 15054eaa4710SRishi Srivatsavai 15064eaa4710SRishi Srivatsavai /* Retrieve any stored TRILL nickname from TRILL SMF service */ 15074eaa4710SRishi Srivatsavai uint16_t 15084eaa4710SRishi Srivatsavai dladm_bridge_get_nick(const char *bridge) 15094eaa4710SRishi Srivatsavai { 15104eaa4710SRishi Srivatsavai scf_state_t sstate; 15114eaa4710SRishi Srivatsavai uint64_t value; 15124eaa4710SRishi Srivatsavai uint16_t nickname = RBRIDGE_NICKNAME_NONE; 15134eaa4710SRishi Srivatsavai 15144eaa4710SRishi Srivatsavai if (bind_instance(TRILL_SVC_NAME, bridge, &sstate) != 0) 15154eaa4710SRishi Srivatsavai return (nickname); 15164eaa4710SRishi Srivatsavai 15174eaa4710SRishi Srivatsavai if (get_composed_properties("config", B_TRUE, &sstate) == 0 && 15184eaa4710SRishi Srivatsavai get_count("nickname", &sstate, &value) == 0) 15194eaa4710SRishi Srivatsavai nickname = value; 15204eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 15214eaa4710SRishi Srivatsavai return (nickname); 15224eaa4710SRishi Srivatsavai } 15234eaa4710SRishi Srivatsavai 15244eaa4710SRishi Srivatsavai /* Stores TRILL nickname in SMF configuraiton for the TRILL service */ 15254eaa4710SRishi Srivatsavai void 15264eaa4710SRishi Srivatsavai dladm_bridge_set_nick(const char *bridge, uint16_t nick) 15274eaa4710SRishi Srivatsavai { 15284eaa4710SRishi Srivatsavai scf_state_t sstate; 15294eaa4710SRishi Srivatsavai scf_transaction_t *tran = NULL; 15304eaa4710SRishi Srivatsavai boolean_t new_pg = B_FALSE; 15314eaa4710SRishi Srivatsavai int rv = 0; 15324eaa4710SRishi Srivatsavai char *fmri; 15334eaa4710SRishi Srivatsavai 15344eaa4710SRishi Srivatsavai if (exact_instance(TRILL_SVC_NAME, &sstate) != DLADM_STATUS_OK) 15354eaa4710SRishi Srivatsavai return; 15364eaa4710SRishi Srivatsavai 15374eaa4710SRishi Srivatsavai if (scf_service_get_instance(sstate.ss_svc, bridge, sstate.ss_inst) != 15384eaa4710SRishi Srivatsavai 0) 15394eaa4710SRishi Srivatsavai goto out; 15404eaa4710SRishi Srivatsavai if ((tran = scf_transaction_create(sstate.ss_handle)) == NULL) 15414eaa4710SRishi Srivatsavai goto out; 15424eaa4710SRishi Srivatsavai if ((sstate.ss_pg = scf_pg_create(sstate.ss_handle)) == NULL) 15434eaa4710SRishi Srivatsavai goto out; 15444eaa4710SRishi Srivatsavai if (scf_instance_add_pg(sstate.ss_inst, "config", 15454eaa4710SRishi Srivatsavai SCF_GROUP_APPLICATION, 0, sstate.ss_pg) == 0) { 15464eaa4710SRishi Srivatsavai new_pg = B_TRUE; 15474eaa4710SRishi Srivatsavai } else if (scf_instance_get_pg(sstate.ss_inst, "config", 15484eaa4710SRishi Srivatsavai sstate.ss_pg) != 0) { 15494eaa4710SRishi Srivatsavai goto out; 15504eaa4710SRishi Srivatsavai } 15514eaa4710SRishi Srivatsavai do { 15524eaa4710SRishi Srivatsavai if (scf_transaction_start(tran, sstate.ss_pg) != 0) 15534eaa4710SRishi Srivatsavai goto out; 15544eaa4710SRishi Srivatsavai if (!set_count_property(sstate.ss_handle, tran, "nickname", 15554eaa4710SRishi Srivatsavai nick)) 15564eaa4710SRishi Srivatsavai goto out; 15574eaa4710SRishi Srivatsavai rv = scf_transaction_commit(tran); 15584eaa4710SRishi Srivatsavai scf_transaction_reset(tran); 15594eaa4710SRishi Srivatsavai if (rv == 0 && scf_pg_update(sstate.ss_pg) == -1) 15604eaa4710SRishi Srivatsavai goto out; 15614eaa4710SRishi Srivatsavai } while (rv == 0); 15624eaa4710SRishi Srivatsavai 15634eaa4710SRishi Srivatsavai out: 15644eaa4710SRishi Srivatsavai if (tran != NULL) { 15654eaa4710SRishi Srivatsavai scf_transaction_destroy_children(tran); 15664eaa4710SRishi Srivatsavai scf_transaction_destroy(tran); 15674eaa4710SRishi Srivatsavai } 15684eaa4710SRishi Srivatsavai 15694eaa4710SRishi Srivatsavai if (rv != 1 && new_pg) 15704eaa4710SRishi Srivatsavai (void) scf_pg_delete(sstate.ss_pg); 15714eaa4710SRishi Srivatsavai 15724eaa4710SRishi Srivatsavai drop_composed(&sstate); 15734eaa4710SRishi Srivatsavai shut_down_scf(&sstate); 15744eaa4710SRishi Srivatsavai if (rv == 1 && (fmri = alloc_fmri(TRILL_SVC_NAME, bridge)) != NULL) { 15754eaa4710SRishi Srivatsavai (void) smf_refresh_instance(fmri); 15764eaa4710SRishi Srivatsavai free(fmri); 15774eaa4710SRishi Srivatsavai } 15784eaa4710SRishi Srivatsavai } 1579