]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/sonmp.c
Update ISC license wording.
[thirdparty/lldpd.git] / src / sonmp.c
CommitLineData
43c02e7b
VB
1/*
2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
3 *
51434125 4 * Permission to use, copy, modify, and/or distribute this software for any
43c02e7b
VB
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "lldpd.h"
a8105c1b 18#include "frame.h"
43c02e7b 19
4bad1937
VB
20#ifdef ENABLE_SONMP
21
43c02e7b
VB
22#include <stdio.h>
23#include <unistd.h>
24#include <errno.h>
25#include <arpa/inet.h>
26
8888d191 27static struct sonmp_chassis sonmp_chassis_types[] = {
43c02e7b
VB
28 {1, "unknown (via SONMP)"},
29 {2, "Nortel 3000"},
30 {3, "Nortel 3030"},
31 {4, "Nortel 2310"},
32 {5, "Nortel 2810"},
33 {6, "Nortel 2912"},
34 {7, "Nortel 2914"},
35 {8, "Nortel 271x"},
36 {9, "Nortel 2813"},
37 {10, "Nortel 2814"},
38 {11, "Nortel 2915"},
39 {12, "Nortel 5000"},
40 {13, "Nortel 2813SA"},
41 {14, "Nortel 2814SA"},
42 {15, "Nortel 810M"},
43 {16, "Nortel EtherCell"},
44 {17, "Nortel 5005"},
45 {18, "Alcatel Ethernet workgroup conc."},
46 {20, "Nortel 2715SA"},
47 {21, "Nortel 2486"},
48 {22, "Nortel 28000 series"},
49 {23, "Nortel 23000 series"},
50 {24, "Nortel 5DN00x series"},
51 {25, "BayStack Ethernet"},
52 {26, "Nortel 23100 series"},
53 {27, "Nortel 100Base-T Hub"},
54 {28, "Nortel 3000 Fast Ethernet"},
55 {29, "Nortel Orion switch"},
56 {30, "unknown"},
57 {31, "Nortel DDS "},
58 {32, "Nortel Centillion"},
59 {33, "Nortel Centillion"},
60 {34, "Nortel Centillion"},
61 {35, "BayStack 301"},
62 {36, "BayStack TokenRing Hub"},
63 {37, "Nortel FVC Multimedia Switch"},
64 {38, "Nortel Switch Node"},
65 {39, "BayStack 302 Switch"},
66 {40, "BayStack 350 Switch"},
67 {41, "BayStack 150 Ethernet Hub"},
68 {42, "Nortel Centillion 50N switch"},
69 {43, "Nortel Centillion 50T switch"},
70 {44, "BayStack 303 and 304 Switches"},
71 {45, "BayStack 200 Ethernet Hub"},
72 {46, "BayStack 250 10/100 Ethernet Hub"},
73 {48, "BayStack 450 10/100/1000 Switches"},
74 {49, "BayStack 410 10/100 Switches"},
75 {50, "Nortel Ethernet Routing 1200 L3 Switch"},
76 {51, "Nortel Ethernet Routing 1250 L3 Switch"},
77 {52, "Nortel Ethernet Routing 1100 L3 Switch"},
78 {53, "Nortel Ethernet Routing 1150 L3 Switch"},
79 {54, "Nortel Ethernet Routing 1050 L3 Switch"},
80 {55, "Nortel Ethernet Routing 1051 L3 Switch"},
81 {56, "Nortel Ethernet Routing 8610 L3 Switch"},
82 {57, "Nortel Ethernet Routing 8606 L3 Switch"},
83 {58, "Nortel Ethernet Routing Switch 8010"},
84 {59, "Nortel Ethernet Routing Switch 8006"},
85 {60, "BayStack 670 wireless access point"},
86 {61, "Nortel Ethernet Routing Switch 740 "},
87 {62, "Nortel Ethernet Routing Switch 750 "},
88 {63, "Nortel Ethernet Routing Switch 790"},
89 {64, "Nortel Business Policy Switch 2000 10/100 Switches"},
90 {65, "Nortel Ethernet Routing 8110 L2 Switch"},
91 {66, "Nortel Ethernet Routing 8106 L2 Switch"},
92 {67, "BayStack 3580 Gig Switch"},
93 {68, "BayStack 10 Power Supply Unit"},
94 {69, "BayStack 420 10/100 Switch"},
95 {70, "OPTera Metro 1200 Ethernet Service Module"},
96 {71, "Nortel Ethernet Routing Switch 8010co"},
97 {72, "Nortel Ethernet Routing 8610co L3 switch"},
98 {73, "Nortel Ethernet Routing 8110co L2 switch"},
99 {74, "Nortel Ethernet Routing 8003"},
100 {75, "Nortel Ethernet Routing 8603 L3 switch"},
101 {76, "Nortel Ethernet Routing 8103 L2 switch"},
102 {77, "BayStack 380 10/100/1000 Switch"},
103 {78, "Nortel Ethernet Switch 470-48T"},
104 {79, "OPTera Metro 1450 Ethernet Service Module"},
105 {80, "OPTera Metro 1400 Ethernet Service Module"},
106 {81, "Alteon Switch Family"},
107 {82, "Ethernet Switch 460-24T-PWR"},
108 {83, "OPTera Metro 8010 OPM L2 Switch"},
109 {84, "OPTera Metro 8010co OPM L2 Switch"},
110 {85, "OPTera Metro 8006 OPM L2 Switch"},
111 {86, "OPTera Metro 8003 OPM L2 Switch"},
112 {87, "Alteon 180e"},
113 {88, "Alteon AD3"},
114 {89, "Alteon 184"},
115 {90, "Alteon AD4"},
116 {91, "Nortel Ethernet Routing 1424 L3 switch"},
117 {92, "Nortel Ethernet Routing 1648 L3 switch"},
118 {93, "Nortel Ethernet Routing 1612 L3 switch"},
119 {94, "Nortel Ethernet Routing 1624 L3 switch "},
120 {95, "BayStack 380-24F Fiber 1000 Switch"},
121 {96, "Nortel Ethernet Routing Switch 5510-24T"},
122 {97, "Nortel Ethernet Routing Switch 5510-48T"},
123 {98, "Nortel Ethernet Switch 470-24T"},
124 {99, "Nortel Networks Wireless LAN Access Point 2220"},
125 {100, "Ethernet Routing RBS 2402 L3 switch"},
126 {101, "Alteon Application Switch 2424 "},
127 {102, "Alteon Application Switch 2224 "},
128 {103, "Alteon Application Switch 2208 "},
129 {104, "Alteon Application Switch 2216"},
130 {105, "Alteon Application Switch 3408"},
131 {106, "Alteon Application Switch 3416"},
132 {107, "Nortel Networks Wireless LAN SecuritySwitch 2250"},
133 {108, "Ethernet Switch 425-48T"},
134 {109, "Ethernet Switch 425-24T"},
135 {110, "Nortel Networks Wireless LAN Access Point 2221"},
136 {111, "Nortel Metro Ethernet Service Unit 24-T SPF switch"},
137 {112, "Nortel Metro Ethernet Service Unit 24-T LX DC switch"},
138 {113, "Nortel Ethernet Routing Switch 8300 10-slot chassis"},
139 {114, "Nortel Ethernet Routing Switch 8300 6-slot chassis"},
140 {115, "Nortel Ethernet Routing Switch 5520-24T-PWR"},
141 {116, "Nortel Ethernet Routing Switch 5520-48T-PWR"},
142 {117, "Nortel Networks VPN Gateway 3050"},
143 {118, "Alteon SSL 310 10/100"},
144 {119, "Alteon SSL 310 10/100 Fiber"},
145 {120, "Alteon SSL 310 10/100 FIPS"},
146 {121, "Alteon SSL 410 10/100/1000"},
147 {122, "Alteon SSL 410 10/100/1000 Fiber"},
148 {123, "Alteon Application Switch 2424-SSL"},
149 {124, "Nortel Ethernet Switch 325-24T"},
150 {125, "Nortel Ethernet Switch 325-24G"},
151 {126, "Nortel Networks Wireless LAN Access Point 2225"},
152 {127, "Nortel Networks Wireless LAN SecuritySwitch 2270"},
153 {128, "Nortel 24-port Ethernet Switch 470-24T-PWR"},
154 {129, "Nortel 48-port Ethernet Switch 470-48T-PWR"},
155 {130, "Nortel Ethernet Routing Switch 5530-24TFD"},
156 {131, "Nortel Ethernet Switch 3510-24T"},
157 {132, "Nortel Metro Ethernet Service Unit 12G AC L3 switch"},
158 {133, "Nortel Metro Ethernet Service Unit 12G DC L3 switch"},
159 {134, "Nortel Secure Access Switch"},
160 {135, "Networks VPN Gateway 3070"},
161 {136, "OPTera Metro 3500"},
162 {137, "SMB BES 1010 24T"},
163 {138, "SMB BES 1010 48T"},
164 {139, "SMB BES 1020 24T PWR"},
165 {140, "SMB BES 1020 48T PWR"},
166 {141, "SMB BES 2010 24T"},
167 {142, "SMB BES 2010 48T"},
168 {143, "SMB BES 2020 24T PWR"},
169 {144, "SMB BES 2020 48T PWR"},
170 {145, "SMB BES 110 24T"},
171 {146, "SMB BES 110 48T"},
172 {147, "SMB BES 120 24T PWR"},
173 {148, "SMB BES 120 48T PWR"},
174 {149, "SMB BES 210 24T"},
175 {150, "SMB BES 210 48T"},
176 {151, "SMB BES 220 24T PWR"},
177 {152, "SMB BES 220 48T PWR"},
178 {153, "OME 6500"},
179 {0, "unknown (via SONMP)"},
180};
181
182int
77507b69 183sonmp_send(struct lldpd *global,
43c02e7b
VB
184 struct lldpd_hardware *hardware)
185{
186 const u_int8_t mcastaddr[] = SONMP_MULTICAST_ADDR;
187 const u_int8_t llcorg[] = LLC_ORG_NORTEL;
77507b69 188 struct lldpd_chassis *chassis;
a8105c1b
VB
189 u_int8_t *packet, *pos, *pos_pid, *end;
190 int length;
191
77507b69 192 chassis = hardware->h_lport.p_chassis;
a8105c1b
VB
193 length = hardware->h_mtu;
194 if ((packet = (u_int8_t*)malloc(length)) == NULL)
195 return ENOMEM;
196 memset(packet, 0, length);
197 pos = packet;
198
199 /* Ethernet header */
200 if (!(
201 /* SONMP multicast address as target */
202 POKE_BYTES(mcastaddr, sizeof(mcastaddr)) &&
203 /* Source MAC addresss */
204 POKE_BYTES(&hardware->h_lladdr, sizeof(hardware->h_lladdr)) &&
205 /* SONMP frame is of fixed size */
206 POKE_UINT16(SONMP_SIZE)))
207 goto toobig;
208
209 /* LLC header */
210 if (!(
211 /* DSAP and SSAP */
212 POKE_UINT8(0xaa) && POKE_UINT8(0xaa) &&
213 /* Control field */
214 POKE_UINT8(0x03) &&
215 /* ORG */
216 POKE_BYTES(llcorg, sizeof(llcorg)) &&
217 POKE_SAVE(pos_pid) && /* We will modify PID later to
218 create a new frame */
219 POKE_UINT16(LLC_PID_SONMP_HELLO)))
220 goto toobig;
221
222 /* SONMP */
223 if (!(
224 /* Our IP address */
225 POKE_BYTES(&chassis->c_mgmt, sizeof(struct in_addr)) &&
226 /* Segment on three bytes, we don't have slots, so we
227 skip the first two bytes */
228 POKE_UINT16(0) &&
6e75df87 229 POKE_UINT8(hardware->h_ifindex) &&
a8105c1b
VB
230 POKE_UINT8(1) && /* Chassis: Other */
231 POKE_UINT8(12) && /* Back: Ethernet, Fast Ethernet and Gigabit */
232 POKE_UINT8(SONMP_TOPOLOGY_NEW) && /* Should work. We have no state */
233 POKE_UINT8(1) && /* Links: Dunno what it is */
234 POKE_SAVE(end)))
235 goto toobig;
43c02e7b 236
6e75df87
VB
237 if (hardware->h_ops->send(global, hardware,
238 (char *)packet, end - packet) == -1) {
43c02e7b
VB
239 LLOG_WARN("unable to send packet on real device for %s",
240 hardware->h_ifname);
a8105c1b 241 free(packet);
43c02e7b
VB
242 return ENETDOWN;
243 }
244
a8105c1b
VB
245 POKE_RESTORE(pos_pid); /* Modify LLC PID */
246 POKE_UINT16(LLC_PID_SONMP_FLATNET);
247 POKE_RESTORE(packet); /* Go to the beginning */
248 PEEK_DISCARD(ETH_ALEN - 1); /* Modify the last byte of the MAC address */
249 POKE_UINT8(1);
43c02e7b 250
6e75df87
VB
251 if (hardware->h_ops->send(global, hardware,
252 (char *)packet, end - packet) == -1) {
43c02e7b
VB
253 LLOG_WARN("unable to send second SONMP packet on real device for %s",
254 hardware->h_ifname);
a8105c1b 255 free(packet);
43c02e7b
VB
256 return ENETDOWN;
257 }
258
a8105c1b 259 free(packet);
43c02e7b
VB
260 hardware->h_tx_cnt++;
261 return 0;
a8105c1b
VB
262 toobig:
263 free(packet);
264 return -1;
43c02e7b
VB
265}
266
267int
268sonmp_decode(struct lldpd *cfg, char *frame, int s,
269 struct lldpd_hardware *hardware,
270 struct lldpd_chassis **newchassis, struct lldpd_port **newport)
271{
43c02e7b
VB
272 const u_int8_t mcastaddr[] = SONMP_MULTICAST_ADDR;
273 struct lldpd_chassis *chassis;
274 struct lldpd_port *port;
a8105c1b
VB
275 int length, i;
276 u_int8_t *pos;
277 u_int8_t seg[3], rchassis;
278 struct in_addr address;
43c02e7b
VB
279
280 if ((chassis = calloc(1, sizeof(struct lldpd_chassis))) == NULL) {
281 LLOG_WARN("failed to allocate remote chassis");
282 return -1;
283 }
284 if ((port = calloc(1, sizeof(struct lldpd_port))) == NULL) {
285 LLOG_WARN("failed to allocate remote port");
286 free(chassis);
287 return -1;
288 }
a1347cd8 289#ifdef ENABLE_DOT1
43c02e7b 290 TAILQ_INIT(&port->p_vlans);
a1347cd8 291#endif
43c02e7b 292
a8105c1b
VB
293 length = s;
294 pos = (u_int8_t*)frame;
295 if (length < SONMP_SIZE) {
296 LLOG_WARNX("too short SONMP frame received on %s", hardware->h_ifname);
43c02e7b
VB
297 goto malformed;
298 }
a8105c1b 299 if (PEEK_CMP(mcastaddr, sizeof(mcastaddr)) != 0)
43c02e7b
VB
300 /* There is two multicast address. We just handle only one of
301 * them. */
302 goto malformed;
a8105c1b
VB
303 /* We skip to LLC PID */
304 PEEK_DISCARD(ETH_ALEN); PEEK_DISCARD_UINT16;
305 PEEK_DISCARD(6);
306 if (PEEK_UINT16 != LLC_PID_SONMP_HELLO) {
307 LLOG_DEBUG("incorrect LLC protocol ID received for SONMP on %s",
43c02e7b
VB
308 hardware->h_ifname);
309 goto malformed;
310 }
311
312 chassis->c_id_subtype = LLDP_CHASSISID_SUBTYPE_ADDR;
313 if ((chassis->c_id = calloc(1, sizeof(struct in_addr) + 1)) == NULL) {
314 LLOG_WARN("unable to allocate memory for chassis id on %s",
315 hardware->h_ifname);
316 goto malformed;
317 }
318 chassis->c_id_len = sizeof(struct in_addr) + 1;
319 chassis->c_id[0] = 1;
a8105c1b
VB
320 PEEK_BYTES(&address, sizeof(struct in_addr));
321 memcpy(chassis->c_id + 1, &address, sizeof(struct in_addr));
322 if (asprintf(&chassis->c_name, "%s", inet_ntoa(address)) == -1) {
43c02e7b
VB
323 LLOG_WARNX("unable to write chassis name for %s",
324 hardware->h_ifname);
325 goto malformed;
326 }
a8105c1b
VB
327 PEEK_BYTES(seg, sizeof(seg));
328 rchassis = PEEK_UINT8;
43c02e7b 329 for (i=0; sonmp_chassis_types[i].type != 0; i++) {
a8105c1b 330 if (sonmp_chassis_types[i].type == rchassis)
43c02e7b
VB
331 break;
332 }
333 if (asprintf(&chassis->c_descr, "%s",
334 sonmp_chassis_types[i].description) == -1) {
335 LLOG_WARNX("unable to write chassis description for %s",
336 hardware->h_ifname);
337 goto malformed;
338 }
a8105c1b 339 memcpy(&chassis->c_mgmt, &address, sizeof(struct in_addr));
43c02e7b
VB
340 chassis->c_ttl = LLDPD_TTL;
341
342 port->p_id_subtype = LLDP_PORTID_SUBTYPE_LOCAL;
343 if (asprintf(&port->p_id, "%02x-%02x-%02x",
a8105c1b 344 seg[0], seg[1], seg[2]) == -1) {
43c02e7b
VB
345 LLOG_WARN("unable to allocate memory for port id on %s",
346 hardware->h_ifname);
347 goto malformed;
348 }
349 port->p_id_len = strlen(port->p_id);
350
a8105c1b
VB
351 /* Port description depend on the number of segments */
352 if ((seg[0] == 0) && (seg[1] == 0)) {
43c02e7b 353 if (asprintf(&port->p_descr, "port %d",
a8105c1b 354 seg[2]) == -1) {
43c02e7b
VB
355 LLOG_WARNX("unable to write port description for %s",
356 hardware->h_ifname);
357 goto malformed;
358 }
a8105c1b 359 } else if (seg[0] == 0) {
43c02e7b 360 if (asprintf(&port->p_descr, "port %d/%d",
a8105c1b 361 seg[1], seg[2]) == -1) {
43c02e7b
VB
362 LLOG_WARNX("unable to write port description for %s",
363 hardware->h_ifname);
364 goto malformed;
365 }
366 } else {
367 if (asprintf(&port->p_descr, "port %x:%x:%x",
a8105c1b 368 seg[0], seg[1], seg[2]) == -1) {
43c02e7b
VB
369 LLOG_WARNX("unable to write port description for %s",
370 hardware->h_ifname);
371 goto malformed;
372 }
373 }
374 *newchassis = chassis;
375 *newport = port;
376 return 1;
377
378malformed:
77507b69 379 lldpd_chassis_cleanup(chassis, 1);
9898ac07 380 lldpd_port_cleanup(cfg, port, 1);
4e624dc2 381 free(port);
43c02e7b
VB
382 return -1;
383}
4bad1937
VB
384
385#endif /* ENABLE_SONMP */