2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
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.
25 #include <arpa/inet.h>
27 static struct sonmp_chassis sonmp_chassis_types
[] = {
28 {1, "unknown (via SONMP)"},
40 {13, "Nortel 2813SA"},
41 {14, "Nortel 2814SA"},
43 {16, "Nortel EtherCell"},
45 {18, "Alcatel Ethernet workgroup conc."},
46 {20, "Nortel 2715SA"},
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"},
58 {32, "Nortel Centillion"},
59 {33, "Nortel Centillion"},
60 {34, "Nortel Centillion"},
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"},
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"},
179 {0, "unknown (via SONMP)"},
183 sonmp_send(struct lldpd
*global
,
184 struct lldpd_hardware
*hardware
)
186 const u_int8_t mcastaddr
[] = SONMP_MULTICAST_ADDR
;
187 const u_int8_t llcorg
[] = LLC_ORG_NORTEL
;
188 struct lldpd_chassis
*chassis
;
189 u_int8_t
*packet
, *pos
, *pos_pid
, *end
;
192 chassis
= hardware
->h_lport
.p_chassis
;
193 length
= hardware
->h_mtu
;
194 if ((packet
= (u_int8_t
*)malloc(length
)) == NULL
)
196 memset(packet
, 0, length
);
199 /* Ethernet header */
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
)))
212 POKE_UINT8(0xaa) && POKE_UINT8(0xaa) &&
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
)))
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 */
229 POKE_UINT8(hardware
->h_ifindex
) &&
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 */
237 if (hardware
->h_ops
->send(global
, hardware
,
238 (char *)packet
, end
- packet
) == -1) {
239 LLOG_WARN("unable to send packet on real device for %s",
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 */
251 if (hardware
->h_ops
->send(global
, hardware
,
252 (char *)packet
, end
- packet
) == -1) {
253 LLOG_WARN("unable to send second SONMP packet on real device for %s",
260 hardware
->h_tx_cnt
++;
268 sonmp_decode(struct lldpd
*cfg
, char *frame
, int s
,
269 struct lldpd_hardware
*hardware
,
270 struct lldpd_chassis
**newchassis
, struct lldpd_port
**newport
)
272 const u_int8_t mcastaddr
[] = SONMP_MULTICAST_ADDR
;
273 struct lldpd_chassis
*chassis
;
274 struct lldpd_port
*port
;
277 u_int8_t seg
[3], rchassis
;
278 struct in_addr address
;
280 if ((chassis
= calloc(1, sizeof(struct lldpd_chassis
))) == NULL
) {
281 LLOG_WARN("failed to allocate remote chassis");
284 if ((port
= calloc(1, sizeof(struct lldpd_port
))) == NULL
) {
285 LLOG_WARN("failed to allocate remote port");
290 TAILQ_INIT(&port
->p_vlans
);
294 pos
= (u_int8_t
*)frame
;
295 if (length
< SONMP_SIZE
) {
296 LLOG_WARNX("too short SONMP frame received on %s", hardware
->h_ifname
);
299 if (PEEK_CMP(mcastaddr
, sizeof(mcastaddr
)) != 0)
300 /* There is two multicast address. We just handle only one of
303 /* We skip to LLC PID */
304 PEEK_DISCARD(ETH_ALEN
); PEEK_DISCARD_UINT16
;
306 if (PEEK_UINT16
!= LLC_PID_SONMP_HELLO
) {
307 LLOG_DEBUG("incorrect LLC protocol ID received for SONMP on %s",
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",
318 chassis
->c_id_len
= sizeof(struct in_addr
) + 1;
319 chassis
->c_id
[0] = 1;
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) {
323 LLOG_WARNX("unable to write chassis name for %s",
327 PEEK_BYTES(seg
, sizeof(seg
));
328 rchassis
= PEEK_UINT8
;
329 for (i
=0; sonmp_chassis_types
[i
].type
!= 0; i
++) {
330 if (sonmp_chassis_types
[i
].type
== rchassis
)
333 if (asprintf(&chassis
->c_descr
, "%s",
334 sonmp_chassis_types
[i
].description
) == -1) {
335 LLOG_WARNX("unable to write chassis description for %s",
339 memcpy(&chassis
->c_mgmt
, &address
, sizeof(struct in_addr
));
340 chassis
->c_ttl
= LLDPD_TTL
;
342 port
->p_id_subtype
= LLDP_PORTID_SUBTYPE_LOCAL
;
343 if (asprintf(&port
->p_id
, "%02x-%02x-%02x",
344 seg
[0], seg
[1], seg
[2]) == -1) {
345 LLOG_WARN("unable to allocate memory for port id on %s",
349 port
->p_id_len
= strlen(port
->p_id
);
351 /* Port description depend on the number of segments */
352 if ((seg
[0] == 0) && (seg
[1] == 0)) {
353 if (asprintf(&port
->p_descr
, "port %d",
355 LLOG_WARNX("unable to write port description for %s",
359 } else if (seg
[0] == 0) {
360 if (asprintf(&port
->p_descr
, "port %d/%d",
361 seg
[1], seg
[2]) == -1) {
362 LLOG_WARNX("unable to write port description for %s",
367 if (asprintf(&port
->p_descr
, "port %x:%x:%x",
368 seg
[0], seg
[1], seg
[2]) == -1) {
369 LLOG_WARNX("unable to write port description for %s",
374 *newchassis
= chassis
;
379 lldpd_chassis_cleanup(chassis
, 1);
380 lldpd_port_cleanup(cfg
, port
, 1);
385 #endif /* ENABLE_SONMP */