-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathlldp_functions.cpp
348 lines (285 loc) · 8.69 KB
/
lldp_functions.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
#include <Arduino.h>
#include "lldp_functions.h";
#include "Packet_Data.h";
PINFO info;
int lldpIPaddr = 0;
int eightOtwo = 0;
byte lldp_mac[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e};
byte lldp_llc_bytes[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x0c, 0x20, 0x00};
byte lldp_encbuff[1500];
unsigned int lldp_check_Packet(int plen, byte lldp_encbuff[], int bufSize ) {
if ( plen > 0 ) {
if (plen > sizeof(lldp_encbuff)) {
plen = sizeof(lldp_encbuff);
}
unsigned int cdpDataIndex = 0;
if (lldp_byte_array_contains(lldp_encbuff, cdpDataIndex, lldp_mac, sizeof(lldp_mac))) {
cdpDataIndex += sizeof(lldp_mac); // Increment index the length of the source MAC address
//LDDP Packet found and is now getting processed
Serial.println("LLDP Packet Recieved");
//Get source MAC Address
byte* macFrom = lldp_encbuff + cdpDataIndex;
info.MAC[1] = lldp_print_mac(macFrom, 0, 6);
cdpDataIndex += sizeof(lldp_mac); // Increment index the length of the MAC address
unsigned int packet_length = (lldp_encbuff[cdpDataIndex] << 8) | lldp_encbuff[cdpDataIndex + 1];
cdpDataIndex += 2;
return cdpDataIndex;
}
else {
return (0);
}
}
}
bool lldp_byte_array_contains(const byte a[], unsigned int offset, const byte b[], unsigned int length) {
for (unsigned int i = offset, j = 0; j < length; ++i, ++j) {
if (a[i] != b[j]) {
return false;
}
}
return true;
}
PINFO lldp_packet_handler( byte cdpData[], uint16_t plen) {
/* Serial.println();
for (int i=0; i<plen; i++){
Serial.print(cdpData[i],HEX);
}
*/
info.Proto[1] = "LLDP";
byte* macFrom = cdpData + sizeof(lldp_mac);
lldp_print_mac(macFrom, 0, 6);
unsigned int cdpDataIndex = 14;
while (cdpDataIndex < plen) { // read all remaining TLV fields
unsigned int lldpFieldType = cdpData[cdpDataIndex];
cdpDataIndex += 1;
unsigned int lldpFieldLength = cdpData[cdpDataIndex];
cdpDataIndex += 1;
switch (lldpFieldType) {
//Chassis ID
case 0x0002:
info.ChassisID[1] = handleportsubtype( cdpData, cdpDataIndex , lldpFieldLength );
break;
//Port Name
case 0x0004:
info.Port[1] = handleportsubtype( cdpData, cdpDataIndex , lldpFieldLength );
break;
//TTL
case 0x0006:
info.TTL[1] = lldp_handleCdpNumField(cdpData, cdpDataIndex , lldpFieldLength);
break;
//Port Description
case 0x0008:
info.PortDesc[1] = handlelldpAsciiField( cdpData, cdpDataIndex , lldpFieldLength);
break;
//Device Name
case 0x000a:
info.Name[1] = handlelldpAsciiField( cdpData, cdpDataIndex , lldpFieldLength);
break;
//Model Name
case 0x000c:
info.Model[1] = handlelldpAsciiField( cdpData, cdpDataIndex, lldpFieldLength);
break;
//Capabilities
case 0x000e:
handlelldpCapabilities( cdpData, cdpDataIndex + 2, lldpFieldLength - 2);
break;
//Management IP Address
case 0x0010:
info.IP[1] = handleManagementSubtype(cdpData, cdpDataIndex , lldpFieldLength);
break;
// MAC/PHY Configuration
case 0x00fe:
//Port VLAN ID
if (eightOtwo == 0) {
// Serial.println(lldp_print_mac(cdpData, cdpDataIndex +4 , lldpFieldLength-4));
info.VLAN[1] = lldp_handleCdpNumField(cdpData, cdpDataIndex + 4 , lldpFieldLength - 4);
}
eightOtwo++;
break;
}
cdpDataIndex += lldpFieldLength;
}
//drawscreen();
// Serial.println("DEBUG: Clear buffer");
//memset(cdpData, 0, sizeof(cdpData));
return info;
}
String handleLLDPIPField(const byte a[], unsigned int offset, unsigned int lengtha) {
int j = 0;
String temp;
for (unsigned int i = offset; i < ( offset + lengtha ); ++i , ++j) {
temp += a[i], DEC;
if (j < 3) {
temp += ".";
}
}
temp += '\0';
return temp;
}
String handlelldpAsciiField(byte a[], unsigned int offset, unsigned int lengtha) {
int j = 0;
char temp [lengtha + 1] ;
for (unsigned int i = offset; i < ( offset + lengtha ); ++i , ++j) {
temp[j] = a[i];
}
temp[lengtha ] = '\0';
String temp1 = temp;
// Serial.print(temp1);
return temp1;
}
void handlelldpCapabilities( const byte a[], unsigned int offset, unsigned int lengtha) {
int j = 0;
String temp;
for (unsigned int i = offset; i < ( offset + lengtha ); ++i , ++j) {
temp = temp + lldp_print_binary(a[i], 8) ;
}
info.Cap[1] = (LldpCapabilities(temp));
}
String lldp_print_binary(int v, int num_places)
{
String output;
int mask = 0, n;
for (n = 1; n <= num_places; n++)
{
mask = (mask << 1) | 0x0001;
}
v = v & mask; // truncate v to specified number of places
while (num_places)
{
if (v & (0x0001 << num_places - 1))
{
output = output + "1" ;
}
else
{
output = output + "0" ;
}
--num_places;
}
return output;
}
String LldpCapabilities(String temp) {
//Serial.print (temp);
String output;
//Serial.print(temp.substring(26,27));
if (temp.substring(15, 16) == "1") {
output = output + "Other ";
}
if (temp.substring(14, 15) == "1") {
output = output + "Repeater ";
}
if (temp.substring(13, 14) == "1") {
output = output + "Bridge ";
}
if (temp.substring(12, 13) == "1") {
output = output + "WLAN ";
}
if (temp.substring(11, 12) == "1") {
output = output + "Router ";
}
if (temp.substring(10, 11) == "1") {
output = output + "Telephone ";
}
if (temp.substring(9, 10) == "1") {
output = output + "DOCSIS ";
}
if (temp.substring(8, 9) == "1") {
output = output + "Station ";
}
return output;
}
String lldp_print_mac(const byte a[], unsigned int offset, unsigned int length) {
String Mac;
char temp [40];
for (unsigned int i = offset; i < offset + length; ++i) {
if (i > offset) {
Mac = Mac + ':';
}
if (a[i] < 0x10) {
Mac = Mac + '0';
}
Mac = Mac + String (a[i], HEX);
}
return Mac;
}
String lldp_handleCdpNumField( const byte a[], unsigned int offset, unsigned int length) {
String temp;
unsigned long num = 0;
for (unsigned int i = 0; i < length; ++i) {
num <<= 8;
num += a[offset + i];
}
temp = "" + String(num, DEC);
return temp;
}
String handleportsubtype(byte cdpData[], unsigned int cdpDataIndex, unsigned int lldpFieldLength) {
lldpFieldLength = lldpFieldLength - 1;
unsigned int charTemp = cdpData[cdpDataIndex];
cdpDataIndex++;
/*
https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_NET_LLDP_PORT_ID_SUBTYPE.html
Subtype 1 = Interface alias
Subtype 2 = Port component
Subtype 3 = MAC address
Subtype 4 = Network address
Subtype 5 = Interface name
Subtype 6 = Agent circuit ID
Subtype 7 = Locally assigned
*/
switch (charTemp) {
case 0x0001:
//ASCII
return handlelldpAsciiField( cdpData, cdpDataIndex , lldpFieldLength);
break;
case 0x0002:
//ASCII
return handlelldpAsciiField( cdpData, cdpDataIndex , lldpFieldLength);
break;
case 0x0003:
//MAC Address
return lldp_print_mac(cdpData, cdpDataIndex, lldpFieldLength);
break;
case 0x0004:
//IP Address
return handleLLDPIPField(cdpData, cdpDataIndex, lldpFieldLength);
break;
case 0x0005:
//ASCII
return handlelldpAsciiField( cdpData, cdpDataIndex , lldpFieldLength);
break;
case 0x0006:
// ??
break;
case 0x0007:
//ASCII ??
return handlelldpAsciiField( cdpData, cdpDataIndex , lldpFieldLength);
break;
}
return " ";
}
String handleManagementSubtype(byte cdpData[], unsigned int cdpDataIndex, unsigned int lldpFieldLength) {
unsigned int SubtypeLength = cdpData[cdpDataIndex] - 1;
cdpDataIndex++;
unsigned int charTemp = cdpData[cdpDataIndex ];
cdpDataIndex++;
/*
https://github.com/boundary/wireshark/blob/master/epan/dissectors/packet-lldp.c
Subtype 1 = IPv4
Subtype 2 = IPv6
Subtype [Other] = MAC
*/
switch (charTemp) {
case 0x0001:
//IPv4
return handleLLDPIPField(cdpData, cdpDataIndex, SubtypeLength);
break;
case 0x0002:
//IPv6
//return handleLLDPIPv6Field(cdpData, cdpDataIndex, SubtypeLength);
break;
default:
//MAC
return lldp_print_mac(cdpData, cdpDataIndex, SubtypeLength);
break;
}
return " ";
}