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.
30 #include <sys/utsname.h>
31 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/select.h>
36 #include <sys/ioctl.h>
37 #include <arpa/inet.h>
38 #include <netinet/if_ether.h>
42 static void usage(void);
44 static struct protocol protos
[] =
46 { LLDPD_MODE_LLDP
, 1, "LLDP", 'l', lldp_send
, lldp_decode
, NULL
,
47 LLDP_ADDR_NEAREST_BRIDGE
,
48 LLDP_ADDR_NEAREST_NONTPMR_BRIDGE
,
49 LLDP_ADDR_NEAREST_CUSTOMER_BRIDGE
},
51 { LLDPD_MODE_CDPV1
, 0, "CDPv1", 'c', cdpv1_send
, cdp_decode
, cdpv1_guess
,
53 { LLDPD_MODE_CDPV2
, 0, "CDPv2", 'c', cdpv2_send
, cdp_decode
, cdpv2_guess
,
57 { LLDPD_MODE_SONMP
, 0, "SONMP", 's', sonmp_send
, sonmp_decode
, NULL
,
58 SONMP_MULTICAST_ADDR
},
61 { LLDPD_MODE_EDP
, 0, "EDP", 'e', edp_send
, edp_decode
, NULL
,
65 { LLDPD_MODE_FDP
, 0, "FDP", 'f', fdp_send
, cdp_decode
, NULL
,
68 { 0, 0, "any", ' ', NULL
, NULL
, NULL
,
72 static char **saved_argv
;
73 #ifdef HAVE___PROGNAME
74 extern const char *__progname
;
76 # define __progname "lldpd"
82 fprintf(stderr
, "Usage: %s [OPTIONS ...]\n", __progname
);
83 fprintf(stderr
, "Version: %s\n", PACKAGE_STRING
);
85 fprintf(stderr
, "\n");
87 fprintf(stderr
, "-d Do not daemonize.\n");
88 fprintf(stderr
, "-r Receive-only mode\n");
89 fprintf(stderr
, "-i Disable LLDP-MED inventory TLV transmission.\n");
90 fprintf(stderr
, "-k Disable advertising of kernel release, version, machine.\n");
91 fprintf(stderr
, "-S descr Override the default system description.\n");
92 fprintf(stderr
, "-P name Override the default hardware platform.\n");
93 fprintf(stderr
, "-m IP Specify the IPv4 management addresses of this system.\n");
94 fprintf(stderr
, "-u file Specify the Unix-domain socket used for communication with lldpctl(8).\n");
95 fprintf(stderr
, "-H mode Specify the behaviour when detecting multiple neighbors.\n");
96 fprintf(stderr
, "-I iface Limit interfaces to use.\n");
98 fprintf(stderr
, "-M class Enable emission of LLDP-MED frame. 'class' should be one of:\n");
99 fprintf(stderr
, " 1 Generic Endpoint (Class I)\n");
100 fprintf(stderr
, " 2 Media Endpoint (Class II)\n");
101 fprintf(stderr
, " 3 Communication Device Endpoints (Class III)\n");
102 fprintf(stderr
, " 4 Network Connectivity Device\n");
105 fprintf(stderr
, "-x Enable SNMP subagent.\n");
107 fprintf(stderr
, "\n");
109 #if defined ENABLE_CDP || defined ENABLE_EDP || defined ENABLE_FDP || defined ENABLE_SONMP
110 fprintf(stderr
, "Additional protocol support.\n");
112 fprintf(stderr
, "-c Enable the support of CDP protocol. (Cisco)\n");
115 fprintf(stderr
, "-e Enable the support of EDP protocol. (Extreme)\n");
118 fprintf(stderr
, "-f Enable the support of FDP protocol. (Foundry)\n");
121 fprintf(stderr
, "-s Enable the support of SONMP protocol. (Nortel)\n");
124 fprintf(stderr
, "\n");
127 fprintf(stderr
, "see manual page lldpd(8) for more information\n");
131 struct lldpd_hardware
*
132 lldpd_get_hardware(struct lldpd
*cfg
, char *name
, int index
)
134 struct lldpd_hardware
*hardware
;
135 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
136 if ((strcmp(hardware
->h_ifname
, name
) == 0) &&
137 (hardware
->h_ifindex
== index
))
144 * Allocate the default local port. This port will be cloned each time we need a
148 lldpd_alloc_default_local_port(struct lldpd
*cfg
)
150 struct lldpd_port
*port
;
152 if ((port
= (struct lldpd_port
*)
153 calloc(1, sizeof(struct lldpd_port
))) == NULL
)
157 TAILQ_INIT(&port
->p_vlans
);
158 TAILQ_INIT(&port
->p_ppvids
);
159 TAILQ_INIT(&port
->p_pids
);
162 TAILQ_INIT(&port
->p_custom_list
);
164 cfg
->g_default_local_port
= port
;
168 * Clone a given port. The destination needs to be already allocated.
171 lldpd_clone_port(struct lldpd_port
*destination
, struct lldpd_port
*source
)
174 u_int8_t
*output
= NULL
;
176 struct lldpd_port
*cloned
= NULL
;
177 output_len
= lldpd_port_serialize(source
, (void**)&output
);
178 if (output_len
== -1 ||
179 lldpd_port_unserialize(output
, output_len
, &cloned
) <= 0) {
180 log_warnx("alloc", "unable to clone default port");
184 memcpy(destination
, cloned
, sizeof(struct lldpd_port
));
188 marshal_repair_tailq(lldpd_vlan
, &destination
->p_vlans
, v_entries
);
189 marshal_repair_tailq(lldpd_ppvid
, &destination
->p_ppvids
, p_entries
);
190 marshal_repair_tailq(lldpd_pi
, &destination
->p_pids
, p_entries
);
193 marshal_repair_tailq(lldpd_custom
, &destination
->p_custom_list
, next
);
198 struct lldpd_hardware
*
199 lldpd_alloc_hardware(struct lldpd
*cfg
, char *name
, int index
)
201 struct lldpd_hardware
*hardware
;
203 log_debug("alloc", "allocate a new local port (%s)", name
);
205 if ((hardware
= (struct lldpd_hardware
*)
206 calloc(1, sizeof(struct lldpd_hardware
))) == NULL
)
209 /* Clone default local port */
210 if (lldpd_clone_port(&hardware
->h_lport
, cfg
->g_default_local_port
) == -1) {
211 log_warnx("alloc", "unable to clone default port");
216 hardware
->h_cfg
= cfg
;
217 strlcpy(hardware
->h_ifname
, name
, sizeof(hardware
->h_ifname
));
218 hardware
->h_ifindex
= index
;
219 hardware
->h_lport
.p_chassis
= LOCAL_CHASSIS(cfg
);
220 hardware
->h_lport
.p_chassis
->c_refcount
++;
221 TAILQ_INIT(&hardware
->h_rports
);
223 #ifdef ENABLE_LLDPMED
224 if (LOCAL_CHASSIS(cfg
)->c_med_cap_available
) {
225 hardware
->h_lport
.p_med_cap_enabled
= LLDP_MED_CAP_CAP
;
226 if (!cfg
->g_config
.c_noinventory
)
227 hardware
->h_lport
.p_med_cap_enabled
|= LLDP_MED_CAP_IV
;
231 levent_hardware_init(hardware
);
236 lldpd_alloc_mgmt(int family
, void *addrptr
, size_t addrsize
, u_int32_t iface
)
238 struct lldpd_mgmt
*mgmt
;
240 log_debug("alloc", "allocate a new management address (family: %d)", family
);
242 if (family
<= LLDPD_AF_UNSPEC
|| family
>= LLDPD_AF_LAST
) {
243 errno
= EAFNOSUPPORT
;
246 if (addrsize
> LLDPD_MGMT_MAXADDRSIZE
) {
250 mgmt
= calloc(1, sizeof(struct lldpd_mgmt
));
255 mgmt
->m_family
= family
;
256 memcpy(&mgmt
->m_addr
, addrptr
, addrsize
);
257 mgmt
->m_addrsize
= addrsize
;
258 mgmt
->m_iface
= iface
;
263 lldpd_hardware_cleanup(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
)
265 log_debug("alloc", "cleanup hardware port %s", hardware
->h_ifname
);
267 free(hardware
->h_lport_previous
);
268 free(hardware
->h_lchassis_previous_id
);
269 free(hardware
->h_lport_previous_id
);
270 lldpd_port_cleanup(&hardware
->h_lport
, 1);
271 if (hardware
->h_ops
&& hardware
->h_ops
->cleanup
)
272 hardware
->h_ops
->cleanup(cfg
, hardware
);
273 levent_hardware_release(hardware
);
278 lldpd_display_neighbors(struct lldpd
*cfg
)
280 if (!cfg
->g_config
.c_set_ifdescr
) return;
281 struct lldpd_hardware
*hardware
;
282 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
283 struct lldpd_port
*port
;
285 const char *neighbor
= NULL
;
286 unsigned neighbors
= 0;
287 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
) {
288 if (SMART_HIDDEN(port
)) continue;
290 neighbor
= port
->p_chassis
->c_name
;
293 priv_iface_description(hardware
->h_ifname
,
295 else if (neighbors
== 1 && neighbor
&& *neighbor
!= '\0') {
296 if (asprintf(&description
, "%s",
298 priv_iface_description(hardware
->h_ifname
, description
);
302 if (asprintf(&description
, "%d neighbor%s",
303 neighbors
, (neighbors
> 1)?"s":"") != -1) {
304 priv_iface_description(hardware
->h_ifname
,
313 lldpd_count_neighbors(struct lldpd
*cfg
)
315 #if HAVE_SETPROCTITLE
316 struct lldpd_chassis
*chassis
;
317 const char *neighbor
;
318 unsigned neighbors
= 0;
319 TAILQ_FOREACH(chassis
, &cfg
->g_chassis
, c_entries
) {
321 neighbor
= chassis
->c_name
;
325 setproctitle("no neighbor.");
326 else if (neighbors
== 1 && neighbor
&& *neighbor
!= '\0')
327 setproctitle("connected to %s.", neighbor
);
329 setproctitle("%d neighbor%s.", neighbors
,
330 (neighbors
> 1)?"s":"");
332 lldpd_display_neighbors(cfg
);
336 notify_clients_deletion(struct lldpd_hardware
*hardware
,
337 struct lldpd_port
*rport
)
339 TRACE(LLDPD_NEIGHBOR_DELETE(hardware
->h_ifname
,
340 rport
->p_chassis
->c_name
,
342 levent_ctl_notify(hardware
->h_ifname
, NEIGHBOR_CHANGE_DELETED
,
345 agent_notify(hardware
, NEIGHBOR_CHANGE_DELETED
, rport
);
350 lldpd_reset_timer(struct lldpd
*cfg
)
352 /* Reset timer for ports that have been changed. */
353 struct lldpd_hardware
*hardware
;
354 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
355 /* We keep a flat copy of the local port to see if there is any
356 * change. To do this, we zero out fields that are not
357 * significant, marshal the port, then restore. */
358 struct lldpd_port
*port
= &hardware
->h_lport
;
359 /* Take the current flags into account to detect a change. */
360 port
->_p_hardware_flags
= hardware
->h_flags
;
361 u_int8_t
*output
= NULL
;
363 char save
[LLDPD_PORT_START_MARKER
];
364 memcpy(save
, port
, sizeof(save
));
365 /* coverity[suspicious_sizeof]
366 We intentionally partially memset port */
367 memset(port
, 0, sizeof(save
));
368 output_len
= lldpd_port_serialize(port
, (void**)&output
);
369 memcpy(port
, save
, sizeof(save
));
370 if (output_len
== -1) {
371 log_warnx("localchassis",
372 "unable to serialize local port %s to check for differences",
377 /* Compare with the previous value */
378 if (hardware
->h_lport_previous
&&
379 output_len
== hardware
->h_lport_previous_len
&&
380 !memcmp(output
, hardware
->h_lport_previous
, output_len
)) {
381 log_debug("localchassis",
382 "no change detected for port %s",
385 log_debug("localchassis",
386 "change detected for port %s, resetting its timer",
388 levent_schedule_pdu(hardware
);
391 /* Update the value */
392 free(hardware
->h_lport_previous
);
393 hardware
->h_lport_previous
= output
;
394 hardware
->h_lport_previous_len
= output_len
;
399 lldpd_all_chassis_cleanup(struct lldpd
*cfg
)
401 struct lldpd_chassis
*chassis
, *chassis_next
;
402 log_debug("localchassis", "cleanup all chassis");
404 for (chassis
= TAILQ_FIRST(&cfg
->g_chassis
); chassis
;
405 chassis
= chassis_next
) {
406 chassis_next
= TAILQ_NEXT(chassis
, c_entries
);
407 if (chassis
->c_refcount
== 0) {
408 TAILQ_REMOVE(&cfg
->g_chassis
, chassis
, c_entries
);
409 lldpd_chassis_cleanup(chassis
, 1);
415 lldpd_cleanup(struct lldpd
*cfg
)
417 struct lldpd_hardware
*hardware
, *hardware_next
;
419 log_debug("localchassis", "cleanup all ports");
421 for (hardware
= TAILQ_FIRST(&cfg
->g_hardware
); hardware
!= NULL
;
422 hardware
= hardware_next
) {
423 hardware_next
= TAILQ_NEXT(hardware
, h_entries
);
424 if (!hardware
->h_flags
) {
425 TRACE(LLDPD_INTERFACES_DELETE(hardware
->h_ifname
));
426 TAILQ_REMOVE(&cfg
->g_hardware
, hardware
, h_entries
);
427 lldpd_remote_cleanup(hardware
, notify_clients_deletion
, 1);
428 lldpd_hardware_cleanup(cfg
, hardware
);
430 lldpd_remote_cleanup(hardware
, notify_clients_deletion
,
431 !(hardware
->h_flags
& IFF_RUNNING
));
435 levent_schedule_cleanup(cfg
);
436 lldpd_all_chassis_cleanup(cfg
);
437 lldpd_count_neighbors(cfg
);
440 /* Update chassis `ochassis' with values from `chassis'. The later one is not
441 expected to be part of a list! It will also be wiped from memory. */
443 lldpd_move_chassis(struct lldpd_chassis
*ochassis
,
444 struct lldpd_chassis
*chassis
) {
445 struct lldpd_mgmt
*mgmt
, *mgmt_next
;
447 /* We want to keep refcount, index and list stuff from the current
449 TAILQ_ENTRY(lldpd_chassis
) entries
;
450 int refcount
= ochassis
->c_refcount
;
451 int index
= ochassis
->c_index
;
452 memcpy(&entries
, &ochassis
->c_entries
,
454 lldpd_chassis_cleanup(ochassis
, 0);
457 /* WARNING: this is a kludgy hack, we need in-place copy and cannot use
459 memcpy(ochassis
, chassis
, sizeof(struct lldpd_chassis
));
460 TAILQ_INIT(&ochassis
->c_mgmt
);
462 /* Copy of management addresses */
463 for (mgmt
= TAILQ_FIRST(&chassis
->c_mgmt
);
466 mgmt_next
= TAILQ_NEXT(mgmt
, m_entries
);
467 TAILQ_REMOVE(&chassis
->c_mgmt
, mgmt
, m_entries
);
468 TAILQ_INSERT_TAIL(&ochassis
->c_mgmt
, mgmt
, m_entries
);
471 /* Restore saved values */
472 ochassis
->c_refcount
= refcount
;
473 ochassis
->c_index
= index
;
474 memcpy(&ochassis
->c_entries
, &entries
, sizeof(entries
));
476 /* Get rid of the new chassis */
481 lldpd_guess_type(struct lldpd
*cfg
, char *frame
, int s
)
484 if (s
< ETHER_ADDR_LEN
)
486 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
487 if (!cfg
->g_protocols
[i
].enabled
)
489 if (cfg
->g_protocols
[i
].guess
== NULL
) {
490 if (memcmp(frame
, cfg
->g_protocols
[i
].mac1
, ETHER_ADDR_LEN
) == 0 ||
491 memcmp(frame
, cfg
->g_protocols
[i
].mac2
, ETHER_ADDR_LEN
) == 0 ||
492 memcmp(frame
, cfg
->g_protocols
[i
].mac3
, ETHER_ADDR_LEN
) == 0) {
493 log_debug("decode", "guessed protocol is %s (from MAC address)",
494 cfg
->g_protocols
[i
].name
);
495 return cfg
->g_protocols
[i
].mode
;
498 if (cfg
->g_protocols
[i
].guess(frame
, s
)) {
499 log_debug("decode", "guessed protocol is %s (from detector function)",
500 cfg
->g_protocols
[i
].name
);
501 return cfg
->g_protocols
[i
].mode
;
509 lldpd_decode(struct lldpd
*cfg
, char *frame
, int s
,
510 struct lldpd_hardware
*hardware
)
513 struct lldpd_chassis
*chassis
, *ochassis
= NULL
;
514 struct lldpd_port
*port
, *oport
= NULL
, *aport
;
515 int guess
= LLDPD_MODE_LLDP
;
517 log_debug("decode", "decode a received frame on %s",
520 if (s
< sizeof(struct ether_header
) + 4)
521 /* Too short, just discard it */
524 /* Decapsulate VLAN frames */
525 struct ether_header eheader
;
526 memcpy(&eheader
, frame
, sizeof(struct ether_header
));
527 if (eheader
.ether_type
== htons(ETHERTYPE_VLAN
)) {
528 /* VLAN decapsulation means to shift 4 bytes left the frame from
529 * offset 2*ETHER_ADDR_LEN */
530 memmove(frame
+ 2*ETHER_ADDR_LEN
, frame
+ 2*ETHER_ADDR_LEN
+ 4, s
- 2*ETHER_ADDR_LEN
);
534 TAILQ_FOREACH(oport
, &hardware
->h_rports
, p_entries
) {
535 if ((oport
->p_lastframe
!= NULL
) &&
536 (oport
->p_lastframe
->size
== s
) &&
537 (memcmp(oport
->p_lastframe
->frame
, frame
, s
) == 0)) {
538 /* Already received the same frame */
539 log_debug("decode", "duplicate frame, no need to decode");
540 oport
->p_lastupdate
= time(NULL
);
545 guess
= lldpd_guess_type(cfg
, frame
, s
);
546 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
547 if (!cfg
->g_protocols
[i
].enabled
)
549 if (cfg
->g_protocols
[i
].mode
== guess
) {
550 log_debug("decode", "using decode function for %s protocol",
551 cfg
->g_protocols
[i
].name
);
552 if (cfg
->g_protocols
[i
].decode(cfg
, frame
,
553 s
, hardware
, &chassis
, &port
) == -1) {
554 log_debug("decode", "function for %s protocol did not decode this frame",
555 cfg
->g_protocols
[i
].name
);
558 chassis
->c_protocol
= port
->p_protocol
=
559 cfg
->g_protocols
[i
].mode
;
563 if (cfg
->g_protocols
[i
].mode
== 0) {
564 log_debug("decode", "unable to guess frame type on %s",
568 TRACE(LLDPD_FRAME_DECODED(
570 cfg
->g_protocols
[i
].name
,
574 /* Do we already have the same MSAP somewhere? */
576 log_debug("decode", "search for the same MSAP");
577 TAILQ_FOREACH(oport
, &hardware
->h_rports
, p_entries
) {
578 if (port
->p_protocol
== oport
->p_protocol
) {
580 if ((port
->p_id_subtype
== oport
->p_id_subtype
) &&
581 (port
->p_id_len
== oport
->p_id_len
) &&
582 (memcmp(port
->p_id
, oport
->p_id
, port
->p_id_len
) == 0) &&
583 (chassis
->c_id_subtype
== oport
->p_chassis
->c_id_subtype
) &&
584 (chassis
->c_id_len
== oport
->p_chassis
->c_id_len
) &&
585 (memcmp(chassis
->c_id
, oport
->p_chassis
->c_id
,
586 chassis
->c_id_len
) == 0)) {
587 ochassis
= oport
->p_chassis
;
588 log_debug("decode", "MSAP is already known");
593 /* Do we have room for a new MSAP? */
594 if (!oport
&& cfg
->g_config
.c_max_neighbors
) {
595 if (count
== (cfg
->g_config
.c_max_neighbors
- 1)) {
597 "max neighbors %d reached for port %s, "
598 "dropping any new ones silently",
599 cfg
->g_config
.c_max_neighbors
,
601 } else if (count
> cfg
->g_config
.c_max_neighbors
- 1) {
603 "too many neighbors for port %s, drop this new one",
605 lldpd_port_cleanup(port
, 1);
606 lldpd_chassis_cleanup(chassis
, 1);
611 /* No, but do we already know the system? */
613 log_debug("decode", "MSAP is unknown, search for the chassis");
614 TAILQ_FOREACH(ochassis
, &cfg
->g_chassis
, c_entries
) {
615 if ((chassis
->c_protocol
== ochassis
->c_protocol
) &&
616 (chassis
->c_id_subtype
== ochassis
->c_id_subtype
) &&
617 (chassis
->c_id_len
== ochassis
->c_id_len
) &&
618 (memcmp(chassis
->c_id
, ochassis
->c_id
,
619 chassis
->c_id_len
) == 0))
625 /* The port is known, remove it before adding it back */
626 TAILQ_REMOVE(&hardware
->h_rports
, oport
, p_entries
);
627 lldpd_port_cleanup(oport
, 1);
631 lldpd_move_chassis(ochassis
, chassis
);
634 /* Chassis not known, add it */
635 log_debug("decode", "unknown chassis, add it to the list");
636 chassis
->c_index
= ++cfg
->g_lastrid
;
637 chassis
->c_refcount
= 0;
638 TAILQ_INSERT_TAIL(&cfg
->g_chassis
, chassis
, c_entries
);
639 i
= 0; TAILQ_FOREACH(ochassis
, &cfg
->g_chassis
, c_entries
) i
++;
640 log_debug("decode", "%d different systems are known", i
);
643 port
->p_lastchange
= port
->p_lastupdate
= time(NULL
);
644 if ((port
->p_lastframe
= (struct lldpd_frame
*)malloc(s
+
645 sizeof(struct lldpd_frame
))) != NULL
) {
646 port
->p_lastframe
->size
= s
;
647 memcpy(port
->p_lastframe
->frame
, frame
, s
);
649 TAILQ_INSERT_TAIL(&hardware
->h_rports
, port
, p_entries
);
650 port
->p_chassis
= chassis
;
651 port
->p_chassis
->c_refcount
++;
652 /* Several cases are possible :
653 1. chassis is new, its refcount was 0. It is now attached
654 to this port, its refcount is 1.
655 2. chassis already exists and was attached to another
656 port, we increase its refcount accordingly.
657 3. chassis already exists and was attached to the same
658 port, its refcount was decreased with
659 lldpd_port_cleanup() and is now increased again.
661 In all cases, if the port already existed, it has been
662 freed with lldpd_port_cleanup() and therefore, the refcount
663 of the chassis that was attached to it is decreased.
665 /* coverity[use_after_free]
666 TAILQ_REMOVE does the right thing */
667 i
= 0; TAILQ_FOREACH(aport
, &hardware
->h_rports
, p_entries
)
669 log_debug("decode", "%d neighbors for %s", i
,
672 if (!oport
) hardware
->h_insert_cnt
++;
675 log_debug("decode", "send notifications for changes on %s",
678 TRACE(LLDPD_NEIGHBOR_UPDATE(hardware
->h_ifname
,
682 levent_ctl_notify(hardware
->h_ifname
, NEIGHBOR_CHANGE_UPDATED
, port
);
684 agent_notify(hardware
, NEIGHBOR_CHANGE_UPDATED
, port
);
687 TRACE(LLDPD_NEIGHBOR_NEW(hardware
->h_ifname
,
691 levent_ctl_notify(hardware
->h_ifname
, NEIGHBOR_CHANGE_ADDED
, port
);
693 agent_notify(hardware
, NEIGHBOR_CHANGE_ADDED
, port
);
697 #ifdef ENABLE_LLDPMED
698 if (!oport
&& port
->p_chassis
->c_med_type
) {
699 /* New neighbor, fast start */
700 if (hardware
->h_cfg
->g_config
.c_enable_fast_start
&&
701 !hardware
->h_tx_fast
) {
702 log_debug("decode", "%s: entering fast start due to "
703 "new neighbor", hardware
->h_ifname
);
704 hardware
->h_tx_fast
= hardware
->h_cfg
->g_config
.c_tx_fast_init
;
707 levent_schedule_pdu(hardware
);
714 /* Get the output of lsb_release -s -d. This is a slow function. It should be
715 called once. It return NULL if any problem happens. Otherwise, this is a
716 statically allocated buffer. The result includes the trailing \n */
718 lldpd_get_lsb_release() {
719 static char release
[1024];
720 char *const command
[] = { "lsb_release", "-s", "-d", NULL
};
721 int pid
, status
, devnull
, count
;
724 log_debug("localchassis", "grab LSB release");
727 log_warn("localchassis", "unable to get a pair of pipes");
734 log_warn("localchassis", "unable to fork");
737 /* Child, exec lsb_release */
739 if ((devnull
= open("/dev/null", O_RDWR
, 0)) != -1) {
740 dup2(devnull
, STDIN_FILENO
);
741 dup2(devnull
, STDERR_FILENO
);
742 dup2(pipefd
[1], STDOUT_FILENO
);
743 if (devnull
> 2) close(devnull
);
744 if (pipefd
[1] > 2) close(pipefd
[1]);
745 execvp("lsb_release", command
);
750 /* Father, read the output from the children */
754 status
= read(pipefd
[0], release
+count
, sizeof(release
)-count
);
755 if ((status
== -1) && (errno
== EINTR
)) continue;
758 } while (count
< sizeof(release
) && (status
> 0));
760 log_info("localchassis", "unable to read from lsb_release");
762 waitpid(pid
, &status
, 0);
766 if (count
>= sizeof(release
)) {
767 log_info("localchassis", "output of lsb_release is too large");
768 waitpid(pid
, &status
, 0);
772 if (waitpid(pid
, &status
, 0) != pid
)
774 if (!WIFEXITED(status
) || (WEXITSTATUS(status
) != 0)) {
775 log_info("localchassis", "lsb_release information not available");
779 log_info("localchassis", "lsb_release returned an empty string");
782 release
[count
] = '\0';
785 /* Should not be here */
789 /* Same like lldpd_get_lsb_release but reads /etc/os-release for PRETTY_NAME=. */
791 lldpd_get_os_release() {
792 static char release
[1024];
795 char *ptr1
= release
;
797 log_debug("localchassis", "grab OS release");
798 FILE *fp
= fopen("/etc/os-release", "r");
800 log_debug("localchassis", "could not open /etc/os-release");
801 fp
= fopen("/usr/lib/os-release", "r");
804 log_info("localchassis",
805 "could not open either /etc/os-release or /usr/lib/os-release");
809 while ((fgets(line
, sizeof(line
), fp
) != NULL
)) {
810 key
= strtok(line
, "=");
811 val
= strtok(NULL
, "=");
813 if (strncmp(key
, "PRETTY_NAME", sizeof(line
)) == 0) {
814 strlcpy(release
, val
, sizeof(line
));
820 /* Remove trailing newline and all " in the string. */
821 ptr1
= release
+ strlen(release
) - 1;
822 while (ptr1
!= release
&&
823 ((*ptr1
== '"') || (*ptr1
== '\n'))) {
827 if (release
[0] == '"')
833 lldpd_hide_ports(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
, int mask
) {
834 struct lldpd_port
*port
;
835 int protocols
[LLDPD_MODE_MAX
+1];
840 log_debug("smartfilter", "apply smart filter for port %s",
843 /* Compute the number of occurrences of each protocol */
844 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++) protocols
[i
] = 0;
845 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
)
846 protocols
[port
->p_protocol
]++;
848 /* Turn the protocols[] array into an array of
849 enabled/disabled protocols. 1 means enabled, 0
851 min
= (unsigned int)-1;
852 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++)
853 if (protocols
[i
] && (protocols
[i
] < min
))
856 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++)
857 if ((protocols
[i
] == min
) && !found
) {
858 /* If we need a tie breaker, we take
859 the first protocol only */
860 if (cfg
->g_config
.c_smart
& mask
&
861 (SMART_OUTGOING_ONE_PROTO
| SMART_INCOMING_ONE_PROTO
))
864 } else protocols
[i
] = 0;
866 /* We set the p_hidden flag to 1 if the protocol is disabled */
867 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
) {
868 if (mask
== SMART_OUTGOING
)
869 port
->p_hidden_out
= protocols
[port
->p_protocol
]?0:1;
871 port
->p_hidden_in
= protocols
[port
->p_protocol
]?0:1;
874 /* If we want only one neighbor, we take the first one */
875 if (cfg
->g_config
.c_smart
& mask
&
876 (SMART_OUTGOING_ONE_NEIGH
| SMART_INCOMING_ONE_NEIGH
)) {
878 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
) {
879 if (mask
== SMART_OUTGOING
) {
880 if (found
) port
->p_hidden_out
= 1;
881 if (!port
->p_hidden_out
)
884 if (mask
== SMART_INCOMING
) {
885 if (found
) port
->p_hidden_in
= 1;
886 if (!port
->p_hidden_in
)
892 /* Print a debug message summarizing the operation */
893 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++) protocols
[i
] = 0;
895 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
) {
896 if (!(((mask
== SMART_OUTGOING
) && port
->p_hidden_out
) ||
897 ((mask
== SMART_INCOMING
) && port
->p_hidden_in
))) {
899 protocols
[port
->p_protocol
] = 1;
904 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
905 if (cfg
->g_protocols
[i
].enabled
&& protocols
[cfg
->g_protocols
[i
].mode
]) {
907 strlen(cfg
->g_protocols
[i
].name
) + 3 > sizeof(buffer
)) {
908 /* Unlikely, our buffer is too small */
909 memcpy(buffer
+ sizeof(buffer
) - 4, "...", 4);
913 strncat(buffer
, ", ", 2);
914 strncat(buffer
, cfg
->g_protocols
[i
].name
, strlen(cfg
->g_protocols
[i
].name
));
917 log_debug("smartfilter", "%s: %s: %d visible neighbors (out of %d)",
919 (mask
== SMART_OUTGOING
)?"out filter":"in filter",
921 log_debug("smartfilter", "%s: protocols: %s",
922 hardware
->h_ifname
, buffer
[0]?buffer
:"(none)");
925 /* Hide unwanted ports depending on smart mode set by the user */
927 lldpd_hide_all(struct lldpd
*cfg
)
929 struct lldpd_hardware
*hardware
;
931 if (!cfg
->g_config
.c_smart
)
933 log_debug("smartfilter", "apply smart filter results on all ports");
934 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
935 if (cfg
->g_config
.c_smart
& SMART_INCOMING_FILTER
)
936 lldpd_hide_ports(cfg
, hardware
, SMART_INCOMING
);
937 if (cfg
->g_config
.c_smart
& SMART_OUTGOING_FILTER
)
938 lldpd_hide_ports(cfg
, hardware
, SMART_OUTGOING
);
943 lldpd_recv(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
, int fd
)
947 log_debug("receive", "receive a frame on %s",
949 if ((buffer
= (char *)malloc(hardware
->h_mtu
)) == NULL
) {
950 log_warn("receive", "failed to alloc reception buffer");
953 if ((n
= hardware
->h_ops
->recv(cfg
, hardware
,
955 hardware
->h_mtu
)) == -1) {
956 log_debug("receive", "discard frame received on %s",
961 if (hardware
->h_lport
.p_disable_rx
) {
962 log_debug("receive", "RX disabled, ignore the frame on %s",
967 if (cfg
->g_config
.c_paused
) {
968 log_debug("receive", "paused, ignore the frame on %s",
973 hardware
->h_rx_cnt
++;
974 log_debug("receive", "decode received frame on %s",
976 TRACE(LLDPD_FRAME_RECEIVED(hardware
->h_ifname
, buffer
, (size_t)n
));
977 lldpd_decode(cfg
, buffer
, n
, hardware
);
978 lldpd_hide_all(cfg
); /* Immediatly hide */
979 lldpd_count_neighbors(cfg
);
984 lldpd_send_shutdown(struct lldpd_hardware
*hardware
)
986 struct lldpd
*cfg
= hardware
->h_cfg
;
987 if (cfg
->g_config
.c_receiveonly
|| cfg
->g_config
.c_paused
) return;
988 if (hardware
->h_lport
.p_disable_tx
) return;
989 if ((hardware
->h_flags
& IFF_RUNNING
) == 0)
992 /* It's safe to call `lldp_send_shutdown()` because shutdown LLDPU will
993 * only be emitted if LLDP was sent on that port. */
994 if (lldp_send_shutdown(hardware
->h_cfg
, hardware
) != 0)
995 log_warnx("send", "unable to send shutdown LLDPDU on %s",
1000 lldpd_send(struct lldpd_hardware
*hardware
)
1002 struct lldpd
*cfg
= hardware
->h_cfg
;
1003 struct lldpd_port
*port
;
1006 if (cfg
->g_config
.c_receiveonly
|| cfg
->g_config
.c_paused
) return;
1007 if (hardware
->h_lport
.p_disable_tx
) return;
1008 if ((hardware
->h_flags
& IFF_RUNNING
) == 0)
1011 log_debug("send", "send PDU on %s", hardware
->h_ifname
);
1013 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
1014 if (!cfg
->g_protocols
[i
].enabled
)
1016 /* We send only if we have at least one remote system
1017 * speaking this protocol or if the protocol is forced */
1018 if (cfg
->g_protocols
[i
].enabled
> 1) {
1019 cfg
->g_protocols
[i
].send(cfg
, hardware
);
1023 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
) {
1024 /* If this remote port is disabled, we don't
1026 if (port
->p_hidden_out
)
1028 if (port
->p_protocol
==
1029 cfg
->g_protocols
[i
].mode
) {
1030 TRACE(LLDPD_FRAME_SEND(hardware
->h_ifname
,
1031 cfg
->g_protocols
[i
].name
));
1032 log_debug("send", "send PDU on %s with protocol %s",
1034 cfg
->g_protocols
[i
].name
);
1035 cfg
->g_protocols
[i
].send(cfg
,
1044 /* Nothing was sent for this port, let's speak the first
1045 * available protocol. */
1046 for (i
= 0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
1047 if (!cfg
->g_protocols
[i
].enabled
) continue;
1048 TRACE(LLDPD_FRAME_SEND(hardware
->h_ifname
,
1049 cfg
->g_protocols
[i
].name
));
1050 log_debug("send", "fallback to protocol %s for %s",
1051 cfg
->g_protocols
[i
].name
, hardware
->h_ifname
);
1052 cfg
->g_protocols
[i
].send(cfg
,
1056 if (cfg
->g_protocols
[i
].mode
== 0)
1057 log_warnx("send", "no protocol enabled, dunno what to send");
1061 #ifdef ENABLE_LLDPMED
1063 lldpd_med(struct lldpd_chassis
*chassis
)
1065 static short int once
= 0;
1067 chassis
->c_med_hw
= dmi_hw();
1068 chassis
->c_med_fw
= dmi_fw();
1069 chassis
->c_med_sn
= dmi_sn();
1070 chassis
->c_med_manuf
= dmi_manuf();
1071 chassis
->c_med_model
= dmi_model();
1072 chassis
->c_med_asset
= dmi_asset();
1079 lldpd_routing_enabled(struct lldpd
*cfg
)
1083 if ((LOCAL_CHASSIS(cfg
)->c_cap_available
& LLDP_CAP_ROUTER
) == 0)
1086 if ((routing
= interfaces_routing_enabled(cfg
)) == -1) {
1087 log_debug("localchassis", "unable to check if routing is enabled");
1094 lldpd_update_localchassis(struct lldpd
*cfg
)
1099 log_debug("localchassis", "update information for local chassis");
1100 assert(LOCAL_CHASSIS(cfg
) != NULL
);
1102 /* Set system name and description */
1104 fatal("localchassis", "failed to get system information");
1105 if (cfg
->g_config
.c_hostname
) {
1106 log_debug("localchassis", "use overridden system name `%s`", cfg
->g_config
.c_hostname
);
1107 hp
= cfg
->g_config
.c_hostname
;
1109 if ((hp
= priv_gethostname()) == NULL
)
1110 fatal("localchassis", "failed to get system name");
1112 free(LOCAL_CHASSIS(cfg
)->c_name
);
1113 free(LOCAL_CHASSIS(cfg
)->c_descr
);
1114 if ((LOCAL_CHASSIS(cfg
)->c_name
= strdup(hp
)) == NULL
)
1115 fatal("localchassis", NULL
);
1116 if (cfg
->g_config
.c_description
) {
1117 log_debug("localchassis", "use overridden description `%s`", cfg
->g_config
.c_description
);
1118 if (asprintf(&LOCAL_CHASSIS(cfg
)->c_descr
, "%s",
1119 cfg
->g_config
.c_description
) == -1)
1120 fatal("localchassis", "failed to set full system description");
1122 if (cfg
->g_config
.c_advertise_version
) {
1123 log_debug("localchassis", "advertise system version");
1124 if (asprintf(&LOCAL_CHASSIS(cfg
)->c_descr
, "%s %s %s %s %s",
1125 cfg
->g_lsb_release
?cfg
->g_lsb_release
:"",
1126 un
.sysname
, un
.release
, un
.version
, un
.machine
)
1128 fatal("localchassis", "failed to set full system description");
1130 log_debug("localchassis", "do not advertise system version");
1131 if (asprintf(&LOCAL_CHASSIS(cfg
)->c_descr
, "%s",
1132 cfg
->g_lsb_release
?cfg
->g_lsb_release
:un
.sysname
) == -1)
1133 fatal("localchassis", "failed to set minimal system description");
1136 if (cfg
->g_config
.c_platform
== NULL
)
1137 cfg
->g_config
.c_platform
= strdup(un
.sysname
);
1140 if (lldpd_routing_enabled(cfg
)) {
1141 log_debug("localchassis", "routing is enabled, enable router capability");
1142 LOCAL_CHASSIS(cfg
)->c_cap_enabled
|= LLDP_CAP_ROUTER
;
1144 LOCAL_CHASSIS(cfg
)->c_cap_enabled
&= ~LLDP_CAP_ROUTER
;
1146 #ifdef ENABLE_LLDPMED
1147 if (LOCAL_CHASSIS(cfg
)->c_cap_available
& LLDP_CAP_TELEPHONE
)
1148 LOCAL_CHASSIS(cfg
)->c_cap_enabled
|= LLDP_CAP_TELEPHONE
;
1149 lldpd_med(LOCAL_CHASSIS(cfg
));
1150 free(LOCAL_CHASSIS(cfg
)->c_med_sw
);
1151 if (cfg
->g_config
.c_advertise_version
)
1152 LOCAL_CHASSIS(cfg
)->c_med_sw
= strdup(un
.release
);
1154 LOCAL_CHASSIS(cfg
)->c_med_sw
= strdup("Unknown");
1156 if ((LOCAL_CHASSIS(cfg
)->c_cap_available
& LLDP_CAP_STATION
) &&
1157 (LOCAL_CHASSIS(cfg
)->c_cap_enabled
== 0))
1158 LOCAL_CHASSIS(cfg
)->c_cap_enabled
= LLDP_CAP_STATION
;
1160 /* Set chassis ID if needed. This is only done if chassis ID
1161 has not been set previously (with the MAC address of an
1162 interface for example)
1164 if (LOCAL_CHASSIS(cfg
)->c_id
== NULL
) {
1165 log_debug("localchassis", "no chassis ID is currently set, use chassis name");
1166 if (!(LOCAL_CHASSIS(cfg
)->c_id
= strdup(LOCAL_CHASSIS(cfg
)->c_name
)))
1167 fatal("localchassis", NULL
);
1168 LOCAL_CHASSIS(cfg
)->c_id_len
= strlen(LOCAL_CHASSIS(cfg
)->c_name
);
1169 LOCAL_CHASSIS(cfg
)->c_id_subtype
= LLDP_CHASSISID_SUBTYPE_LOCAL
;
1174 lldpd_update_localports(struct lldpd
*cfg
)
1176 struct lldpd_hardware
*hardware
;
1178 log_debug("localchassis", "update information for local ports");
1180 /* h_flags is set to 0 for each port. If the port is updated, h_flags
1181 * will be set to a non-zero value. This will allow us to clean up any
1182 * non up-to-date port */
1183 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
1184 hardware
->h_flags
= 0;
1186 TRACE(LLDPD_INTERFACES_UPDATE());
1187 interfaces_update(cfg
);
1189 lldpd_reset_timer(cfg
);
1193 lldpd_loop(struct lldpd
*cfg
)
1196 1. Update local ports information
1197 2. Update local chassis information
1199 log_debug("loop", "start new loop");
1200 LOCAL_CHASSIS(cfg
)->c_cap_enabled
= 0;
1201 /* Information for local ports is triggered even when it is possible to
1202 * update them on some other event because we want to refresh them if we
1203 * missed something. */
1204 log_debug("loop", "update information for local ports");
1205 lldpd_update_localports(cfg
);
1206 log_debug("loop", "update information for local chassis");
1207 lldpd_update_localchassis(cfg
);
1208 lldpd_count_neighbors(cfg
);
1212 lldpd_exit(struct lldpd
*cfg
)
1214 struct lldpd_hardware
*hardware
, *hardware_next
;
1215 log_debug("main", "exit lldpd");
1217 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
1218 lldpd_send_shutdown(hardware
);
1221 priv_ctl_cleanup(cfg
->g_ctlname
);
1222 log_debug("main", "cleanup hardware information");
1223 for (hardware
= TAILQ_FIRST(&cfg
->g_hardware
); hardware
!= NULL
;
1224 hardware
= hardware_next
) {
1225 hardware_next
= TAILQ_NEXT(hardware
, h_entries
);
1226 log_debug("main", "cleanup interface %s", hardware
->h_ifname
);
1227 lldpd_remote_cleanup(hardware
, NULL
, 1);
1228 lldpd_hardware_cleanup(cfg
, hardware
);
1230 interfaces_cleanup(cfg
);
1231 lldpd_port_cleanup(cfg
->g_default_local_port
, 1);
1232 lldpd_all_chassis_cleanup(cfg
);
1233 free(cfg
->g_default_local_port
);
1234 free(cfg
->g_config
.c_platform
);
1238 * Run lldpcli to configure lldpd.
1240 * @return PID of running lldpcli or -1 if error.
1243 lldpd_configure(int use_syslog
, int debug
, const char *path
, const char *ctlname
)
1245 pid_t lldpcli
= vfork();
1248 char sdebug
[debug
+ 4];
1250 strlcpy(sdebug
, "-s", 3);
1252 /* debug = 0 -> -sd */
1253 /* debug = 1 -> -sdd */
1254 /* debug = 2 -> -sddd */
1255 memset(sdebug
, 'd', sizeof(sdebug
));
1256 sdebug
[debug
+ 3] = '\0';
1257 sdebug
[0] = '-'; sdebug
[1] = 's';
1259 log_debug("main", "invoke %s %s", path
, sdebug
);
1263 log_warn("main", "unable to fork");
1266 /* Child, exec lldpcli */
1267 if ((devnull
= open("/dev/null", O_RDWR
, 0)) != -1) {
1268 dup2(devnull
, STDIN_FILENO
);
1269 dup2(devnull
, STDOUT_FILENO
);
1270 if (devnull
> 2) close(devnull
);
1272 execl(path
, "lldpcli", sdebug
,
1274 "-c", SYSCONFDIR
"/lldpd.conf",
1275 "-c", SYSCONFDIR
"/lldpd.d",
1278 log_warn("main", "unable to execute %s", path
);
1279 log_warnx("main", "configuration is incomplete, lldpd needs to be unpaused");
1284 /* Father, don't do anything stupid */
1287 /* Should not be here */
1291 struct intint
{ int a
; int b
; };
1292 static const struct intint filters
[] = {
1294 { 1, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
1295 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
1296 { 2, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
},
1297 { 3, SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
1298 { 4, SMART_INCOMING_FILTER
| SMART_OUTGOING_FILTER
},
1299 { 5, SMART_INCOMING_FILTER
},
1300 { 6, SMART_OUTGOING_FILTER
},
1301 { 7, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_INCOMING_ONE_NEIGH
|
1302 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
1303 { 8, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_INCOMING_ONE_NEIGH
},
1304 { 9, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
|
1305 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
1306 { 10, SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1307 { 11, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
},
1308 { 12, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
|
1309 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1310 { 13, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
|
1311 SMART_OUTGOING_FILTER
},
1312 { 14, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
1313 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1314 { 15, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
1315 SMART_OUTGOING_FILTER
},
1316 { 16, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_INCOMING_ONE_NEIGH
|
1317 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1318 { 17, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_INCOMING_ONE_NEIGH
|
1319 SMART_OUTGOING_FILTER
},
1320 { 18, SMART_INCOMING_FILTER
|
1321 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1322 { 19, SMART_INCOMING_FILTER
|
1323 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
1329 * Tell if we have been started by upstart.
1332 lldpd_started_by_upstart()
1334 #ifdef HOST_OS_LINUX
1335 const char *upstartjob
= getenv("UPSTART_JOB");
1336 if (!(upstartjob
&& !strcmp(upstartjob
, "lldpd")))
1338 log_debug("main", "running with upstart, don't fork but stop");
1340 unsetenv("UPSTART_JOB");
1348 * Tell if we have been started by systemd.
1351 lldpd_started_by_systemd()
1353 #ifdef HOST_OS_LINUX
1355 const char *notifysocket
= getenv("NOTIFY_SOCKET");
1356 if (!notifysocket
||
1357 !strchr("@/", notifysocket
[0]) ||
1358 strlen(notifysocket
) < 2)
1361 log_debug("main", "running with systemd, don't fork but signal ready");
1362 if ((fd
= socket(AF_UNIX
, SOCK_DGRAM
, 0)) < 0) {
1363 log_warn("main", "unable to open systemd notification socket %s",
1368 struct sockaddr_un su
= { .sun_family
= AF_UNIX
};
1369 strlcpy(su
.sun_path
, notifysocket
, sizeof(su
.sun_path
));
1370 if (notifysocket
[0] == '@') su
.sun_path
[0] = 0;
1372 struct iovec iov
= {
1373 .iov_base
= "READY=1",
1374 .iov_len
= strlen("READY=1")
1376 struct msghdr hdr
= {
1378 .msg_namelen
= offsetof(struct sockaddr_un
, sun_path
) + strlen(notifysocket
),
1382 unsetenv("NOTIFY_SOCKET");
1383 if (sendmsg(fd
, &hdr
, MSG_NOSIGNAL
) < 0) {
1384 log_warn("main", "unable to send notification to systemd");
1396 #ifdef HOST_OS_LINUX
1398 version_convert(const char *sversion
, unsigned iversion
[], size_t n
)
1400 const char *p
= sversion
;
1402 for (size_t i
= 0; i
< n
; i
++) {
1403 iversion
[i
] = strtol(p
, &end
, 10);
1404 if (*end
!= '.') break;
1413 if (uname(&uts
) == -1) return;
1414 unsigned version_min
[3] = {};
1415 unsigned version_cur
[3] = {};
1416 version_convert(uts
.release
, version_cur
, 3);
1417 version_convert(MIN_LINUX_KERNEL_VERSION
, version_min
, 3);
1418 if (version_min
[0] > version_cur
[0] ||
1419 (version_min
[0] == version_cur
[0] && version_min
[1] > version_cur
[1]) ||
1420 (version_min
[0] == version_cur
[0] && version_min
[1] == version_cur
[1] &&
1421 version_min
[2] > version_cur
[2])) {
1422 log_warnx("lldpd", "minimal kernel version required is %s, got %s",
1423 MIN_LINUX_KERNEL_VERSION
, uts
.release
);
1424 log_warnx("lldpd", "lldpd may be unable to detect bonds and bridges correctly");
1425 #ifndef ENABLE_OLDIES
1426 log_warnx("lldpd", "consider recompiling with --enable-oldies option");
1431 static void version_check(void) {}
1435 lldpd_main(int argc
, char *argv
[], char *envp
[])
1438 struct lldpd_chassis
*lchassis
;
1439 int ch
, debug
= 0, use_syslog
= 1, daemonize
= 1;
1443 const char *agentx
= NULL
; /* AgentX socket */
1445 const char *ctlname
= NULL
;
1448 char *interfaces
= NULL
;
1449 /* We do not want more options here. Please add them in lldpcli instead
1450 * unless there is a very good reason. Most command-line options will
1451 * get deprecated at some point. */
1452 char *popt
, opts
[] =
1453 "H:vhkrdD:p:xX:m:u:4:6:I:C:p:M:P:S:iL:@ ";
1454 int i
, found
, advertise_version
= 1;
1455 #ifdef ENABLE_LLDPMED
1456 int lldpmed
= 0, noinventory
= 0;
1457 int enable_fast_start
= 1;
1459 char *descr_override
= NULL
;
1460 char *platform_override
= NULL
;
1461 char *lsb_release
= NULL
;
1462 const char *lldpcli
= LLDPCLI_PATH
;
1463 const char *pidfile
= LLDPD_PID_FILE
;
1465 int receiveonly
= 0, version
= 0;
1468 #ifdef ENABLE_PRIVSEP
1469 /* Non privileged user */
1470 struct passwd
*user
;
1471 struct group
*group
;
1478 #if HAVE_SETPROCTITLE_INIT
1479 setproctitle_init(argc
, argv
, envp
);
1483 * Get and parse command line options
1485 if ((popt
= strchr(opts
, '@')) != NULL
) {
1487 protos
[i
].mode
!= 0 && *popt
!= '\0';
1489 *(popt
++) = protos
[i
].arg
;
1492 while ((ch
= getopt(argc
, argv
, opts
)) != -1) {
1503 else if (use_syslog
)
1519 fprintf(stderr
, "-m can only be used once\n");
1522 mgmtp
= strdup(optarg
);
1526 fprintf(stderr
, "-u can only be used once\n");
1533 fprintf(stderr
, "-I can only be used once\n");
1536 interfaces
= strdup(optarg
);
1540 fprintf(stderr
, "-C can only be used once\n");
1543 cidp
= strdup(optarg
);
1546 if (strlen(optarg
)) lldpcli
= optarg
;
1547 else lldpcli
= NULL
;
1550 advertise_version
= 0;
1552 #ifdef ENABLE_LLDPMED
1554 lldpmed
= strtonum(optarg
, 1, 4, &errstr
);
1556 fprintf(stderr
, "-M requires an argument between 1 and 4\n");
1566 fprintf(stderr
, "LLDP-MED support is not built-in\n");
1576 fprintf(stderr
, "-X can only be used once\n");
1585 fprintf(stderr
, "SNMP support is not built-in\n");
1590 if (descr_override
) {
1591 fprintf(stderr
, "-S can only be used once\n");
1594 descr_override
= strdup(optarg
);
1597 if (platform_override
) {
1598 fprintf(stderr
, "-P can only be used once\n");
1601 platform_override
= strdup(optarg
);
1604 smart
= strtonum(optarg
, 0, sizeof(filters
)/sizeof(filters
[0]),
1607 fprintf(stderr
, "-H requires an int between 0 and %zu\n",
1608 sizeof(filters
)/sizeof(filters
[0]));
1614 for (i
=0; protos
[i
].mode
!= 0; i
++) {
1615 if (ch
== protos
[i
].arg
) {
1617 protos
[i
].enabled
++;
1626 version_display(stdout
, "lldpd", version
> 1);
1630 if (ctlname
== NULL
) ctlname
= LLDPD_CTL_SOCKET
;
1632 /* Set correct smart mode */
1633 for (i
=0; (filters
[i
].a
!= -1) && (filters
[i
].a
!= smart
); i
++);
1634 if (filters
[i
].a
== -1) {
1635 fprintf(stderr
, "Incorrect mode for -H\n");
1638 smart
= filters
[i
].b
;
1640 log_init(use_syslog
, debug
, __progname
);
1641 tzset(); /* Get timezone info before chroot */
1643 log_debug("main", "lldpd " PACKAGE_VERSION
" starting...");
1646 /* Grab uid and gid to use for priv sep */
1647 #ifdef ENABLE_PRIVSEP
1648 if ((user
= getpwnam(PRIVSEP_USER
)) == NULL
)
1649 fatalx("main", "no " PRIVSEP_USER
" user for privilege separation, please create it");
1651 if ((group
= getgrnam(PRIVSEP_GROUP
)) == NULL
)
1652 fatalx("main", "no " PRIVSEP_GROUP
" group for privilege separation, please create it");
1653 gid
= group
->gr_gid
;
1656 /* Create and setup socket */
1658 log_debug("main", "creating control socket");
1659 while ((ctl
= ctl_create(ctlname
)) == -1) {
1660 if (retry
-- && errno
== EADDRINUSE
) {
1661 /* Check if a daemon is really listening */
1663 log_info("main", "unable to create control socket because it already exists");
1664 log_info("main", "check if another instance is running");
1665 if ((tfd
= ctl_connect(ctlname
)) != -1) {
1666 /* Another instance is running */
1668 log_warnx("main", "another instance is running, please stop it");
1669 fatalx("main", "giving up");
1670 } else if (errno
== ECONNREFUSED
) {
1671 /* Nobody is listening */
1672 log_info("main", "old control socket is present, clean it");
1673 ctl_cleanup(ctlname
);
1676 log_warn("main", "cannot determine if another daemon is already running");
1677 fatalx("main", "giving up");
1679 log_warn("main", "unable to create control socket at %s", ctlname
);
1680 fatalx("main", "giving up");
1682 #ifdef ENABLE_PRIVSEP
1683 if (chown(ctlname
, uid
, gid
) == -1)
1684 log_warn("main", "unable to chown control socket");
1686 S_IRUSR
| S_IWUSR
| S_IXUSR
|
1687 S_IRGRP
| S_IWGRP
| S_IXGRP
) == -1)
1688 log_warn("main", "unable to chmod control socket");
1691 /* Disable SIGPIPE */
1692 signal(SIGPIPE
, SIG_IGN
);
1694 /* Disable SIGHUP, until handlers are installed */
1695 signal(SIGHUP
, SIG_IGN
);
1697 /* Daemonization, unless started by upstart, systemd or launchd or debug */
1700 !lldpd_started_by_upstart() && !lldpd_started_by_systemd()) {
1703 log_info("main", "going into background");
1704 if (daemon(0, 0) != 0)
1705 fatal("main", "failed to detach daemon");
1706 if ((pid
= open(pidfile
,
1707 O_TRUNC
| O_CREAT
| O_WRONLY
, 0666)) == -1)
1708 fatal("main", "unable to open pid file " LLDPD_PID_FILE
1709 " (or the specified one)");
1710 if (asprintf(&spid
, "%d\n", getpid()) == -1)
1711 fatal("main", "unable to create pid file " LLDPD_PID_FILE
1712 " (or the specified one)");
1713 if (write(pid
, spid
, strlen(spid
)) == -1)
1714 fatal("main", "unable to write pid file " LLDPD_PID_FILE
1715 " (or the specified one)");
1721 /* Configuration with lldpcli */
1723 log_debug("main", "invoking lldpcli for configuration");
1724 if (lldpd_configure(use_syslog
, debug
, lldpcli
, ctlname
) == -1)
1725 fatal("main", "unable to spawn lldpcli");
1728 /* Try to read system information from /etc/os-release if possible.
1729 Fall back to lsb_release for compatibility. */
1730 log_debug("main", "get OS/LSB release information");
1731 lsb_release
= lldpd_get_os_release();
1733 lsb_release
= lldpd_get_lsb_release();
1736 log_debug("main", "initialize privilege separation");
1737 #ifdef ENABLE_PRIVSEP
1738 priv_init(PRIVSEP_CHROOT
, ctl
, uid
, gid
);
1740 priv_init(PRIVSEP_CHROOT
, ctl
, 0, 0);
1743 /* Initialization of global configuration */
1744 if ((cfg
= (struct lldpd
*)
1745 calloc(1, sizeof(struct lldpd
))) == NULL
)
1746 fatal("main", NULL
);
1748 lldpd_alloc_default_local_port(cfg
);
1749 cfg
->g_ctlname
= ctlname
;
1751 cfg
->g_config
.c_mgmt_pattern
= mgmtp
;
1752 cfg
->g_config
.c_cid_pattern
= cidp
;
1753 cfg
->g_config
.c_iface_pattern
= interfaces
;
1754 cfg
->g_config
.c_smart
= smart
;
1756 cfg
->g_config
.c_paused
= 1;
1757 cfg
->g_config
.c_receiveonly
= receiveonly
;
1758 cfg
->g_config
.c_tx_interval
= LLDPD_TX_INTERVAL
;
1759 cfg
->g_config
.c_tx_hold
= LLDPD_TX_HOLD
;
1760 cfg
->g_config
.c_max_neighbors
= LLDPD_MAX_NEIGHBORS
;
1761 #ifdef ENABLE_LLDPMED
1762 cfg
->g_config
.c_enable_fast_start
= enable_fast_start
;
1763 cfg
->g_config
.c_tx_fast_init
= LLDPD_FAST_INIT
;
1764 cfg
->g_config
.c_tx_fast_interval
= LLDPD_FAST_TX_INTERVAL
;
1768 cfg
->g_snmp_agentx
= agentx
;
1769 #endif /* USE_SNMP */
1770 cfg
->g_config
.c_bond_slave_src_mac_type
= \
1771 LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED
;
1773 /* Get ioctl socket */
1774 log_debug("main", "get an ioctl socket");
1775 if ((cfg
->g_sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1776 fatal("main", "failed to get ioctl socket");
1779 if (!(cfg
->g_config
.c_advertise_version
= advertise_version
) &&
1780 lsb_release
&& lsb_release
[strlen(lsb_release
) - 1] == '\n')
1781 lsb_release
[strlen(lsb_release
) - 1] = '\0';
1782 cfg
->g_lsb_release
= lsb_release
;
1784 cfg
->g_config
.c_description
= descr_override
;
1786 if (platform_override
)
1787 cfg
->g_config
.c_platform
= platform_override
;
1789 /* Set system capabilities */
1790 log_debug("main", "set system capabilities");
1791 if ((lchassis
= (struct lldpd_chassis
*)
1792 calloc(1, sizeof(struct lldpd_chassis
))) == NULL
)
1793 fatal("localchassis", NULL
);
1794 cfg
->g_config
.c_cap_advertise
= 1;
1795 lchassis
->c_cap_available
= LLDP_CAP_BRIDGE
| LLDP_CAP_WLAN
|
1796 LLDP_CAP_ROUTER
| LLDP_CAP_STATION
;
1797 cfg
->g_config
.c_mgmt_advertise
= 1;
1798 TAILQ_INIT(&lchassis
->c_mgmt
);
1799 #ifdef ENABLE_LLDPMED
1801 if (lldpmed
== LLDP_MED_CLASS_III
)
1802 lchassis
->c_cap_available
|= LLDP_CAP_TELEPHONE
;
1803 lchassis
->c_med_type
= lldpmed
;
1804 lchassis
->c_med_cap_available
= LLDP_MED_CAP_CAP
|
1805 LLDP_MED_CAP_IV
| LLDP_MED_CAP_LOCATION
|
1806 LLDP_MED_CAP_POLICY
| LLDP_MED_CAP_MDI_PSE
| LLDP_MED_CAP_MDI_PD
;
1807 cfg
->g_config
.c_noinventory
= noinventory
;
1809 cfg
->g_config
.c_noinventory
= 1;
1813 lchassis
->c_ttl
= cfg
->g_config
.c_tx_interval
* cfg
->g_config
.c_tx_hold
;
1815 log_debug("main", "initialize protocols");
1816 cfg
->g_protocols
= protos
;
1817 for (i
=0; protos
[i
].mode
!= 0; i
++) {
1819 /* With -ll, disable LLDP */
1820 if (protos
[i
].mode
== LLDPD_MODE_LLDP
)
1821 protos
[i
].enabled
%= 3;
1822 /* With -ccc force CDPV2, enable CDPV1 */
1823 if (protos
[i
].mode
== LLDPD_MODE_CDPV1
&& protos
[i
].enabled
== 3) {
1824 protos
[i
].enabled
= 1;
1826 /* With -cc force CDPV1, enable CDPV2 */
1827 if (protos
[i
].mode
== LLDPD_MODE_CDPV2
&& protos
[i
].enabled
== 2) {
1828 protos
[i
].enabled
= 1;
1831 /* With -cccc disable CDPV1, enable CDPV2 */
1832 if (protos
[i
].mode
== LLDPD_MODE_CDPV1
&& protos
[i
].enabled
>= 4) {
1833 protos
[i
].enabled
= 0;
1836 /* With -cccc disable CDPV1, enable CDPV2; -ccccc will force CDPv2 */
1837 if (protos
[i
].mode
== LLDPD_MODE_CDPV2
&& protos
[i
].enabled
== 4) {
1838 protos
[i
].enabled
= 1;
1841 if (protos
[i
].enabled
> 1)
1842 log_info("main", "protocol %s enabled and forced", protos
[i
].name
);
1843 else if (protos
[i
].enabled
)
1844 log_info("main", "protocol %s enabled", protos
[i
].name
);
1846 log_info("main", "protocol %s disabled", protos
[i
].name
);
1849 TAILQ_INIT(&cfg
->g_hardware
);
1850 TAILQ_INIT(&cfg
->g_chassis
);
1851 TAILQ_INSERT_TAIL(&cfg
->g_chassis
, lchassis
, c_entries
);
1852 lchassis
->c_refcount
++; /* We should always keep a reference to local chassis */
1855 log_debug("main", "start main loop");
1857 lchassis
->c_refcount
--;