1*4eaa4710SRishi Srivatsavai /* 2*4eaa4710SRishi Srivatsavai * CDDL HEADER START 3*4eaa4710SRishi Srivatsavai * 4*4eaa4710SRishi Srivatsavai * The contents of this file are subject to the terms of the 5*4eaa4710SRishi Srivatsavai * Common Development and Distribution License (the "License"). 6*4eaa4710SRishi Srivatsavai * You may not use this file except in compliance with the License. 7*4eaa4710SRishi Srivatsavai * 8*4eaa4710SRishi Srivatsavai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*4eaa4710SRishi Srivatsavai * or http://www.opensolaris.org/os/licensing. 10*4eaa4710SRishi Srivatsavai * See the License for the specific language governing permissions 11*4eaa4710SRishi Srivatsavai * and limitations under the License. 12*4eaa4710SRishi Srivatsavai * 13*4eaa4710SRishi Srivatsavai * When distributing Covered Code, include this CDDL HEADER in each 14*4eaa4710SRishi Srivatsavai * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*4eaa4710SRishi Srivatsavai * If applicable, add the following below this CDDL HEADER, with the 16*4eaa4710SRishi Srivatsavai * fields enclosed by brackets "[]" replaced with your own identifying 17*4eaa4710SRishi Srivatsavai * information: Portions Copyright [yyyy] [name of copyright owner] 18*4eaa4710SRishi Srivatsavai * 19*4eaa4710SRishi Srivatsavai * CDDL HEADER END 20*4eaa4710SRishi Srivatsavai */ 21*4eaa4710SRishi Srivatsavai 22*4eaa4710SRishi Srivatsavai /* 23*4eaa4710SRishi Srivatsavai * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*4eaa4710SRishi Srivatsavai * Use is subject to license terms. 25*4eaa4710SRishi Srivatsavai */ 26*4eaa4710SRishi Srivatsavai 27*4eaa4710SRishi Srivatsavai /* 28*4eaa4710SRishi Srivatsavai * bridged - bridging control daemon. This module provides the door-based 29*4eaa4710SRishi Srivatsavai * interface used by user applications to gather bridge status information. 30*4eaa4710SRishi Srivatsavai */ 31*4eaa4710SRishi Srivatsavai 32*4eaa4710SRishi Srivatsavai #include <stdio.h> 33*4eaa4710SRishi Srivatsavai #include <stdlib.h> 34*4eaa4710SRishi Srivatsavai #include <unistd.h> 35*4eaa4710SRishi Srivatsavai #include <fcntl.h> 36*4eaa4710SRishi Srivatsavai #include <sys/stat.h> 37*4eaa4710SRishi Srivatsavai #include <sys/types.h> 38*4eaa4710SRishi Srivatsavai #include <syslog.h> 39*4eaa4710SRishi Srivatsavai #include <door.h> 40*4eaa4710SRishi Srivatsavai #include <errno.h> 41*4eaa4710SRishi Srivatsavai #include <alloca.h> 42*4eaa4710SRishi Srivatsavai #include <libdlpi.h> 43*4eaa4710SRishi Srivatsavai #include <libdlbridge.h> 44*4eaa4710SRishi Srivatsavai #include <stp_in.h> 45*4eaa4710SRishi Srivatsavai #include <net/bridge.h> 46*4eaa4710SRishi Srivatsavai 47*4eaa4710SRishi Srivatsavai #include "global.h" 48*4eaa4710SRishi Srivatsavai 49*4eaa4710SRishi Srivatsavai #define DOOR_DIRMODE 0755 50*4eaa4710SRishi Srivatsavai #define DOOR_FILEMODE 0444 51*4eaa4710SRishi Srivatsavai 52*4eaa4710SRishi Srivatsavai static int door_fd = -1; 53*4eaa4710SRishi Srivatsavai static char doorname[MAXPATHLEN]; 54*4eaa4710SRishi Srivatsavai 55*4eaa4710SRishi Srivatsavai /*ARGSUSED*/ 56*4eaa4710SRishi Srivatsavai static void 57*4eaa4710SRishi Srivatsavai bridge_door_server(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, 58*4eaa4710SRishi Srivatsavai uint_t ndesc) 59*4eaa4710SRishi Srivatsavai { 60*4eaa4710SRishi Srivatsavai /* LINTED: alignment */ 61*4eaa4710SRishi Srivatsavai bridge_door_cmd_t *bdc = (bridge_door_cmd_t *)argp; 62*4eaa4710SRishi Srivatsavai int retv = EINVAL; 63*4eaa4710SRishi Srivatsavai bridge_door_cfg_t bdcf; 64*4eaa4710SRishi Srivatsavai UID_STP_STATE_T smstate; 65*4eaa4710SRishi Srivatsavai UID_STP_PORT_CFG_T portcfg; 66*4eaa4710SRishi Srivatsavai UID_STP_PORT_STATE_T portstate; 67*4eaa4710SRishi Srivatsavai struct portdata *pdp; 68*4eaa4710SRishi Srivatsavai int twoints[2]; 69*4eaa4710SRishi Srivatsavai 70*4eaa4710SRishi Srivatsavai if (arg_size < sizeof (*bdc) || lock_engine() != 0) { 71*4eaa4710SRishi Srivatsavai (void) door_return((char *)&retv, sizeof (retv), NULL, 0); 72*4eaa4710SRishi Srivatsavai return; 73*4eaa4710SRishi Srivatsavai } 74*4eaa4710SRishi Srivatsavai 75*4eaa4710SRishi Srivatsavai switch (bdc->bdc_type) { 76*4eaa4710SRishi Srivatsavai case bdcBridgeGetConfig: 77*4eaa4710SRishi Srivatsavai if ((retv = STP_IN_stpm_get_cfg(0, &bdcf.bdcf_cfg)) != 0) 78*4eaa4710SRishi Srivatsavai break; 79*4eaa4710SRishi Srivatsavai bdcf.bdcf_prot = protect; 80*4eaa4710SRishi Srivatsavai unlock_engine(); 81*4eaa4710SRishi Srivatsavai (void) door_return((char *)&bdcf, sizeof (bdcf), NULL, 0); 82*4eaa4710SRishi Srivatsavai return; 83*4eaa4710SRishi Srivatsavai 84*4eaa4710SRishi Srivatsavai case bdcBridgeGetState: 85*4eaa4710SRishi Srivatsavai if ((retv = STP_IN_stpm_get_state(0, &smstate)) != 0) 86*4eaa4710SRishi Srivatsavai break; 87*4eaa4710SRishi Srivatsavai unlock_engine(); 88*4eaa4710SRishi Srivatsavai (void) door_return((char *)&smstate, sizeof (smstate), NULL, 0); 89*4eaa4710SRishi Srivatsavai return; 90*4eaa4710SRishi Srivatsavai 91*4eaa4710SRishi Srivatsavai case bdcBridgeGetPorts: { 92*4eaa4710SRishi Srivatsavai datalink_id_t *dlp; 93*4eaa4710SRishi Srivatsavai int *rbuf; 94*4eaa4710SRishi Srivatsavai size_t rlen; 95*4eaa4710SRishi Srivatsavai int i, nports; 96*4eaa4710SRishi Srivatsavai 97*4eaa4710SRishi Srivatsavai if (nextport == 0) { 98*4eaa4710SRishi Srivatsavai twoints[0] = 0; 99*4eaa4710SRishi Srivatsavai rbuf = twoints; 100*4eaa4710SRishi Srivatsavai rlen = sizeof (twoints); 101*4eaa4710SRishi Srivatsavai } else { 102*4eaa4710SRishi Srivatsavai rlen = sizeof (int) + nextport * sizeof (datalink_id_t); 103*4eaa4710SRishi Srivatsavai rbuf = alloca(rlen); 104*4eaa4710SRishi Srivatsavai dlp = (datalink_id_t *)(rbuf + 1); 105*4eaa4710SRishi Srivatsavai for (i = nports = 0; i < nextport; i++) { 106*4eaa4710SRishi Srivatsavai if (allports[i]->kern_added) 107*4eaa4710SRishi Srivatsavai dlp[nports++] = allports[i]->linkid; 108*4eaa4710SRishi Srivatsavai } 109*4eaa4710SRishi Srivatsavai rbuf[0] = nports; 110*4eaa4710SRishi Srivatsavai rlen = sizeof (int) + nports * sizeof (datalink_id_t); 111*4eaa4710SRishi Srivatsavai } 112*4eaa4710SRishi Srivatsavai unlock_engine(); 113*4eaa4710SRishi Srivatsavai (void) door_return((char *)rbuf, rlen, NULL, 0); 114*4eaa4710SRishi Srivatsavai return; 115*4eaa4710SRishi Srivatsavai } 116*4eaa4710SRishi Srivatsavai 117*4eaa4710SRishi Srivatsavai case bdcBridgeGetRefreshCount: 118*4eaa4710SRishi Srivatsavai twoints[0] = refresh_count; 119*4eaa4710SRishi Srivatsavai twoints[1] = 0; 120*4eaa4710SRishi Srivatsavai unlock_engine(); 121*4eaa4710SRishi Srivatsavai (void) door_return((char *)twoints, sizeof (twoints), NULL, 0); 122*4eaa4710SRishi Srivatsavai return; 123*4eaa4710SRishi Srivatsavai 124*4eaa4710SRishi Srivatsavai case bdcPortGetConfig: 125*4eaa4710SRishi Srivatsavai if ((pdp = find_by_linkid(bdc->bdc_linkid)) == NULL) 126*4eaa4710SRishi Srivatsavai break; 127*4eaa4710SRishi Srivatsavai retv = STP_IN_port_get_cfg(0, pdp->port_index, &portcfg); 128*4eaa4710SRishi Srivatsavai if (retv != 0) 129*4eaa4710SRishi Srivatsavai break; 130*4eaa4710SRishi Srivatsavai unlock_engine(); 131*4eaa4710SRishi Srivatsavai (void) door_return((char *)&portcfg, sizeof (portcfg), NULL, 0); 132*4eaa4710SRishi Srivatsavai return; 133*4eaa4710SRishi Srivatsavai 134*4eaa4710SRishi Srivatsavai case bdcPortGetState: 135*4eaa4710SRishi Srivatsavai if ((pdp = find_by_linkid(bdc->bdc_linkid)) == NULL) 136*4eaa4710SRishi Srivatsavai break; 137*4eaa4710SRishi Srivatsavai portstate.port_no = pdp->port_index; 138*4eaa4710SRishi Srivatsavai if ((retv = STP_IN_port_get_state(0, &portstate)) != 0) 139*4eaa4710SRishi Srivatsavai break; 140*4eaa4710SRishi Srivatsavai if (pdp->sdu_failed) 141*4eaa4710SRishi Srivatsavai portstate.state = UID_PORT_BADSDU; 142*4eaa4710SRishi Srivatsavai else if (protect != DLADM_BRIDGE_PROT_STP) 143*4eaa4710SRishi Srivatsavai portstate.state = UID_PORT_NON_STP; 144*4eaa4710SRishi Srivatsavai else if (pdp->admin_non_stp && pdp->bpdu_protect) 145*4eaa4710SRishi Srivatsavai portstate.state = UID_PORT_DISABLED; 146*4eaa4710SRishi Srivatsavai unlock_engine(); 147*4eaa4710SRishi Srivatsavai (void) door_return((char *)&portstate, sizeof (portstate), 148*4eaa4710SRishi Srivatsavai NULL, 0); 149*4eaa4710SRishi Srivatsavai return; 150*4eaa4710SRishi Srivatsavai 151*4eaa4710SRishi Srivatsavai case bdcPortGetForwarding: 152*4eaa4710SRishi Srivatsavai if ((pdp = find_by_linkid(bdc->bdc_linkid)) == NULL) 153*4eaa4710SRishi Srivatsavai break; 154*4eaa4710SRishi Srivatsavai twoints[0] = pdp->admin_status ? 1 : 0; 155*4eaa4710SRishi Srivatsavai twoints[1] = 0; 156*4eaa4710SRishi Srivatsavai unlock_engine(); 157*4eaa4710SRishi Srivatsavai (void) door_return((char *)twoints, sizeof (twoints), NULL, 0); 158*4eaa4710SRishi Srivatsavai return; 159*4eaa4710SRishi Srivatsavai } 160*4eaa4710SRishi Srivatsavai unlock_engine(); 161*4eaa4710SRishi Srivatsavai (void) door_return((char *)&retv, sizeof (retv), NULL, 0); 162*4eaa4710SRishi Srivatsavai } 163*4eaa4710SRishi Srivatsavai 164*4eaa4710SRishi Srivatsavai static void 165*4eaa4710SRishi Srivatsavai cleanup_door(void) 166*4eaa4710SRishi Srivatsavai { 167*4eaa4710SRishi Srivatsavai if (door_fd != -1) { 168*4eaa4710SRishi Srivatsavai (void) door_revoke(door_fd); 169*4eaa4710SRishi Srivatsavai door_fd = -1; 170*4eaa4710SRishi Srivatsavai } 171*4eaa4710SRishi Srivatsavai if (doorname[0] != '\0') { 172*4eaa4710SRishi Srivatsavai (void) unlink(doorname); 173*4eaa4710SRishi Srivatsavai doorname[0] = '\0'; 174*4eaa4710SRishi Srivatsavai } 175*4eaa4710SRishi Srivatsavai } 176*4eaa4710SRishi Srivatsavai 177*4eaa4710SRishi Srivatsavai void 178*4eaa4710SRishi Srivatsavai init_door(void) 179*4eaa4710SRishi Srivatsavai { 180*4eaa4710SRishi Srivatsavai int fd; 181*4eaa4710SRishi Srivatsavai 182*4eaa4710SRishi Srivatsavai /* Make sure that the control directory exists */ 183*4eaa4710SRishi Srivatsavai (void) mkdir(DOOR_DIRNAME, DOOR_DIRMODE); 184*4eaa4710SRishi Srivatsavai 185*4eaa4710SRishi Srivatsavai /* Each instance gets a separate door. */ 186*4eaa4710SRishi Srivatsavai (void) snprintf(doorname, sizeof (doorname), "%s/%s", DOOR_DIRNAME, 187*4eaa4710SRishi Srivatsavai instance_name); 188*4eaa4710SRishi Srivatsavai 189*4eaa4710SRishi Srivatsavai /* Do a low-overhead "touch" on the file that will be the door node. */ 190*4eaa4710SRishi Srivatsavai fd = open(doorname, 191*4eaa4710SRishi Srivatsavai O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_NONBLOCK, 192*4eaa4710SRishi Srivatsavai DOOR_FILEMODE); 193*4eaa4710SRishi Srivatsavai if (fd != -1) { 194*4eaa4710SRishi Srivatsavai (void) close(fd); 195*4eaa4710SRishi Srivatsavai } else if (errno != EEXIST) { 196*4eaa4710SRishi Srivatsavai syslog(LOG_ERR, "unable to create control door node: %m"); 197*4eaa4710SRishi Srivatsavai exit(EXIT_FAILURE); 198*4eaa4710SRishi Srivatsavai } 199*4eaa4710SRishi Srivatsavai 200*4eaa4710SRishi Srivatsavai (void) atexit(cleanup_door); 201*4eaa4710SRishi Srivatsavai 202*4eaa4710SRishi Srivatsavai /* Create the door. */ 203*4eaa4710SRishi Srivatsavai door_fd = door_create(bridge_door_server, NULL, 204*4eaa4710SRishi Srivatsavai DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 205*4eaa4710SRishi Srivatsavai if (door_fd == -1) { 206*4eaa4710SRishi Srivatsavai syslog(LOG_ERR, "unable to create control door: %m"); 207*4eaa4710SRishi Srivatsavai exit(EXIT_FAILURE); 208*4eaa4710SRishi Srivatsavai } 209*4eaa4710SRishi Srivatsavai 210*4eaa4710SRishi Srivatsavai /* Attach the door to the file. */ 211*4eaa4710SRishi Srivatsavai (void) fdetach(doorname); 212*4eaa4710SRishi Srivatsavai if (fattach(door_fd, doorname) == -1) { 213*4eaa4710SRishi Srivatsavai syslog(LOG_ERR, "unable to attach control door: %m"); 214*4eaa4710SRishi Srivatsavai exit(EXIT_FAILURE); 215*4eaa4710SRishi Srivatsavai } 216*4eaa4710SRishi Srivatsavai } 217