#ifndef _netxmsdb_h
#define _netxmsdb_h
-#define DB_FORMAT_VERSION 317
+#define DB_FORMAT_VERSION 318
#endif
#define EVENT_IF_PEER_CHANGED 71
#define EVENT_AP_ADOPTED 72
#define EVENT_AP_UNADOPTED 73
+#define EVENT_AP_DOWN 74
#define EVENT_SNMP_UNMATCHED_TRAP 500
#define EVENT_SNMP_COLD_START 501
' 6) Access point model' CONCAT CRLF CONCAT
' 7) Access point serial number'
);
+INSERT INTO event_cfg (event_code,event_name,severity,flags,message,description) VALUES
+ (
+ EVENT_AP_DOWN, 'SYS_AP_DOWN',
+ EVENT_SEVERITY_CRITICAL, 1,
+ 'Access point %2 changed state to DOWN',
+ 'Generated when access point state changes to DOWN.' CONCAT CRLF CONCAT
+ 'Parameters:' CONCAT CRLF CONCAT
+ ' 1) Access point object ID' CONCAT CRLF CONCAT
+ ' 2) Access point name' CONCAT CRLF CONCAT
+ ' 3) Access point MAC address' CONCAT CRLF CONCAT
+ ' 4) Access point IP address' CONCAT CRLF CONCAT
+ ' 5) Access point vendor name' CONCAT CRLF CONCAT
+ ' 6) Access point model' CONCAT CRLF CONCAT
+ ' 7) Access point serial number'
+ );
/*
** SNMP traps
LockData();
m_state = state;
if (m_iStatus != STATUS_UNMANAGED)
- m_iStatus = (state == AP_ADOPTED) ? STATUS_NORMAL : STATUS_MAJOR;
+ m_iStatus = (state == AP_ADOPTED) ? STATUS_NORMAL : ((state == AP_UNADOPTED) ? STATUS_MAJOR : STATUS_CRITICAL);
Modify();
UnlockData();
static const TCHAR *names[] = { _T("id"), _T("name"), _T("macAddr"), _T("ipAddr"), _T("vendor"), _T("model"), _T("serialNumber") };
- PostEventWithNames((state == AP_ADOPTED) ? EVENT_AP_ADOPTED : EVENT_AP_UNADOPTED, m_nodeId, "ishasss", names,
- m_dwId, m_szName, m_macAddr, m_dwIpAddr, CHECK_NULL_EX(m_vendor), CHECK_NULL_EX(m_model), CHECK_NULL_EX(m_serialNumber));
+ PostEventWithNames((state == AP_ADOPTED) ? EVENT_AP_ADOPTED : ((state == AP_UNADOPTED) ? EVENT_AP_UNADOPTED : EVENT_AP_DOWN),
+ m_nodeId, "ishasss", names,
+ m_dwId, m_szName, m_macAddr, m_dwIpAddr,
+ CHECK_NULL_EX(m_vendor), CHECK_NULL_EX(m_model), CHECK_NULL_EX(m_serialNumber));
+}
+
+/**
+ * Do status poll
+ */
+void AccessPoint::statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueue, Node *controller)
+{
+ m_pollRequestor = session;
+ AccessPointState state = m_state;
+
+ sendPollerMsg(rqId, _T(" Starting status poll on access point %s\r\n"), m_szName);
+ sendPollerMsg(rqId, _T(" Current access point status is %s\r\n"), g_szStatusText[m_iStatus]);
+
+ /* TODO: read status from controller via driver and use ping as last resort only */
+
+ if (m_dwIpAddr != 0)
+ {
+ UINT32 icmpProxy = 0;
+
+ if (IsZoningEnabled() && (controller->getZoneId() != 0))
+ {
+ Zone *zone = (Zone *)g_idxZoneByGUID.get(controller->getZoneId());
+ if (zone != NULL)
+ {
+ icmpProxy = zone->getIcmpProxy();
+ }
+ }
+
+ if (icmpProxy != 0)
+ {
+ sendPollerMsg(rqId, _T(" Starting ICMP ping via proxy\r\n"));
+ DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): ping via proxy [%u]"), m_dwId, m_szName, icmpProxy);
+ Node *proxyNode = (Node *)g_idxNodeById.get(icmpProxy);
+ if ((proxyNode != NULL) && proxyNode->isNativeAgent() && !proxyNode->isDown())
+ {
+ DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): proxy node found: %s"), m_dwId, m_szName, proxyNode->Name());
+ AgentConnection *conn = proxyNode->createAgentConnection();
+ if (conn != NULL)
+ {
+ TCHAR parameter[64], buffer[64];
+
+ _sntprintf(parameter, 64, _T("Icmp.Ping(%s)"), IpToStr(m_dwIpAddr, buffer));
+ if (conn->getParameter(parameter, 64, buffer) == ERR_SUCCESS)
+ {
+ DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): proxy response: \"%s\""), m_dwId, m_szName, buffer);
+ TCHAR *eptr;
+ long value = _tcstol(buffer, &eptr, 10);
+ if ((*eptr == 0) && (value >= 0))
+ {
+ if (value >= 10000)
+ {
+ sendPollerMsg(rqId, POLLER_ERROR _T(" no response to ICMP ping\r\n"));
+ state = AP_DOWN;
+ }
+ }
+ }
+ conn->disconnect();
+ delete conn;
+ }
+ else
+ {
+ DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): cannot connect to agent on proxy node"), m_dwId, m_szName);
+ sendPollerMsg(rqId, POLLER_ERROR _T(" Unable to establish connection with proxy node\r\n"));
+ }
+ }
+ else
+ {
+ DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): proxy node not available"), m_dwId, m_szName);
+ sendPollerMsg(rqId, POLLER_ERROR _T(" ICMP proxy not available\r\n"));
+ }
+ }
+ else // not using ICMP proxy
+ {
+ sendPollerMsg(rqId, _T(" Starting ICMP ping\r\n"));
+ DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): calling IcmpPing(0x%08X,3,%d,NULL,%d)"), m_dwId, m_szName, htonl(m_dwIpAddr), g_icmpPingTimeout, g_icmpPingSize);
+ UINT32 dwPingStatus = IcmpPing(htonl(m_dwIpAddr), 3, g_icmpPingTimeout, NULL, g_icmpPingSize);
+ if (dwPingStatus == ICMP_RAW_SOCK_FAILED)
+ nxlog_write(MSG_RAW_SOCK_FAILED, EVENTLOG_WARNING_TYPE, NULL);
+ if (dwPingStatus != ICMP_SUCCESS)
+ {
+ sendPollerMsg(rqId, POLLER_ERROR _T(" no response to ICMP ping\r\n"));
+ state = AP_DOWN;
+ }
+ DbgPrintf(7, _T("AccessPoint::StatusPoll(%d,%s): ping result %d, state=%d"), m_dwId, m_szName, dwPingStatus, state);
+ }
+ }
+
+ updateState(state);
+
+ sendPollerMsg(rqId, _T(" Access point status after poll is %s\r\n"), g_szStatusText[m_iStatus]);
+ sendPollerMsg(rqId, _T(" Finished status poll on access point %s\r\n"), m_szName);
}
((NetworkService *)ppPollList[i])->statusPoll(pSession, dwRqId,
(Node *)pPollerNode, pQueue);
break;
+ case OBJECT_ACCESSPOINT:
+ DbgPrintf(7, _T("StatusPoll(%s): polling access point %d [%s]"), m_szName, ppPollList[i]->Id(), ppPollList[i]->Name());
+ ((AccessPoint *)ppPollList[i])->statusPoll(pSession, dwRqId, pQueue, this);
+ break;
default:
+ DbgPrintf(7, _T("StatusPoll(%s): skipping object %d [%s] class %d"), m_szName, ppPollList[i]->Id(), ppPollList[i]->Name(), ppPollList[i]->Type());
break;
}
ppPollList[i]->decRefCount();
if (info->getState() == AP_ADOPTED)
adopted++;
+ bool newAp = false;
AccessPoint *ap = (clusterMode == CLUSTER_MODE_STANDALONE) ? findAccessPointByMAC(info->getMacAddr()) : FindAccessPointByMAC(info->getMacAddr());
if (ap == NULL)
{
ap = new AccessPoint((const TCHAR *)name, info->getMacAddr());
NetObjInsert(ap, TRUE);
DbgPrintf(5, _T("ConfPoll(%s): created new access point object %s [%d]"), m_szName, ap->Name(), ap->Id());
+ newAp = true;
}
ap->attachToNode(m_dwId);
- if (info->getState() == AP_ADOPTED)
+ ap->setIpAddr(info->getIpAddr());
+ if ((info->getState() == AP_ADOPTED) || newAp)
{
ap->updateRadioInterfaces(info->getRadioInterfaces());
- ap->updateInfo(NULL, info->getModel(), info->getSerial());
+ ap->updateInfo(info->getVendor(), info->getModel(), info->getSerial());
}
ap->unhide();
ap->updateState(info->getState());
oid[11] = 1; // bsnAPDot3MacAddress
request->bindVariable(new SNMP_Variable(oid, nameLen));
+ oid[11] = 19; // bsnApIpAddress
+ request->bindVariable(new SNMP_Variable(oid, nameLen));
+
oid[11] = 6; // bsnAPOperationStatus
request->bindVariable(new SNMP_Variable(oid, nameLen));
oid[11] = 3; // bsnAPName
request->bindVariable(new SNMP_Variable(oid, nameLen));
- oid[11] = 7; // bsnAPModel
+ oid[11] = 16; // bsnAPModel
request->bindVariable(new SNMP_Variable(oid, nameLen));
- oid[11] = 17; // bsnAPSerialNumber
+ oid[11] = 17; // bsnAPSerialNumber
request->bindVariable(new SNMP_Variable(oid, nameLen));
oid[9] = 2; // bsnAPIfTable
delete request;
if (rcc == SNMP_ERR_SUCCESS)
{
- if (response->getNumVariables() == 7)
+ if (response->getNumVariables() == 8)
{
BYTE macAddr[16];
memset(macAddr, 0, sizeof(macAddr));
var->getRawValue(macAddr, sizeof(macAddr));
- TCHAR name[MAX_OBJECT_NAME], model[MAX_OBJECT_NAME], serial[MAX_OBJECT_NAME];
+ TCHAR ipAddr[32], name[MAX_OBJECT_NAME], model[MAX_OBJECT_NAME], serial[MAX_OBJECT_NAME];
AccessPointInfo *ap =
new AccessPointInfo(
- macAddr,
- (response->getVariable(1)->getValueAsInt() == 1) ? AP_ADOPTED : AP_UNADOPTED,
- response->getVariable(2)->getValueAsString(name, MAX_OBJECT_NAME),
- response->getVariable(3)->getValueAsString(model, MAX_OBJECT_NAME),
- response->getVariable(4)->getValueAsString(serial, MAX_OBJECT_NAME));
+ macAddr,
+ ntohl(_t_inet_addr(response->getVariable(1)->getValueAsString(ipAddr, 32))),
+ (response->getVariable(2)->getValueAsInt() == 1) ? AP_ADOPTED : AP_UNADOPTED,
+ response->getVariable(3)->getValueAsString(name, MAX_OBJECT_NAME),
+ _T("Cisco"), // vendor
+ response->getVariable(4)->getValueAsString(model, MAX_OBJECT_NAME),
+ response->getVariable(5)->getValueAsString(serial, MAX_OBJECT_NAME));
RadioInterfaceInfo radio;
memset(&radio, 0, sizeof(RadioInterfaceInfo));
_tcscpy(radio.name, _T("slot0"));
radio.index = 0;
response->getVariable(0)->getRawValue(radio.macAddr, MAC_ADDR_LENGTH);
- radio.channel = response->getVariable(5)->getValueAsInt();
+ radio.channel = response->getVariable(6)->getValueAsInt();
ap->addRadioInterface(&radio);
- if ((response->getVariable(6)->getType() != ASN_NO_SUCH_INSTANCE) && (response->getVariable(6)->getType() != ASN_NO_SUCH_OBJECT))
+ if ((response->getVariable(7)->getType() != ASN_NO_SUCH_INSTANCE) && (response->getVariable(7)->getType() != ASN_NO_SUCH_OBJECT))
{
_tcscpy(radio.name, _T("slot1"));
radio.index = 1;
- radio.channel = response->getVariable(6)->getValueAsInt();
+ radio.channel = response->getVariable(7)->getValueAsInt();
ap->addRadioInterface(&radio);
}
response->getVariable(3)->getRawValue(macAddr, MAC_ADDR_LENGTH);
TCHAR name[MAX_OBJECT_NAME];
- AccessPointInfo *ap = new AccessPointInfo(macAddr, AP_ADOPTED, var->getValueAsString(name, MAX_OBJECT_NAME), _T(""), _T(""));
+ AccessPointInfo *ap = new AccessPointInfo(macAddr, 0, AP_ADOPTED, var->getValueAsString(name, MAX_OBJECT_NAME), NULL, NULL, NULL);
RadioInterfaceInfo radio;
memset(&radio, 0, sizeof(RadioInterfaceInfo));
ObjectArray<AccessPointInfo> *apList = (ObjectArray<AccessPointInfo> *)arg;
TCHAR model[128];
- AccessPointInfo *info = new AccessPointInfo((BYTE *)"\x00\x00\x00\x00\x00\x00", AP_UNADOPTED, NULL, var->getValueAsString(model, 128), NULL);
+ AccessPointInfo *info = new AccessPointInfo((BYTE *)"\x00\x00\x00\x00\x00\x00", 0, AP_UNADOPTED, NULL, NULL, var->getValueAsString(model, 128), NULL);
apList->add(info);
return SNMP_ERR_SUCCESS;
oid[15] = 8; // ntwsApStatApStatusApName
request->bindVariable(new SNMP_Variable(oid, nameLen));
+ oid[15] = 10; // ntwsApStatApStatusIpAddress
+ request->bindVariable(new SNMP_Variable(oid, nameLen));
+
+ oid[15] = 13; // ntwsApStatApStatusManufacturerId
+ request->bindVariable(new SNMP_Variable(oid, nameLen));
+
SNMP_PDU *response;
if (transport->doRequest(request, &response, g_dwSNMPTimeout, 3) == SNMP_ERR_SUCCESS)
{
- if (response->getNumVariables() >= 2)
+ if (response->getNumVariables() >= 4)
{
- TCHAR model[256], name[256];
- AccessPointInfo *ap = new AccessPointInfo((BYTE *)var->getValue(), AP_ADOPTED,
- response->getVariable(1)->getValueAsString(name, 256), response->getVariable(0)->getValueAsString(model, 256), serial);
+ TCHAR model[256], name[256], vendor[256], ipAddr[32];
+ AccessPointInfo *ap =
+ new AccessPointInfo(
+ (BYTE *)var->getValue(),
+ ntohl(_t_inet_addr(response->getVariable(2)->getValueAsString(ipAddr, 32))),
+ AP_ADOPTED,
+ response->getVariable(1)->getValueAsString(name, 256),
+ response->getVariable(3)->getValueAsString(vendor, 256),
+ response->getVariable(0)->getValueAsString(model, 256),
+ serial);
apList->add(ap);
}
delete response;
/>
<Tool
Name="VCLinkerTool"
+ AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)\$(ProjectName).ndd"
LinkIncremental="2"
GenerateDebugInformation="true"
/>
<Tool
Name="VCLinkerTool"
+ AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)\$(ProjectName).ndd"
LinkIncremental="2"
GenerateDebugInformation="true"
/>
<Tool
Name="VCLinkerTool"
+ AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)\$(ProjectName).ndd"
LinkIncremental="1"
GenerateDebugInformation="true"
/>
<Tool
Name="VCLinkerTool"
+ AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)\$(ProjectName).ndd"
LinkIncremental="1"
GenerateDebugInformation="true"
>
</File>
<File
- RelativePath="..\..\include\nxsrvapi.h"
+ RelativePath=".\ntws.h"
>
</File>
<File
- RelativePath=".\ntws.h"
+ RelativePath="..\..\include\nxsrvapi.h"
>
</File>
</Filter>
break;
}
- AccessPointInfo *info = new AccessPointInfo((BYTE *)var->getValue(), AP_UNADOPTED, NULL, model, NULL);
+ AccessPointInfo *info = new AccessPointInfo((BYTE *)var->getValue(), 0, AP_UNADOPTED, NULL, NULL, model, NULL);
apList->add(info);
return SNMP_ERR_SUCCESS;
AccessPointInfo *info;
if (ret == SNMP_ERR_SUCCESS)
{
- info = new AccessPointInfo((BYTE *)var->getValue(), AP_ADOPTED, NULL, model, serial);
+ info = new AccessPointInfo((BYTE *)var->getValue(), 0, AP_ADOPTED, NULL, NULL, model, serial);
apList->add(info);
}
enum AccessPointState
{
AP_ADOPTED = 0,
- AP_UNADOPTED = 1
+ AP_UNADOPTED = 1,
+ AP_DOWN = 2
};
/**
{
private:
BYTE m_macAddr[MAC_ADDR_LENGTH];
+ UINT32 m_ipAddr;
AccessPointState m_state;
TCHAR *m_name;
+ TCHAR *m_vendor;
TCHAR *m_model;
TCHAR *m_serial;
ObjectArray<RadioInterfaceInfo> *m_radioInterfaces;
public:
- AccessPointInfo(BYTE *macAddr, AccessPointState state, const TCHAR *name, const TCHAR *model, const TCHAR *serial);
+ AccessPointInfo(BYTE *macAddr, UINT32 ipAddr, AccessPointState state, const TCHAR *name, const TCHAR *vendor, const TCHAR *model, const TCHAR *serial);
~AccessPointInfo();
void addRadioInterface(RadioInterfaceInfo *iface);
BYTE *getMacAddr() { return m_macAddr; }
+ UINT32 getIpAddr() { return m_ipAddr; }
AccessPointState getState() { return m_state; }
const TCHAR *getName() { return m_name; }
+ const TCHAR *getVendor() { return m_vendor; }
const TCHAR *getModel() { return m_model; }
const TCHAR *getSerial() { return m_serial; }
ObjectArray<RadioInterfaceInfo> *getRadioInterfaces() { return m_radioInterfaces; }
virtual void CreateMessage(CSCPMessage *pMsg);
virtual UINT32 ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked = FALSE);
+ void statusPoll(ClientSession *session, UINT32 rqId, Queue *eventQueue, Node *controller);
+
BYTE *getMacAddr() { return m_macAddr; }
bool isMyRadio(int rfIndex);
bool isMyRadio(const BYTE *macAddr);
AccessPointState getState() { return m_state; }
Node *getParentNode();
+ void setIpAddr(UINT32 ipAddr) { LockData(); m_dwIpAddr = ipAddr; Modify(); UnlockData(); }
+
void attachToNode(UINT32 nodeId);
void updateRadioInterfaces(ObjectArray<RadioInterfaceInfo> *ri);
void updateInfo(const TCHAR *vendor, const TCHAR *model, const TCHAR *serialNumber);
/**
* Access point info constructor
*/
-AccessPointInfo::AccessPointInfo(BYTE *macAddr, AccessPointState state, const TCHAR *name, const TCHAR *model, const TCHAR *serial)
+AccessPointInfo::AccessPointInfo(BYTE *macAddr, UINT32 ipAddr, AccessPointState state, const TCHAR *name, const TCHAR *vendor, const TCHAR *model, const TCHAR *serial)
{
memcpy(m_macAddr, macAddr, MAC_ADDR_LENGTH);
+ m_ipAddr = ipAddr;
m_state = state;
m_name = (name != NULL) ? _tcsdup(name) : NULL;
+ m_vendor = (vendor != NULL) ? _tcsdup(vendor) : NULL;
m_model = (model != NULL) ? _tcsdup(model) : NULL;
m_serial = (serial != NULL) ? _tcsdup(serial) : NULL;
m_radioInterfaces = new ObjectArray<RadioInterfaceInfo>(4, 4, true);
AccessPointInfo::~AccessPointInfo()
{
safe_free(m_name);
+ safe_free(m_vendor);
safe_free(m_model);
safe_free(m_serial);
delete m_radioInterfaces;
}
/**
+ * Upgrade from V317 to V318
+ */
+static BOOL H_UpgradeFromV317(int currVersion, int newVersion)
+{
+ CHK_EXEC(CreateEventTemplate(EVENT_AP_DOWN, _T("SYS_AP_DOWN"), SEVERITY_CRITICAL, EF_LOG,
+ _T("Access point %2 changed state to DOWN"),
+ _T("Generated when access point state changes to DOWN.\r\n")
+ _T("Parameters:\r\n")
+ _T(" 1) Access point object ID\r\n")
+ _T(" 2) Access point name\r\n")
+ _T(" 3) Access point MAC address\r\n")
+ _T(" 4) Access point IP address\r\n")
+ _T(" 5) Access point vendor name\r\n")
+ _T(" 6) Access point model\r\n")
+ _T(" 7) Access point serial number")));
+
+ CHK_EXEC(SQLQuery(_T("UPDATE metadata SET var_value='318' WHERE var_name='SchemaVersion'")));
+ return TRUE;
+}
+
+/**
* Upgrade from V316 to V317
*/
static BOOL H_UpgradeFromV316(int currVersion, int newVersion)
{ 314, 315, H_UpgradeFromV314 },
{ 315, 316, H_UpgradeFromV315 },
{ 316, 317, H_UpgradeFromV316 },
+ { 317, 318, H_UpgradeFromV317 },
{ 0, 0, NULL }
};