]> git.ipfire.org Git - thirdparty/lldpd.git/blame_incremental - src/daemon/lldpd.c
build: bump cross-platform-actions/action from 0.27.0 to 0.28.0
[thirdparty/lldpd.git] / src / daemon / lldpd.c
... / ...
CommitLineData
1/* -*- mode: c; c-file-style: "openbsd" -*- */
2/*
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include "lldpd.h"
19#include "trace.h"
20
21#include <stdio.h>
22#include <unistd.h>
23#include <errno.h>
24#include <limits.h>
25#include <signal.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28#include <time.h>
29#include <libgen.h>
30#include <assert.h>
31#include <sys/param.h>
32#include <sys/utsname.h>
33#include <sys/types.h>
34#include <sys/wait.h>
35#include <sys/socket.h>
36#include <sys/select.h>
37#include <sys/time.h>
38#include <sys/ioctl.h>
39#include <arpa/inet.h>
40#include <netinet/if_ether.h>
41#include <pwd.h>
42#include <grp.h>
43
44#if HAVE_VFORK_H
45# include <vfork.h>
46#endif
47#if HAVE_WORKING_FORK
48# define vfork fork
49#endif
50
51static void usage(void);
52
53static 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 } },
57#ifdef ENABLE_CDP
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 } },
62#endif
63#ifdef ENABLE_SONMP
64 { LLDPD_MODE_SONMP, 0, "SONMP", 's', sonmp_send, sonmp_decode, NULL,
65 { SONMP_MULTICAST_ADDR } },
66#endif
67#ifdef ENABLE_EDP
68 { LLDPD_MODE_EDP, 0, "EDP", 'e', edp_send, edp_decode, NULL,
69 { EDP_MULTICAST_ADDR } },
70#endif
71#ifdef ENABLE_FDP
72 { LLDPD_MODE_FDP, 0, "FDP", 'f', fdp_send, cdp_decode, NULL,
73 { FDP_MULTICAST_ADDR } },
74#endif
75 { 0, 0, "any", ' ', NULL, NULL, NULL, { { 0, 0, 0, 0, 0, 0 } } }
76};
77
78static char **saved_argv;
79#ifdef HAVE___PROGNAME
80extern const char *__progname;
81#else
82# define __progname "lldpd"
83#endif
84
85static void
86usage(void)
87{
88 fprintf(stderr, "Usage: %s [OPTIONS ...]\n", __progname);
89 fprintf(stderr, "Version: %s\n", PACKAGE_STRING);
90
91 fprintf(stderr, "\n");
92
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");
96 fprintf(stderr,
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");
100 fprintf(stderr,
101 "-m IP Specify the IP management addresses of this system.\n");
102 fprintf(stderr,
103 "-u file Specify the Unix-domain socket used for communication with lldpctl(8).\n");
104 fprintf(stderr,
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");
109 fprintf(stderr,
110 "-O file Override default configuration locations processed by lldpcli(8) at start.\n");
111#ifdef ENABLE_LLDPMED
112 fprintf(stderr,
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");
118#endif
119#ifdef USE_SNMP
120 fprintf(stderr, "-x Enable SNMP subagent.\n");
121 fprintf(stderr, "-X sock Specify the SNMP subagent socket.\n");
122#endif
123 fprintf(stderr, "\n");
124
125#if defined ENABLE_CDP || defined ENABLE_EDP || defined ENABLE_FDP || \
126 defined ENABLE_SONMP
127 fprintf(stderr, "Additional protocol support.\n");
128# ifdef ENABLE_CDP
129 fprintf(stderr, "-c Enable the support of CDP protocol. (Cisco)\n");
130# endif
131# ifdef ENABLE_EDP
132 fprintf(stderr, "-e Enable the support of EDP protocol. (Extreme)\n");
133# endif
134# ifdef ENABLE_FDP
135 fprintf(stderr, "-f Enable the support of FDP protocol. (Foundry)\n");
136# endif
137# ifdef ENABLE_SONMP
138 fprintf(stderr, "-s Enable the support of SONMP protocol. (Nortel)\n");
139# endif
140
141 fprintf(stderr, "\n");
142#endif
143
144 fprintf(stderr, "See manual page lldpd(8) for more information\n");
145 exit(1);
146}
147
148struct lldpd_hardware *
149lldpd_get_hardware(struct lldpd *cfg, char *name, int index)
150{
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,
160 index);
161 hardware->h_ifindex_changed = 1;
162 }
163 hardware->h_ifindex = index;
164 break;
165 }
166 if (hardware->h_ifindex == index) break;
167 }
168 }
169 return hardware;
170}
171
172/**
173 * Allocate the default local port. This port will be cloned each time we need a
174 * new local port.
175 */
176static void
177lldpd_alloc_default_local_port(struct lldpd *cfg)
178{
179 struct lldpd_port *port;
180
181 if ((port = (struct lldpd_port *)calloc(1, sizeof(struct lldpd_port))) == NULL)
182 fatal("main", NULL);
183
184#ifdef ENABLE_DOT1
185 TAILQ_INIT(&port->p_vlans);
186 TAILQ_INIT(&port->p_ppvids);
187 TAILQ_INIT(&port->p_pids);
188#endif
189#ifdef ENABLE_CUSTOM
190 TAILQ_INIT(&port->p_custom_list);
191#endif
192 cfg->g_default_local_port = port;
193}
194
195/**
196 * Clone a given port. The destination needs to be already allocated.
197 */
198static int
199lldpd_clone_port(struct lldpd_port *destination, struct lldpd_port *source)
200{
201
202 u_int8_t *output = NULL;
203 ssize_t output_len;
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");
209 free(output);
210 return -1;
211 }
212 memcpy(destination, cloned, sizeof(struct lldpd_port));
213 free(cloned);
214 free(output);
215#ifdef ENABLE_DOT1
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);
219#endif
220#ifdef ENABLE_CUSTOM
221 marshal_repair_tailq(lldpd_custom, &destination->p_custom_list, next);
222#endif
223 return 0;
224}
225
226struct lldpd_hardware *
227lldpd_alloc_hardware(struct lldpd *cfg, char *name, int index)
228{
229 struct lldpd_hardware *hardware;
230
231 log_debug("alloc", "allocate a new local port (%s)", name);
232
233 if ((hardware = (struct lldpd_hardware *)calloc(1,
234 sizeof(struct lldpd_hardware))) == NULL)
235 return NULL;
236
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");
240 free(hardware);
241 return NULL;
242 }
243
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);
250
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;
256 }
257#endif
258
259 levent_hardware_init(hardware);
260 return hardware;
261}
262
263struct lldpd_mgmt *
264lldpd_alloc_mgmt(int family, void *addrptr, size_t addrsize, u_int32_t iface)
265{
266 struct lldpd_mgmt *mgmt;
267
268 log_debug("alloc", "allocate a new management address (family: %d)", family);
269
270 if (family <= LLDPD_AF_UNSPEC || family >= LLDPD_AF_LAST) {
271 errno = EAFNOSUPPORT;
272 return NULL;
273 }
274 if (addrsize > LLDPD_MGMT_MAXADDRSIZE) {
275 errno = EOVERFLOW;
276 return NULL;
277 }
278 mgmt = calloc(1, sizeof(struct lldpd_mgmt));
279 if (mgmt == NULL) {
280 errno = ENOMEM;
281 return NULL;
282 }
283 mgmt->m_family = family;
284 memcpy(&mgmt->m_addr, addrptr, addrsize);
285 mgmt->m_addrsize = addrsize;
286 mgmt->m_iface = iface;
287 return mgmt;
288}
289
290void
291lldpd_hardware_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware)
292{
293 log_debug("alloc", "cleanup hardware port %s", hardware->h_ifname);
294
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);
303 free(hardware);
304}
305
306static void
307lldpd_ifdescr_neighbors(struct lldpd *cfg)
308{
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;
313 char *description;
314 const char *neighbor = NULL;
315 unsigned neighbors = 0;
316 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
317 if (SMART_HIDDEN(port)) continue;
318 neighbors++;
319 neighbor = port->p_chassis->c_name;
320 }
321 if (neighbors == 0)
322 description = strdup("");
323 else if (neighbors == 1 && neighbor && *neighbor != '\0') {
324 if (asprintf(&description, "%s", neighbor) == -1) {
325 continue;
326 }
327 } else {
328 if (asprintf(&description, "%d neighbor%s", neighbors,
329 (neighbors > 1) ? "s" : "") == -1) {
330 continue;
331 }
332 }
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;
338 } else
339 free(description);
340 }
341}
342
343static void
344lldpd_count_neighbors(struct lldpd *cfg)
345{
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) {
351 neighbors++;
352 neighbor = chassis->c_name;
353 }
354 neighbors--;
355 if (neighbors == 0)
356 setproctitle("no neighbor.");
357 else if (neighbors == 1 && neighbor && *neighbor != '\0')
358 setproctitle("connected to %s.", neighbor);
359 else
360 setproctitle("%d neighbor%s.", neighbors, (neighbors > 1) ? "s" : "");
361#endif
362 lldpd_ifdescr_neighbors(cfg);
363}
364
365static void
366notify_clients_deletion(struct lldpd_hardware *hardware, struct lldpd_port *rport)
367{
368 TRACE(LLDPD_NEIGHBOR_DELETE(hardware->h_ifname, rport->p_chassis->c_name,
369 rport->p_descr));
370 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_DELETED, rport);
371#ifdef USE_SNMP
372 agent_notify(hardware, NEIGHBOR_CHANGE_DELETED, rport);
373#endif
374}
375
376static void
377lldpd_reset_timer(struct lldpd *cfg)
378{
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;
389 ssize_t output_len;
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",
400 hardware->h_ifname);
401 continue;
402 }
403
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",
409 hardware->h_ifname);
410 } else {
411 log_debug("localchassis",
412 "change detected for port %s, resetting its timer",
413 hardware->h_ifname);
414 hardware->h_ifindex_changed = 0;
415 levent_schedule_pdu(hardware);
416 }
417
418 /* Update the value */
419 free(hardware->h_lport_previous);
420 hardware->h_lport_previous = output;
421 hardware->h_lport_previous_len = output_len;
422 }
423}
424
425static void
426lldpd_all_chassis_cleanup(struct lldpd *cfg)
427{
428 struct lldpd_chassis *chassis, *chassis_next;
429 log_debug("localchassis", "cleanup all chassis");
430
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);
436 }
437 }
438}
439
440void
441lldpd_cleanup(struct lldpd *cfg)
442{
443 struct lldpd_hardware *hardware, *hardware_next;
444
445 log_debug("localchassis", "cleanup all ports");
446
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) :
454 0;
455 switch (m) {
456 case PATTERN_MATCH_DENIED:
457 log_debug("localchassis",
458 "delete non-permanent interface %s",
459 hardware->h_ifname);
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,
463 1);
464 lldpd_hardware_cleanup(cfg, hardware);
465 break;
466 case PATTERN_MATCH_ALLOWED:
467 case PATTERN_MATCH_ALLOWED_EXACT:
468 log_debug("localchassis", "do not delete %s, permanent",
469 hardware->h_ifname);
470 lldpd_remote_cleanup(hardware, notify_clients_deletion,
471 1);
472 break;
473 }
474 } else {
475 lldpd_remote_cleanup(hardware, notify_clients_deletion,
476 !(hardware->h_flags & IFF_RUNNING));
477 }
478 }
479
480 levent_schedule_cleanup(cfg);
481 lldpd_all_chassis_cleanup(cfg);
482 lldpd_count_neighbors(cfg);
483}
484
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. */
487static void
488lldpd_move_chassis(struct lldpd_chassis *ochassis, struct lldpd_chassis *chassis)
489{
490 struct lldpd_mgmt *mgmt, *mgmt_next;
491
492 /* We want to keep refcount, index and list stuff from the current
493 * chassis */
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);
499
500 /* Make the copy. */
501 /* WARNING: this is a kludgy hack, we need in-place copy and cannot use
502 * marshaling. */
503 memcpy(ochassis, chassis, sizeof(struct lldpd_chassis));
504 TAILQ_INIT(&ochassis->c_mgmt);
505
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);
511 }
512
513 /* Restore saved values */
514 ochassis->c_refcount = refcount;
515 ochassis->c_index = index;
516 memcpy(&ochassis->c_entries, &entries, sizeof(entries));
517
518 /* Get rid of the new chassis */
519 free(chassis);
520}
521
522static int
523lldpd_guess_type(struct lldpd *cfg, char *frame, int s)
524{
525 size_t i, j;
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]);
532 j++) {
533 if (memcmp(frame, cfg->g_protocols[i].mac[j],
534 ETHER_ADDR_LEN) == 0) {
535 log_debug("decode",
536 "guessed protocol is %s (from MAC address)",
537 cfg->g_protocols[i].name);
538 return cfg->g_protocols[i].mode;
539 }
540 }
541 } else {
542 if (cfg->g_protocols[i].guess(frame, s)) {
543 log_debug("decode",
544 "guessed protocol is %s (from detector function)",
545 cfg->g_protocols[i].name);
546 return cfg->g_protocols[i].mode;
547 }
548 }
549 }
550 return -1;
551}
552
553static void
554lldpd_decode(struct lldpd *cfg, char *frame, int s, struct lldpd_hardware *hardware)
555{
556 int i;
557 struct lldpd_chassis *chassis, *ochassis = NULL;
558 struct lldpd_port *port, *oport = NULL, *aport;
559 int guess = LLDPD_MODE_LLDP;
560
561 log_debug("decode", "decode a received frame on %s", hardware->h_ifname);
562
563 if (s < sizeof(struct ether_header) + 4) {
564 /* Too short, just discard it */
565 hardware->h_rx_discarded_cnt++;
566 return;
567 }
568
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);
577 s -= 4;
578 }
579
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);
586 return;
587 }
588 }
589
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) {
598 log_debug("decode",
599 "function for %s protocol did not decode this frame",
600 cfg->g_protocols[i].name);
601 hardware->h_rx_discarded_cnt++;
602 return;
603 }
604 chassis->c_protocol = port->p_protocol =
605 cfg->g_protocols[i].mode;
606 break;
607 }
608 }
609 if (cfg->g_protocols[i].mode == 0) {
610 log_debug("decode", "unable to guess frame type on %s",
611 hardware->h_ifname);
612 return;
613 }
614 TRACE(LLDPD_FRAME_DECODED(hardware->h_ifname, cfg->g_protocols[i].name,
615 chassis->c_name, port->p_descr));
616
617 /* Do we already have the same MSAP somewhere? */
618 int count = 0;
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) {
622 count++;
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");
632 break;
633 }
634 }
635 }
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)) {
639 log_debug("decode",
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) {
644 log_debug("decode",
645 "too many neighbors for port %s, drop this new one",
646 hardware->h_ifname);
647 lldpd_port_cleanup(port, 1);
648 lldpd_chassis_cleanup(chassis, 1);
649 free(port);
650 return;
651 }
652 }
653 /* No, but do we already know the system? */
654 if (!oport) {
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) ==
661 0))
662 break;
663 }
664 }
665
666 if (oport) {
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);
670 free(oport);
671 }
672 if (ochassis) {
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);
678 } else {
679 lldpd_move_chassis(ochassis, chassis);
680 }
681 chassis = ochassis;
682 } else {
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);
688 i = 0;
689 TAILQ_FOREACH (ochassis, &cfg->g_chassis, c_entries)
690 i++;
691 log_debug("decode", "%d different systems are known", i);
692 }
693 /* Add port */
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);
699 }
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.
711
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.
715 */
716 i = 0;
717 /* coverity[use_after_free]
718 TAILQ_REMOVE does the right thing */
719 TAILQ_FOREACH (aport, &hardware->h_rports, p_entries)
720 i++;
721 log_debug("decode", "%d neighbors for %s", i, hardware->h_ifname);
722
723 if (!oport) hardware->h_insert_cnt++;
724
725 /* Notify */
726 log_debug("decode", "send notifications for changes on %s", hardware->h_ifname);
727 if (oport) {
728 TRACE(LLDPD_NEIGHBOR_UPDATE(hardware->h_ifname, chassis->c_name,
729 port->p_descr, i));
730 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_UPDATED, port);
731#ifdef USE_SNMP
732 agent_notify(hardware, NEIGHBOR_CHANGE_UPDATED, port);
733#endif
734 } else {
735 TRACE(LLDPD_NEIGHBOR_NEW(hardware->h_ifname, chassis->c_name,
736 port->p_descr, i));
737 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_ADDED, port);
738#ifdef USE_SNMP
739 agent_notify(hardware, NEIGHBOR_CHANGE_ADDED, port);
740#endif
741 }
742
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) {
748 log_debug("decode",
749 "%s: entering fast start due to "
750 "new neighbor",
751 hardware->h_ifname);
752 hardware->h_tx_fast = hardware->h_cfg->g_config.c_tx_fast_init;
753 }
754
755 levent_schedule_pdu(hardware);
756 }
757#endif
758
759 return;
760}
761
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 */
765static char *
766lldpd_get_lsb_release()
767{
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;
772 int pipefd[2];
773
774 log_debug("localchassis", "grab LSB release");
775
776 if (pipe(pipefd)) {
777 log_warn("localchassis", "unable to get a pair of pipes");
778 return NULL;
779 }
780
781 pid = vfork();
782 switch (pid) {
783 case -1:
784 log_warn("localchassis", "unable to fork");
785 return NULL;
786 case 0:
787 /* Child, exec lsb_release */
788 close(pipefd[0]);
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);
796 }
797 _exit(127);
798 break;
799 default:
800 /* Father, read the output from the children */
801 close(pipefd[1]);
802 count = 0;
803 do {
804 status =
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));
809 if (status < 0) {
810 log_info("localchassis", "unable to read from lsb_release");
811 close(pipefd[0]);
812 waitpid(pid, &status, 0);
813 return NULL;
814 }
815 close(pipefd[0]);
816 if (count >= sizeof(release)) {
817 log_info("localchassis", "output of lsb_release is too large");
818 waitpid(pid, &status, 0);
819 return NULL;
820 }
821 status = -1;
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");
826 return NULL;
827 }
828 if (!count) {
829 log_info("localchassis",
830 "lsb_release returned an empty string");
831 return NULL;
832 }
833 release[count] = '\0';
834 return release;
835 }
836 /* Should not be here */
837 return NULL;
838}
839
840/* Same like lldpd_get_lsb_release but reads /etc/os-release for PRETTY_NAME=. */
841static char *
842lldpd_get_os_release()
843{
844 static char release[1024];
845 char line[1024];
846 char *key, *val;
847 char *ptr1 = release;
848
849 log_debug("localchassis", "grab OS release");
850 FILE *fp = fopen("/etc/os-release", "r");
851 if (!fp) {
852 log_debug("localchassis", "could not open /etc/os-release");
853 fp = fopen("/usr/lib/os-release", "r");
854 }
855 if (!fp) {
856 log_info("localchassis",
857 "could not open either /etc/os-release or /usr/lib/os-release");
858 return NULL;
859 }
860
861 while ((fgets(line, sizeof(line), fp) != NULL)) {
862 key = strtok(line, "=");
863 if (key == NULL) continue;
864
865 val = strtok(NULL, "=");
866
867 if (strncmp(key, "PRETTY_NAME", sizeof(line)) == 0) {
868 strlcpy(release, val, sizeof(line));
869 break;
870 }
871 }
872 fclose(fp);
873
874 /* Remove trailing newline and all " in the string. */
875 ptr1 = release + strlen(release) - 1;
876 while (ptr1 != release && ((*ptr1 == '"') || (*ptr1 == '\n'))) {
877 *ptr1 = '\0';
878 ptr1--;
879 }
880 if (release[0] == '"') return release + 1;
881 return release;
882}
883
884static void
885lldpd_hide_ports(struct lldpd *cfg, struct lldpd_hardware *hardware, int mask)
886{
887 struct lldpd_port *port;
888 int protocols[LLDPD_MODE_MAX + 1];
889 char buffer[256];
890 int i, j, k, found;
891 unsigned int min;
892
893 log_debug("smartfilter", "apply smart filter for port %s", hardware->h_ifname);
894
895 /* Compute the number of occurrences of each protocol */
896 for (i = 0; i <= LLDPD_MODE_MAX; i++)
897 protocols[i] = 0;
898 TAILQ_FOREACH (port, &hardware->h_rports, p_entries)
899 protocols[port->p_protocol]++;
900
901 /* Turn the protocols[] array into an array of
902 enabled/disabled protocols. 1 means enabled, 0
903 means disabled. */
904 min = (unsigned int)-1;
905 for (i = 0; i <= LLDPD_MODE_MAX; i++)
906 if (protocols[i] && (protocols[i] < min)) min = protocols[i];
907 found = 0;
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))
914 found = 1;
915 protocols[i] = 1;
916 } else
917 protocols[i] = 0;
918
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;
923 else
924 port->p_hidden_in = protocols[port->p_protocol] ? 0 : 1;
925 }
926
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)) {
930 found = 0;
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;
935 }
936 if (mask == SMART_INCOMING) {
937 if (found) port->p_hidden_in = 1;
938 if (!port->p_hidden_in) found = 1;
939 }
940 }
941 }
942
943 /* Print a debug message summarizing the operation */
944 for (i = 0; i <= LLDPD_MODE_MAX; i++)
945 protocols[i] = 0;
946 k = j = 0;
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))) {
950 k++;
951 protocols[port->p_protocol] = 1;
952 }
953 j++;
954 }
955 buffer[0] = '\0';
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 >
960 sizeof(buffer)) {
961 /* Unlikely, our buffer is too small */
962 memcpy(buffer + sizeof(buffer) - 4, "...", 4);
963 break;
964 }
965 if (buffer[0])
966 strncat(buffer, ", ",
967 sizeof(buffer) - strlen(buffer) - 1);
968 strncat(buffer, cfg->g_protocols[i].name,
969 sizeof(buffer) - strlen(buffer) - 1);
970 }
971 }
972 log_debug("smartfilter", "%s: %s: %d visible neighbors (out of %d)",
973 hardware->h_ifname, (mask == SMART_OUTGOING) ? "out filter" : "in filter",
974 k, j);
975 log_debug("smartfilter", "%s: protocols: %s", hardware->h_ifname,
976 buffer[0] ? buffer : "(none)");
977}
978
979/* Hide unwanted ports depending on smart mode set by the user */
980static void
981lldpd_hide_all(struct lldpd *cfg)
982{
983 struct lldpd_hardware *hardware;
984
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);
992 }
993}
994
995/* If PD device and PSE allocated power, echo back this change. If we have
996 * several LLDP neighbors, we use the latest updated. */
997static void
998lldpd_dot3_power_pd_pse(struct lldpd_hardware *hardware)
999{
1000#ifdef ENABLE_DOT3
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;
1006
1007 if (port->p_protocol != LLDPD_MODE_LLDP &&
1008 port->p_protocol != LLDPD_MODE_CDPV2)
1009 continue;
1010
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;
1014 }
1015 if (selected_port &&
1016 selected_port->p_power.allocated != hardware->h_lport.p_power.allocated) {
1017 log_info("receive",
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);
1023 }
1024
1025# ifdef ENABLE_CDP
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;
1031 }
1032# endif
1033
1034#endif
1035}
1036
1037void
1038lldpd_recv(struct lldpd *cfg, struct lldpd_hardware *hardware, int fd)
1039{
1040 char *buffer = NULL;
1041 int n;
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");
1045 return;
1046 }
1047 if ((n = hardware->h_ops->recv(cfg, hardware, fd, buffer, hardware->h_mtu)) ==
1048 -1) {
1049 log_debug("receive", "discard frame received on %s",
1050 hardware->h_ifname);
1051 free(buffer);
1052 return;
1053 }
1054 if (hardware->h_lport.p_disable_rx) {
1055 log_debug("receive", "RX disabled, ignore the frame on %s",
1056 hardware->h_ifname);
1057 free(buffer);
1058 return;
1059 }
1060 if (cfg->g_config.c_paused) {
1061 log_debug("receive", "paused, ignore the frame on %s",
1062 hardware->h_ifname);
1063 free(buffer);
1064 return;
1065 }
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);
1073 free(buffer);
1074}
1075
1076static void
1077lldpd_send_shutdown(struct lldpd_hardware *hardware)
1078{
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;
1083
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);
1089}
1090
1091void
1092lldpd_send(struct lldpd_hardware *hardware)
1093{
1094 struct lldpd *cfg = hardware->h_cfg;
1095 struct lldpd_port *port;
1096 int i, sent;
1097
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;
1101
1102 log_debug("send", "send PDU on %s", hardware->h_ifname);
1103 sent = 0;
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);
1110 sent++;
1111 continue;
1112 }
1113 TAILQ_FOREACH (port, &hardware->h_rports, p_entries) {
1114 /* If this remote port is disabled, we don't
1115 * consider it */
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;
1124 sent++;
1125 break;
1126 }
1127 }
1128 }
1129
1130 if (!sent) {
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);
1140 break;
1141 }
1142 if (cfg->g_protocols[i].mode == 0)
1143 log_warnx("send", "no protocol enabled, dunno what to send");
1144 }
1145}
1146
1147#ifdef ENABLE_LLDPMED
1148static void
1149lldpd_med(struct lldpd *cfg, struct utsname *un)
1150{
1151 static short int once = 0;
1152 if (!once && cfg) {
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();
1159 if (un) {
1160 if (LOCAL_CHASSIS(cfg)->c_med_sw)
1161 free(LOCAL_CHASSIS(cfg)->c_med_sw);
1162
1163 if (cfg->g_config.c_advertise_version)
1164 LOCAL_CHASSIS(cfg)->c_med_sw = strdup(un->release);
1165 else
1166 LOCAL_CHASSIS(cfg)->c_med_sw = strdup("Unknown");
1167 }
1168 once = 1;
1169 }
1170}
1171#endif
1172
1173static int
1174lldpd_routing_enabled(struct lldpd *cfg)
1175{
1176 int routing;
1177
1178 if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_ROUTER) == 0) return 0;
1179
1180 if ((routing = interfaces_routing_enabled(cfg)) == -1) {
1181 log_debug("localchassis", "unable to check if routing is enabled");
1182 return 0;
1183 }
1184 return routing;
1185}
1186
1187void
1188lldpd_update_localchassis(struct lldpd *cfg)
1189{
1190 struct utsname un;
1191 char *hp;
1192
1193 log_debug("localchassis", "update information for local chassis");
1194 assert(LOCAL_CHASSIS(cfg) != NULL);
1195
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;
1202 } else {
1203 if ((hp = priv_gethostname()) == NULL)
1204 fatal("localchassis", "failed to get system name");
1205 }
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");
1216 } else {
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");
1224 } else {
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) ==
1228 -1)
1229 fatal("localchassis",
1230 "failed to set minimal system description");
1231 }
1232 }
1233 if (cfg->g_config.c_platform == NULL)
1234 cfg->g_config.c_platform = strdup(un.sysname);
1235
1236 if (!cfg->g_config.c_cap_override) {
1237 /* Check routing */
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;
1242 } else
1243 LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_ROUTER;
1244
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);
1249#endif
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;
1255 }
1256
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)
1260 */
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;
1268 }
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;
1276 }
1277}
1278
1279void
1280lldpd_update_localports(struct lldpd *cfg)
1281{
1282 struct lldpd_hardware *hardware;
1283
1284 log_debug("localchassis", "update information for local ports");
1285
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;
1291
1292 TRACE(LLDPD_INTERFACES_UPDATE());
1293 interfaces_update(cfg);
1294 lldpd_cleanup(cfg);
1295 lldpd_reset_timer(cfg);
1296}
1297
1298void
1299lldpd_loop(struct lldpd *cfg)
1300{
1301 /* Main loop.
1302 1. Update local ports information
1303 2. Update local chassis information
1304 */
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);
1315}
1316
1317static void
1318lldpd_exit(struct lldpd *cfg)
1319{
1320 char *lockname = NULL;
1321 struct lldpd_hardware *hardware, *hardware_next;
1322 log_debug("main", "exit lldpd");
1323
1324 TAILQ_FOREACH (hardware, &cfg->g_hardware, h_entries)
1325 lldpd_send_shutdown(hardware);
1326
1327 if (asprintf(&lockname, "%s.lock", cfg->g_ctlname) != -1) {
1328 priv_ctl_cleanup(lockname);
1329 free(lockname);
1330 }
1331 close(cfg->g_ctl);
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);
1340 }
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);
1347}
1348
1349/**
1350 * Run lldpcli to configure lldpd.
1351 *
1352 * @return PID of running lldpcli or -1 if error.
1353 */
1354static pid_t
1355lldpd_configure(int use_syslog, int debug, const char *path, const char *ctlname,
1356 const char *config_path)
1357{
1358 pid_t lldpcli = vfork();
1359 int devnull;
1360
1361 char sdebug[debug + 4];
1362 if (use_syslog)
1363 strlcpy(sdebug, "-s", 3);
1364 else {
1365 /* debug = 0 -> -sd */
1366 /* debug = 1 -> -sdd */
1367 /* debug = 2 -> -sddd */
1368 memset(sdebug, 'd', sizeof(sdebug));
1369 sdebug[debug + 3] = '\0';
1370 sdebug[0] = '-';
1371 sdebug[1] = 's';
1372 }
1373 log_debug("main", "invoke %s %s", path, sdebug);
1374
1375 switch (lldpcli) {
1376 case -1:
1377 log_warn("main", "unable to fork");
1378 return -1;
1379 case 0:
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);
1385
1386 if (config_path) {
1387 execl(path, "lldpcli", sdebug, "-u", ctlname, "-C",
1388 config_path, "resume", (char *)NULL);
1389 } else {
1390 execl(path, "lldpcli", sdebug, "-u", ctlname, "-C",
1391 SYSCONFDIR "/lldpd.conf", "-C",
1392 SYSCONFDIR "/lldpd.d", "resume", (char *)NULL);
1393 }
1394
1395 log_warn("main", "unable to execute %s", path);
1396 log_warnx("main",
1397 "configuration is incomplete, lldpd needs to be unpaused");
1398 }
1399 _exit(127);
1400 break;
1401 default:
1402 /* Father, don't do anything stupid */
1403 return lldpcli;
1404 }
1405 /* Should not be here */
1406 return -1;
1407}
1408
1409struct intint {
1410 int a;
1411 int b;
1412};
1413static const struct intint filters[] = { { 0, 0 },
1414 { 1,
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 },
1421 { 7,
1422 SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1423 SMART_INCOMING_ONE_NEIGH | SMART_OUTGOING_FILTER |
1424 SMART_OUTGOING_ONE_PROTO },
1425 { 8,
1426 SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1427 SMART_INCOMING_ONE_NEIGH },
1428 { 9,
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 },
1433 { 12,
1434 SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH | SMART_OUTGOING_FILTER |
1435 SMART_OUTGOING_ONE_NEIGH },
1436 { 13,
1437 SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH | SMART_OUTGOING_FILTER },
1438 { 14,
1439 SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_OUTGOING_FILTER |
1440 SMART_OUTGOING_ONE_NEIGH },
1441 { 15,
1442 SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_OUTGOING_FILTER },
1443 { 16,
1444 SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1445 SMART_INCOMING_ONE_NEIGH | SMART_OUTGOING_FILTER |
1446 SMART_OUTGOING_ONE_NEIGH },
1447 { 17,
1448 SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1449 SMART_INCOMING_ONE_NEIGH | SMART_OUTGOING_FILTER },
1450 { 18,
1451 SMART_INCOMING_FILTER | SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1452 { 19,
1453 SMART_INCOMING_FILTER | SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1454 { -1, 0 } };
1455
1456#ifndef HOST_OS_OSX
1457/**
1458 * Tell if we have been started by systemd.
1459 */
1460static int
1461lldpd_started_by_systemd()
1462{
1463# ifdef HOST_OS_LINUX
1464 int fd = -1;
1465 int ret = 0;
1466 size_t path_length;
1467 union sockaddr_union {
1468 struct sockaddr sa;
1469 struct sockaddr_un sun;
1470 } socket_addr = {
1471 .sun.sun_family = AF_UNIX,
1472 };
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)
1476 goto done;
1477
1478 if (path_length >= sizeof(socket_addr.sun.sun_path)) {
1479 log_warnx("main", "systemd notification socket is too long");
1480 goto done;
1481 }
1482 memcpy(socket_addr.sun.sun_path, socket_path, path_length);
1483
1484 /* Support for abstract socket */
1485 if (socket_addr.sun.sun_path[0] == '@') socket_addr.sun.sun_path[0] = 0;
1486
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",
1490 socket_path);
1491 goto done;
1492 }
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");
1496 goto done;
1497 }
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");
1502 goto done;
1503 }
1504 unsetenv("NOTIFY_SOCKET");
1505 ret = 1;
1506done:
1507 if (fd >= 0) close(fd);
1508 return ret;
1509# else
1510 return 0;
1511# endif
1512}
1513#endif
1514
1515#ifdef HOST_OS_LINUX
1516static void
1517version_convert(const char *sversion, unsigned iversion[], size_t n)
1518{
1519 const char *p = sversion;
1520 char *end;
1521 for (size_t i = 0; i < n; i++) {
1522 iversion[i] = strtol(p, &end, 10);
1523 if (*end != '.') break;
1524 p = end + 1;
1525 }
1526}
1527
1528static void
1529version_check(void)
1530{
1531 struct utsname uts;
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);
1543 log_warnx("lldpd",
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");
1547# endif
1548 }
1549}
1550#else
1551static void
1552version_check(void)
1553{
1554}
1555#endif
1556
1557int
1558lldpd_main(int argc, char *argv[], char *envp[])
1559{
1560 struct lldpd *cfg;
1561 struct lldpd_chassis *lchassis;
1562 int ch, debug = 0, use_syslog = 1, daemonize = 1;
1563 const char *errstr;
1564#ifdef USE_SNMP
1565 int snmp = 0;
1566 const char *agentx = NULL; /* AgentX socket */
1567#endif
1568 const char *ctlname = NULL;
1569 char *mgmtp = NULL;
1570 char *cidp = 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. */
1575 char *popt,
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;
1581#endif
1582 char *descr_override = NULL;
1583 char *platform_override = NULL;
1584 char *lsb_release = NULL;
1585 const char *lldpcli = LLDPCLI_PATH;
1586#ifndef HOST_OS_OSX
1587 const char *pidfile = LLDPD_PID_FILE;
1588#endif
1589 int smart = 15;
1590 int receiveonly = 0, version = 0;
1591 int ctl;
1592 const char *config_file = NULL;
1593
1594#ifdef ENABLE_PRIVSEP
1595 /* Non privileged user */
1596 struct passwd *user;
1597 struct group *group;
1598 uid_t uid;
1599 gid_t gid;
1600#endif
1601
1602 saved_argv = argv;
1603
1604#if HAVE_SETPROCTITLE_INIT
1605 setproctitle_init(argc, argv, envp);
1606#endif
1607
1608 /*
1609 * Get and parse command line options
1610 */
1611 if ((popt = strchr(opts, '@')) != NULL) {
1612 for (i = 0; protos[i].mode != 0 && *popt != '\0'; i++)
1613 *(popt++) = protos[i].arg;
1614 *popt = '\0';
1615 }
1616 while ((ch = getopt(argc, argv, opts)) != -1) {
1617 switch (ch) {
1618 case 'h':
1619 usage();
1620 break;
1621 case 'v':
1622 version++;
1623 break;
1624 case 'd':
1625 if (daemonize)
1626 daemonize = 0;
1627 else if (use_syslog)
1628 use_syslog = 0;
1629 else
1630 debug++;
1631 break;
1632 case 'D':
1633 log_accept(optarg);
1634 break;
1635#ifndef HOST_OS_OSX
1636 case 'p':
1637 pidfile = optarg;
1638 break;
1639#endif
1640 case 'r':
1641 receiveonly = 1;
1642 break;
1643 case 'm':
1644 if (mgmtp) {
1645 fprintf(stderr, "-m can only be used once\n");
1646 usage();
1647 }
1648 mgmtp = strdup(optarg);
1649 break;
1650 case 'u':
1651 if (ctlname) {
1652 fprintf(stderr, "-u can only be used once\n");
1653 usage();
1654 }
1655 ctlname = optarg;
1656 break;
1657 case 'I':
1658 if (interfaces) {
1659 fprintf(stderr, "-I can only be used once\n");
1660 usage();
1661 }
1662 interfaces = strdup(optarg);
1663 break;
1664 case 'C':
1665 if (cidp) {
1666 fprintf(stderr, "-C can only be used once\n");
1667 usage();
1668 }
1669 cidp = strdup(optarg);
1670 break;
1671 case 'L':
1672 if (strlen(optarg))
1673 lldpcli = optarg;
1674 else
1675 lldpcli = NULL;
1676 break;
1677 case 'k':
1678 advertise_version = 0;
1679 break;
1680#ifdef ENABLE_LLDPMED
1681 case 'M':
1682 lldpmed = strtonum(optarg, 1, 4, &errstr);
1683 if (errstr) {
1684 fprintf(stderr,
1685 "-M requires an argument between 1 and 4\n");
1686 usage();
1687 }
1688 break;
1689 case 'i':
1690 noinventory = 1;
1691 break;
1692#else
1693 case 'M':
1694 case 'i':
1695 fprintf(stderr, "LLDP-MED support is not built-in\n");
1696 usage();
1697 break;
1698#endif
1699#ifdef USE_SNMP
1700 case 'x':
1701 snmp = 1;
1702 break;
1703 case 'X':
1704 if (agentx) {
1705 fprintf(stderr, "-X can only be used once\n");
1706 usage();
1707 }
1708 snmp = 1;
1709 agentx = optarg;
1710 break;
1711#else
1712 case 'x':
1713 case 'X':
1714 fprintf(stderr, "SNMP support is not built-in\n");
1715 usage();
1716#endif
1717 break;
1718 case 'S':
1719 if (descr_override) {
1720 fprintf(stderr, "-S can only be used once\n");
1721 usage();
1722 }
1723 descr_override = strdup(optarg);
1724 break;
1725 case 'P':
1726 if (platform_override) {
1727 fprintf(stderr, "-P can only be used once\n");
1728 usage();
1729 }
1730 platform_override = strdup(optarg);
1731 break;
1732 case 'H':
1733 smart = strtonum(optarg, 0,
1734 sizeof(filters) / sizeof(filters[0]), &errstr);
1735 if (errstr) {
1736 fprintf(stderr,
1737 "-H requires an int between 0 and %zu\n",
1738 sizeof(filters) / sizeof(filters[0]));
1739 usage();
1740 }
1741 break;
1742 case 'O':
1743 if (config_file) {
1744 fprintf(stderr, "-O can only be used once\n");
1745 usage();
1746 }
1747 config_file = optarg;
1748 break;
1749 default:
1750 found = 0;
1751 for (i = 0; protos[i].mode != 0; i++) {
1752 if (ch == protos[i].arg) {
1753 found = 1;
1754 protos[i].enabled++;
1755 }
1756 }
1757 if (!found) usage();
1758 }
1759 }
1760
1761 if (version) {
1762 version_display(stdout, "lldpd", version > 1);
1763 exit(0);
1764 }
1765
1766 if (ctlname == NULL) ctlname = LLDPD_CTL_SOCKET;
1767
1768 /* Set correct smart mode */
1769 for (i = 0; (filters[i].a != -1) && (filters[i].a != smart); i++)
1770 ;
1771 if (filters[i].a == -1) {
1772 fprintf(stderr, "Incorrect mode for -H\n");
1773 usage();
1774 }
1775 smart = filters[i].b;
1776
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. */
1782 int fd;
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);
1790 }
1791 }
1792 log_debug("main", "lldpd " PACKAGE_VERSION " starting...");
1793 version_check();
1794#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1795 fatalx("main", "fuzzing enabled, unsafe for production");
1796#endif
1797
1798 /* Grab uid and gid to use for priv sep */
1799#ifdef ENABLE_PRIVSEP
1800 if ((user = getpwnam(PRIVSEP_USER)) == NULL)
1801 fatalx("main",
1802 "no " PRIVSEP_USER
1803 " user for privilege separation, please create it");
1804 uid = user->pw_uid;
1805 if ((group = getgrnam(PRIVSEP_GROUP)) == NULL)
1806 fatalx("main",
1807 "no " PRIVSEP_GROUP
1808 " group for privilege separation, please create it");
1809 gid = group->gr_gid;
1810#endif
1811
1812 /* Create and setup socket */
1813 int retry = 1;
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 */
1818 int tfd;
1819 log_info("main",
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 */
1824 close(tfd);
1825 log_warnx("main",
1826 "another instance is running, please stop it");
1827 fatalx("main", "giving up");
1828 } else if (errno == ECONNREFUSED) {
1829 /* Nobody is listening */
1830 log_info("main",
1831 "old control socket is present, clean it");
1832 ctl_cleanup(ctlname);
1833 continue;
1834 }
1835 log_warn("main",
1836 "cannot determine if another daemon is already running");
1837 fatalx("main", "giving up");
1838 }
1839 log_warn("main", "unable to create control socket at %s", ctlname);
1840 fatalx("main", "giving up");
1841 }
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) ==
1846 -1)
1847 log_warn("main", "unable to chmod control socket");
1848#endif
1849
1850 /* Create associated advisory lock file */
1851 char *lockname = NULL;
1852 int fd;
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");
1857 close(fd);
1858#ifdef ENABLE_PRIVSEP
1859 if (chown(lockname, uid, gid) == -1)
1860 log_warn("main", "unable to chown control socket lock");
1861 if (chmod(lockname,
1862 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP) == -1)
1863 log_warn("main", "unable to chmod control socket lock");
1864#endif
1865 free(lockname);
1866
1867 /* Disable SIGPIPE */
1868 signal(SIGPIPE, SIG_IGN);
1869
1870 /* Disable SIGHUP, until handlers are installed */
1871 signal(SIGHUP, SIG_IGN);
1872
1873 /* Daemonization, unless started by systemd or launchd or debug */
1874#ifndef HOST_OS_OSX
1875 if (!lldpd_started_by_systemd() && daemonize) {
1876 int pid;
1877 char *spid;
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)
1881 fatal("main",
1882 "unable to open pid file " LLDPD_PID_FILE
1883 " (or the specified one)");
1884 if (asprintf(&spid, "%d\n", getpid()) == -1)
1885 fatal("main",
1886 "unable to create pid file " LLDPD_PID_FILE
1887 " (or the specified one)");
1888 if (write(pid, spid, strlen(spid)) == -1)
1889 fatal("main",
1890 "unable to write pid file " LLDPD_PID_FILE
1891 " (or the specified one)");
1892 free(spid);
1893 close(pid);
1894 }
1895#endif
1896
1897 /* Configuration with lldpcli */
1898 if (lldpcli) {
1899 if (!config_file) {
1900 log_debug("main",
1901 "invoking lldpcli for default configuration locations");
1902 } else {
1903 log_debug("main",
1904 "invoking lldpcli for user supplied configuration location");
1905 }
1906 if (lldpd_configure(use_syslog, debug, lldpcli, ctlname, config_file) ==
1907 -1)
1908 fatal("main", "unable to spawn lldpcli");
1909 }
1910
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();
1915 if (!lsb_release) {
1916 lsb_release = lldpd_get_lsb_release();
1917 }
1918
1919 log_debug("main", "initialize privilege separation");
1920#ifdef ENABLE_PRIVSEP
1921 priv_init(PRIVSEP_CHROOT, ctl, uid, gid);
1922#else
1923 priv_init();
1924#endif
1925
1926 /* Initialization of global configuration */
1927 if ((cfg = (struct lldpd *)calloc(1, sizeof(struct lldpd))) == NULL)
1928 fatal("main", NULL);
1929
1930 lldpd_alloc_default_local_port(cfg);
1931 cfg->g_ctlname = ctlname;
1932 cfg->g_ctl = ctl;
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;
1948#endif
1949#ifdef USE_SNMP
1950 cfg->g_snmp = snmp;
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;
1955
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");
1960
1961 /* Description */
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;
1967
1968 if (platform_override) cfg->g_config.c_platform = platform_override;
1969
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
1982 if (lldpmed > 0) {
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;
1990 } else
1991 cfg->g_config.c_noinventory = 1;
1992#endif
1993
1994 log_debug("main", "initialize protocols");
1995 cfg->g_protocols = protos;
1996 for (i = 0; protos[i].mode != 0; i++) {
1997
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;
2003 }
2004 /* With -cc force CDPV1, enable CDPV2 */
2005 if (protos[i].mode == LLDPD_MODE_CDPV2 && protos[i].enabled == 2) {
2006 protos[i].enabled = 1;
2007 }
2008
2009 /* With -cccc disable CDPV1, enable CDPV2 */
2010 if (protos[i].mode == LLDPD_MODE_CDPV1 && protos[i].enabled >= 4) {
2011 protos[i].enabled = 0;
2012 }
2013
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;
2017 }
2018
2019 if (protos[i].enabled > 1)
2020 log_info("main", "protocol %s enabled and forced",
2021 protos[i].name);
2022 else if (protos[i].enabled)
2023 log_info("main", "protocol %s enabled", protos[i].name);
2024 else
2025 log_info("main", "protocol %s disabled", protos[i].name);
2026 }
2027
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 */
2032
2033 /* Main loop */
2034 log_debug("main", "start main loop");
2035 levent_loop(cfg);
2036 lchassis->c_refcount--;
2037 lldpd_exit(cfg);
2038 free(cfg);
2039
2040 return (0);
2041}