/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* bridged - bridging control daemon. This module handles events and general
* port-related operations.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <syslog.h>
#include <libdlpi.h>
#include <libdladm.h>
#include <libdllink.h>
#include <libdlbridge.h>
#include <libdlvlan.h>
#include <libdlstat.h>
#include <stp_in.h>
#include <stp_vectors.h>
#include <net/if_types.h>
#include <sys/ethernet.h>
#include "global.h"
/*
* The 'allports' array is an array of pointers to the struct portdata
* structures. We reallocate 'allports' as needed, but the portdata must
* remain where it's initially allocated, because libdlpi's notification
* mechanism has a copy of a pointer to this structure.
*/
/* Port allocation increment (arbitrary) */
int control_fd;
static void
linkdown(void)
{
}
void
open_bridge_control(void)
{
}
if (status != DLADM_STATUS_OK) {
}
perror("NEWBRIDGE");
}
sizeof (tablemax)) == -1) {
}
/*
* This covers for any previous incarnation where we might have crashed
* or been SIGKILL'd and failed to take down the datalink.
*/
linkdown();
if (status != DLADM_STATUS_OK) {
}
}
struct portdata *
{
int i;
for (i = 0; i < nextport; i++) {
return (port);
}
return (NULL);
}
/*ARGSUSED2*/
static int
{
if (status != DLADM_STATUS_OK) {
return (DLADM_WALK_CONTINUE);
}
return (DLADM_WALK_CONTINUE);
return (DLADM_WALK_TERMINATE);
} else {
return (DLADM_WALK_CONTINUE);
}
}
/*
* If the named port already exists, then update its configuration. If it
* doesn't, then create and enable it.
*/
static void
{
int posn;
int port_index;
struct {
} adddata;
break;
}
/* If we need to allocate more array space, then do so in chunks. */
portname);
return;
}
}
/* If our linkid search ran to the end, then this is a new port. */
portname);
return;
}
nextport++;
} else {
/* Located port by linkid; we're just updating existing data */
/*
* If it changed name, then close and reopen so we log under
* the most current name for this port.
*/
}
}
/*
* If the port is not yet attached to the bridge in the kernel, then do
* that now.
*/
if (!port->kern_added) {
goto failure;
}
}
valcnt = 1;
if (status == DLADM_STATUS_OK)
if (status == DLADM_STATUS_OK)
goto failure;
}
goto failure;
}
if (rstp_add_port(port))
return;
}
if (port->kern_added) {
portname);
else
}
nextport--;
}
}
/*ARGSUSED2*/
static int
{
if (status == DLADM_STATUS_OK) {
} else {
}
} else if (debugging) {
if (status != DLADM_STATUS_OK)
"unable to get bridge data for ID %u: %s",
else
}
return (DLADM_WALK_CONTINUE);
}
/*
* Refresh action - reread configuration properties.
*/
static void
{
int i;
/* Drain signal events from pipe */
if (sigfd != -1)
&new_tablemax);
if (status == DLADM_STATUS_OK) {
if (new_tablemax != tablemax) {
sizeof (tablemax)) == -1)
"%lu on bridge %s: %m", tablemax,
else
}
} else {
}
rstp_refresh();
for (i = 0; i < nextport; i++)
/*
* libdladm doesn't guarantee anything about link ordering in a walk,
* so we do this walk twice: once to pick up the ports, and a second
* time to get the enabled VLANs on all ports.
*/
/*
* If any ports now show up as unreferenced, then they've been removed
* from the configuration.
*/
for (i = 0; i < nextport; i++) {
if (!pdp->referenced) {
pdp->port_index);
}
}
if (pdp->kern_added) {
"%u from bridge %s: %m",
}
}
}
if (++refresh_count == 0)
refresh_count = 1;
}
/*
* Handle messages on the common control stream. This currently just deals
* with port SDU mismatches.
*/
static void
handle_control(void)
{
int rc;
return;
return;
return;
return;
if (port->admin_non_stp) {
sizeof (bss)) == -1) {
}
}
}
static void
{
int rc;
if (rc != DLPI_SUCCESS) {
if (rc != DLPI_ETIMEDOUT)
dlpi_strerror(rc));
return;
}
/*
* If we're administratively disabled, then don't deliver packets to
* the STP state machine. It will re-enable the port because it uses
* the same variable for both link status and administrative state.
*/
if (debugging)
"discard BPDU on non-forwarding interface %s",
return;
}
/*
* There's a mismatch between the librstp and libdlpi expectations on
* receive. librstp wants the packet to start with the 802 length
* field, not the destination address.
*/
/*
* Note that we attempt to avoid calling the relatively expensive
* _link_ntoa function unless we're going to use the result. In normal
* usage, we don't need this string.
*/
if (rc == 0) {
sizeof (bss)) == -1) {
}
return;
}
if (debugging) {
}
}
if (rc != 0) {
"discarded malformed packet on %s from %s: %s",
}
}
void
{
else
}
void
{
}
void
event_loop(void)
{
int i;
int tout;
if (lock_engine() != 0) {
}
/* Bootstrap configuration */
handle_refresh(-1);
while (!shutting_down) {
(void) STP_IN_one_second();
tout = 1000;
} else {
}
if (lock_engine() != 0) {
}
for (i = 0; i < nextport; i++) {
receive_packet(allports[i]);
}
}
}