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