1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
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.
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.
31 #include <sys/param.h>
32 #include <sys/utsname.h>
33 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/select.h>
38 #include <sys/ioctl.h>
39 #include <arpa/inet.h>
40 #include <netinet/if_ether.h>
51 static void usage(void);
53 static struct protocol protos
[] = {
54 { LLDPD_MODE_LLDP
, 1, "LLDP", 'l', lldp_send
, lldp_decode
, NULL
,
55 { LLDP_ADDR_NEAREST_BRIDGE
, LLDP_ADDR_NEAREST_NONTPMR_BRIDGE
,
56 LLDP_ADDR_NEAREST_CUSTOMER_BRIDGE
} },
58 { LLDPD_MODE_CDPV1
, 0, "CDPv1", 'c', cdpv1_send
, cdp_decode
, cdpv1_guess
,
59 { CDP_MULTICAST_ADDR
} },
60 { LLDPD_MODE_CDPV2
, 0, "CDPv2", 'c', cdpv2_send
, cdp_decode
, cdpv2_guess
,
61 { CDP_MULTICAST_ADDR
} },
64 { LLDPD_MODE_SONMP
, 0, "SONMP", 's', sonmp_send
, sonmp_decode
, NULL
,
65 { SONMP_MULTICAST_ADDR
} },
68 { LLDPD_MODE_EDP
, 0, "EDP", 'e', edp_send
, edp_decode
, NULL
,
69 { EDP_MULTICAST_ADDR
} },
72 { LLDPD_MODE_FDP
, 0, "FDP", 'f', fdp_send
, cdp_decode
, NULL
,
73 { FDP_MULTICAST_ADDR
} },
75 { 0, 0, "any", ' ', NULL
, NULL
, NULL
, { { 0, 0, 0, 0, 0, 0 } } }
78 static char **saved_argv
;
79 #ifdef HAVE___PROGNAME
80 extern const char *__progname
;
82 # define __progname "lldpd"
88 fprintf(stderr
, "Usage: %s [OPTIONS ...]\n", __progname
);
89 fprintf(stderr
, "Version: %s\n", PACKAGE_STRING
);
91 fprintf(stderr
, "\n");
93 fprintf(stderr
, "-d Do not daemonize.\n");
94 fprintf(stderr
, "-r Receive-only mode\n");
95 fprintf(stderr
, "-i Disable LLDP-MED inventory TLV transmission.\n");
97 "-k Disable advertising of kernel release, version, machine.\n");
98 fprintf(stderr
, "-S descr Override the default system description.\n");
99 fprintf(stderr
, "-P name Override the default hardware platform.\n");
101 "-m IP Specify the IP management addresses of this system.\n");
103 "-u file Specify the Unix-domain socket used for communication with lldpctl(8).\n");
105 "-H mode Specify the behaviour when detecting multiple neighbors.\n");
106 fprintf(stderr
, "-I iface Limit interfaces to use.\n");
107 fprintf(stderr
, "-C iface Limit interfaces to use for computing chassis ID.\n");
108 fprintf(stderr
, "-L path Override path for lldpcli command.\n");
110 "-O file Override default configuration locations processed by lldpcli(8) at start.\n");
111 #ifdef ENABLE_LLDPMED
113 "-M class Enable emission of LLDP-MED frames. 'class' should be one of:\n");
114 fprintf(stderr
, " 1 Generic Endpoint (Class I)\n");
115 fprintf(stderr
, " 2 Media Endpoint (Class II)\n");
116 fprintf(stderr
, " 3 Communication Device Endpoints (Class III)\n");
117 fprintf(stderr
, " 4 Network Connectivity Device\n");
120 fprintf(stderr
, "-x Enable SNMP subagent.\n");
121 fprintf(stderr
, "-X sock Specify the SNMP subagent socket.\n");
123 fprintf(stderr
, "\n");
125 #if defined ENABLE_CDP || defined ENABLE_EDP || defined ENABLE_FDP || \
127 fprintf(stderr
, "Additional protocol support.\n");
129 fprintf(stderr
, "-c Enable the support of CDP protocol. (Cisco)\n");
132 fprintf(stderr
, "-e Enable the support of EDP protocol. (Extreme)\n");
135 fprintf(stderr
, "-f Enable the support of FDP protocol. (Foundry)\n");
138 fprintf(stderr
, "-s Enable the support of SONMP protocol. (Nortel)\n");
141 fprintf(stderr
, "\n");
144 fprintf(stderr
, "See manual page lldpd(8) for more information\n");
148 struct lldpd_hardware
*
149 lldpd_get_hardware(struct lldpd
*cfg
, char *name
, int index
)
151 struct lldpd_hardware
*hardware
;
152 TAILQ_FOREACH (hardware
, &cfg
->g_hardware
, h_entries
) {
153 if (strcmp(hardware
->h_ifname
, name
) == 0) {
154 if (hardware
->h_flags
== 0) {
155 if (hardware
->h_ifindex
!= 0 &&
156 hardware
->h_ifindex
!= index
) {
157 log_debug("interfaces",
158 "%s changed index: from %d to %d",
159 hardware
->h_ifname
, hardware
->h_ifindex
,
161 hardware
->h_ifindex_changed
= 1;
163 hardware
->h_ifindex
= index
;
166 if (hardware
->h_ifindex
== index
) break;
173 * Allocate the default local port. This port will be cloned each time we need a
177 lldpd_alloc_default_local_port(struct lldpd
*cfg
)
179 struct lldpd_port
*port
;
181 if ((port
= (struct lldpd_port
*)calloc(1, sizeof(struct lldpd_port
))) == NULL
)
185 TAILQ_INIT(&port
->p_vlans
);
186 TAILQ_INIT(&port
->p_ppvids
);
187 TAILQ_INIT(&port
->p_pids
);
190 TAILQ_INIT(&port
->p_custom_list
);
192 cfg
->g_default_local_port
= port
;
196 * Clone a given port. The destination needs to be already allocated.
199 lldpd_clone_port(struct lldpd_port
*destination
, struct lldpd_port
*source
)
202 u_int8_t
*output
= NULL
;
204 struct lldpd_port
*cloned
= NULL
;
205 output_len
= lldpd_port_serialize(source
, (void **)&output
);
206 if (output_len
== -1 ||
207 lldpd_port_unserialize(output
, output_len
, &cloned
) <= 0) {
208 log_warnx("alloc", "unable to clone default port");
212 memcpy(destination
, cloned
, sizeof(struct lldpd_port
));
216 marshal_repair_tailq(lldpd_vlan
, &destination
->p_vlans
, v_entries
);
217 marshal_repair_tailq(lldpd_ppvid
, &destination
->p_ppvids
, p_entries
);
218 marshal_repair_tailq(lldpd_pi
, &destination
->p_pids
, p_entries
);
221 marshal_repair_tailq(lldpd_custom
, &destination
->p_custom_list
, next
);
226 struct lldpd_hardware
*
227 lldpd_alloc_hardware(struct lldpd
*cfg
, char *name
, int index
)
229 struct lldpd_hardware
*hardware
;
231 log_debug("alloc", "allocate a new local port (%s)", name
);
233 if ((hardware
= (struct lldpd_hardware
*)calloc(1,
234 sizeof(struct lldpd_hardware
))) == NULL
)
237 /* Clone default local port */
238 if (lldpd_clone_port(&hardware
->h_lport
, cfg
->g_default_local_port
) == -1) {
239 log_warnx("alloc", "unable to clone default port");
244 hardware
->h_cfg
= cfg
;
245 strlcpy(hardware
->h_ifname
, name
, sizeof(hardware
->h_ifname
));
246 hardware
->h_ifindex
= index
;
247 hardware
->h_lport
.p_chassis
= LOCAL_CHASSIS(cfg
);
248 hardware
->h_lport
.p_chassis
->c_refcount
++;
249 TAILQ_INIT(&hardware
->h_rports
);
251 #ifdef ENABLE_LLDPMED
252 if (LOCAL_CHASSIS(cfg
)->c_med_cap_available
) {
253 hardware
->h_lport
.p_med_cap_enabled
= LLDP_MED_CAP_CAP
;
254 if (!cfg
->g_config
.c_noinventory
)
255 hardware
->h_lport
.p_med_cap_enabled
|= LLDP_MED_CAP_IV
;
259 levent_hardware_init(hardware
);
264 lldpd_alloc_mgmt(int family
, void *addrptr
, size_t addrsize
, u_int32_t iface
)
266 struct lldpd_mgmt
*mgmt
;
268 log_debug("alloc", "allocate a new management address (family: %d)", family
);
270 if (family
<= LLDPD_AF_UNSPEC
|| family
>= LLDPD_AF_LAST
) {
271 errno
= EAFNOSUPPORT
;
274 if (addrsize
> LLDPD_MGMT_MAXADDRSIZE
) {
278 mgmt
= calloc(1, sizeof(struct lldpd_mgmt
));
283 mgmt
->m_family
= family
;
284 memcpy(&mgmt
->m_addr
, addrptr
, addrsize
);
285 mgmt
->m_addrsize
= addrsize
;
286 mgmt
->m_iface
= iface
;
291 lldpd_hardware_cleanup(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
)
293 log_debug("alloc", "cleanup hardware port %s", hardware
->h_ifname
);
295 free(hardware
->h_lport_previous
);
296 free(hardware
->h_lchassis_previous_id
);
297 free(hardware
->h_lport_previous_id
);
298 free(hardware
->h_ifdescr_previous
);
299 lldpd_port_cleanup(&hardware
->h_lport
, 1);
300 if (hardware
->h_ops
&& hardware
->h_ops
->cleanup
)
301 hardware
->h_ops
->cleanup(cfg
, hardware
);
302 levent_hardware_release(hardware
);
307 lldpd_ifdescr_neighbors(struct lldpd
*cfg
)
309 if (!cfg
->g_config
.c_set_ifdescr
) return;
310 struct lldpd_hardware
*hardware
;
311 TAILQ_FOREACH (hardware
, &cfg
->g_hardware
, h_entries
) {
312 struct lldpd_port
*port
;
314 const char *neighbor
= NULL
;
315 unsigned neighbors
= 0;
316 TAILQ_FOREACH (port
, &hardware
->h_rports
, p_entries
) {
317 if (SMART_HIDDEN(port
)) continue;
319 neighbor
= port
->p_chassis
->c_name
;
322 description
= strdup("");
323 else if (neighbors
== 1 && neighbor
&& *neighbor
!= '\0') {
324 if (asprintf(&description
, "%s", neighbor
) == -1) {
328 if (asprintf(&description
, "%d neighbor%s", neighbors
,
329 (neighbors
> 1) ? "s" : "") == -1) {
333 if (hardware
->h_ifdescr_previous
== NULL
||
334 strcmp(hardware
->h_ifdescr_previous
, description
)) {
335 priv_iface_description(hardware
->h_ifname
, description
);
336 free(hardware
->h_ifdescr_previous
);
337 hardware
->h_ifdescr_previous
= description
;
344 lldpd_count_neighbors(struct lldpd
*cfg
)
346 #if HAVE_SETPROCTITLE
347 struct lldpd_chassis
*chassis
;
348 const char *neighbor
;
349 unsigned neighbors
= 0;
350 TAILQ_FOREACH (chassis
, &cfg
->g_chassis
, c_entries
) {
352 neighbor
= chassis
->c_name
;
356 setproctitle("no neighbor.");
357 else if (neighbors
== 1 && neighbor
&& *neighbor
!= '\0')
358 setproctitle("connected to %s.", neighbor
);
360 setproctitle("%d neighbor%s.", neighbors
, (neighbors
> 1) ? "s" : "");
362 lldpd_ifdescr_neighbors(cfg
);
366 notify_clients_deletion(struct lldpd_hardware
*hardware
, struct lldpd_port
*rport
)
368 TRACE(LLDPD_NEIGHBOR_DELETE(hardware
->h_ifname
, rport
->p_chassis
->c_name
,
370 levent_ctl_notify(hardware
->h_ifname
, NEIGHBOR_CHANGE_DELETED
, rport
);
372 agent_notify(hardware
, NEIGHBOR_CHANGE_DELETED
, rport
);
377 lldpd_reset_timer(struct lldpd
*cfg
)
379 /* Reset timer for ports that have been changed. */
380 struct lldpd_hardware
*hardware
;
381 TAILQ_FOREACH (hardware
, &cfg
->g_hardware
, h_entries
) {
382 /* We keep a flat copy of the local port to see if there is any
383 * change. To do this, we zero out fields that are not
384 * significant, marshal the port, then restore. */
385 struct lldpd_port
*port
= &hardware
->h_lport
;
386 /* Take the current flags into account to detect a change. */
387 port
->_p_hardware_flags
= hardware
->h_flags
;
388 u_int8_t
*output
= NULL
;
390 char save
[LLDPD_PORT_START_MARKER
];
391 memcpy(save
, port
, sizeof(save
));
392 /* coverity[sizeof_mismatch]
393 We intentionally partially memset port */
394 memset(port
, 0, sizeof(save
));
395 output_len
= lldpd_port_serialize(port
, (void **)&output
);
396 memcpy(port
, save
, sizeof(save
));
397 if (output_len
== -1) {
398 log_warnx("localchassis",
399 "unable to serialize local port %s to check for differences",
404 /* Compare with the previous value */
405 if (!hardware
->h_ifindex_changed
&& hardware
->h_lport_previous
&&
406 output_len
== hardware
->h_lport_previous_len
&&
407 !memcmp(output
, hardware
->h_lport_previous
, output_len
)) {
408 log_debug("localchassis", "no change detected for port %s",
411 log_debug("localchassis",
412 "change detected for port %s, resetting its timer",
414 hardware
->h_ifindex_changed
= 0;
415 levent_schedule_pdu(hardware
);
418 /* Update the value */
419 free(hardware
->h_lport_previous
);
420 hardware
->h_lport_previous
= output
;
421 hardware
->h_lport_previous_len
= output_len
;
426 lldpd_all_chassis_cleanup(struct lldpd
*cfg
)
428 struct lldpd_chassis
*chassis
, *chassis_next
;
429 log_debug("localchassis", "cleanup all chassis");
431 for (chassis
= TAILQ_FIRST(&cfg
->g_chassis
); chassis
; chassis
= chassis_next
) {
432 chassis_next
= TAILQ_NEXT(chassis
, c_entries
);
433 if (chassis
->c_refcount
== 0) {
434 TAILQ_REMOVE(&cfg
->g_chassis
, chassis
, c_entries
);
435 lldpd_chassis_cleanup(chassis
, 1);
441 lldpd_cleanup(struct lldpd
*cfg
)
443 struct lldpd_hardware
*hardware
, *hardware_next
;
445 log_debug("localchassis", "cleanup all ports");
447 for (hardware
= TAILQ_FIRST(&cfg
->g_hardware
); hardware
!= NULL
;
448 hardware
= hardware_next
) {
449 hardware_next
= TAILQ_NEXT(hardware
, h_entries
);
450 if (!hardware
->h_flags
) {
451 int m
= cfg
->g_config
.c_perm_ifaces
?
452 pattern_match(hardware
->h_ifname
,
453 cfg
->g_config
.c_perm_ifaces
, 0) :
456 case PATTERN_MATCH_DENIED
:
457 log_debug("localchassis",
458 "delete non-permanent interface %s",
460 TRACE(LLDPD_INTERFACES_DELETE(hardware
->h_ifname
));
461 TAILQ_REMOVE(&cfg
->g_hardware
, hardware
, h_entries
);
462 lldpd_remote_cleanup(hardware
, notify_clients_deletion
,
464 lldpd_hardware_cleanup(cfg
, hardware
);
466 case PATTERN_MATCH_ALLOWED
:
467 case PATTERN_MATCH_ALLOWED_EXACT
:
468 log_debug("localchassis", "do not delete %s, permanent",
470 lldpd_remote_cleanup(hardware
, notify_clients_deletion
,
475 lldpd_remote_cleanup(hardware
, notify_clients_deletion
,
476 !(hardware
->h_flags
& IFF_RUNNING
));
480 levent_schedule_cleanup(cfg
);
481 lldpd_all_chassis_cleanup(cfg
);
482 lldpd_count_neighbors(cfg
);
485 /* Update chassis `ochassis' with values from `chassis'. The later one is not
486 expected to be part of a list! It will also be wiped from memory. */
488 lldpd_move_chassis(struct lldpd_chassis
*ochassis
, struct lldpd_chassis
*chassis
)
490 struct lldpd_mgmt
*mgmt
, *mgmt_next
;
492 /* We want to keep refcount, index and list stuff from the current
494 TAILQ_ENTRY(lldpd_chassis
) entries
;
495 int refcount
= ochassis
->c_refcount
;
496 int index
= ochassis
->c_index
;
497 memcpy(&entries
, &ochassis
->c_entries
, sizeof(entries
));
498 lldpd_chassis_cleanup(ochassis
, 0);
501 /* WARNING: this is a kludgy hack, we need in-place copy and cannot use
503 memcpy(ochassis
, chassis
, sizeof(struct lldpd_chassis
));
504 TAILQ_INIT(&ochassis
->c_mgmt
);
506 /* Copy of management addresses */
507 for (mgmt
= TAILQ_FIRST(&chassis
->c_mgmt
); mgmt
!= NULL
; mgmt
= mgmt_next
) {
508 mgmt_next
= TAILQ_NEXT(mgmt
, m_entries
);
509 TAILQ_REMOVE(&chassis
->c_mgmt
, mgmt
, m_entries
);
510 TAILQ_INSERT_TAIL(&ochassis
->c_mgmt
, mgmt
, m_entries
);
513 /* Restore saved values */
514 ochassis
->c_refcount
= refcount
;
515 ochassis
->c_index
= index
;
516 memcpy(&ochassis
->c_entries
, &entries
, sizeof(entries
));
518 /* Get rid of the new chassis */
523 lldpd_guess_type(struct lldpd
*cfg
, char *frame
, int s
)
526 if (s
< ETHER_ADDR_LEN
) return -1;
527 for (i
= 0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
528 if (!cfg
->g_protocols
[i
].enabled
) continue;
529 if (cfg
->g_protocols
[i
].guess
== NULL
) {
530 for (j
= 0; j
< sizeof(cfg
->g_protocols
[0].mac
) /
531 sizeof(cfg
->g_protocols
[0].mac
[0]);
533 if (memcmp(frame
, cfg
->g_protocols
[i
].mac
[j
],
534 ETHER_ADDR_LEN
) == 0) {
536 "guessed protocol is %s (from MAC address)",
537 cfg
->g_protocols
[i
].name
);
538 return cfg
->g_protocols
[i
].mode
;
542 if (cfg
->g_protocols
[i
].guess(frame
, s
)) {
544 "guessed protocol is %s (from detector function)",
545 cfg
->g_protocols
[i
].name
);
546 return cfg
->g_protocols
[i
].mode
;
554 lldpd_decode(struct lldpd
*cfg
, char *frame
, int s
, struct lldpd_hardware
*hardware
)
557 struct lldpd_chassis
*chassis
, *ochassis
= NULL
;
558 struct lldpd_port
*port
, *oport
= NULL
, *aport
;
559 int guess
= LLDPD_MODE_LLDP
;
561 log_debug("decode", "decode a received frame on %s", hardware
->h_ifname
);
563 if (s
< sizeof(struct ether_header
) + 4) {
564 /* Too short, just discard it */
565 hardware
->h_rx_discarded_cnt
++;
569 /* Decapsulate VLAN frames */
570 struct ether_header eheader
;
571 memcpy(&eheader
, frame
, sizeof(struct ether_header
));
572 if (eheader
.ether_type
== htons(ETHERTYPE_VLAN
)) {
573 /* VLAN decapsulation means to shift 4 bytes left the frame from
574 * offset 2*ETHER_ADDR_LEN */
575 memmove(frame
+ 2 * ETHER_ADDR_LEN
, frame
+ 2 * ETHER_ADDR_LEN
+ 4,
576 s
- 2 * ETHER_ADDR_LEN
);
580 TAILQ_FOREACH (oport
, &hardware
->h_rports
, p_entries
) {
581 if ((oport
->p_lastframe
!= NULL
) && (oport
->p_lastframe
->size
== s
) &&
582 (memcmp(oport
->p_lastframe
->frame
, frame
, s
) == 0)) {
583 /* Already received the same frame */
584 log_debug("decode", "duplicate frame, no need to decode");
585 oport
->p_lastupdate
= time(NULL
);
590 guess
= lldpd_guess_type(cfg
, frame
, s
);
591 for (i
= 0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
592 if (!cfg
->g_protocols
[i
].enabled
) continue;
593 if (cfg
->g_protocols
[i
].mode
== guess
) {
594 log_debug("decode", "using decode function for %s protocol",
595 cfg
->g_protocols
[i
].name
);
596 if (cfg
->g_protocols
[i
].decode(cfg
, frame
, s
, hardware
,
597 &chassis
, &port
) == -1) {
599 "function for %s protocol did not decode this frame",
600 cfg
->g_protocols
[i
].name
);
601 hardware
->h_rx_discarded_cnt
++;
604 chassis
->c_protocol
= port
->p_protocol
=
605 cfg
->g_protocols
[i
].mode
;
609 if (cfg
->g_protocols
[i
].mode
== 0) {
610 log_debug("decode", "unable to guess frame type on %s",
614 TRACE(LLDPD_FRAME_DECODED(hardware
->h_ifname
, cfg
->g_protocols
[i
].name
,
615 chassis
->c_name
, port
->p_descr
));
617 /* Do we already have the same MSAP somewhere? */
619 log_debug("decode", "search for the same MSAP");
620 TAILQ_FOREACH (oport
, &hardware
->h_rports
, p_entries
) {
621 if (port
->p_protocol
== oport
->p_protocol
) {
623 if ((port
->p_id_subtype
== oport
->p_id_subtype
) &&
624 (port
->p_id_len
== oport
->p_id_len
) &&
625 (memcmp(port
->p_id
, oport
->p_id
, port
->p_id_len
) == 0) &&
626 (chassis
->c_id_subtype
== oport
->p_chassis
->c_id_subtype
) &&
627 (chassis
->c_id_len
== oport
->p_chassis
->c_id_len
) &&
628 (memcmp(chassis
->c_id
, oport
->p_chassis
->c_id
,
629 chassis
->c_id_len
) == 0)) {
630 ochassis
= oport
->p_chassis
;
631 log_debug("decode", "MSAP is already known");
636 /* Do we have room for a new MSAP? */
637 if (!oport
&& cfg
->g_config
.c_max_neighbors
) {
638 if (count
== (cfg
->g_config
.c_max_neighbors
- 1)) {
640 "max neighbors %d reached for port %s, "
641 "dropping any new ones silently",
642 cfg
->g_config
.c_max_neighbors
, hardware
->h_ifname
);
643 } else if (count
> cfg
->g_config
.c_max_neighbors
- 1) {
645 "too many neighbors for port %s, drop this new one",
647 lldpd_port_cleanup(port
, 1);
648 lldpd_chassis_cleanup(chassis
, 1);
653 /* No, but do we already know the system? */
655 log_debug("decode", "MSAP is unknown, search for the chassis");
656 TAILQ_FOREACH (ochassis
, &cfg
->g_chassis
, c_entries
) {
657 if ((chassis
->c_protocol
== ochassis
->c_protocol
) &&
658 (chassis
->c_id_subtype
== ochassis
->c_id_subtype
) &&
659 (chassis
->c_id_len
== ochassis
->c_id_len
) &&
660 (memcmp(chassis
->c_id
, ochassis
->c_id
, chassis
->c_id_len
) ==
667 /* The port is known, remove it before adding it back */
668 TAILQ_REMOVE(&hardware
->h_rports
, oport
, p_entries
);
669 lldpd_port_cleanup(oport
, 1);
673 if (port
->p_ttl
== 0) {
674 /* Shutdown LLDPDU is special. We do not want to replace
675 * the chassis. Free the new chassis (which is mostly empty) */
676 log_debug("decode", "received a shutdown LLDPDU");
677 lldpd_chassis_cleanup(chassis
, 1);
679 lldpd_move_chassis(ochassis
, chassis
);
683 /* Chassis not known, add it */
684 log_debug("decode", "unknown chassis, add it to the list");
685 chassis
->c_index
= ++cfg
->g_lastrid
;
686 chassis
->c_refcount
= 0;
687 TAILQ_INSERT_TAIL(&cfg
->g_chassis
, chassis
, c_entries
);
689 TAILQ_FOREACH (ochassis
, &cfg
->g_chassis
, c_entries
)
691 log_debug("decode", "%d different systems are known", i
);
694 port
->p_lastchange
= port
->p_lastupdate
= time(NULL
);
695 if ((port
->p_lastframe
= (struct lldpd_frame
*)malloc(
696 s
+ sizeof(struct lldpd_frame
))) != NULL
) {
697 port
->p_lastframe
->size
= s
;
698 memcpy(port
->p_lastframe
->frame
, frame
, s
);
700 TAILQ_INSERT_TAIL(&hardware
->h_rports
, port
, p_entries
);
701 port
->p_chassis
= chassis
;
702 port
->p_chassis
->c_refcount
++;
703 /* Several cases are possible :
704 1. chassis is new, its refcount was 0. It is now attached
705 to this port, its refcount is 1.
706 2. chassis already exists and was attached to another
707 port, we increase its refcount accordingly.
708 3. chassis already exists and was attached to the same
709 port, its refcount was decreased with
710 lldpd_port_cleanup() and is now increased again.
712 In all cases, if the port already existed, it has been
713 freed with lldpd_port_cleanup() and therefore, the refcount
714 of the chassis that was attached to it is decreased.
717 /* coverity[use_after_free]
718 TAILQ_REMOVE does the right thing */
719 TAILQ_FOREACH (aport
, &hardware
->h_rports
, p_entries
)
721 log_debug("decode", "%d neighbors for %s", i
, hardware
->h_ifname
);
723 if (!oport
) hardware
->h_insert_cnt
++;
726 log_debug("decode", "send notifications for changes on %s", hardware
->h_ifname
);
728 TRACE(LLDPD_NEIGHBOR_UPDATE(hardware
->h_ifname
, chassis
->c_name
,
730 levent_ctl_notify(hardware
->h_ifname
, NEIGHBOR_CHANGE_UPDATED
, port
);
732 agent_notify(hardware
, NEIGHBOR_CHANGE_UPDATED
, port
);
735 TRACE(LLDPD_NEIGHBOR_NEW(hardware
->h_ifname
, chassis
->c_name
,
737 levent_ctl_notify(hardware
->h_ifname
, NEIGHBOR_CHANGE_ADDED
, port
);
739 agent_notify(hardware
, NEIGHBOR_CHANGE_ADDED
, port
);
743 #ifdef ENABLE_LLDPMED
744 if (!oport
&& port
->p_chassis
->c_med_type
) {
745 /* New neighbor, fast start */
746 if (hardware
->h_cfg
->g_config
.c_enable_fast_start
&&
747 !hardware
->h_tx_fast
) {
749 "%s: entering fast start due to "
752 hardware
->h_tx_fast
= hardware
->h_cfg
->g_config
.c_tx_fast_init
;
755 levent_schedule_pdu(hardware
);
762 /* Get the output of lsb_release -s -d. This is a slow function. It should be
763 called once. It return NULL if any problem happens. Otherwise, this is a
764 statically allocated buffer. The result includes the trailing \n */
766 lldpd_get_lsb_release()
768 static char release
[1024];
769 char cmd
[][12] = { "lsb_release", "-s", "-d" };
770 char *const command
[] = { cmd
[0], cmd
[1], cmd
[2], NULL
};
771 int pid
, status
, devnull
, count
;
774 log_debug("localchassis", "grab LSB release");
777 log_warn("localchassis", "unable to get a pair of pipes");
784 log_warn("localchassis", "unable to fork");
787 /* Child, exec lsb_release */
789 if ((devnull
= open("/dev/null", O_RDWR
, 0)) != -1) {
790 dup2(devnull
, STDIN_FILENO
);
791 dup2(devnull
, STDERR_FILENO
);
792 dup2(pipefd
[1], STDOUT_FILENO
);
793 if (devnull
> 2) close(devnull
);
794 if (pipefd
[1] > 2) close(pipefd
[1]);
795 execvp("lsb_release", command
);
800 /* Father, read the output from the children */
805 read(pipefd
[0], release
+ count
, sizeof(release
) - count
);
806 if ((status
== -1) && (errno
== EINTR
)) continue;
807 if (status
> 0) count
+= status
;
808 } while (count
< sizeof(release
) && (status
> 0));
810 log_info("localchassis", "unable to read from lsb_release");
812 waitpid(pid
, &status
, 0);
816 if (count
>= sizeof(release
)) {
817 log_info("localchassis", "output of lsb_release is too large");
818 waitpid(pid
, &status
, 0);
822 if (waitpid(pid
, &status
, 0) != pid
) return NULL
;
823 if (!WIFEXITED(status
) || (WEXITSTATUS(status
) != 0)) {
824 log_info("localchassis",
825 "lsb_release information not available");
829 log_info("localchassis",
830 "lsb_release returned an empty string");
833 release
[count
] = '\0';
836 /* Should not be here */
840 /* Same like lldpd_get_lsb_release but reads /etc/os-release for PRETTY_NAME=. */
842 lldpd_get_os_release()
844 static char release
[1024];
847 char *ptr1
= release
;
849 log_debug("localchassis", "grab OS release");
850 FILE *fp
= fopen("/etc/os-release", "r");
852 log_debug("localchassis", "could not open /etc/os-release");
853 fp
= fopen("/usr/lib/os-release", "r");
856 log_info("localchassis",
857 "could not open either /etc/os-release or /usr/lib/os-release");
861 while ((fgets(line
, sizeof(line
), fp
) != NULL
)) {
862 key
= strtok(line
, "=");
863 if (key
== NULL
) continue;
865 val
= strtok(NULL
, "=");
867 if (strncmp(key
, "PRETTY_NAME", sizeof(line
)) == 0) {
868 strlcpy(release
, val
, sizeof(line
));
874 /* Remove trailing newline and all " in the string. */
875 ptr1
= release
+ strlen(release
) - 1;
876 while (ptr1
!= release
&& ((*ptr1
== '"') || (*ptr1
== '\n'))) {
880 if (release
[0] == '"') return release
+ 1;
885 lldpd_hide_ports(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
, int mask
)
887 struct lldpd_port
*port
;
888 int protocols
[LLDPD_MODE_MAX
+ 1];
893 log_debug("smartfilter", "apply smart filter for port %s", hardware
->h_ifname
);
895 /* Compute the number of occurrences of each protocol */
896 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++)
898 TAILQ_FOREACH (port
, &hardware
->h_rports
, p_entries
)
899 protocols
[port
->p_protocol
]++;
901 /* Turn the protocols[] array into an array of
902 enabled/disabled protocols. 1 means enabled, 0
904 min
= (unsigned int)-1;
905 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++)
906 if (protocols
[i
] && (protocols
[i
] < min
)) min
= protocols
[i
];
908 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++)
909 if ((protocols
[i
] == min
) && !found
) {
910 /* If we need a tie breaker, we take
911 the first protocol only */
912 if (cfg
->g_config
.c_smart
& mask
&
913 (SMART_OUTGOING_ONE_PROTO
| SMART_INCOMING_ONE_PROTO
))
919 /* We set the p_hidden flag to 1 if the protocol is disabled */
920 TAILQ_FOREACH (port
, &hardware
->h_rports
, p_entries
) {
921 if (mask
== SMART_OUTGOING
)
922 port
->p_hidden_out
= protocols
[port
->p_protocol
] ? 0 : 1;
924 port
->p_hidden_in
= protocols
[port
->p_protocol
] ? 0 : 1;
927 /* If we want only one neighbor, we take the first one */
928 if (cfg
->g_config
.c_smart
& mask
&
929 (SMART_OUTGOING_ONE_NEIGH
| SMART_INCOMING_ONE_NEIGH
)) {
931 TAILQ_FOREACH (port
, &hardware
->h_rports
, p_entries
) {
932 if (mask
== SMART_OUTGOING
) {
933 if (found
) port
->p_hidden_out
= 1;
934 if (!port
->p_hidden_out
) found
= 1;
936 if (mask
== SMART_INCOMING
) {
937 if (found
) port
->p_hidden_in
= 1;
938 if (!port
->p_hidden_in
) found
= 1;
943 /* Print a debug message summarizing the operation */
944 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++)
947 TAILQ_FOREACH (port
, &hardware
->h_rports
, p_entries
) {
948 if (!(((mask
== SMART_OUTGOING
) && port
->p_hidden_out
) ||
949 ((mask
== SMART_INCOMING
) && port
->p_hidden_in
))) {
951 protocols
[port
->p_protocol
] = 1;
956 for (i
= 0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
957 if (cfg
->g_protocols
[i
].enabled
&&
958 protocols
[cfg
->g_protocols
[i
].mode
]) {
959 if (strlen(buffer
) + strlen(cfg
->g_protocols
[i
].name
) + 3 >
961 /* Unlikely, our buffer is too small */
962 memcpy(buffer
+ sizeof(buffer
) - 4, "...", 4);
966 strncat(buffer
, ", ",
967 sizeof(buffer
) - strlen(buffer
) - 1);
968 strncat(buffer
, cfg
->g_protocols
[i
].name
,
969 sizeof(buffer
) - strlen(buffer
) - 1);
972 log_debug("smartfilter", "%s: %s: %d visible neighbors (out of %d)",
973 hardware
->h_ifname
, (mask
== SMART_OUTGOING
) ? "out filter" : "in filter",
975 log_debug("smartfilter", "%s: protocols: %s", hardware
->h_ifname
,
976 buffer
[0] ? buffer
: "(none)");
979 /* Hide unwanted ports depending on smart mode set by the user */
981 lldpd_hide_all(struct lldpd
*cfg
)
983 struct lldpd_hardware
*hardware
;
985 if (!cfg
->g_config
.c_smart
) return;
986 log_debug("smartfilter", "apply smart filter results on all ports");
987 TAILQ_FOREACH (hardware
, &cfg
->g_hardware
, h_entries
) {
988 if (cfg
->g_config
.c_smart
& SMART_INCOMING_FILTER
)
989 lldpd_hide_ports(cfg
, hardware
, SMART_INCOMING
);
990 if (cfg
->g_config
.c_smart
& SMART_OUTGOING_FILTER
)
991 lldpd_hide_ports(cfg
, hardware
, SMART_OUTGOING
);
995 /* If PD device and PSE allocated power, echo back this change. If we have
996 * several LLDP neighbors, we use the latest updated. */
998 lldpd_dot3_power_pd_pse(struct lldpd_hardware
*hardware
)
1001 struct lldpd_port
*port
, *selected_port
= NULL
;
1002 /* Are we a PD device? */
1003 if (hardware
->h_lport
.p_power
.devicetype
!= LLDP_DOT3_POWER_PD
) return;
1004 TAILQ_FOREACH (port
, &hardware
->h_rports
, p_entries
) {
1005 if (port
->p_hidden_in
) continue;
1007 if (port
->p_protocol
!= LLDPD_MODE_LLDP
&&
1008 port
->p_protocol
!= LLDPD_MODE_CDPV2
)
1011 if (port
->p_power
.devicetype
!= LLDP_DOT3_POWER_PSE
) continue;
1012 if (!selected_port
|| port
->p_lastupdate
> selected_port
->p_lastupdate
)
1013 selected_port
= port
;
1015 if (selected_port
&&
1016 selected_port
->p_power
.allocated
!= hardware
->h_lport
.p_power
.allocated
) {
1018 "for %s, PSE told us allocated is now %d instead of %d",
1019 hardware
->h_ifname
, selected_port
->p_power
.allocated
,
1020 hardware
->h_lport
.p_power
.allocated
);
1021 hardware
->h_lport
.p_power
.allocated
= selected_port
->p_power
.allocated
;
1022 levent_schedule_pdu(hardware
);
1026 if (selected_port
&&
1027 selected_port
->p_cdp_power
.management_id
!=
1028 hardware
->h_lport
.p_cdp_power
.management_id
) {
1029 hardware
->h_lport
.p_cdp_power
.management_id
=
1030 selected_port
->p_cdp_power
.management_id
;
1038 lldpd_recv(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
, int fd
)
1040 char *buffer
= NULL
;
1042 log_debug("receive", "receive a frame on %s", hardware
->h_ifname
);
1043 if ((buffer
= (char *)malloc(hardware
->h_mtu
)) == NULL
) {
1044 log_warn("receive", "failed to alloc reception buffer");
1047 if ((n
= hardware
->h_ops
->recv(cfg
, hardware
, fd
, buffer
, hardware
->h_mtu
)) ==
1049 log_debug("receive", "discard frame received on %s",
1050 hardware
->h_ifname
);
1054 if (hardware
->h_lport
.p_disable_rx
) {
1055 log_debug("receive", "RX disabled, ignore the frame on %s",
1056 hardware
->h_ifname
);
1060 if (cfg
->g_config
.c_paused
) {
1061 log_debug("receive", "paused, ignore the frame on %s",
1062 hardware
->h_ifname
);
1066 hardware
->h_rx_cnt
++;
1067 log_debug("receive", "decode received frame on %s", hardware
->h_ifname
);
1068 TRACE(LLDPD_FRAME_RECEIVED(hardware
->h_ifname
, buffer
, (size_t)n
));
1069 lldpd_decode(cfg
, buffer
, n
, hardware
);
1070 lldpd_hide_all(cfg
); /* Immediately hide */
1071 lldpd_dot3_power_pd_pse(hardware
);
1072 lldpd_count_neighbors(cfg
);
1077 lldpd_send_shutdown(struct lldpd_hardware
*hardware
)
1079 struct lldpd
*cfg
= hardware
->h_cfg
;
1080 if (cfg
->g_config
.c_receiveonly
|| cfg
->g_config
.c_paused
) return;
1081 if (hardware
->h_lport
.p_disable_tx
) return;
1082 if ((hardware
->h_flags
& IFF_RUNNING
) == 0) return;
1084 /* It's safe to call `lldp_send_shutdown()` because shutdown LLDPU will
1085 * only be emitted if LLDP was sent on that port. */
1086 if (lldp_send_shutdown(hardware
->h_cfg
, hardware
) != 0)
1087 log_warnx("send", "unable to send shutdown LLDPDU on %s",
1088 hardware
->h_ifname
);
1092 lldpd_send(struct lldpd_hardware
*hardware
)
1094 struct lldpd
*cfg
= hardware
->h_cfg
;
1095 struct lldpd_port
*port
;
1098 if (cfg
->g_config
.c_receiveonly
|| cfg
->g_config
.c_paused
) return;
1099 if (hardware
->h_lport
.p_disable_tx
) return;
1100 if ((hardware
->h_flags
& IFF_RUNNING
) == 0) return;
1102 log_debug("send", "send PDU on %s", hardware
->h_ifname
);
1104 for (i
= 0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
1105 if (!cfg
->g_protocols
[i
].enabled
) continue;
1106 /* We send only if we have at least one remote system
1107 * speaking this protocol or if the protocol is forced */
1108 if (cfg
->g_protocols
[i
].enabled
> 1) {
1109 cfg
->g_protocols
[i
].send(cfg
, hardware
);
1113 TAILQ_FOREACH (port
, &hardware
->h_rports
, p_entries
) {
1114 /* If this remote port is disabled, we don't
1116 if (port
->p_hidden_out
) continue;
1117 if (port
->p_protocol
== cfg
->g_protocols
[i
].mode
) {
1118 TRACE(LLDPD_FRAME_SEND(hardware
->h_ifname
,
1119 cfg
->g_protocols
[i
].name
));
1120 log_debug("send", "send PDU on %s with protocol %s",
1121 hardware
->h_ifname
, cfg
->g_protocols
[i
].name
);
1122 cfg
->g_protocols
[i
].send(cfg
, hardware
);
1123 hardware
->h_lport
.p_protocol
= cfg
->g_protocols
[i
].mode
;
1131 /* Nothing was sent for this port, let's speak the first
1132 * available protocol. */
1133 for (i
= 0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
1134 if (!cfg
->g_protocols
[i
].enabled
) continue;
1135 TRACE(LLDPD_FRAME_SEND(hardware
->h_ifname
,
1136 cfg
->g_protocols
[i
].name
));
1137 log_debug("send", "fallback to protocol %s for %s",
1138 cfg
->g_protocols
[i
].name
, hardware
->h_ifname
);
1139 cfg
->g_protocols
[i
].send(cfg
, hardware
);
1142 if (cfg
->g_protocols
[i
].mode
== 0)
1143 log_warnx("send", "no protocol enabled, dunno what to send");
1147 #ifdef ENABLE_LLDPMED
1149 lldpd_med(struct lldpd
*cfg
, struct utsname
*un
)
1151 static short int once
= 0;
1153 LOCAL_CHASSIS(cfg
)->c_med_hw
= dmi_hw();
1154 LOCAL_CHASSIS(cfg
)->c_med_fw
= dmi_fw();
1155 LOCAL_CHASSIS(cfg
)->c_med_sn
= dmi_sn();
1156 LOCAL_CHASSIS(cfg
)->c_med_manuf
= dmi_manuf();
1157 LOCAL_CHASSIS(cfg
)->c_med_model
= dmi_model();
1158 LOCAL_CHASSIS(cfg
)->c_med_asset
= dmi_asset();
1160 if (LOCAL_CHASSIS(cfg
)->c_med_sw
)
1161 free(LOCAL_CHASSIS(cfg
)->c_med_sw
);
1163 if (cfg
->g_config
.c_advertise_version
)
1164 LOCAL_CHASSIS(cfg
)->c_med_sw
= strdup(un
->release
);
1166 LOCAL_CHASSIS(cfg
)->c_med_sw
= strdup("Unknown");
1174 lldpd_routing_enabled(struct lldpd
*cfg
)
1178 if ((LOCAL_CHASSIS(cfg
)->c_cap_available
& LLDP_CAP_ROUTER
) == 0) return 0;
1180 if ((routing
= interfaces_routing_enabled(cfg
)) == -1) {
1181 log_debug("localchassis", "unable to check if routing is enabled");
1188 lldpd_update_localchassis(struct lldpd
*cfg
)
1193 log_debug("localchassis", "update information for local chassis");
1194 assert(LOCAL_CHASSIS(cfg
) != NULL
);
1196 /* Set system name and description */
1197 if (uname(&un
) < 0) fatal("localchassis", "failed to get system information");
1198 if (cfg
->g_config
.c_hostname
) {
1199 log_debug("localchassis", "use overridden system name `%s`",
1200 cfg
->g_config
.c_hostname
);
1201 hp
= cfg
->g_config
.c_hostname
;
1203 if ((hp
= priv_gethostname()) == NULL
)
1204 fatal("localchassis", "failed to get system name");
1206 free(LOCAL_CHASSIS(cfg
)->c_name
);
1207 free(LOCAL_CHASSIS(cfg
)->c_descr
);
1208 if ((LOCAL_CHASSIS(cfg
)->c_name
= strdup(hp
)) == NULL
)
1209 fatal("localchassis", NULL
);
1210 if (cfg
->g_config
.c_description
) {
1211 log_debug("localchassis", "use overridden description `%s`",
1212 cfg
->g_config
.c_description
);
1213 if (asprintf(&LOCAL_CHASSIS(cfg
)->c_descr
, "%s",
1214 cfg
->g_config
.c_description
) == -1)
1215 fatal("localchassis", "failed to set full system description");
1217 if (cfg
->g_config
.c_advertise_version
) {
1218 log_debug("localchassis", "advertise system version");
1219 if (asprintf(&LOCAL_CHASSIS(cfg
)->c_descr
, "%s %s %s %s %s",
1220 cfg
->g_lsb_release
? cfg
->g_lsb_release
: "",
1221 un
.sysname
, un
.release
, un
.version
, un
.machine
) == -1)
1222 fatal("localchassis",
1223 "failed to set full system description");
1225 log_debug("localchassis", "do not advertise system version");
1226 if (asprintf(&LOCAL_CHASSIS(cfg
)->c_descr
, "%s",
1227 cfg
->g_lsb_release
? cfg
->g_lsb_release
: un
.sysname
) ==
1229 fatal("localchassis",
1230 "failed to set minimal system description");
1233 if (cfg
->g_config
.c_platform
== NULL
)
1234 cfg
->g_config
.c_platform
= strdup(un
.sysname
);
1236 if (!cfg
->g_config
.c_cap_override
) {
1238 if (lldpd_routing_enabled(cfg
)) {
1239 log_debug("localchassis",
1240 "routing is enabled, enable router capability");
1241 LOCAL_CHASSIS(cfg
)->c_cap_enabled
|= LLDP_CAP_ROUTER
;
1243 LOCAL_CHASSIS(cfg
)->c_cap_enabled
&= ~LLDP_CAP_ROUTER
;
1245 #ifdef ENABLE_LLDPMED
1246 if (LOCAL_CHASSIS(cfg
)->c_cap_available
& LLDP_CAP_TELEPHONE
)
1247 LOCAL_CHASSIS(cfg
)->c_cap_enabled
|= LLDP_CAP_TELEPHONE
;
1248 lldpd_med(cfg
, &un
);
1250 if ((LOCAL_CHASSIS(cfg
)->c_cap_available
& LLDP_CAP_STATION
) &&
1251 (LOCAL_CHASSIS(cfg
)->c_cap_enabled
== 0))
1252 LOCAL_CHASSIS(cfg
)->c_cap_enabled
= LLDP_CAP_STATION
;
1253 else if (LOCAL_CHASSIS(cfg
)->c_cap_enabled
!= LLDP_CAP_STATION
)
1254 LOCAL_CHASSIS(cfg
)->c_cap_enabled
&= ~LLDP_CAP_STATION
;
1257 /* Set chassis ID if needed. This is only done if chassis ID
1258 has not been set previously (with the MAC address of an
1259 interface for example)
1261 if (cfg
->g_config
.c_cid_string
!= NULL
) {
1262 log_debug("localchassis", "use specified chassis ID string");
1263 free(LOCAL_CHASSIS(cfg
)->c_id
);
1264 if (!(LOCAL_CHASSIS(cfg
)->c_id
= strdup(cfg
->g_config
.c_cid_string
)))
1265 fatal("localchassis", NULL
);
1266 LOCAL_CHASSIS(cfg
)->c_id_len
= strlen(cfg
->g_config
.c_cid_string
);
1267 LOCAL_CHASSIS(cfg
)->c_id_subtype
= LLDP_CHASSISID_SUBTYPE_LOCAL
;
1269 if (LOCAL_CHASSIS(cfg
)->c_id
== NULL
) {
1270 log_debug("localchassis",
1271 "no chassis ID is currently set, use chassis name");
1272 if (!(LOCAL_CHASSIS(cfg
)->c_id
= strdup(LOCAL_CHASSIS(cfg
)->c_name
)))
1273 fatal("localchassis", NULL
);
1274 LOCAL_CHASSIS(cfg
)->c_id_len
= strlen(LOCAL_CHASSIS(cfg
)->c_name
);
1275 LOCAL_CHASSIS(cfg
)->c_id_subtype
= LLDP_CHASSISID_SUBTYPE_LOCAL
;
1280 lldpd_update_localports(struct lldpd
*cfg
)
1282 struct lldpd_hardware
*hardware
;
1284 log_debug("localchassis", "update information for local ports");
1286 /* h_flags is set to 0 for each port. If the port is updated, h_flags
1287 * will be set to a non-zero value. This will allow us to clean up any
1288 * non up-to-date port */
1289 TAILQ_FOREACH (hardware
, &cfg
->g_hardware
, h_entries
)
1290 hardware
->h_flags
= 0;
1292 TRACE(LLDPD_INTERFACES_UPDATE());
1293 interfaces_update(cfg
);
1295 lldpd_reset_timer(cfg
);
1299 lldpd_loop(struct lldpd
*cfg
)
1302 1. Update local ports information
1303 2. Update local chassis information
1305 log_debug("loop", "start new loop");
1306 if (!cfg
->g_config
.c_cap_override
) LOCAL_CHASSIS(cfg
)->c_cap_enabled
= 0;
1307 /* Information for local ports is triggered even when it is possible to
1308 * update them on some other event because we want to refresh them if we
1309 * missed something. */
1310 log_debug("loop", "update information for local ports");
1311 lldpd_update_localports(cfg
);
1312 log_debug("loop", "update information for local chassis");
1313 lldpd_update_localchassis(cfg
);
1314 lldpd_count_neighbors(cfg
);
1318 lldpd_exit(struct lldpd
*cfg
)
1320 char *lockname
= NULL
;
1321 struct lldpd_hardware
*hardware
, *hardware_next
;
1322 log_debug("main", "exit lldpd");
1324 TAILQ_FOREACH (hardware
, &cfg
->g_hardware
, h_entries
)
1325 lldpd_send_shutdown(hardware
);
1327 if (asprintf(&lockname
, "%s.lock", cfg
->g_ctlname
) != -1) {
1328 priv_ctl_cleanup(lockname
);
1332 priv_ctl_cleanup(cfg
->g_ctlname
);
1333 log_debug("main", "cleanup hardware information");
1334 for (hardware
= TAILQ_FIRST(&cfg
->g_hardware
); hardware
!= NULL
;
1335 hardware
= hardware_next
) {
1336 hardware_next
= TAILQ_NEXT(hardware
, h_entries
);
1337 log_debug("main", "cleanup interface %s", hardware
->h_ifname
);
1338 lldpd_remote_cleanup(hardware
, NULL
, 1);
1339 lldpd_hardware_cleanup(cfg
, hardware
);
1341 interfaces_cleanup(cfg
);
1342 lldpd_port_cleanup(cfg
->g_default_local_port
, 1);
1343 lldpd_all_chassis_cleanup(cfg
);
1344 free(cfg
->g_default_local_port
);
1345 free(cfg
->g_config
.c_platform
);
1346 levent_shutdown(cfg
);
1350 * Run lldpcli to configure lldpd.
1352 * @return PID of running lldpcli or -1 if error.
1355 lldpd_configure(int use_syslog
, int debug
, const char *path
, const char *ctlname
,
1356 const char *config_path
)
1358 pid_t lldpcli
= vfork();
1361 char sdebug
[debug
+ 4];
1363 strlcpy(sdebug
, "-s", 3);
1365 /* debug = 0 -> -sd */
1366 /* debug = 1 -> -sdd */
1367 /* debug = 2 -> -sddd */
1368 memset(sdebug
, 'd', sizeof(sdebug
));
1369 sdebug
[debug
+ 3] = '\0';
1373 log_debug("main", "invoke %s %s", path
, sdebug
);
1377 log_warn("main", "unable to fork");
1380 /* Child, exec lldpcli */
1381 if ((devnull
= open("/dev/null", O_RDWR
, 0)) != -1) {
1382 dup2(devnull
, STDIN_FILENO
);
1383 dup2(devnull
, STDOUT_FILENO
);
1384 if (devnull
> 2) close(devnull
);
1387 execl(path
, "lldpcli", sdebug
, "-u", ctlname
, "-C",
1388 config_path
, "resume", (char *)NULL
);
1390 execl(path
, "lldpcli", sdebug
, "-u", ctlname
, "-C",
1391 SYSCONFDIR
"/lldpd.conf", "-C",
1392 SYSCONFDIR
"/lldpd.d", "resume", (char *)NULL
);
1395 log_warn("main", "unable to execute %s", path
);
1397 "configuration is incomplete, lldpd needs to be unpaused");
1402 /* Father, don't do anything stupid */
1405 /* Should not be here */
1413 static const struct intint filters
[] = { { 0, 0 },
1415 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_OUTGOING_FILTER
|
1416 SMART_OUTGOING_ONE_PROTO
},
1417 { 2, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
},
1418 { 3, SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
1419 { 4, SMART_INCOMING_FILTER
| SMART_OUTGOING_FILTER
},
1420 { 5, SMART_INCOMING_FILTER
}, { 6, SMART_OUTGOING_FILTER
},
1422 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
1423 SMART_INCOMING_ONE_NEIGH
| SMART_OUTGOING_FILTER
|
1424 SMART_OUTGOING_ONE_PROTO
},
1426 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
1427 SMART_INCOMING_ONE_NEIGH
},
1429 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
| SMART_OUTGOING_FILTER
|
1430 SMART_OUTGOING_ONE_PROTO
},
1431 { 10, SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1432 { 11, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
},
1434 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
| SMART_OUTGOING_FILTER
|
1435 SMART_OUTGOING_ONE_NEIGH
},
1437 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
| SMART_OUTGOING_FILTER
},
1439 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_OUTGOING_FILTER
|
1440 SMART_OUTGOING_ONE_NEIGH
},
1442 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_OUTGOING_FILTER
},
1444 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
1445 SMART_INCOMING_ONE_NEIGH
| SMART_OUTGOING_FILTER
|
1446 SMART_OUTGOING_ONE_NEIGH
},
1448 SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
1449 SMART_INCOMING_ONE_NEIGH
| SMART_OUTGOING_FILTER
},
1451 SMART_INCOMING_FILTER
| SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1453 SMART_INCOMING_FILTER
| SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
1458 * Tell if we have been started by systemd.
1461 lldpd_started_by_systemd()
1463 # ifdef HOST_OS_LINUX
1467 union sockaddr_union
{
1469 struct sockaddr_un sun
;
1471 .sun
.sun_family
= AF_UNIX
,
1473 const char *socket_path
= getenv("NOTIFY_SOCKET");
1474 if (!socket_path
|| (socket_path
[0] != '/' && socket_path
[0] != '@') ||
1475 (path_length
= strlen(socket_path
)) < 2)
1478 if (path_length
>= sizeof(socket_addr
.sun
.sun_path
)) {
1479 log_warnx("main", "systemd notification socket is too long");
1482 memcpy(socket_addr
.sun
.sun_path
, socket_path
, path_length
);
1484 /* Support for abstract socket */
1485 if (socket_addr
.sun
.sun_path
[0] == '@') socket_addr
.sun
.sun_path
[0] = 0;
1487 log_debug("main", "running with systemd, don't fork but signal ready");
1488 if ((fd
= socket(AF_UNIX
, SOCK_DGRAM
| SOCK_CLOEXEC
, 0)) < 0) {
1489 log_warn("main", "unable to open systemd notification socket %s",
1493 if (connect(fd
, &socket_addr
.sa
,
1494 offsetof(struct sockaddr_un
, sun_path
) + path_length
) != 0) {
1495 log_warn("main", "unable to connect to systemd notification socket");
1498 char ready
[] = "READY=1";
1499 ssize_t written
= write(fd
, ready
, sizeof ready
- 1);
1500 if (written
!= (ssize_t
)sizeof ready
- 1) {
1501 log_warn("main", "unable to send notification to systemd");
1504 unsetenv("NOTIFY_SOCKET");
1507 if (fd
>= 0) close(fd
);
1515 #ifdef HOST_OS_LINUX
1517 version_convert(const char *sversion
, unsigned iversion
[], size_t n
)
1519 const char *p
= sversion
;
1521 for (size_t i
= 0; i
< n
; i
++) {
1522 iversion
[i
] = strtol(p
, &end
, 10);
1523 if (*end
!= '.') break;
1532 if (uname(&uts
) == -1) return;
1533 unsigned version_min
[3] = {};
1534 unsigned version_cur
[3] = {};
1535 version_convert(uts
.release
, version_cur
, 3);
1536 version_convert(MIN_LINUX_KERNEL_VERSION
, version_min
, 3);
1537 if (version_min
[0] > version_cur
[0] ||
1538 (version_min
[0] == version_cur
[0] && version_min
[1] > version_cur
[1]) ||
1539 (version_min
[0] == version_cur
[0] && version_min
[1] == version_cur
[1] &&
1540 version_min
[2] > version_cur
[2])) {
1541 log_warnx("lldpd", "minimal kernel version required is %s, got %s",
1542 MIN_LINUX_KERNEL_VERSION
, uts
.release
);
1544 "lldpd may be unable to detect bonds and bridges correctly");
1545 # ifndef ENABLE_OLDIES
1546 log_warnx("lldpd", "consider recompiling with --enable-oldies option");
1558 lldpd_main(int argc
, char *argv
[], char *envp
[])
1561 struct lldpd_chassis
*lchassis
;
1562 int ch
, debug
= 0, use_syslog
= 1, daemonize
= 1;
1566 const char *agentx
= NULL
; /* AgentX socket */
1568 const char *ctlname
= NULL
;
1571 char *interfaces
= NULL
;
1572 /* We do not want more options here. Please add them in lldpcli instead
1573 * unless there is a very good reason. Most command-line options will
1574 * get deprecated at some point. */
1576 opts
[] = "H:vhkrdD:p:xX:m:u:4:6:I:C:p:M:P:S:iL:O:@ ";
1577 int i
, found
, advertise_version
= 1;
1578 #ifdef ENABLE_LLDPMED
1579 int lldpmed
= 0, noinventory
= 0;
1580 int enable_fast_start
= 1;
1582 char *descr_override
= NULL
;
1583 char *platform_override
= NULL
;
1584 char *lsb_release
= NULL
;
1585 const char *lldpcli
= LLDPCLI_PATH
;
1587 const char *pidfile
= LLDPD_PID_FILE
;
1590 int receiveonly
= 0, version
= 0;
1592 const char *config_file
= NULL
;
1594 #ifdef ENABLE_PRIVSEP
1595 /* Non privileged user */
1596 struct passwd
*user
;
1597 struct group
*group
;
1604 #if HAVE_SETPROCTITLE_INIT
1605 setproctitle_init(argc
, argv
, envp
);
1609 * Get and parse command line options
1611 if ((popt
= strchr(opts
, '@')) != NULL
) {
1612 for (i
= 0; protos
[i
].mode
!= 0 && *popt
!= '\0'; i
++)
1613 *(popt
++) = protos
[i
].arg
;
1616 while ((ch
= getopt(argc
, argv
, opts
)) != -1) {
1627 else if (use_syslog
)
1645 fprintf(stderr
, "-m can only be used once\n");
1648 mgmtp
= strdup(optarg
);
1652 fprintf(stderr
, "-u can only be used once\n");
1659 fprintf(stderr
, "-I can only be used once\n");
1662 interfaces
= strdup(optarg
);
1666 fprintf(stderr
, "-C can only be used once\n");
1669 cidp
= strdup(optarg
);
1678 advertise_version
= 0;
1680 #ifdef ENABLE_LLDPMED
1682 lldpmed
= strtonum(optarg
, 1, 4, &errstr
);
1685 "-M requires an argument between 1 and 4\n");
1695 fprintf(stderr
, "LLDP-MED support is not built-in\n");
1705 fprintf(stderr
, "-X can only be used once\n");
1714 fprintf(stderr
, "SNMP support is not built-in\n");
1719 if (descr_override
) {
1720 fprintf(stderr
, "-S can only be used once\n");
1723 descr_override
= strdup(optarg
);
1726 if (platform_override
) {
1727 fprintf(stderr
, "-P can only be used once\n");
1730 platform_override
= strdup(optarg
);
1733 smart
= strtonum(optarg
, 0,
1734 sizeof(filters
) / sizeof(filters
[0]), &errstr
);
1737 "-H requires an int between 0 and %zu\n",
1738 sizeof(filters
) / sizeof(filters
[0]));
1744 fprintf(stderr
, "-O can only be used once\n");
1747 config_file
= optarg
;
1751 for (i
= 0; protos
[i
].mode
!= 0; i
++) {
1752 if (ch
== protos
[i
].arg
) {
1754 protos
[i
].enabled
++;
1757 if (!found
) usage();
1762 version_display(stdout
, "lldpd", version
> 1);
1766 if (ctlname
== NULL
) ctlname
= LLDPD_CTL_SOCKET
;
1768 /* Set correct smart mode */
1769 for (i
= 0; (filters
[i
].a
!= -1) && (filters
[i
].a
!= smart
); i
++)
1771 if (filters
[i
].a
== -1) {
1772 fprintf(stderr
, "Incorrect mode for -H\n");
1775 smart
= filters
[i
].b
;
1777 log_init(use_syslog
, debug
, __progname
);
1778 tzset(); /* Get timezone info before chroot */
1779 if (use_syslog
&& daemonize
) {
1780 /* So, we use syslog and we daemonize (or we are started by
1781 * systemd). No need to continue writing to stdout. */
1783 /* coverity[resource_leak]
1784 fd may be leaked if < 2, it's expected */
1785 if ((fd
= open("/dev/null", O_RDWR
, 0)) != -1) {
1786 dup2(fd
, STDIN_FILENO
);
1787 dup2(fd
, STDOUT_FILENO
);
1788 dup2(fd
, STDERR_FILENO
);
1789 if (fd
> 2) close(fd
);
1792 log_debug("main", "lldpd " PACKAGE_VERSION
" starting...");
1794 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1795 fatalx("main", "fuzzing enabled, unsafe for production");
1798 /* Grab uid and gid to use for priv sep */
1799 #ifdef ENABLE_PRIVSEP
1800 if ((user
= getpwnam(PRIVSEP_USER
)) == NULL
)
1803 " user for privilege separation, please create it");
1805 if ((group
= getgrnam(PRIVSEP_GROUP
)) == NULL
)
1808 " group for privilege separation, please create it");
1809 gid
= group
->gr_gid
;
1812 /* Create and setup socket */
1814 log_debug("main", "creating control socket");
1815 while ((ctl
= ctl_create(ctlname
)) == -1) {
1816 if (retry
-- && errno
== EADDRINUSE
) {
1817 /* Check if a daemon is really listening */
1820 "unable to create control socket because it already exists");
1821 log_info("main", "check if another instance is running");
1822 if ((tfd
= ctl_connect(ctlname
)) != -1) {
1823 /* Another instance is running */
1826 "another instance is running, please stop it");
1827 fatalx("main", "giving up");
1828 } else if (errno
== ECONNREFUSED
) {
1829 /* Nobody is listening */
1831 "old control socket is present, clean it");
1832 ctl_cleanup(ctlname
);
1836 "cannot determine if another daemon is already running");
1837 fatalx("main", "giving up");
1839 log_warn("main", "unable to create control socket at %s", ctlname
);
1840 fatalx("main", "giving up");
1842 #ifdef ENABLE_PRIVSEP
1843 if (chown(ctlname
, uid
, gid
) == -1)
1844 log_warn("main", "unable to chown control socket");
1845 if (chmod(ctlname
, S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IWGRP
| S_IXGRP
) ==
1847 log_warn("main", "unable to chmod control socket");
1850 /* Create associated advisory lock file */
1851 char *lockname
= NULL
;
1853 if (asprintf(&lockname
, "%s.lock", ctlname
) == -1)
1854 fatal("main", "cannot build lock name");
1855 if ((fd
= open(lockname
, O_CREAT
| O_RDWR
, 0000)) == -1)
1856 fatal("main", "cannot create lock file for control socket");
1858 #ifdef ENABLE_PRIVSEP
1859 if (chown(lockname
, uid
, gid
) == -1)
1860 log_warn("main", "unable to chown control socket lock");
1862 S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IWGRP
| S_IXGRP
) == -1)
1863 log_warn("main", "unable to chmod control socket lock");
1867 /* Disable SIGPIPE */
1868 signal(SIGPIPE
, SIG_IGN
);
1870 /* Disable SIGHUP, until handlers are installed */
1871 signal(SIGHUP
, SIG_IGN
);
1873 /* Daemonization, unless started by systemd or launchd or debug */
1875 if (!lldpd_started_by_systemd() && daemonize
) {
1878 log_debug("main", "going into background");
1879 if (daemon(0, 1) != 0) fatal("main", "failed to detach daemon");
1880 if ((pid
= open(pidfile
, O_TRUNC
| O_CREAT
| O_WRONLY
, 0666)) == -1)
1882 "unable to open pid file " LLDPD_PID_FILE
1883 " (or the specified one)");
1884 if (asprintf(&spid
, "%d\n", getpid()) == -1)
1886 "unable to create pid file " LLDPD_PID_FILE
1887 " (or the specified one)");
1888 if (write(pid
, spid
, strlen(spid
)) == -1)
1890 "unable to write pid file " LLDPD_PID_FILE
1891 " (or the specified one)");
1897 /* Configuration with lldpcli */
1901 "invoking lldpcli for default configuration locations");
1904 "invoking lldpcli for user supplied configuration location");
1906 if (lldpd_configure(use_syslog
, debug
, lldpcli
, ctlname
, config_file
) ==
1908 fatal("main", "unable to spawn lldpcli");
1911 /* Try to read system information from /etc/os-release if possible.
1912 Fall back to lsb_release for compatibility. */
1913 log_debug("main", "get OS/LSB release information");
1914 lsb_release
= lldpd_get_os_release();
1916 lsb_release
= lldpd_get_lsb_release();
1919 log_debug("main", "initialize privilege separation");
1920 #ifdef ENABLE_PRIVSEP
1921 priv_init(PRIVSEP_CHROOT
, ctl
, uid
, gid
);
1926 /* Initialization of global configuration */
1927 if ((cfg
= (struct lldpd
*)calloc(1, sizeof(struct lldpd
))) == NULL
)
1928 fatal("main", NULL
);
1930 lldpd_alloc_default_local_port(cfg
);
1931 cfg
->g_ctlname
= ctlname
;
1933 cfg
->g_config
.c_mgmt_pattern
= mgmtp
;
1934 cfg
->g_config
.c_cid_pattern
= cidp
;
1935 cfg
->g_config
.c_iface_pattern
= interfaces
;
1936 cfg
->g_config
.c_smart
= smart
;
1937 if (lldpcli
) cfg
->g_config
.c_paused
= 1;
1938 cfg
->g_config
.c_receiveonly
= receiveonly
;
1939 cfg
->g_config
.c_tx_interval
= LLDPD_TX_INTERVAL
* 1000;
1940 cfg
->g_config
.c_tx_hold
= LLDPD_TX_HOLD
;
1941 cfg
->g_config
.c_ttl
= cfg
->g_config
.c_tx_interval
* cfg
->g_config
.c_tx_hold
;
1942 cfg
->g_config
.c_ttl
= MIN((cfg
->g_config
.c_ttl
+ 999) / 1000, 65535);
1943 cfg
->g_config
.c_max_neighbors
= LLDPD_MAX_NEIGHBORS
;
1944 #ifdef ENABLE_LLDPMED
1945 cfg
->g_config
.c_enable_fast_start
= enable_fast_start
;
1946 cfg
->g_config
.c_tx_fast_init
= LLDPD_FAST_INIT
;
1947 cfg
->g_config
.c_tx_fast_interval
= LLDPD_FAST_TX_INTERVAL
;
1951 cfg
->g_snmp_agentx
= agentx
;
1952 #endif /* USE_SNMP */
1953 cfg
->g_config
.c_bond_slave_src_mac_type
=
1954 LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED
;
1956 /* Get ioctl socket */
1957 log_debug("main", "get an ioctl socket");
1958 if ((cfg
->g_sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1959 fatal("main", "failed to get ioctl socket");
1962 if (!(cfg
->g_config
.c_advertise_version
= advertise_version
) && lsb_release
&&
1963 lsb_release
[strlen(lsb_release
) - 1] == '\n')
1964 lsb_release
[strlen(lsb_release
) - 1] = '\0';
1965 cfg
->g_lsb_release
= lsb_release
;
1966 if (descr_override
) cfg
->g_config
.c_description
= descr_override
;
1968 if (platform_override
) cfg
->g_config
.c_platform
= platform_override
;
1970 /* Set system capabilities */
1971 log_debug("main", "set system capabilities");
1972 if ((lchassis
= (struct lldpd_chassis
*)calloc(1,
1973 sizeof(struct lldpd_chassis
))) == NULL
)
1974 fatal("localchassis", NULL
);
1975 cfg
->g_config
.c_cap_advertise
= 1;
1976 cfg
->g_config
.c_cap_override
= 0;
1977 lchassis
->c_cap_available
=
1978 LLDP_CAP_BRIDGE
| LLDP_CAP_WLAN
| LLDP_CAP_ROUTER
| LLDP_CAP_STATION
;
1979 cfg
->g_config
.c_mgmt_advertise
= 1;
1980 TAILQ_INIT(&lchassis
->c_mgmt
);
1981 #ifdef ENABLE_LLDPMED
1983 if (lldpmed
== LLDP_MED_CLASS_III
)
1984 lchassis
->c_cap_available
|= LLDP_CAP_TELEPHONE
;
1985 lchassis
->c_med_type
= lldpmed
;
1986 lchassis
->c_med_cap_available
= LLDP_MED_CAP_CAP
| LLDP_MED_CAP_IV
|
1987 LLDP_MED_CAP_LOCATION
| LLDP_MED_CAP_POLICY
| LLDP_MED_CAP_MDI_PSE
|
1988 LLDP_MED_CAP_MDI_PD
;
1989 cfg
->g_config
.c_noinventory
= noinventory
;
1991 cfg
->g_config
.c_noinventory
= 1;
1994 log_debug("main", "initialize protocols");
1995 cfg
->g_protocols
= protos
;
1996 for (i
= 0; protos
[i
].mode
!= 0; i
++) {
1998 /* With -ll, disable LLDP */
1999 if (protos
[i
].mode
== LLDPD_MODE_LLDP
) protos
[i
].enabled
%= 3;
2000 /* With -ccc force CDPV2, enable CDPV1 */
2001 if (protos
[i
].mode
== LLDPD_MODE_CDPV1
&& protos
[i
].enabled
== 3) {
2002 protos
[i
].enabled
= 1;
2004 /* With -cc force CDPV1, enable CDPV2 */
2005 if (protos
[i
].mode
== LLDPD_MODE_CDPV2
&& protos
[i
].enabled
== 2) {
2006 protos
[i
].enabled
= 1;
2009 /* With -cccc disable CDPV1, enable CDPV2 */
2010 if (protos
[i
].mode
== LLDPD_MODE_CDPV1
&& protos
[i
].enabled
>= 4) {
2011 protos
[i
].enabled
= 0;
2014 /* With -cccc disable CDPV1, enable CDPV2; -ccccc will force CDPv2 */
2015 if (protos
[i
].mode
== LLDPD_MODE_CDPV2
&& protos
[i
].enabled
== 4) {
2016 protos
[i
].enabled
= 1;
2019 if (protos
[i
].enabled
> 1)
2020 log_info("main", "protocol %s enabled and forced",
2022 else if (protos
[i
].enabled
)
2023 log_info("main", "protocol %s enabled", protos
[i
].name
);
2025 log_info("main", "protocol %s disabled", protos
[i
].name
);
2028 TAILQ_INIT(&cfg
->g_hardware
);
2029 TAILQ_INIT(&cfg
->g_chassis
);
2030 TAILQ_INSERT_TAIL(&cfg
->g_chassis
, lchassis
, c_entries
);
2031 lchassis
->c_refcount
++; /* We should always keep a reference to local chassis */
2034 log_debug("main", "start main loop");
2036 lchassis
->c_refcount
--;