LLDPv2 MIBs added
[public/netxms.git] / src / server / core / lldp.cpp
CommitLineData
eec253a8
VK
1/*
2** NetXMS - Network Management System
3** Copyright (C) 2003-2011 Victor Kirhenshtein
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: lldp.cpp
20**
21**/
22
23#include "nxcore.h"
24
25
26//
27// Find remote interface
28//
29
30static Interface *FindRemoteInterface(Node *node, DWORD idType, BYTE *id, size_t idLen)
31{
32 switch(idType)
33 {
34 case 3: // MAC address
35 return node->findInterfaceByMAC(id);
36 case 4: // Network address
37 if (id[0] == 1) // IPv4
38 {
39 DWORD ipAddr;
40 memcpy(&ipAddr, &id[1], sizeof(DWORD));
41 return node->findInterfaceByIP(ntohl(ipAddr));
42 }
43 return NULL;
44 default:
45 return NULL;
46 }
47}
48
49
50//
51// Topology table walker's callback for LLDP topology table
52//
53
54static DWORD LLDPTopoHandler(DWORD snmpVersion, SNMP_Variable *var, SNMP_Transport *transport, void *arg)
55{
56 LinkLayerNeighbors *nbs = (LinkLayerNeighbors *)arg;
57 Node *node = (Node *)nbs->getData();
58 SNMP_ObjectId *oid = var->GetName();
59
60 // Get additional info for current record
61 DWORD newOid[128];
62 memcpy(newOid, oid->GetValue(), oid->Length() * sizeof(DWORD));
63 SNMP_PDU *pRqPDU = new SNMP_PDU(SNMP_GET_REQUEST, SnmpNewRequestId(), snmpVersion);
64
65 newOid[oid->Length() - 4] = 4; // lldpRemChassisIdSubtype
66 pRqPDU->bindVariable(new SNMP_Variable(newOid, oid->Length()));
67
68 newOid[oid->Length() - 4] = 7; // lldpRemPortId
69 pRqPDU->bindVariable(new SNMP_Variable(newOid, oid->Length()));
70
71 newOid[oid->Length() - 4] = 6; // lldpRemPortIdSubtype
72 pRqPDU->bindVariable(new SNMP_Variable(newOid, oid->Length()));
73
74 SNMP_PDU *pRespPDU;
75 DWORD rcc = transport->doRequest(pRqPDU, &pRespPDU, g_dwSNMPTimeout, 3);
76 delete pRqPDU;
77 if (rcc == SNMP_ERR_SUCCESS)
78 {
79 // Build LLDP ID for remote system
80 TCHAR remoteId[256];
81 _sntprintf(remoteId, 256, _T("%d@"), (int)pRespPDU->getVariable(0)->GetValueAsInt());
82 BinToStr(var->GetValue(), var->GetValueLength(), &remoteId[_tcslen(remoteId)]);
83
84 Node *remoteNode = FindNodeByLLDPId(remoteId);
85 if (remoteNode != NULL)
86 {
87 BYTE remoteIfId[1024];
88 size_t remoteIfIdLen = pRespPDU->getVariable(1)->getRawValue(remoteIfId, 1024);
89 Interface *ifRemote = FindRemoteInterface(remoteNode, pRespPDU->getVariable(2)->GetValueAsUInt(), remoteIfId, remoteIfIdLen);
90
91 LL_NEIGHBOR_INFO info;
92
93 info.objectId = remoteNode->Id();
94 info.ifRemote = (ifRemote != NULL) ? ifRemote->getIfIndex() : 0;
95 info.isPtToPt = true;
96 info.protocol = LL_PROTO_LLDP;
97
98 // Index to lldpRemTable is lldpRemTimeMark, lldpRemLocalPortNum, lldpRemIndex
99 DWORD localPort = oid->GetValue()[oid->Length() - 2];
100
101 // Determine interface index from local port number. It can be
102 // either ifIndex or dot1dBasePort, as described in LLDP MIB:
103 // A port number has no mandatory relationship to an
104 // InterfaceIndex object (of the interfaces MIB, IETF RFC 2863).
105 // If the LLDP agent is a IEEE 802.1D, IEEE 802.1Q bridge, the
106 // LldpPortNumber will have the same value as the dot1dBasePort
107 // object (defined in IETF RFC 1493) associated corresponding
108 // bridge port. If the system hosting LLDP agent is not an
109 // IEEE 802.1D or an IEEE 802.1Q bridge, the LldpPortNumber
110 // will have the same value as the corresponding interface's
111 // InterfaceIndex object.
112 if (node->isBridge())
113 {
114 Interface *localIf = node->findBridgePort(localPort);
115 if (localIf != NULL)
116 info.ifLocal = localIf->getIfIndex();
117 }
118 else
119 {
120 info.ifLocal = localPort;
121 }
122
123 nbs->addConnection(&info);
124 }
125 }
126 return SNMP_ERR_SUCCESS;
127}
128
129
130//
131// Add LLDP-discovered neighbors
132//
133
134void AddLLDPNeighbors(Node *node, LinkLayerNeighbors *nbs)
135{
136 if (!(node->getFlags() & NF_IS_LLDP))
137 return;
138
139 nbs->setData(node);
140 node->CallSnmpEnumerate(_T(".1.0.8802.1.1.2.1.4.1.1.5"), LLDPTopoHandler, nbs);
141}