Files
2026-07-30 11:19:44 +05:30

1057 lines
31 KiB
C

/* usrNetBridgeCfg.c - Simple Learning Bridge init routines */
/* Copyright 2002-2005 Wind River Systems, Inc. */
/*
modification history
--------------------
02d,21apr16,l_y Add bridge aging timeout time.(VXW6-85482)
02c,23mar10,kxr Do not ipDetach() wireless interface
02b,26nov07,tlu Replace INCLUDE_IPCOM_USE_INET6 by INET6
02a,14nov06,tlu Remove un-used variable addr (defect 69139)
01z,18sep06,tlu Un-comment ipDetach and ip6Detach
01y,15aug06,tlu Ported to IPNET stack
01x,24jun05,svk Fix another diab compiler warning
01w,27may05,svk Fix compilation warnings
01v,28apr05,zhu Set IFF_IFNET6_UP before assigning IPv6 address
01u,19mar05,zhu Changed the string format to be consistent with NAT and
Firewall
01t,28mar05,svk Allow bridge to attach to IPv6 stack
01s,02feb05,svk WDB END handling unnecessary if WDB_END_DEVICE_NAME and
WDB_END_DEVICE_UNIT are defined
01r,19oct04,svk Include config.h for command-line BSP build
01q,07oct04,svk Detach bridge ports from IPv6 stack also
01p,13sep04,svk Fix compilation warnings
01o,06jul04,zhu Updated for dual stack
01n,02jul03,myz Added INCLUDE_WDB_COMM_END macro to the WDB END check
01m,03jun03,myz Added WDB END handling when its interface is a bridge port
01l,30may03,myz Modify promiscuousModeSet to use driver's ioctl to set the mode
01k,15may03,svk Added includes needed for cmdline build, fixed warnings
01j,25apr03,zhu updated copyright
01i,10may02,svk Changed mirrorInit() and promiscuousModeSet() to be callable
from outside configlette
01h,25apr02,svk Coding standard and linked list changes
01g,24apr02,vks code-review changes: linked-list usage, project facility
parameter dependency removal (usrNetBridgeInit() signature),
several minor changes as per coding standards.
01f,22apr02,svk Replace ports buffer on stack with malloc'ed buffer
01e,11apr02,svk Add function to use socket ioctl.
01d,10apr02,svk More minor changes.
01c,10apr02,vks merged bridge and mirror configlettes
01b,10apr02,svk Various minor changes.
01a,09apr02,svk written
*/
/*
DESCRIPTION
This file is used to configure and initialize the Simple Learning Bridge.
INCLUDE FILES: bridge.h, mirrorEnd.h
NOMANUAL
*/
/* includes */
#include <ipProto.h>
#include "wrn/bridge/bridge.h"
#include "wrn/bridge/mirrorEnd.h"
#include "private/muxLibP.h"
#include <ipcom_sock.h>
#include <ipcom_sock2.h>
#include <ipcom_sock6.h>
#include <ipcom_vxworks.h>
/* defines */
#define MIRROR_NAME_MAX 15 /* max size of mirror name */
#define MIRROR_LOAD_STRING "" /* used in mirror muxDevLoad */
#define PORT_SEPARATOR "," /* separator in port string */
/* typedefs */
typedef struct /* bridge node - BRIDGE_NODE */
{
NODE node; /* must be first member for lstLib */
char devName[END_NAME_MAX]; /* device name */
int unit; /* unit number */
} BRIDGE_NODE;
#ifdef INCLUDE_WDB
#if ((WDB_COMM_TYPE == WDB_COMM_END || defined(INCLUDE_WDB_COMM_END)) && \
!defined(WDB_END_DEVICE_NAME) && !defined(WDB_END_DEVICE_UNIT))
LOCAL END_TBL_ENTRY* pSavedEndTbl = NULL;
LOCAL int savedTblEntries = 0;
LOCAL STATUS bridgeWdbEndEntryFind (BRIDGE_NODE *);
LOCAL void bridgeEndTblRestore (WIND_TCB *);
IMPORT END_TBL_ENTRY endDevTbl[];
#endif
#endif /* INCLUDE_WDB */
int BridgeAgingTime;
/* imports */
IMPORT END_OBJ* mirrorEndLoad (char*, void*);
IMPORT void mirrorBaseParamsSet (char*, int);
/* forward declarations */
LOCAL STATUS portsStringParse (char *, LIST*);
LOCAL STATUS bridgePortsInit(LIST*);
LOCAL void devicePromiscuousModeSet(END_OBJ *);
STATUS mirrorInit (char *, int, char *, int, char*, int);
STATUS promiscuousModeSet (char *, int);
/*******************************************************************************
*
* usrNetBridgeInit - Simple Learning Bridge initialization
*
* This routine initializes the bridge. It first parses the bridge ports
* string argument, and populates a linked list. It then initializes the
* bridge, bridge ports, and the mirror device.
*
* RETURNS:
* OK, or
* ERROR if there is a problem in initializing bridge
*
* NOMANUAL
*/
STATUS usrNetBridgeInit
(
char* pPortString, /* interfaces to be configured as bridge ports */
/* e.g., "fei0,fei1,elPci0" */
char* pAddr, /* IP address for this bridge */
int mask, /* netmask for this bridge */
char* pAddrv6, /* IPv6 address for this bridge */
int prefixLen, /* IPv6 prefix length for this bridge */
int timeout /* bridge aging timeout time */
)
{
LIST bridgePortList; /* list of BRIDGE_NODEs */
BRIDGE_NODE* pFirstNode; /* first node in the list */
/* Initialize the list */
lstInit(&bridgePortList);
/* RFC 6325: 4.8.3. Forgetting End-Station Addresses
* While RBridges need to learn end-station addresses as described
* above, it is equally important that they be able to forget such
* information. Otherwise, frames for end stations that have moved to a
* different part of the campus could be indefinitely black-holed by
* RBridges with stale information as to the link to which the end
* station is attached.
* For end-station address information locally learned from frames
* received, the time out from the last time a native frame was received
* or decapsulated with the information conforms to the recommendations
* of [802.1D]. It is referred to as the "Ageing Time" and is
* configurable per RBridge with a range of from 10 seconds to 1,000,000
* seconds and a default value of 300 seconds.
*/
if (timeout > 1000000 || timeout < 10)
{
BridgeAgingTime = 300;
}
else
{
BridgeAgingTime = timeout;
}
/* Parse the port string and populate the list */
if (portsStringParse(pPortString, &bridgePortList) != OK)
{
printf("portsStringParse failed!\n");
lstFree(&bridgePortList);
return ERROR;
}
/* Initialize the bridge */
if (bridgeInit() != OK)
{
printf("bridgeInit failed!\n");
lstFree(&bridgePortList);
return ERROR;
}
/* Initialize the bridge ports */
if (bridgePortsInit(&bridgePortList) != OK)
{
printf("bridgePortsInit failed!\n");
lstFree(&bridgePortList);
return ERROR;
}
/* Initialize the mirror interface.
*
* NOTE: The first bridge port's device name and number is used
* to initialize the mirror interface.
*/
pFirstNode = (BRIDGE_NODE*) lstFirst(&bridgePortList);
if (mirrorInit(pFirstNode->devName, pFirstNode->unit,
pAddr, mask, pAddrv6, prefixLen) != OK)
{
printf("mirrorInit failed!\n");
lstFree(&bridgePortList);
return ERROR;
}
/* Cleanup */
lstFree(&bridgePortList);
return OK;
}
/*******************************************************************************
*
* portsStringParse - Parse the string for device names and unit numbers
*
* This routine parses the given string to extract the device names and
* unit numbers. The extracted values are stored in a linked list.
*
* RETURNS:
* OK, or
* ERROR if there is a problem in parsing the port string
*
* NOMANUAL
*/
LOCAL STATUS portsStringParse
(
char* pPorts, /* string to parse for bridge ports */
LIST* pBridgePortList /* linked list to hold bridge ports */
)
{
char* pPortsBuf = NULL; /* buffer to hold copy of ports string */
char* ptr = NULL; /* pointer used to copy ports string */
char* token = NULL; /* one token in the ports string */
STATUS status = OK; /* return status */
BRIDGE_NODE* pNode; /* one node in the list */
char * pHolder = NULL; /* string holder */
char * pStrEnd = NULL; /* string end holder */
/* Parameter check */
if (pPorts == NULL)
{
printf("Bridge port string is NULL!\n");
return ERROR;
}
if (pBridgePortList == NULL)
{
printf("List of bridge ports is NULL!\n");
return ERROR;
}
/* Is the bridge port string configuration parameter specified? */
if (strlen(pPorts) == 0)
{
printf("List of bridge ports not specified! -\n");
printf("Please set the bridge configuration parameter BRIDGE_PORTS.\n");
printf("This must a list of comma-separated device name and unit \
number pairs.\nFor example: \"fei,0,fei,1,elPci,0\"\n");
return ERROR;
}
/*
* The for-loop below uses strtok() to parse the list of bridge ports.
* strtok() modifies the string given to it. Therefore, make a copy of the
* string and give strtok() the copy to work with.
*/
pPortsBuf = malloc(strlen(pPorts) + 1);
for (ptr = pPortsBuf; *pPorts != '\0'; pPorts++)
{
if (!isspace((int)*pPorts)) /* ignore space */
*ptr++ = *pPorts;
}
*ptr = '\0';
for (token = strtok_r(pPortsBuf, PORT_SEPARATOR, &pHolder); token != NULL;
token = strtok_r(NULL, PORT_SEPARATOR, &pHolder))
{
/* Create a new node */
char devName[END_NAME_MAX];
int unit = 0;
if (strlen(token) > END_NAME_MAX - 1)
{
printf("Device name too long in bridge port string: %s\n", token);
status = ERROR;
break;
}
bzero(devName, END_NAME_MAX);
strcpy(devName, token);
if ((token = strtok_r(NULL, PORT_SEPARATOR, &pHolder)) == NULL)
{
printf("Unit number missing in bridge port string\n");
printf("Specify device name and unit number pairs. e.g., fei,0,fei,1\n");
status = ERROR;
break;
}
unit = strtol(token, &pStrEnd, 10);
if (*pStrEnd)
{
printf("Invalid unit number in bridge port string: %s\n", token);
status = ERROR;
break;
}
if (endFindByName(devName,unit) == NULL)
{
printf("Can't find device %s%d\n", devName, unit);
status = ERROR;
break;
}
/* Add the node to the list */
pNode = (BRIDGE_NODE*) malloc(sizeof(BRIDGE_NODE));
if (pNode == NULL)
{
printf("Can't allocate memory for device %s%d\n", devName, unit);
status = ERROR;
break;
}
bzero((char*) pNode, sizeof(BRIDGE_NODE));
strcpy(pNode->devName, devName);
pNode->unit = unit;
lstAdd(pBridgePortList, (NODE *) pNode);
} /* for */
/* Cleanup */
if (pPortsBuf != NULL)
free(pPortsBuf);
return status;
}
/*******************************************************************************
*
* bridgePortsInit - Bridge ports initialization
*
* This routine walks through the list of interfaces to initialize as
* bridge ports and sets each interface to promicuous mode before adding it
* as a bridge port.
*
* RETURNS:
* OK, or
* ERROR if there is a problem in initializing bridge ports
*
* NOMANUAL
*/
LOCAL STATUS bridgePortsInit
(
LIST* pBridgePortList /* list of interfaces */
)
{
STATUS status = OK; /* return status */
BRIDGE_NODE* pNode = NULL; /* one node in the list */
END_OBJ * pEnd = NULL;
char ifName[END_NAME_MAX * 2];
char * oldifname;
#ifdef INCLUDE_WDB
#if ((WDB_COMM_TYPE == WDB_COMM_END || defined(INCLUDE_WDB_COMM_END)) && \
!defined(WDB_END_DEVICE_NAME) && !defined(WDB_END_DEVICE_UNIT))
BRIDGE_NODE bridgeWdbIf;
#endif
#endif
/* Parameter check */
if (pBridgePortList == NULL)
{
printf("List of bridge ports is NULL!\n");
return ERROR;
}
#ifdef INCLUDE_WDB
#if ((WDB_COMM_TYPE == WDB_COMM_END || defined(INCLUDE_WDB_COMM_END)) && \
!defined(WDB_END_DEVICE_NAME) && !defined(WDB_END_DEVICE_UNIT))
/* The WDB END communication requires a standard IP stack attached to the
* interface to retrive the IP address and answering ARP requests in the
* task mode although it has its own UDP lite stack to handle the WDB
* traffics. With concerned interface joined as bridge port, that IP
* stack is no longer available. So we need to use the bridge's virtual
* interface mirror0 as WDB END's new interface if the original network
* interface becomes as a bridge port in order to keep WDB END communication
* going. This also implies the mirror0 should be initialized before WDB.
* If the WDB END is intialized before the bridge, it may just work if
* the IP address is not changed. In that case, the WDB protocol is the
* first SNARF protocol to attach the MUX, therefore will intercept all
* the traffic bound to that interface first
*/
/* find the original designated WDB END interface */
bzero(bridgeWdbIf.devName,END_NAME_MAX);
if (bridgeWdbEndEntryFind(&bridgeWdbIf) != OK)
bridgeWdbIf.unit = NONE;
else
{
/* Found the WDB interface. Do nothing if WDB is already initialized */
if (taskNameToId("tWdbTask") != ERROR)
bridgeWdbIf.unit = NONE;
}
#endif
#endif
for (pNode = (BRIDGE_NODE*)lstFirst(pBridgePortList); pNode != NULL;
pNode = (BRIDGE_NODE*)lstNext((NODE*) pNode))
{
sprintf(ifName, "%s%d", pNode->devName, pNode->unit);
oldifname = (char *)ipcom_get_ip_if_name(ifName);
if (oldifname != IP_NULL)
{
#if defined(_WRS_CONFIG_COMPONENT_IP8021X) \
&& defined( _WRS_CONFIG_COMPONENT_DOT1X) \
&& defined( _WRS_CONFIG_COMPONENT_IPWPS)
/* Consider the following scenario:
* - a wireless interface is being added to the bridge;
* - the ip8021x supplicant has opened a socket on the wireless interface.
* In this scenario, ipDetach() should not be called.
* Scenario occurs only when have the ip8021x supplicant, the WPS module
* and dot1x authenticator.
*/
if (*pNode->devName != 'w')
#endif
{
ipDetach(pNode->unit, pNode->devName);
#ifdef INET6
ip6Detach(pNode->unit, pNode->devName);
#endif /* INET6 */
}
}
#ifdef INCLUDE_WDB
#if ((WDB_COMM_TYPE == WDB_COMM_END || defined(INCLUDE_WDB_COMM_END)) && \
!defined(WDB_END_DEVICE_NAME) && !defined(WDB_END_DEVICE_UNIT))
/* check if it is the interface used by WDB */
if ( (strcmp(pNode->devName,bridgeWdbIf.devName) == 0) &&
(pNode->unit == bridgeWdbIf.unit) )
{
/* yes, one of the bridge port is used by WDB */
/* The WDB END interface selection algorithm is that it searches
* the endDevTbl to see if one of them matches the boot device.
* If does, then the boot device is selected. If doesn't, then the
* first one in the endDevTbl is selected. The mirror0 is always
* not in the endDevTbl. In order to make mirror0 as WDB END
* interface, we use this hack, first save the entire endDevTbl,
* re-intialize the first entry with mirror0 and mark the second
* entry as end entry, Then the endDevTbl will be restored back
* when the "tWdbTask" is created.
*/
if (pSavedEndTbl == NULL)
{
END_TBL_ENTRY * pDevTbl;
int count;
for (count = 0, pDevTbl = endDevTbl;
pDevTbl->endLoadFunc != END_TBL_END;
pDevTbl++, count++);
count++; /* add the end-mark entry */
pSavedEndTbl =(END_TBL_ENTRY *)malloc(
count * sizeof(END_TBL_ENTRY));
bcopy((char *)endDevTbl,(char *)pSavedEndTbl,
count * sizeof(END_TBL_ENTRY));
savedTblEntries = count;
endDevTbl[0].unit = MIRROR_STACK_UNIT_NUM;
endDevTbl[0].endLoadFunc = mirrorEndLoad;
endDevTbl[0].endLoadString = MIRROR_LOAD_STRING;
endDevTbl[0].endLoan = FALSE;
endDevTbl[0].pBSP = NULL;
endDevTbl[1].unit = 0;
endDevTbl[1].endLoadFunc = END_TBL_END;
endDevTbl[1].endLoadString = NULL;
endDevTbl[1].endLoan = FALSE;
endDevTbl[1].pBSP = NULL;
endDevTbl[1].processed = FALSE;
taskCreateHookAdd ((FUNCPTR)bridgeEndTblRestore);
}
}
#endif
#endif
/* Set the port to promiscuous mode */
pEnd = endFindByName(pNode->devName,pNode->unit);
if (pEnd == NULL)
{
printf("Can't set device %s%d to promiscuous mode\n",
pNode->devName, pNode->unit);
status = ERROR;
break;
}
netJobAdd ((FUNCPTR)devicePromiscuousModeSet,(_Vx_usr_arg_t)pEnd,0,0,0,0);
/* Add the port to the bridge */
if (bridgePortAdd (pNode->devName, pNode->unit) != OK)
{
printf ("bridgePortAdd failed for device %s%d\n",
pNode->devName, pNode->unit);
status = ERROR;
break;
}
} /* for */
return status;
}
/*******************************************************************************
*
* configMirrorInterface - IPv4 mirror interface configuration
*
* This routine attaches the IPv4 stack to the mirror device. It also sets
* the IP address and mask
*
*
* RETURNS:
* OK, or
* ERROR if there is a problem in configuring the mirror interface
*
* NOMANUAL
*/
LOCAL STATUS configMirrorInterface
(
char* mirrorDevName,
char* pAddr, /* IP address of bridge */
int mask /* netmask of bridge */
)
{
char* ip_if_name = IP_NULL;
Ip_fd fd;
struct Ip_ifreq ifr;
/* Attach TCP/IP stack to the mirror END */
if (ipAttach (MIRROR_STACK_UNIT_NUM, MIRROR_DEV_NAME) != OK)
{
printf("ipAttach failed for %s\n", mirrorDevName);
return ERROR;
}
fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
if (fd == IP_INVALID_SOCKET) {
printf("Failed to open a socket\n");
return ERROR;
}
memset(&ifr, 0, sizeof(struct Ip_ifreq));
ip_if_name = (char *)ipcom_get_ip_if_name(mirrorDevName);
if(ip_if_name == IP_NULL)
{
printf("ipAttach failed to register dev name mapping for %s\n",
mirrorDevName);
goto bailout;
}
strcpy(ifr.ifr_name, ip_if_name);
/* Bring the interface up */
if (ipcom_socketioctl(fd, IP_SIOCGIFFLAGS, &ifr) < 0)
{
printf("ifconfig: failed to get interface flags");
goto bailout;
}
IP_BIT_SET(ifr.ip_ifr_flags, IP_IFF_UP);
if (ipcom_socketioctl(fd, IP_SIOCSIFFLAGS, &ifr) < 0)
{
printf("ifconfig: failed to set interface flags");
goto bailout;
}
((struct Ip_sockaddr_in *)&ifr.ip_ifr_addr)->sin_family = IP_AF_INET;
((struct Ip_sockaddr_in *)&ifr.ip_ifr_addr)->sin_len = sizeof(struct Ip_sockaddr_in);
((struct Ip_sockaddr_in *)&ifr.ip_ifr_addr)->sin_addr.s_addr = ipcom_inet_addr(pAddr);
/* Set IP address */
if (ipcom_socketioctl(fd, IP_SIOCSIFADDR, &ifr) == IP_SOCKERR)
{
printf("Failed to set address for %s\n", mirrorDevName);
goto bailout;
}
((struct Ip_sockaddr_in *)&ifr.ip_ifr_addr)->sin_addr.s_addr = (Ip_u32)ip_htonl(mask);
/* Set subnet mask. */
if (ipcom_socketioctl(fd, IP_SIOCSIFNETMASK, &ifr) == IP_SOCKERR)
{
printf("Failed to set subnet mask for %s, errno %d\n", mirrorDevName, ipcom_errno);
goto bailout;
}
ipcom_socketclose(fd);
return OK;
bailout:
ipcom_socketclose(fd);
return ERROR;
}
/*******************************************************************************
*
* configMirrorInterface6 - IPv6 mirror interface configuration
*
* This routine attaches the IPv6 stack to the mirror device. It also sets
* the IP address.
*
* RETURNS:
* OK, or
* ERROR if there is a problem in configuring the mirror interface
*
* NOMANUAL
*/
#ifdef INET6
LOCAL STATUS configMirrorInterface6
(
char* mirrorDevName,
char* pAddrv6, /* IPv6 address of bridge */
int prefixLen /* IPv6 prefix length */
)
{
char* ip_if_name = IP_NULL;
struct Ip_in6_addr inaddr6;
struct Ip_in6_aliasreq ifareq6;
int i;
Ip_fd fd;
if (ip6Attach (MIRROR_STACK_UNIT_NUM, MIRROR_DEV_NAME) != OK)
{
printf("ip6Attach failed for %s\n", mirrorDevName);
return ERROR;
}
fd = ipcom_socket(IP_AF_INET6, IP_SOCK_DGRAM, 0);
if (fd == IP_INVALID_SOCKET) {
printf("Failed to open a socket\n");
return ERROR;
}
memset(&ifareq6, 0, sizeof(struct Ip_in6_aliasreq));
ip_if_name = (char *)ipcom_get_ip_if_name(mirrorDevName);
if(ip_if_name == IP_NULL) {
printf("ip6Attach failed to register dev name mapping for %s\n",
mirrorDevName);
goto bailout;
}
strcpy(ifareq6.ifra_name, ip_if_name);
if (ipcom_inet_pton(IP_AF_INET6, pAddrv6, &inaddr6) <= 0) {
printf("Failed to convert an IPv6 address\n");
goto bailout;
}
ifareq6.ifra_addr.sin6_addr = inaddr6;
ifareq6.ifra_addr.sin6_family = IP_AF_INET6;
ifareq6.ifra_addr.sin6_len = sizeof(struct Ip_sockaddr_in6);
if (IP_IN6_IS_ADDR_LINK_LOCAL(&inaddr6))
ifareq6.ifra_addr.sin6_scope_id = ipcom_if_nametoindex(ifareq6.ifra_name);
ifareq6.ifra_prefixmask.sin6_family = IP_AF_INET6;
ifareq6.ifra_prefixmask.sin6_len = sizeof(struct Ip_sockaddr_in6);
for (i = 0; i < prefixLen; i++)
{
IP_BIT_SET(((Ip_u16*) &ifareq6.ifra_prefixmask.sin6_addr)[i / 16], ip_htons(0x8000 >> (i % 16)));
}
/* Set lifetimes */
ifareq6.ifra_lifetime.ia6t_preferred = (long)IPCOM_ADDR_INFINITE;
ifareq6.ifra_lifetime.ia6t_expire = (long)IPCOM_ADDR_INFINITE;
/* Sanity */
ifareq6.ifra_flags = IP_IN6_IFF_TENTATIVE;
/* Add IPv6 address */
if (ipcom_socketioctl(fd, IP_SIOCAIFADDR_IN6, &ifareq6) == IP_SOCKERR)
{
printf("Failed to add IPv6 address for %s\n", mirrorDevName);
goto bailout;
}
ipcom_socketclose(fd);
return OK;
bailout:
ipcom_socketclose(fd);
return ERROR;
}
#endif /* INET6 */
/*******************************************************************************
*
* mirrorInit - Mirror interface initialization
*
* This routine initializes the mirror interface by performing the
* following tasks:
*
* 1. Passes the specified device name and unit number to mirrorBaseParamsSet().
* These values are needed for mirrorEnetAddrGet().
* 2. Loads two mirror END drivers, and attaches one to the network stack and
* the other to the bridge.
* 3. Assigns specified IP address and mask to the mirror device 0 (the mirror
* attached to the IP stack).
*
* RETURNS:
* OK, or
* ERROR if there is a problem in initializing the mirror interface
*
* NOMANUAL
*/
STATUS mirrorInit
(
char* pDevName, /* name of a bridge port device */
int unit, /* unit number of a bridge port device */
char* pAddr, /* IP address of bridge */
int mask, /* netmask of bridge */
char* pAddrv6, /* IPv6 address of bridge */
int prefixLen /* IPv6 prefix length */
)
{
void* pMuxCookie; /* cookie returned by muxDevLoad */
char mirrorDevName[MIRROR_NAME_MAX]; /* mirror name and number */
END_OBJ* pEnd; /* end object from cookie */
BOOL gotAddrv4 = FALSE; /* IPv4 address specified? */
BOOL gotAddrv6 = FALSE; /* IPv6 address specified? */
/* Parameter check */
if (pDevName == NULL)
{
printf("Name of bridge port device is NULL!\n");
return ERROR;
}
/* Is the bridge address configuration parameter specified? */
if ((pAddr != NULL) && (pAddr[0] != 0))
gotAddrv4 = TRUE;
if ((pAddrv6 != NULL) && (pAddrv6[0] != 0))
gotAddrv6 = TRUE;
#ifdef INET6
if (!gotAddrv4 && !gotAddrv6)
{
/* In dual mode, neither IPv4 nor IPv6 address was specified */
printf("IP address of the bridge not specified! Specify IPv4"
" and/or IPv6 address -\n");
printf("Please set the bridge configuration parameters BRIDGE_IP_ADDR"
" and/or\nBRIDGE_IPV6_ADDR. For example:\n");
printf("BRIDGE_IP_ADDR - \"10.11.12.1\""
" BRIDGE_IPV6_ADDR - \"2002:C000:0240::66\"\n");
return ERROR;
}
#else
if (!gotAddrv4)
{
/* In IPv4-only mode, no IPv4 address was specified */
printf("IP address of the bridge not specified! -\n");
printf("Please set the bridge configuration parameter BRIDGE_IP_ADDR.\n");
printf("For example: \"10.11.12.1\"\n");
return ERROR;
}
#endif /* INET6 */
/*
* Set the device name and the unit number that will be
* used by mirrorEnetAddrGet()
*/
mirrorBaseParamsSet (pDevName, unit);
sprintf (mirrorDevName, "%s%d", MIRROR_DEV_NAME, MIRROR_STACK_UNIT_NUM);
/* Load the network stack side of the mirror END driver */
pMuxCookie = muxDevLoad (MIRROR_STACK_UNIT_NUM,
mirrorEndLoad,
MIRROR_LOAD_STRING,
FALSE,
NULL);
if (pMuxCookie == NULL)
{
printf ("muxDevLoad failed for %s\n", mirrorDevName);
return ERROR;
}
if (muxDevStart (pMuxCookie) != OK)
{
printf ("muxDevStart failed for %s\n", mirrorDevName);
muxDevUnload (MIRROR_DEV_NAME, MIRROR_STACK_UNIT_NUM);
return ERROR;
}
#ifdef INET6
if (gotAddrv4)
{
#endif
if(configMirrorInterface(mirrorDevName, pAddr, mask) != OK)
{
muxDevUnload (MIRROR_DEV_NAME, MIRROR_STACK_UNIT_NUM);
return ERROR;
}
#ifdef INET6
}
if (gotAddrv6)
{
if(configMirrorInterface6(mirrorDevName, pAddrv6, prefixLen) != OK)
{
muxDevUnload (MIRROR_DEV_NAME, MIRROR_STACK_UNIT_NUM);
return ERROR;
}
}
#endif /* INET6 */
/* Load the bridge side of the mirror END driver */
pMuxCookie = muxDevLoad (MIRROR_BRIDGE_UNIT_NUM,
mirrorEndLoad,
MIRROR_LOAD_STRING,
FALSE,
NULL);
if (pMuxCookie == NULL)
{
printf("muxDevLoad failed for %s%d\n",
MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM);
return ERROR;
}
if (muxDevStart(pMuxCookie) != OK)
{
muxDevUnload (MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM);
printf ("muxDevStart failed for %s%d\n",
MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM);
return ERROR;
}
/* Set the bridge side driver to promiscuous mode */
pEnd = PDEVCOOKIE_TO_ENDOBJ(pMuxCookie);
devicePromiscuousModeSet(pEnd);
/* Add this mirror port to the bridge */
if (bridgePortAdd (MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM) != OK)
{
printf ("bridgePortAdd failed for %s%d\n",
MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM);
muxDevStop (pMuxCookie);
muxDevUnload (MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM);
return ERROR;
}
return OK;
}
/*******************************************************************************
*
* promiscuousModeSet - Change mode to promiscuous
*
* This routine sets the specified interface to promiscuous mode using the
* the driver's ioctl call.
*
* RETURNS: OK or ERROR if fail
*
* NOMANUAL
*/
STATUS promiscuousModeSet
(
char * pEndName, /* name of device */
int unit /* unit number of device */
)
{
END_OBJ * pEnd;
pEnd = endFindByName(pEndName,unit);
if (pEnd == NULL)
{
printf("%s%d: Device does not exist or its driver is not loaded\n",
pEndName, unit);
return ERROR;
}
devicePromiscuousModeSet(pEnd);
return OK;
}
/*****************************************************************************
*
* devicePromiscuousModeSet - Turn on hardware device's promiscuous mode
*
*/
LOCAL void devicePromiscuousModeSet
(
END_OBJ * pEnd /* end object */
)
{
int ifFlags = 0;
/* get the current interface flag settings */
if (pEnd->pFuncTable->ioctl != NULL)
pEnd->pFuncTable->ioctl (pEnd, (int)EIOCGFLAGS, (void *)&ifFlags);
/* add the flag we want to set */
ifFlags |= IP_IFF_PROMISC;
/* add the IP_IFF_UP flag anyway, the ipDetach clears this flag. Mostly like
* the driver won't perform the actual action of setting the device to the
* promiscuous mode if this flag is not set.
*/
ifFlags |= IP_IFF_UP;
if (pEnd->pFuncTable->ioctl != NULL)
pEnd->pFuncTable->ioctl (pEnd, (int)EIOCSFLAGS, (void *)(long)ifFlags);
}
#ifdef INCLUDE_WDB
#if ((WDB_COMM_TYPE == WDB_COMM_END || defined(INCLUDE_WDB_COMM_END)) && \
!defined(WDB_END_DEVICE_NAME) && !defined(WDB_END_DEVICE_UNIT))
/*****************************************************************************
*
* bridgeWdbEndEntryFind - Find the WDB END interface
*
*/
LOCAL STATUS bridgeWdbEndEntryFind
(
BRIDGE_NODE * pGetEntry
)
{
END_TBL_ENTRY * pDevTbl;
char devName[END_NAME_MAX + 1];
for (pDevTbl = endDevTbl; pDevTbl->endLoadFunc != NULL; pDevTbl++)
{
/* get the name of the device by passing argument devName = '\0' */
bzero (devName, END_NAME_MAX + 1);
if (pDevTbl->endLoadFunc(devName, NULL) != 0)
return (ERROR);
/* compare the name of the device to the boot device selected */
if (strncmp (sysBootParams.bootDev, (const char *) devName,
strlen((const char *) devName)) == 0)
{
/* Verify that the device unit number matches */
if (pDevTbl->unit == sysBootParams.unitNum)
break;
}
}
/* if no END Device found, default to first valid table entry */
if (pDevTbl->endLoadFunc == NULL)
{
if (endDevTbl->endLoadFunc == NULL)
return (ERROR);
else
pDevTbl = endDevTbl;
}
pGetEntry->unit = pDevTbl->unit;
pDevTbl->endLoadFunc(pGetEntry->devName, NULL);
return OK;
}
/*****************************************************************************
*
* bridgeEndTblRestore - Restore the endDevTbl when WDB task is created
*
*/
LOCAL void bridgeEndTblRestore
(
WIND_TCB * pNewTcb
)
{
/* restore back the endTbl entry */
#if (defined(_WRS_VXWORKS_MAJOR) && (_WRS_VXWORKS_MAJOR >= 6)) /* VxW 6.x */
if (strcmp(pNewTcb->objCore.name,"tWdbTask") == 0)
#else
if (strcmp(pNewTcb->name,"tWdbTask") == 0)
#endif
{
/* the WDB task has been created, restore back the endTbl */
bcopy((char *)pSavedEndTbl, (char *)endDevTbl,
savedTblEntries * sizeof(END_TBL_ENTRY));
free((void *)pSavedEndTbl);
taskCreateHookDelete((FUNCPTR)bridgeEndTblRestore);
}
}
#endif
#endif