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 }