]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/daemon/lldp.c
snmp: don't send traps when SNMP is not enabled
[thirdparty/lldpd.git] / src / daemon / lldp.c
CommitLineData
4b292b55 1/* -*- mode: c; c-file-style: "openbsd" -*- */
43c02e7b
VB
2/*
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 *
51434125 5 * Permission to use, copy, modify, and/or distribute this software for any
43c02e7b
VB
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"
a8105c1b 19#include "frame.h"
43c02e7b
VB
20
21#include <unistd.h>
22#include <errno.h>
e6b36c87 23#include <assert.h>
43c02e7b
VB
24#include <time.h>
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <sys/ioctl.h>
28#include <netpacket/packet.h>
29#include <linux/sockios.h>
30
e6b36c87
JV
31inline static int
32lldpd_af_to_lldp_proto(int af)
33{
34 switch (af) {
35 case LLDPD_AF_IPV4:
36 return LLDP_MGMT_ADDR_IP4;
37 case LLDPD_AF_IPV6:
38 return LLDP_MGMT_ADDR_IP6;
39 default:
40 return LLDP_MGMT_ADDR_NONE;
41 }
42}
43
44inline static int
45lldpd_af_from_lldp_proto(int proto)
46{
47 switch (proto) {
48 case LLDP_MGMT_ADDR_IP4:
49 return LLDPD_AF_IPV4;
50 case LLDP_MGMT_ADDR_IP6:
51 return LLDPD_AF_IPV6;
52 default:
53 return LLDPD_AF_UNSPEC;
54 }
55}
56
43c02e7b 57int
77507b69 58lldp_send(struct lldpd *global,
a8105c1b 59 struct lldpd_hardware *hardware)
43c02e7b 60{
a8105c1b 61 struct lldpd_port *port;
77507b69 62 struct lldpd_chassis *chassis;
a8105c1b
VB
63 struct lldpd_frame *frame;
64 int length;
65 u_int8_t *packet, *pos, *tlv;
e6b36c87
JV
66 struct lldpd_mgmt *mgmt;
67 int proto;
a8105c1b
VB
68
69 u_int8_t mcastaddr[] = LLDP_MULTICAST_ADDR;
a1347cd8
VB
70#ifdef ENABLE_DOT1
71 const u_int8_t dot1[] = LLDP_TLV_ORG_DOT1;
a1347cd8 72 struct lldpd_vlan *vlan;
9757bfbc
SK
73 struct lldpd_ppvid *ppvid;
74 struct lldpd_pi *pi;
a1347cd8
VB
75#endif
76#ifdef ENABLE_DOT3
77 const u_int8_t dot3[] = LLDP_TLV_ORG_DOT3;
a1347cd8 78#endif
89840df0 79#ifdef ENABLE_LLDPMED
115ff55c 80 int i;
89840df0 81 const u_int8_t med[] = LLDP_TLV_ORG_MED;
89840df0 82#endif
43c02e7b 83
a8105c1b 84 port = &hardware->h_lport;
77507b69 85 chassis = port->p_chassis;
a8105c1b
VB
86 length = hardware->h_mtu;
87 if ((packet = (u_int8_t*)malloc(length)) == NULL)
88 return ENOMEM;
89 memset(packet, 0, length);
90 pos = packet;
43c02e7b
VB
91
92 /* Ethernet header */
a8105c1b
VB
93 if (!(
94 /* LLDP multicast address */
95 POKE_BYTES(mcastaddr, sizeof(mcastaddr)) &&
96 /* Source MAC address */
97 POKE_BYTES(&hardware->h_lladdr, sizeof(hardware->h_lladdr)) &&
98 /* LLDP frame */
99 POKE_UINT16(ETHERTYPE_LLDP)))
100 goto toobig;
43c02e7b
VB
101
102 /* Chassis ID */
a8105c1b
VB
103 if (!(
104 POKE_START_LLDP_TLV(LLDP_TLV_CHASSIS_ID) &&
105 POKE_UINT8(chassis->c_id_subtype) &&
106 POKE_BYTES(chassis->c_id, chassis->c_id_len) &&
107 POKE_END_LLDP_TLV))
108 goto toobig;
43c02e7b
VB
109
110 /* Port ID */
a8105c1b
VB
111 if (!(
112 POKE_START_LLDP_TLV(LLDP_TLV_PORT_ID) &&
113 POKE_UINT8(port->p_id_subtype) &&
114 POKE_BYTES(port->p_id, port->p_id_len) &&
115 POKE_END_LLDP_TLV))
116 goto toobig;
43c02e7b
VB
117
118 /* Time to live */
a8105c1b
VB
119 if (!(
120 POKE_START_LLDP_TLV(LLDP_TLV_TTL) &&
121 POKE_UINT16(chassis->c_ttl) &&
122 POKE_END_LLDP_TLV))
123 goto toobig;
43c02e7b
VB
124
125 /* System name */
a8105c1b
VB
126 if (!(
127 POKE_START_LLDP_TLV(LLDP_TLV_SYSTEM_NAME) &&
128 POKE_BYTES(chassis->c_name, strlen(chassis->c_name)) &&
129 POKE_END_LLDP_TLV))
130 goto toobig;
43c02e7b
VB
131
132 /* System description */
a8105c1b
VB
133 if (!(
134 POKE_START_LLDP_TLV(LLDP_TLV_SYSTEM_DESCR) &&
135 POKE_BYTES(chassis->c_descr, strlen(chassis->c_descr)) &&
136 POKE_END_LLDP_TLV))
137 goto toobig;
43c02e7b
VB
138
139 /* System capabilities */
a8105c1b
VB
140 if (!(
141 POKE_START_LLDP_TLV(LLDP_TLV_SYSTEM_CAP) &&
142 POKE_UINT16(chassis->c_cap_available) &&
143 POKE_UINT16(chassis->c_cap_enabled) &&
144 POKE_END_LLDP_TLV))
145 goto toobig;
43c02e7b 146
e6b36c87
JV
147 /* Management addresses */
148 TAILQ_FOREACH(mgmt, &chassis->c_mgmt, m_entries) {
149 proto = lldpd_af_to_lldp_proto(mgmt->m_family);
150 assert(proto != LLDP_MGMT_ADDR_NONE);
a8105c1b 151 if (!(
e6b36c87
JV
152 POKE_START_LLDP_TLV(LLDP_TLV_MGMT_ADDR) &&
153 /* Size of the address, including its type */
154 POKE_UINT8(mgmt->m_addrsize + 1) &&
155 POKE_UINT8(proto) &&
156 POKE_BYTES(&mgmt->m_addr, mgmt->m_addrsize)))
a8105c1b 157 goto toobig;
43c02e7b
VB
158
159 /* Interface port type, OID */
e6b36c87 160 if (mgmt->m_iface == 0) {
a8105c1b 161 if (!(
e6b36c87
JV
162 /* We don't know the management interface */
163 POKE_UINT8(LLDP_MGMT_IFACE_UNKNOWN) &&
164 POKE_UINT32(0)))
a8105c1b
VB
165 goto toobig;
166 } else {
167 if (!(
e6b36c87
JV
168 /* We have the index of the management interface */
169 POKE_UINT8(LLDP_MGMT_IFACE_IFINDEX) &&
170 POKE_UINT32(mgmt->m_iface)))
a8105c1b 171 goto toobig;
43c02e7b 172 }
a8105c1b 173 if (!(
e6b36c87
JV
174 /* We don't provide an OID for management */
175 POKE_UINT8(0) &&
176 POKE_END_LLDP_TLV))
a8105c1b 177 goto toobig;
43c02e7b
VB
178 }
179
180 /* Port description */
a8105c1b
VB
181 if (!(
182 POKE_START_LLDP_TLV(LLDP_TLV_PORT_DESCR) &&
183 POKE_BYTES(port->p_descr, strlen(port->p_descr)) &&
184 POKE_END_LLDP_TLV))
185 goto toobig;
43c02e7b 186
a1347cd8 187#ifdef ENABLE_DOT1
9757bfbc
SK
188 /* Port VLAN ID */
189 if(port->p_pvid != 0) {
190 if (!(
191 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
192 POKE_BYTES(dot1, sizeof(dot1)) &&
193 POKE_UINT8(LLDP_TLV_DOT1_PVID) &&
194 POKE_UINT16(port->p_pvid) &&
195 POKE_END_LLDP_TLV)) {
196 goto toobig;
197 }
198 }
199 /* Port and Protocol VLAN IDs */
200 TAILQ_FOREACH(ppvid, &port->p_ppvids, p_entries) {
201 if (!(
202 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
203 POKE_BYTES(dot1, sizeof(dot1)) &&
204 POKE_UINT8(LLDP_TLV_DOT1_PPVID) &&
205 POKE_UINT8(ppvid->p_cap_status) &&
206 POKE_UINT16(ppvid->p_ppvid) &&
207 POKE_END_LLDP_TLV)) {
208 goto toobig;
209 }
210 }
43c02e7b 211 /* VLANs */
a8105c1b
VB
212 TAILQ_FOREACH(vlan, &port->p_vlans, v_entries) {
213 if (!(
214 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
215 POKE_BYTES(dot1, sizeof(dot1)) &&
216 POKE_UINT8(LLDP_TLV_DOT1_VLANNAME) &&
217 POKE_UINT16(vlan->v_vid) &&
218 POKE_UINT8(strlen(vlan->v_name)) &&
219 POKE_BYTES(vlan->v_name, strlen(vlan->v_name)) &&
220 POKE_END_LLDP_TLV))
221 goto toobig;
43c02e7b 222 }
9757bfbc
SK
223 /* Protocol Identities */
224 TAILQ_FOREACH(pi, &port->p_pids, p_entries) {
225 if (!(
226 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
227 POKE_BYTES(dot1, sizeof(dot1)) &&
228 POKE_UINT8(LLDP_TLV_DOT1_PI) &&
48acfcaf
VB
229 POKE_UINT8(pi->p_pi_len) &&
230 POKE_BYTES(pi->p_pi, pi->p_pi_len) &&
9757bfbc
SK
231 POKE_END_LLDP_TLV))
232 goto toobig;
233 }
a1347cd8 234#endif
43c02e7b 235
a1347cd8 236#ifdef ENABLE_DOT3
43c02e7b 237 /* Aggregation status */
a8105c1b
VB
238 if (!(
239 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
240 POKE_BYTES(dot3, sizeof(dot3)) &&
241 POKE_UINT8(LLDP_TLV_DOT3_LA) &&
242 /* Bit 0 = capability ; Bit 1 = status */
243 POKE_UINT8((port->p_aggregid) ? 3:1) &&
244 POKE_UINT32(port->p_aggregid) &&
245 POKE_END_LLDP_TLV))
246 goto toobig;
43c02e7b
VB
247
248 /* MAC/PHY */
a8105c1b
VB
249 if (!(
250 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
251 POKE_BYTES(dot3, sizeof(dot3)) &&
252 POKE_UINT8(LLDP_TLV_DOT3_MAC) &&
3fd015c0
VB
253 POKE_UINT8(port->p_macphy.autoneg_support |
254 (port->p_macphy.autoneg_enabled << 1)) &&
255 POKE_UINT16(port->p_macphy.autoneg_advertised) &&
256 POKE_UINT16(port->p_macphy.mau_type) &&
a8105c1b
VB
257 POKE_END_LLDP_TLV))
258 goto toobig;
548109b2
VB
259
260 /* MFS */
683b1710
VB
261 if (port->p_mfs) {
262 if (!(
263 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
264 POKE_BYTES(dot3, sizeof(dot3)) &&
265 POKE_UINT8(LLDP_TLV_DOT3_MFS) &&
266 POKE_UINT16(port->p_mfs) &&
267 POKE_END_LLDP_TLV))
268 goto toobig;
269 }
42ee7382
VB
270 /* Power */
271 if (port->p_power.devicetype) {
272 if (!(
273 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
274 POKE_BYTES(dot3, sizeof(dot3)) &&
275 POKE_UINT8(LLDP_TLV_DOT3_POWER) &&
276 POKE_UINT8((
277 (((2 - port->p_power.devicetype) %(1<< 1))<<0) |
278 (( port->p_power.supported %(1<< 1))<<1) |
279 (( port->p_power.enabled %(1<< 1))<<2) |
280 (( port->p_power.paircontrol %(1<< 1))<<3))) &&
281 POKE_UINT8(port->p_power.pairs) &&
608cb51c
VB
282 POKE_UINT8(port->p_power.class)))
283 goto toobig;
284 /* 802.3at */
285 if (port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
286 if (!(
287 POKE_UINT8((
288 (((port->p_power.powertype ==
289 LLDP_DOT3_POWER_8023AT_TYPE1)?1:0) << 7) |
290 (((port->p_power.devicetype ==
291 LLDP_DOT3_POWER_PSE)?0:1) << 6) |
292 ((port->p_power.source %(1<< 2))<<4) |
293 ((port->p_power.priority %(1<< 2))<<0))) &&
294 POKE_UINT16(port->p_power.requested) &&
295 POKE_UINT16(port->p_power.allocated)))
296 goto toobig;
297 }
298 if (!(POKE_END_LLDP_TLV))
42ee7382
VB
299 goto toobig;
300 }
a1347cd8 301#endif
43c02e7b 302
89840df0 303#ifdef ENABLE_LLDPMED
740593ff 304 if (port->p_med_cap_enabled) {
89840df0 305 /* LLDP-MED cap */
a8105c1b
VB
306 if (!(
307 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
308 POKE_BYTES(med, sizeof(med)) &&
309 POKE_UINT8(LLDP_TLV_MED_CAP) &&
310 POKE_UINT16(chassis->c_med_cap_available) &&
bc08499a 311 POKE_UINT8(chassis->c_med_type) &&
a8105c1b
VB
312 POKE_END_LLDP_TLV))
313 goto toobig;
89840df0
VB
314
315 /* LLDP-MED inventory */
a8105c1b 316#define LLDP_INVENTORY(value, subtype) \
89840df0 317 if (value) { \
a8105c1b
VB
318 if (!( \
319 POKE_START_LLDP_TLV(LLDP_TLV_ORG) && \
320 POKE_BYTES(med, sizeof(med)) && \
321 POKE_UINT8(subtype) && \
322 POKE_BYTES(value, \
323 (strlen(value)>32)?32:strlen(value)) && \
324 POKE_END_LLDP_TLV)) \
325 goto toobig; \
89840df0 326 }
e809a587 327
4b292b55 328 if (port->p_med_cap_enabled & LLDP_MED_CAP_IV) {
a8105c1b
VB
329 LLDP_INVENTORY(chassis->c_med_hw,
330 LLDP_TLV_MED_IV_HW);
331 LLDP_INVENTORY(chassis->c_med_fw,
332 LLDP_TLV_MED_IV_FW);
333 LLDP_INVENTORY(chassis->c_med_sw,
334 LLDP_TLV_MED_IV_SW);
335 LLDP_INVENTORY(chassis->c_med_sn,
336 LLDP_TLV_MED_IV_SN);
337 LLDP_INVENTORY(chassis->c_med_manuf,
338 LLDP_TLV_MED_IV_MANUF);
339 LLDP_INVENTORY(chassis->c_med_model,
340 LLDP_TLV_MED_IV_MODEL);
341 LLDP_INVENTORY(chassis->c_med_asset,
342 LLDP_TLV_MED_IV_ASSET);
e809a587 343 }
115ff55c
VB
344
345 /* LLDP-MED location */
4b292b55 346 for (i = 0; i < LLDP_MED_LOCFORMAT_LAST; i++) {
740593ff 347 if (port->p_med_location[i].format == i + 1) {
a8105c1b
VB
348 if (!(
349 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
350 POKE_BYTES(med, sizeof(med)) &&
351 POKE_UINT8(LLDP_TLV_MED_LOCATION) &&
352 POKE_UINT8(port->p_med_location[i].format) &&
353 POKE_BYTES(port->p_med_location[i].data,
354 port->p_med_location[i].data_len) &&
355 POKE_END_LLDP_TLV))
356 goto toobig;
115ff55c
VB
357 }
358 }
86f24df3
VB
359
360 /* LLDP-MED network policy */
4b292b55 361 for (i = 0; i < LLDP_MED_APPTYPE_LAST; i++) {
86f24df3
VB
362 if (port->p_med_policy[i].type == i + 1) {
363 if (!(
364 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
365 POKE_BYTES(med, sizeof(med)) &&
366 POKE_UINT8(LLDP_TLV_MED_POLICY) &&
367 POKE_UINT32((
368 ((port->p_med_policy[i].type %(1<< 8))<<24) |
369 ((port->p_med_policy[i].unknown %(1<< 1))<<23) |
370 ((port->p_med_policy[i].tagged %(1<< 1))<<22) |
371 /*((0 %(1<< 1))<<21) |*/
372 ((port->p_med_policy[i].vid %(1<<12))<< 9) |
373 ((port->p_med_policy[i].priority %(1<< 3))<< 6) |
374 ((port->p_med_policy[i].dscp %(1<< 6))<< 0) )) &&
375 POKE_END_LLDP_TLV))
376 goto toobig;
377 }
378 }
009ddd23
VB
379
380 /* LLDP-MED POE-MDI */
4b292b55
VB
381 if ((port->p_med_power.devicetype == LLDP_MED_POW_TYPE_PSE) ||
382 (port->p_med_power.devicetype == LLDP_MED_POW_TYPE_PD)) {
009ddd23
VB
383 int devicetype = 0, source = 0;
384 if (!(
385 POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
386 POKE_BYTES(med, sizeof(med)) &&
387 POKE_UINT8(LLDP_TLV_MED_MDI)))
388 goto toobig;
389 switch (port->p_med_power.devicetype) {
4b292b55 390 case LLDP_MED_POW_TYPE_PSE:
009ddd23
VB
391 devicetype = 0;
392 switch (port->p_med_power.source) {
4b292b55
VB
393 case LLDP_MED_POW_SOURCE_PRIMARY: source = 1; break;
394 case LLDP_MED_POW_SOURCE_BACKUP: source = 2; break;
395 case LLDP_MED_POW_SOURCE_RESERVED: source = 3; break;
009ddd23
VB
396 default: source = 0; break;
397 }
398 break;
4b292b55 399 case LLDP_MED_POW_TYPE_PD:
009ddd23
VB
400 devicetype = 1;
401 switch (port->p_med_power.source) {
4b292b55
VB
402 case LLDP_MED_POW_SOURCE_PSE: source = 1; break;
403 case LLDP_MED_POW_SOURCE_LOCAL: source = 2; break;
404 case LLDP_MED_POW_SOURCE_BOTH: source = 3; break;
009ddd23
VB
405 default: source = 0; break;
406 }
407 break;
408 }
409 if (!(
410 POKE_UINT8((
411 ((devicetype %(1<< 2))<<6) |
412 ((source %(1<< 2))<<4) |
413 ((port->p_med_power.priority %(1<< 4))<<0) )) &&
414 POKE_UINT16(port->p_med_power.val) &&
415 POKE_END_LLDP_TLV))
416 goto toobig;
417 }
89840df0
VB
418 }
419#endif
420
43c02e7b 421 /* END */
a8105c1b
VB
422 if (!(
423 POKE_START_LLDP_TLV(LLDP_TLV_END) &&
424 POKE_END_LLDP_TLV))
425 goto toobig;
43c02e7b 426
6e75df87
VB
427 if (hardware->h_ops->send(global, hardware,
428 (char *)packet, pos - packet) == -1) {
f2dcb180
VB
429 LLOG_WARN("unable to send packet on real device for %s",
430 hardware->h_ifname);
431 free(packet);
432 return ENETDOWN;
43c02e7b
VB
433 }
434
f2dcb180
VB
435 hardware->h_tx_cnt++;
436
a8105c1b
VB
437 /* We assume that LLDP frame is the reference */
438 if ((frame = (struct lldpd_frame*)malloc(
439 sizeof(int) + pos - packet)) != NULL) {
440 frame->size = pos - packet;
441 memcpy(&frame->frame, packet, frame->size);
77507b69
VB
442 if ((hardware->h_lport.p_lastframe == NULL) ||
443 (hardware->h_lport.p_lastframe->size != frame->size) ||
444 (memcmp(hardware->h_lport.p_lastframe->frame, frame->frame,
a8105c1b 445 frame->size) != 0)) {
77507b69
VB
446 free(hardware->h_lport.p_lastframe);
447 hardware->h_lport.p_lastframe = frame;
448 hardware->h_lport.p_lastchange = time(NULL);
43c02e7b 449 } else
a8105c1b 450 free(frame);
43c02e7b
VB
451 }
452
a8105c1b 453 free(packet);
43c02e7b 454 return 0;
a8105c1b
VB
455
456toobig:
457 free(packet);
458 return E2BIG;
43c02e7b
VB
459}
460
a8105c1b
VB
461#define CHECK_TLV_SIZE(x, name) \
462 do { if (tlv_size < (x)) { \
463 LLOG_WARNX(name " TLV too short received on %s",\
464 hardware->h_ifname); \
465 goto malformed; \
466 } } while (0)
467
43c02e7b
VB
468int
469lldp_decode(struct lldpd *cfg, char *frame, int s,
470 struct lldpd_hardware *hardware,
471 struct lldpd_chassis **newchassis, struct lldpd_port **newport)
472{
473 struct lldpd_chassis *chassis;
474 struct lldpd_port *port;
43c02e7b
VB
475 const char lldpaddr[] = LLDP_MULTICAST_ADDR;
476 const char dot1[] = LLDP_TLV_ORG_DOT1;
477 const char dot3[] = LLDP_TLV_ORG_DOT3;
6772b237 478 const char med[] = LLDP_TLV_ORG_MED;
a8105c1b
VB
479 char orgid[3];
480 int length, gotend = 0;
481 int tlv_size, tlv_type, tlv_subtype;
482 u_int8_t *pos, *tlv;
43c02e7b 483 char *b;
a8105c1b 484#ifdef ENABLE_DOT1
75b3469d
VB
485 struct lldpd_vlan *vlan;
486 int vlan_len;
9757bfbc
SK
487 struct lldpd_ppvid *ppvid;
488 struct lldpd_pi *pi;
a8105c1b 489#endif
e6b36c87
JV
490 struct lldpd_mgmt *mgmt;
491 int af;
492 u_int8_t addr_str_length, addr_str_buffer[32];
493 u_int8_t addr_family, addr_length, *addr_ptr, iface_subtype;
494 u_int32_t iface_number, iface;
43c02e7b
VB
495
496 if ((chassis = calloc(1, sizeof(struct lldpd_chassis))) == NULL) {
497 LLOG_WARN("failed to allocate remote chassis");
498 return -1;
499 }
e6b36c87 500 TAILQ_INIT(&chassis->c_mgmt);
43c02e7b
VB
501 if ((port = calloc(1, sizeof(struct lldpd_port))) == NULL) {
502 LLOG_WARN("failed to allocate remote port");
503 free(chassis);
504 return -1;
505 }
a1347cd8 506#ifdef ENABLE_DOT1
43c02e7b 507 TAILQ_INIT(&port->p_vlans);
9757bfbc
SK
508 TAILQ_INIT(&port->p_ppvids);
509 TAILQ_INIT(&port->p_pids);
a1347cd8 510#endif
43c02e7b 511
a8105c1b
VB
512 length = s;
513 pos = (u_int8_t*)frame;
514
515 if (length < 2*ETH_ALEN + sizeof(u_int16_t)) {
43c02e7b
VB
516 LLOG_WARNX("too short frame received on %s", hardware->h_ifname);
517 goto malformed;
518 }
a8105c1b 519 if (PEEK_CMP(lldpaddr, ETH_ALEN) != 0) {
43c02e7b
VB
520 LLOG_INFO("frame not targeted at LLDP multicast address received on %s",
521 hardware->h_ifname);
522 goto malformed;
523 }
a8105c1b
VB
524 PEEK_DISCARD(ETH_ALEN); /* Skip source address */
525 if (PEEK_UINT16 != ETHERTYPE_LLDP) {
43c02e7b
VB
526 LLOG_INFO("non LLDP frame received on %s",
527 hardware->h_ifname);
528 goto malformed;
529 }
530
a8105c1b
VB
531 while (length && (!gotend)) {
532 if (length < 2) {
43c02e7b
VB
533 LLOG_WARNX("tlv header too short received on %s",
534 hardware->h_ifname);
535 goto malformed;
536 }
a8105c1b
VB
537 tlv_size = PEEK_UINT16;
538 tlv_type = tlv_size >> 9;
539 tlv_size = tlv_size & 0x1ff;
540 PEEK_SAVE(tlv);
541 if (length < tlv_size) {
542 LLOG_WARNX("frame too short for tlv received on %s",
43c02e7b
VB
543 hardware->h_ifname);
544 goto malformed;
545 }
a8105c1b 546 switch (tlv_type) {
43c02e7b 547 case LLDP_TLV_END:
a8105c1b 548 if (tlv_size != 0) {
43c02e7b
VB
549 LLOG_WARNX("lldp end received with size not null on %s",
550 hardware->h_ifname);
551 goto malformed;
552 }
a8105c1b 553 if (length)
43c02e7b
VB
554 LLOG_DEBUG("extra data after lldp end on %s",
555 hardware->h_ifname);
556 gotend = 1;
557 break;
558 case LLDP_TLV_CHASSIS_ID:
559 case LLDP_TLV_PORT_ID:
a8105c1b
VB
560 CHECK_TLV_SIZE(2, "Port Id");
561 tlv_subtype = PEEK_UINT8;
562 if ((tlv_subtype == 0) || (tlv_subtype > 7)) {
43c02e7b
VB
563 LLOG_WARNX("unknown subtype for tlv id received on %s",
564 hardware->h_ifname);
565 goto malformed;
566 }
a8105c1b 567 if ((b = (char *)calloc(1, tlv_size - 1)) == NULL) {
43c02e7b
VB
568 LLOG_WARN("unable to allocate memory for id tlv "
569 "received on %s",
570 hardware->h_ifname);
571 goto malformed;
572 }
a8105c1b
VB
573 PEEK_BYTES(b, tlv_size - 1);
574 if (tlv_type == LLDP_TLV_PORT_ID) {
575 port->p_id_subtype = tlv_subtype;
43c02e7b 576 port->p_id = b;
a8105c1b 577 port->p_id_len = tlv_size - 1;
43c02e7b 578 } else {
a8105c1b 579 chassis->c_id_subtype = tlv_subtype;
43c02e7b 580 chassis->c_id = b;
a8105c1b 581 chassis->c_id_len = tlv_size - 1;
43c02e7b 582 }
43c02e7b
VB
583 break;
584 case LLDP_TLV_TTL:
a8105c1b
VB
585 CHECK_TLV_SIZE(2, "TTL");
586 chassis->c_ttl = PEEK_UINT16;
43c02e7b
VB
587 break;
588 case LLDP_TLV_PORT_DESCR:
589 case LLDP_TLV_SYSTEM_NAME:
590 case LLDP_TLV_SYSTEM_DESCR:
a8105c1b 591 if (tlv_size < 1) {
a700e935 592 LLOG_DEBUG("empty tlv received on %s",
43c02e7b 593 hardware->h_ifname);
a700e935 594 break;
43c02e7b 595 }
a8105c1b 596 if ((b = (char *)calloc(1, tlv_size + 1)) == NULL) {
43c02e7b
VB
597 LLOG_WARN("unable to allocate memory for string tlv "
598 "received on %s",
599 hardware->h_ifname);
600 goto malformed;
601 }
a8105c1b
VB
602 PEEK_BYTES(b, tlv_size);
603 if (tlv_type == LLDP_TLV_PORT_DESCR)
43c02e7b 604 port->p_descr = b;
a8105c1b 605 else if (tlv_type == LLDP_TLV_SYSTEM_NAME)
43c02e7b
VB
606 chassis->c_name = b;
607 else chassis->c_descr = b;
608 break;
609 case LLDP_TLV_SYSTEM_CAP:
a8105c1b
VB
610 CHECK_TLV_SIZE(4, "System capabilities");
611 chassis->c_cap_available = PEEK_UINT16;
612 chassis->c_cap_enabled = PEEK_UINT16;
43c02e7b
VB
613 break;
614 case LLDP_TLV_MGMT_ADDR:
e6b36c87
JV
615 CHECK_TLV_SIZE(1, "Management address");
616 addr_str_length = PEEK_UINT8;
617 CHECK_TLV_SIZE(addr_str_length, "Management address");
618 PEEK_BYTES(addr_str_buffer, addr_str_length);
619 addr_length = addr_str_length - 1;
620 addr_family = addr_str_buffer[0];
621 addr_ptr = &addr_str_buffer[1];
622 CHECK_TLV_SIZE(5, "Management address");
623 iface_subtype = PEEK_UINT8;
624 iface_number = PEEK_UINT32;
625
626 af = lldpd_af_from_lldp_proto(addr_family);
627 if (af == LLDPD_AF_UNSPEC)
628 break;
629 if (iface_subtype == LLDP_MGMT_IFACE_IFINDEX)
630 iface = iface_number;
631 else
632 iface = 0;
633 mgmt = lldpd_alloc_mgmt(af, addr_ptr, addr_length, iface);
634 if (mgmt == NULL) {
635 assert(errno == ENOMEM);
636 LLOG_WARN("unable to allocate memory "
637 "for management address");
638 goto malformed;
43c02e7b 639 }
e6b36c87 640 TAILQ_INSERT_TAIL(&chassis->c_mgmt, mgmt, m_entries);
43c02e7b
VB
641 break;
642 case LLDP_TLV_ORG:
a8105c1b
VB
643 CHECK_TLV_SIZE(4, "Organisational");
644 PEEK_BYTES(orgid, sizeof(orgid));
645 tlv_subtype = PEEK_UINT8;
646 if (memcmp(dot1, orgid, sizeof(orgid)) == 0) {
a1347cd8 647#ifndef ENABLE_DOT1
a1347cd8
VB
648 hardware->h_rx_unrecognized_cnt++;
649#else
43c02e7b 650 /* Dot1 */
a8105c1b 651 switch (tlv_subtype) {
75b3469d 652 case LLDP_TLV_DOT1_VLANNAME:
a8105c1b 653 CHECK_TLV_SIZE(7, "VLAN");
43c02e7b
VB
654 if ((vlan = (struct lldpd_vlan *)calloc(1,
655 sizeof(struct lldpd_vlan))) == NULL) {
efe3f9b0
VB
656 LLOG_WARN("unable to alloc vlan "
657 "structure for "
43c02e7b
VB
658 "tlv received on %s",
659 hardware->h_ifname);
660 goto malformed;
661 }
a8105c1b
VB
662 vlan->v_vid = PEEK_UINT16;
663 vlan_len = PEEK_UINT8;
664 CHECK_TLV_SIZE(7 + vlan_len, "VLAN");
43c02e7b
VB
665 if ((vlan->v_name =
666 (char *)calloc(1, vlan_len + 1)) == NULL) {
667 LLOG_WARN("unable to alloc vlan name for "
668 "tlv received on %s",
669 hardware->h_ifname);
670 goto malformed;
671 }
a8105c1b 672 PEEK_BYTES(vlan->v_name, vlan_len);
43c02e7b
VB
673 TAILQ_INSERT_TAIL(&port->p_vlans,
674 vlan, v_entries);
75b3469d
VB
675 break;
676 case LLDP_TLV_DOT1_PVID:
a8105c1b
VB
677 CHECK_TLV_SIZE(6, "PVID");
678 port->p_pvid = PEEK_UINT16;
75b3469d 679 break;
9757bfbc
SK
680 case LLDP_TLV_DOT1_PPVID:
681 CHECK_TLV_SIZE(7, "PPVID");
682 /* validation needed */
683 /* PPVID has to be unique if more than
684 one PPVID TLVs are received -
685 discard if duplicate */
686 /* if support bit is not set and
687 enabled bit is set - PPVID TLV is
688 considered error and discarded */
689 /* if PPVID > 4096 - bad and discard */
690 if ((ppvid = (struct lldpd_ppvid *)calloc(1,
691 sizeof(struct lldpd_ppvid))) == NULL) {
692 LLOG_WARN("unable to alloc ppvid "
693 "structure for "
694 "tlv received on %s",
695 hardware->h_ifname);
696 goto malformed;
697 }
698 ppvid->p_cap_status = PEEK_UINT8;
699 ppvid->p_ppvid = PEEK_UINT16;
700 TAILQ_INSERT_TAIL(&port->p_ppvids,
701 ppvid, p_entries);
702 break;
703 case LLDP_TLV_DOT1_PI:
704 /* validation needed */
705 /* PI has to be unique if more than
706 one PI TLVs are received - discard
707 if duplicate ?? */
708 CHECK_TLV_SIZE(5, "PI");
709 if ((pi = (struct lldpd_pi *)calloc(1,
710 sizeof(struct lldpd_pi))) == NULL) {
711 LLOG_WARN("unable to alloc PI "
712 "structure for "
713 "tlv received on %s",
714 hardware->h_ifname);
715 goto malformed;
716 }
48acfcaf
VB
717 pi->p_pi_len = PEEK_UINT8;
718 CHECK_TLV_SIZE(1 + pi->p_pi_len, "PI");
9757bfbc 719 if ((pi->p_pi =
48acfcaf 720 (char *)calloc(1, pi->p_pi_len)) == NULL) {
9757bfbc
SK
721 LLOG_WARN("unable to alloc pid name for "
722 "tlv received on %s",
723 hardware->h_ifname);
724 goto malformed;
725 }
48acfcaf 726 PEEK_BYTES(pi->p_pi, pi->p_pi_len);
9757bfbc
SK
727 TAILQ_INSERT_TAIL(&port->p_pids,
728 pi, p_entries);
729 break;
75b3469d 730 default:
43c02e7b 731 /* Unknown Dot1 TLV, ignore it */
a1347cd8
VB
732 hardware->h_rx_unrecognized_cnt++;
733 }
734#endif
a8105c1b 735 } else if (memcmp(dot3, orgid, sizeof(orgid)) == 0) {
a1347cd8 736#ifndef ENABLE_DOT3
a1347cd8
VB
737 hardware->h_rx_unrecognized_cnt++;
738#else
43c02e7b 739 /* Dot3 */
a8105c1b 740 switch (tlv_subtype) {
43c02e7b 741 case LLDP_TLV_DOT3_MAC:
a8105c1b 742 CHECK_TLV_SIZE(9, "MAC/PHY");
3fd015c0
VB
743 port->p_macphy.autoneg_support = PEEK_UINT8;
744 port->p_macphy.autoneg_enabled =
0a36d97b 745 (port->p_macphy.autoneg_support & 0x2) >> 1;
3fd015c0 746 port->p_macphy.autoneg_support =
befbdf89 747 port->p_macphy.autoneg_support & 0x1;
3fd015c0 748 port->p_macphy.autoneg_advertised =
a8105c1b 749 PEEK_UINT16;
3fd015c0 750 port->p_macphy.mau_type = PEEK_UINT16;
43c02e7b
VB
751 break;
752 case LLDP_TLV_DOT3_LA:
a8105c1b 753 CHECK_TLV_SIZE(9, "Link aggregation");
a204514f 754 PEEK_DISCARD_UINT8;
a8105c1b 755 port->p_aggregid = PEEK_UINT32;
43c02e7b 756 break;
548109b2 757 case LLDP_TLV_DOT3_MFS:
a8105c1b
VB
758 CHECK_TLV_SIZE(6, "MFS");
759 port->p_mfs = PEEK_UINT16;
548109b2 760 break;
befbdf89
VB
761 case LLDP_TLV_DOT3_POWER:
762 CHECK_TLV_SIZE(7, "Power");
763 port->p_power.devicetype = PEEK_UINT8;
764 port->p_power.supported =
0a36d97b 765 (port->p_power.devicetype & 0x2) >> 1;
befbdf89 766 port->p_power.enabled =
0a36d97b 767 (port->p_power.devicetype & 0x4) >> 2;
befbdf89 768 port->p_power.paircontrol =
181351d6 769 (port->p_power.devicetype & 0x8) >> 3;
befbdf89
VB
770 port->p_power.devicetype =
771 (port->p_power.devicetype & 0x1)?
772 LLDP_DOT3_POWER_PSE:LLDP_DOT3_POWER_PD;
773 port->p_power.pairs = PEEK_UINT8;
774 port->p_power.class = PEEK_UINT8;
608cb51c
VB
775 /* 802.3at? */
776 if (tlv_size >= 12) {
777 port->p_power.powertype = PEEK_UINT8;
778 port->p_power.source =
779 (port->p_power.powertype & (1<<5 | 1<<4)) >> 4;
780 port->p_power.priority =
781 (port->p_power.powertype & (1<<1 | 1<<0));
782 port->p_power.powertype =
783 (port->p_power.powertype & (1<<7))?
784 LLDP_DOT3_POWER_8023AT_TYPE1:
785 LLDP_DOT3_POWER_8023AT_TYPE2;
786 port->p_power.requested = PEEK_UINT16;
787 port->p_power.allocated = PEEK_UINT16;
788 } else
789 port->p_power.powertype =
790 LLDP_DOT3_POWER_8023AT_OFF;
befbdf89 791 break;
43c02e7b
VB
792 default:
793 /* Unknown Dot3 TLV, ignore it */
37387046 794 hardware->h_rx_unrecognized_cnt++;
43c02e7b 795 }
a1347cd8 796#endif
a8105c1b 797 } else if (memcmp(med, orgid, sizeof(orgid)) == 0) {
6772b237
VB
798 /* LLDP-MED */
799#ifndef ENABLE_LLDPMED
6772b237
VB
800 hardware->h_rx_unrecognized_cnt++;
801#else
e3a44efb
VB
802 u_int32_t policy;
803 int loctype;
a8105c1b 804 int power;
e3a44efb 805
a8105c1b 806 switch (tlv_subtype) {
6772b237 807 case LLDP_TLV_MED_CAP:
a8105c1b
VB
808 CHECK_TLV_SIZE(7, "LLDP-MED capabilities");
809 chassis->c_med_cap_available = PEEK_UINT16;
810 chassis->c_med_type = PEEK_UINT8;
740593ff 811 port->p_med_cap_enabled |=
4b292b55 812 LLDP_MED_CAP_CAP;
6772b237 813 break;
efe3f9b0 814 case LLDP_TLV_MED_POLICY:
a8105c1b
VB
815 CHECK_TLV_SIZE(8, "LLDP-MED policy");
816 policy = PEEK_UINT32;
e3a44efb 817 if (((policy >> 24) < 1) ||
4b292b55 818 ((policy >> 24) > LLDP_MED_APPTYPE_LAST)) {
e3a44efb
VB
819 LLOG_INFO("unknown policy field %d "
820 "received on %s",
e51da5ec 821 policy,
e3a44efb 822 hardware->h_ifname);
e3a44efb
VB
823 break;
824 }
740593ff 825 port->p_med_policy[(policy >> 24) - 1].type =
e3a44efb 826 (policy >> 24);
740593ff 827 port->p_med_policy[(policy >> 24) - 1].unknown =
e3a44efb 828 ((policy & 0x800000) != 0);
740593ff 829 port->p_med_policy[(policy >> 24) - 1].tagged =
e3a44efb 830 ((policy & 0x400000) != 0);
740593ff 831 port->p_med_policy[(policy >> 24) - 1].vid =
e3a44efb 832 (policy & 0x001FFE00) >> 9;
740593ff 833 port->p_med_policy[(policy >> 24) - 1].priority =
e3a44efb 834 (policy & 0x1C0) >> 6;
740593ff 835 port->p_med_policy[(policy >> 24) - 1].dscp =
e3a44efb 836 policy & 0x3F;
740593ff 837 port->p_med_cap_enabled |=
4b292b55 838 LLDP_MED_CAP_POLICY;
efe3f9b0
VB
839 break;
840 case LLDP_TLV_MED_LOCATION:
a8105c1b
VB
841 CHECK_TLV_SIZE(5, "LLDP-MED Location");
842 loctype = PEEK_UINT8;
843 if ((loctype < 1) ||
4b292b55 844 (loctype > LLDP_MED_LOCFORMAT_LAST)) {
e3a44efb
VB
845 LLOG_INFO("unknown location type "
846 "received on %s",
847 hardware->h_ifname);
e3a44efb
VB
848 break;
849 }
740593ff 850 if ((port->p_med_location[loctype - 1].data =
a8105c1b 851 (char*)malloc(tlv_size - 5)) == NULL) {
efe3f9b0
VB
852 LLOG_WARN("unable to allocate memory "
853 "for LLDP-MED location for "
854 "frame received on %s",
855 hardware->h_ifname);
856 goto malformed;
857 }
a8105c1b
VB
858 PEEK_BYTES(port->p_med_location[loctype - 1].data,
859 tlv_size - 5);
740593ff 860 port->p_med_location[loctype - 1].data_len =
a8105c1b 861 tlv_size - 5;
740593ff 862 port->p_med_location[loctype - 1].format = loctype;
740593ff 863 port->p_med_cap_enabled |=
4b292b55 864 LLDP_MED_CAP_LOCATION;
efe3f9b0
VB
865 break;
866 case LLDP_TLV_MED_MDI:
a8105c1b
VB
867 CHECK_TLV_SIZE(7, "LLDP-MED PoE-MDI");
868 power = PEEK_UINT8;
869 switch (power & 0xC0) {
994812b9 870 case 0x0:
4b292b55 871 port->p_med_power.devicetype = LLDP_MED_POW_TYPE_PSE;
740593ff 872 port->p_med_cap_enabled |=
4b292b55 873 LLDP_MED_CAP_MDI_PSE;
a8105c1b 874 switch (power & 0x30) {
994812b9 875 case 0x0:
6d08df0e 876 port->p_med_power.source =
4b292b55 877 LLDP_MED_POW_SOURCE_UNKNOWN;
994812b9
VB
878 break;
879 case 0x10:
6d08df0e 880 port->p_med_power.source =
4b292b55 881 LLDP_MED_POW_SOURCE_PRIMARY;
994812b9
VB
882 break;
883 case 0x20:
6d08df0e 884 port->p_med_power.source =
4b292b55 885 LLDP_MED_POW_SOURCE_BACKUP;
994812b9
VB
886 break;
887 default:
6d08df0e 888 port->p_med_power.source =
4b292b55 889 LLDP_MED_POW_SOURCE_RESERVED;
994812b9
VB
890 }
891 break;
892 case 0x40:
4b292b55 893 port->p_med_power.devicetype = LLDP_MED_POW_TYPE_PD;
740593ff 894 port->p_med_cap_enabled |=
4b292b55 895 LLDP_MED_CAP_MDI_PD;
a8105c1b 896 switch (power & 0x30) {
994812b9 897 case 0x0:
6d08df0e 898 port->p_med_power.source =
4b292b55 899 LLDP_MED_POW_SOURCE_UNKNOWN;
994812b9
VB
900 break;
901 case 0x10:
6d08df0e 902 port->p_med_power.source =
4b292b55 903 LLDP_MED_POW_SOURCE_PSE;
994812b9
VB
904 break;
905 case 0x20:
6d08df0e 906 port->p_med_power.source =
4b292b55 907 LLDP_MED_POW_SOURCE_LOCAL;
994812b9
VB
908 break;
909 default:
6d08df0e 910 port->p_med_power.source =
4b292b55 911 LLDP_MED_POW_SOURCE_BOTH;
994812b9
VB
912 }
913 break;
914 default:
6d08df0e 915 port->p_med_power.devicetype =
4b292b55 916 LLDP_MED_POW_TYPE_RESERVED;
994812b9 917 }
009ddd23 918 if (((power & 0x0F) < 0) ||
4b292b55 919 ((power & 0x0F) > LLDP_MED_POW_PRIO_LOW))
6d08df0e 920 port->p_med_power.priority =
4b292b55 921 LLDP_MED_POW_PRIO_UNKNOWN;
009ddd23 922 else
6d08df0e 923 port->p_med_power.priority =
009ddd23 924 power & 0x0F;
6d08df0e 925 port->p_med_power.val = PEEK_UINT16;
efe3f9b0 926 break;
6772b237
VB
927 case LLDP_TLV_MED_IV_HW:
928 case LLDP_TLV_MED_IV_SW:
929 case LLDP_TLV_MED_IV_FW:
930 case LLDP_TLV_MED_IV_SN:
931 case LLDP_TLV_MED_IV_MANUF:
932 case LLDP_TLV_MED_IV_MODEL:
933 case LLDP_TLV_MED_IV_ASSET:
a8105c1b 934 if (tlv_size <= 4)
6772b237
VB
935 b = NULL;
936 else {
a8105c1b 937 if ((b = (char*)malloc(tlv_size - 3)) ==
efe3f9b0
VB
938 NULL) {
939 LLOG_WARN("unable to allocate "
940 "memory for LLDP-MED "
941 "inventory for frame "
942 "received on %s",
943 hardware->h_ifname);
944 goto malformed;
945 }
a8105c1b
VB
946 PEEK_BYTES(b, tlv_size - 4);
947 b[tlv_size - 4] = '\0';
6772b237 948 }
a8105c1b 949 switch (tlv_subtype) {
6772b237
VB
950 case LLDP_TLV_MED_IV_HW:
951 chassis->c_med_hw = b;
952 break;
953 case LLDP_TLV_MED_IV_FW:
954 chassis->c_med_fw = b;
955 break;
956 case LLDP_TLV_MED_IV_SW:
957 chassis->c_med_sw = b;
958 break;
959 case LLDP_TLV_MED_IV_SN:
960 chassis->c_med_sn = b;
961 break;
962 case LLDP_TLV_MED_IV_MANUF:
963 chassis->c_med_manuf = b;
964 break;
965 case LLDP_TLV_MED_IV_MODEL:
397dee69 966 chassis->c_med_model = b;
6772b237
VB
967 break;
968 case LLDP_TLV_MED_IV_ASSET:
72c4c96f 969 chassis->c_med_asset = b;
6772b237
VB
970 break;
971 default:
972 LLOG_WARNX("should not be there!");
973 free(b);
974 break;
975 }
740593ff 976 port->p_med_cap_enabled |=
4b292b55 977 LLDP_MED_CAP_IV;
6772b237
VB
978 break;
979 default:
980 /* Unknown LLDP MED, ignore it */
6772b237
VB
981 hardware->h_rx_unrecognized_cnt++;
982 }
983#endif /* ENABLE_LLDPMED */
43c02e7b 984 } else {
9ca19b69 985 LLOG_INFO("unknown org tlv received on %s",
43c02e7b 986 hardware->h_ifname);
37387046 987 hardware->h_rx_unrecognized_cnt++;
43c02e7b
VB
988 }
989 break;
990 default:
991 LLOG_WARNX("unknown tlv (%d) received on %s",
a8105c1b
VB
992 tlv_type, hardware->h_ifname);
993 goto malformed;
994 }
995 if (pos > tlv + tlv_size) {
996 LLOG_WARNX("BUG: already past TLV!");
43c02e7b
VB
997 goto malformed;
998 }
a8105c1b 999 PEEK_DISCARD(tlv + tlv_size - pos);
43c02e7b
VB
1000 }
1001
1002 /* Some random check */
1003 if ((chassis->c_id == NULL) ||
1004 (port->p_id == NULL) ||
1005 (chassis->c_ttl == 0) ||
1006 (gotend == 0)) {
1007 LLOG_WARNX("some mandatory tlv are missing for frame received on %s",
1008 hardware->h_ifname);
1009 goto malformed;
1010 }
1011#define NOTRECEIVED "Not received"
1012 if (chassis->c_name == NULL) {
1013 if ((chassis->c_name = (char *)calloc(1, strlen(NOTRECEIVED) + 1)) == NULL) {
1014 LLOG_WARNX("unable to allocate null chassis name");
1015 goto malformed;
1016 }
1017 memcpy(chassis->c_name, NOTRECEIVED, strlen(NOTRECEIVED));
1018 }
1019 if (chassis->c_descr == NULL) {
1020 if ((chassis->c_descr = (char *)calloc(1, strlen(NOTRECEIVED) + 1)) == NULL) {
1021 LLOG_WARNX("unable to allocate null chassis description");
1022 goto malformed;
1023 }
1024 memcpy(chassis->c_descr, NOTRECEIVED, strlen(NOTRECEIVED));
1025 }
1026 if (port->p_descr == NULL) {
1027 if ((port->p_descr = (char *)calloc(1, strlen(NOTRECEIVED) + 1)) == NULL) {
1028 LLOG_WARNX("unable to allocate null port description");
1029 goto malformed;
1030 }
1031 memcpy(port->p_descr, NOTRECEIVED, strlen(NOTRECEIVED));
1032 }
1033 *newchassis = chassis;
1034 *newport = port;
1035 return 1;
1036malformed:
77507b69 1037 lldpd_chassis_cleanup(chassis, 1);
4b292b55 1038 lldpd_port_cleanup(port, 1);
4e624dc2 1039 free(port);
43c02e7b
VB
1040 return -1;
1041}