4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * bridged - bridging control daemon. This module provides the door-based
29 * interface used by user applications to gather bridge status information.
37 #include <sys/types.h>
43 #include <libdlbridge.h>
45 #include <net/bridge.h>
49 #define DOOR_DIRMODE 0755
50 #define DOOR_FILEMODE 0444
52 static int door_fd
= -1;
53 static char doorname
[MAXPATHLEN
];
57 bridge_door_server(void *cookie
, char *argp
, size_t arg_size
, door_desc_t
*dp
,
60 /* LINTED: alignment */
61 bridge_door_cmd_t
*bdc
= (bridge_door_cmd_t
*)argp
;
63 bridge_door_cfg_t bdcf
;
64 UID_STP_STATE_T smstate
;
65 UID_STP_PORT_CFG_T portcfg
;
66 UID_STP_PORT_STATE_T portstate
;
70 if (arg_size
< sizeof (*bdc
) || lock_engine() != 0) {
71 (void) door_return((char *)&retv
, sizeof (retv
), NULL
, 0);
75 switch (bdc
->bdc_type
) {
76 case bdcBridgeGetConfig
:
77 if ((retv
= STP_IN_stpm_get_cfg(0, &bdcf
.bdcf_cfg
)) != 0)
79 bdcf
.bdcf_prot
= protect
;
81 (void) door_return((char *)&bdcf
, sizeof (bdcf
), NULL
, 0);
84 case bdcBridgeGetState
:
85 if ((retv
= STP_IN_stpm_get_state(0, &smstate
)) != 0)
88 (void) door_return((char *)&smstate
, sizeof (smstate
), NULL
, 0);
91 case bdcBridgeGetPorts
: {
100 rlen
= sizeof (twoints
);
102 rlen
= sizeof (int) + nextport
* sizeof (datalink_id_t
);
104 dlp
= (datalink_id_t
*)(rbuf
+ 1);
105 for (i
= nports
= 0; i
< nextport
; i
++) {
106 if (allports
[i
]->kern_added
)
107 dlp
[nports
++] = allports
[i
]->linkid
;
110 rlen
= sizeof (int) + nports
* sizeof (datalink_id_t
);
113 (void) door_return((char *)rbuf
, rlen
, NULL
, 0);
117 case bdcBridgeGetRefreshCount
:
118 twoints
[0] = refresh_count
;
121 (void) door_return((char *)twoints
, sizeof (twoints
), NULL
, 0);
124 case bdcPortGetConfig
:
125 if ((pdp
= find_by_linkid(bdc
->bdc_linkid
)) == NULL
)
127 retv
= STP_IN_port_get_cfg(0, pdp
->port_index
, &portcfg
);
131 (void) door_return((char *)&portcfg
, sizeof (portcfg
), NULL
, 0);
134 case bdcPortGetState
:
135 if ((pdp
= find_by_linkid(bdc
->bdc_linkid
)) == NULL
)
137 portstate
.port_no
= pdp
->port_index
;
138 if ((retv
= STP_IN_port_get_state(0, &portstate
)) != 0)
141 portstate
.state
= UID_PORT_BADSDU
;
142 else if (protect
!= DLADM_BRIDGE_PROT_STP
)
143 portstate
.state
= UID_PORT_NON_STP
;
144 else if (pdp
->admin_non_stp
&& pdp
->bpdu_protect
)
145 portstate
.state
= UID_PORT_DISABLED
;
147 (void) door_return((char *)&portstate
, sizeof (portstate
),
151 case bdcPortGetForwarding
:
152 if ((pdp
= find_by_linkid(bdc
->bdc_linkid
)) == NULL
)
154 twoints
[0] = pdp
->admin_status
? 1 : 0;
157 (void) door_return((char *)twoints
, sizeof (twoints
), NULL
, 0);
161 (void) door_return((char *)&retv
, sizeof (retv
), NULL
, 0);
168 (void) door_revoke(door_fd
);
171 if (doorname
[0] != '\0') {
172 (void) unlink(doorname
);
182 /* Make sure that the control directory exists */
183 (void) mkdir(DOOR_DIRNAME
, DOOR_DIRMODE
);
185 /* Each instance gets a separate door. */
186 (void) snprintf(doorname
, sizeof (doorname
), "%s/%s", DOOR_DIRNAME
,
189 /* Do a low-overhead "touch" on the file that will be the door node. */
191 O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
| O_NONBLOCK
,
195 } else if (errno
!= EEXIST
) {
196 syslog(LOG_ERR
, "unable to create control door node: %m");
200 (void) atexit(cleanup_door
);
202 /* Create the door. */
203 door_fd
= door_create(bridge_door_server
, NULL
,
204 DOOR_REFUSE_DESC
| DOOR_NO_CANCEL
);
206 syslog(LOG_ERR
, "unable to create control door: %m");
210 /* Attach the door to the file. */
211 (void) fdetach(doorname
);
212 if (fattach(door_fd
, doorname
) == -1) {
213 syslog(LOG_ERR
, "unable to attach control door: %m");