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
bridge_door_server(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t ndesc)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
cleanup_door(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
init_door(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