-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlldp.cpp
138 lines (108 loc) · 3.39 KB
/
lldp.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
// (C) 2022 by folkert van heusden <[email protected]>, released under Apache License v2.0
#include <assert.h>
#include <chrono>
#include <stdint.h>
#include <string>
#include <string.h>
#include <arpa/inet.h>
#include "lldp.h"
#include "log.h"
#include "phys.h"
#include "router.h"
#include "time.h"
#include "utils.h"
lldp::lldp(stats *const s, const any_addr & my_mac, const any_addr & mgmt_addr, const int interface_idx, router *const r) : network_layer(s, "lldp", r), my_mac(my_mac), mgmt_addr(mgmt_addr), interface_idx(interface_idx)
{
th = new std::thread(std::ref(*this));
}
lldp::~lldp()
{
stop_flag.signal_stop();
th->join();
delete th;
}
bool lldp::transmit_packet(const std::optional<any_addr> & dst_mac, const any_addr & dst_ip, const any_addr & src_ip, const uint8_t protocol, const uint8_t *payload, const size_t pl_size, const uint8_t *const header_template)
{
assert(0);
return false;
}
void lldp::queue_incoming_packet(phys *const interface, packet *p)
{
delete p;
}
void lldp::add_tlv(std::vector<uint8_t> *const target, const uint8_t type, const std::vector<uint8_t> & payload)
{
uint16_t header = (type << 9) | payload.size();
target->push_back(header >> 8);
target->push_back(header);
std::copy(payload.begin(), payload.end(), std::back_inserter(*target));
}
std::vector<uint8_t> str_to_uvec(const std::string & in)
{
std::vector<uint8_t> out;
for(size_t i=0; i<in.size(); i++)
out.push_back(in[i]);
return out;
}
std::vector<uint8_t> lldp::generate_lldp_packet()
{
std::vector<uint8_t> out;
// CHASSIS ID
std::vector<uint8_t> chassis_id { 4 }; // mac adress
for(int i=0; i<6; i++)
chassis_id.push_back(my_mac[i]);
add_tlv(&out, 1, chassis_id);
// PORT ID
std::vector<uint8_t> port_id { 3 }; // mac adress
for(int i=0; i<6; i++)
port_id.push_back(my_mac[i]);
add_tlv(&out, 2, port_id);
// TTL
std::vector<uint8_t> ttl;
ttl.push_back(0);
ttl.push_back(30); // 30s
add_tlv(&out, 3, ttl);
// SYSTEM DESCRIPTION
std::string description = "MyIP - www.vanheusden.com";
std::vector<uint8_t> system_description = str_to_uvec(description);
add_tlv(&out, 6, system_description);
// CAPABILITIES
uint16_t capabilities = 0x01 /* other */ | 0x10 /* router */ | 0x80 /* station */;
std::vector<uint8_t> caps;
caps.push_back(capabilities >> 8);
caps.push_back(capabilities);
caps.push_back(0); // reserved
caps.push_back(0);
add_tlv(&out, 7, caps);
// MANAGEMENT ADDRESS
std::vector<uint8_t> mgmt;
mgmt.push_back(1 + mgmt_addr.get_len()); // the address
mgmt.push_back(mgmt_addr.get_len() == 4 ? 1 : 6); // '6' is a guess (for IPv6)
for(int i=0; i<mgmt_addr.get_len(); i++)
mgmt.push_back(mgmt_addr[i]);
mgmt.push_back(2); // ifIndex
mgmt.push_back(interface_idx >> 24);
mgmt.push_back(interface_idx >> 16);
mgmt.push_back(interface_idx >> 8);
mgmt.push_back(interface_idx);
mgmt.push_back(0); // oid string length
add_tlv(&out, 8, mgmt);
// end marker
add_tlv(&out, 0, { });
return out;
}
void lldp::operator()()
{
set_thread_name("myip-lldp");
any_addr dest_mac(any_addr::mac, std::initializer_list<uint8_t>({ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }).begin());
auto payload = generate_lldp_packet();
for(;;) {
if (stop_flag.sleep(15000))
break;
// every 15s
if (default_pdev) {
DOLOG(ll_debug, "lldp::operator: transmit LLDP packet\n");
default_pdev->transmit_packet(dest_mac, my_mac, 0x88cc, payload.data(), payload.size());
}
}
}