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