]>
Commit | Line | Data |
---|---|---|
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 | 27 | static 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 | ||
182 | int | |
77507b69 | 183 | sonmp_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 | ||
267 | int | |
268 | sonmp_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 | ||
378 | malformed: | |
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 */ |