]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/daemon/lldpd.c
daemon: don't invoke lldpcli after dropping privileges
[thirdparty/lldpd.git] / src / daemon / lldpd.c
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 <signal.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <time.h>
28 #include <libgen.h>
29 #include <assert.h>
30 #include <sys/utsname.h>
31 #include <sys/types.h>
32 #include <sys/wait.h>
33 #include <sys/socket.h>
34 #include <sys/select.h>
35 #include <sys/time.h>
36 #include <sys/ioctl.h>
37 #include <arpa/inet.h>
38 #include <netinet/if_ether.h>
39 #include <pwd.h>
40 #include <grp.h>
41
42 static void usage(void);
43
44 static struct protocol protos[] =
45 {
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 },
50 #ifdef ENABLE_CDP
51 { LLDPD_MODE_CDPV1, 0, "CDPv1", 'c', cdpv1_send, cdp_decode, cdpv1_guess,
52 CDP_MULTICAST_ADDR },
53 { LLDPD_MODE_CDPV2, 0, "CDPv2", 'c', cdpv2_send, cdp_decode, cdpv2_guess,
54 CDP_MULTICAST_ADDR },
55 #endif
56 #ifdef ENABLE_SONMP
57 { LLDPD_MODE_SONMP, 0, "SONMP", 's', sonmp_send, sonmp_decode, NULL,
58 SONMP_MULTICAST_ADDR },
59 #endif
60 #ifdef ENABLE_EDP
61 { LLDPD_MODE_EDP, 0, "EDP", 'e', edp_send, edp_decode, NULL,
62 EDP_MULTICAST_ADDR },
63 #endif
64 #ifdef ENABLE_FDP
65 { LLDPD_MODE_FDP, 0, "FDP", 'f', fdp_send, cdp_decode, NULL,
66 FDP_MULTICAST_ADDR },
67 #endif
68 { 0, 0, "any", ' ', NULL, NULL, NULL,
69 {0,0,0,0,0,0} }
70 };
71
72 static char **saved_argv;
73 #ifdef HAVE___PROGNAME
74 extern const char *__progname;
75 #else
76 # define __progname "lldpd"
77 #endif
78
79 static void
80 usage(void)
81 {
82 fprintf(stderr, "Usage: %s [OPTIONS ...]\n", __progname);
83 fprintf(stderr, "Version: %s\n", PACKAGE_STRING);
84
85 fprintf(stderr, "\n");
86
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");
97 #ifdef ENABLE_LLDPMED
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");
103 #endif
104 #ifdef USE_SNMP
105 fprintf(stderr, "-x Enable SNMP subagent.\n");
106 #endif
107 fprintf(stderr, "\n");
108
109 #if defined ENABLE_CDP || defined ENABLE_EDP || defined ENABLE_FDP || defined ENABLE_SONMP
110 fprintf(stderr, "Additional protocol support.\n");
111 #ifdef ENABLE_CDP
112 fprintf(stderr, "-c Enable the support of CDP protocol. (Cisco)\n");
113 #endif
114 #ifdef ENABLE_EDP
115 fprintf(stderr, "-e Enable the support of EDP protocol. (Extreme)\n");
116 #endif
117 #ifdef ENABLE_FDP
118 fprintf(stderr, "-f Enable the support of FDP protocol. (Foundry)\n");
119 #endif
120 #ifdef ENABLE_SONMP
121 fprintf(stderr, "-s Enable the support of SONMP protocol. (Nortel)\n");
122 #endif
123
124 fprintf(stderr, "\n");
125 #endif
126
127 fprintf(stderr, "see manual page lldpd(8) for more information\n");
128 exit(1);
129 }
130
131 struct lldpd_hardware *
132 lldpd_get_hardware(struct lldpd *cfg, char *name, int index)
133 {
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))
138 break;
139 }
140 return hardware;
141 }
142
143 /**
144 * Allocate the default local port. This port will be cloned each time we need a
145 * new local port.
146 */
147 static void
148 lldpd_alloc_default_local_port(struct lldpd *cfg)
149 {
150 struct lldpd_port *port;
151
152 if ((port = (struct lldpd_port *)
153 calloc(1, sizeof(struct lldpd_port))) == NULL)
154 fatal("main", NULL);
155
156 #ifdef ENABLE_DOT1
157 TAILQ_INIT(&port->p_vlans);
158 TAILQ_INIT(&port->p_ppvids);
159 TAILQ_INIT(&port->p_pids);
160 #endif
161 #ifdef ENABLE_CUSTOM
162 TAILQ_INIT(&port->p_custom_list);
163 #endif
164 cfg->g_default_local_port = port;
165 }
166
167 /**
168 * Clone a given port. The destination needs to be already allocated.
169 */
170 static int
171 lldpd_clone_port(struct lldpd_port *destination, struct lldpd_port *source)
172 {
173
174 u_int8_t *output = NULL;
175 ssize_t output_len;
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");
181 free(output);
182 return -1;
183 }
184 memcpy(destination, cloned, sizeof(struct lldpd_port));
185 free(cloned);
186 free(output);
187 #ifdef ENABLE_DOT1
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);
191 #endif
192 #ifdef ENABLE_CUSTOM
193 marshal_repair_tailq(lldpd_custom, &destination->p_custom_list, next);
194 #endif
195 return 0;
196 }
197
198 struct lldpd_hardware *
199 lldpd_alloc_hardware(struct lldpd *cfg, char *name, int index)
200 {
201 struct lldpd_hardware *hardware;
202
203 log_debug("alloc", "allocate a new local port (%s)", name);
204
205 if ((hardware = (struct lldpd_hardware *)
206 calloc(1, sizeof(struct lldpd_hardware))) == NULL)
207 return NULL;
208
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");
212 free(hardware);
213 return NULL;
214 }
215
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);
222
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;
228 }
229 #endif
230
231 levent_hardware_init(hardware);
232 return hardware;
233 }
234
235 struct lldpd_mgmt *
236 lldpd_alloc_mgmt(int family, void *addrptr, size_t addrsize, u_int32_t iface)
237 {
238 struct lldpd_mgmt *mgmt;
239
240 log_debug("alloc", "allocate a new management address (family: %d)", family);
241
242 if (family <= LLDPD_AF_UNSPEC || family >= LLDPD_AF_LAST) {
243 errno = EAFNOSUPPORT;
244 return NULL;
245 }
246 if (addrsize > LLDPD_MGMT_MAXADDRSIZE) {
247 errno = EOVERFLOW;
248 return NULL;
249 }
250 mgmt = calloc(1, sizeof(struct lldpd_mgmt));
251 if (mgmt == NULL) {
252 errno = ENOMEM;
253 return NULL;
254 }
255 mgmt->m_family = family;
256 memcpy(&mgmt->m_addr, addrptr, addrsize);
257 mgmt->m_addrsize = addrsize;
258 mgmt->m_iface = iface;
259 return mgmt;
260 }
261
262 void
263 lldpd_hardware_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware)
264 {
265 log_debug("alloc", "cleanup hardware port %s", hardware->h_ifname);
266
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);
274 free(hardware);
275 }
276
277 static void
278 lldpd_display_neighbors(struct lldpd *cfg)
279 {
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;
284 char *description;
285 const char *neighbor = NULL;
286 unsigned neighbors = 0;
287 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
288 if (SMART_HIDDEN(port)) continue;
289 neighbors++;
290 neighbor = port->p_chassis->c_name;
291 }
292 if (neighbors == 0)
293 priv_iface_description(hardware->h_ifname,
294 "");
295 else if (neighbors == 1 && neighbor && *neighbor != '\0') {
296 if (asprintf(&description, "%s",
297 neighbor) != -1) {
298 priv_iface_description(hardware->h_ifname, description);
299 free(description);
300 }
301 } else {
302 if (asprintf(&description, "%d neighbor%s",
303 neighbors, (neighbors > 1)?"s":"") != -1) {
304 priv_iface_description(hardware->h_ifname,
305 description);
306 free(description);
307 }
308 }
309 }
310 }
311
312 static void
313 lldpd_count_neighbors(struct lldpd *cfg)
314 {
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) {
320 neighbors++;
321 neighbor = chassis->c_name;
322 }
323 neighbors--;
324 if (neighbors == 0)
325 setproctitle("no neighbor.");
326 else if (neighbors == 1 && neighbor && *neighbor != '\0')
327 setproctitle("connected to %s.", neighbor);
328 else
329 setproctitle("%d neighbor%s.", neighbors,
330 (neighbors > 1)?"s":"");
331 #endif
332 lldpd_display_neighbors(cfg);
333 }
334
335 static void
336 notify_clients_deletion(struct lldpd_hardware *hardware,
337 struct lldpd_port *rport)
338 {
339 TRACE(LLDPD_NEIGHBOR_DELETE(hardware->h_ifname,
340 rport->p_chassis->c_name,
341 rport->p_descr));
342 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_DELETED,
343 rport);
344 #ifdef USE_SNMP
345 agent_notify(hardware, NEIGHBOR_CHANGE_DELETED, rport);
346 #endif
347 }
348
349 static void
350 lldpd_reset_timer(struct lldpd *cfg)
351 {
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;
362 ssize_t output_len;
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",
373 hardware->h_ifname);
374 continue;
375 }
376
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",
383 hardware->h_ifname);
384 } else {
385 log_debug("localchassis",
386 "change detected for port %s, resetting its timer",
387 hardware->h_ifname);
388 levent_schedule_pdu(hardware);
389 }
390
391 /* Update the value */
392 free(hardware->h_lport_previous);
393 hardware->h_lport_previous = output;
394 hardware->h_lport_previous_len = output_len;
395 }
396 }
397
398 static void
399 lldpd_all_chassis_cleanup(struct lldpd *cfg)
400 {
401 struct lldpd_chassis *chassis, *chassis_next;
402 log_debug("localchassis", "cleanup all chassis");
403
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);
410 }
411 }
412 }
413
414 void
415 lldpd_cleanup(struct lldpd *cfg)
416 {
417 struct lldpd_hardware *hardware, *hardware_next;
418
419 log_debug("localchassis", "cleanup all ports");
420
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);
429 } else {
430 lldpd_remote_cleanup(hardware, notify_clients_deletion,
431 !(hardware->h_flags & IFF_RUNNING));
432 }
433 }
434
435 levent_schedule_cleanup(cfg);
436 lldpd_all_chassis_cleanup(cfg);
437 lldpd_count_neighbors(cfg);
438 }
439
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. */
442 static void
443 lldpd_move_chassis(struct lldpd_chassis *ochassis,
444 struct lldpd_chassis *chassis) {
445 struct lldpd_mgmt *mgmt, *mgmt_next;
446
447 /* We want to keep refcount, index and list stuff from the current
448 * chassis */
449 TAILQ_ENTRY(lldpd_chassis) entries;
450 int refcount = ochassis->c_refcount;
451 int index = ochassis->c_index;
452 memcpy(&entries, &ochassis->c_entries,
453 sizeof(entries));
454 lldpd_chassis_cleanup(ochassis, 0);
455
456 /* Make the copy. */
457 /* WARNING: this is a kludgy hack, we need in-place copy and cannot use
458 * marshaling. */
459 memcpy(ochassis, chassis, sizeof(struct lldpd_chassis));
460 TAILQ_INIT(&ochassis->c_mgmt);
461
462 /* Copy of management addresses */
463 for (mgmt = TAILQ_FIRST(&chassis->c_mgmt);
464 mgmt != NULL;
465 mgmt = mgmt_next) {
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);
469 }
470
471 /* Restore saved values */
472 ochassis->c_refcount = refcount;
473 ochassis->c_index = index;
474 memcpy(&ochassis->c_entries, &entries, sizeof(entries));
475
476 /* Get rid of the new chassis */
477 free(chassis);
478 }
479
480 static int
481 lldpd_guess_type(struct lldpd *cfg, char *frame, int s)
482 {
483 int i;
484 if (s < ETHER_ADDR_LEN)
485 return -1;
486 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
487 if (!cfg->g_protocols[i].enabled)
488 continue;
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;
496 }
497 } else {
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;
502 }
503 }
504 }
505 return -1;
506 }
507
508 static void
509 lldpd_decode(struct lldpd *cfg, char *frame, int s,
510 struct lldpd_hardware *hardware)
511 {
512 int i;
513 struct lldpd_chassis *chassis, *ochassis = NULL;
514 struct lldpd_port *port, *oport = NULL, *aport;
515 int guess = LLDPD_MODE_LLDP;
516
517 log_debug("decode", "decode a received frame on %s",
518 hardware->h_ifname);
519
520 if (s < sizeof(struct ether_header) + 4)
521 /* Too short, just discard it */
522 return;
523
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);
531 s -= 4;
532 }
533
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);
541 return;
542 }
543 }
544
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)
548 continue;
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);
556 return;
557 }
558 chassis->c_protocol = port->p_protocol =
559 cfg->g_protocols[i].mode;
560 break;
561 }
562 }
563 if (cfg->g_protocols[i].mode == 0) {
564 log_debug("decode", "unable to guess frame type on %s",
565 hardware->h_ifname);
566 return;
567 }
568 TRACE(LLDPD_FRAME_DECODED(
569 hardware->h_ifname,
570 cfg->g_protocols[i].name,
571 chassis->c_name,
572 port->p_descr));
573
574 /* Do we already have the same MSAP somewhere? */
575 int count = 0;
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) {
579 count++;
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");
589 break;
590 }
591 }
592 }
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)) {
596 log_debug("decode",
597 "max neighbors %d reached for port %s, "
598 "dropping any new ones silently",
599 cfg->g_config.c_max_neighbors,
600 hardware->h_ifname);
601 } else if (count > cfg->g_config.c_max_neighbors - 1) {
602 log_debug("decode",
603 "too many neighbors for port %s, drop this new one",
604 hardware->h_ifname);
605 lldpd_port_cleanup(port, 1);
606 lldpd_chassis_cleanup(chassis, 1);
607 free(port);
608 return;
609 }
610 }
611 /* No, but do we already know the system? */
612 if (!oport) {
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))
620 break;
621 }
622 }
623
624 if (oport) {
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);
628 free(oport);
629 }
630 if (ochassis) {
631 lldpd_move_chassis(ochassis, chassis);
632 chassis = ochassis;
633 } else {
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);
641 }
642 /* Add port */
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);
648 }
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.
660
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.
664 */
665 /* coverity[use_after_free]
666 TAILQ_REMOVE does the right thing */
667 i = 0; TAILQ_FOREACH(aport, &hardware->h_rports, p_entries)
668 i++;
669 log_debug("decode", "%d neighbors for %s", i,
670 hardware->h_ifname);
671
672 if (!oport) hardware->h_insert_cnt++;
673
674 /* Notify */
675 log_debug("decode", "send notifications for changes on %s",
676 hardware->h_ifname);
677 if (oport) {
678 TRACE(LLDPD_NEIGHBOR_UPDATE(hardware->h_ifname,
679 chassis->c_name,
680 port->p_descr,
681 i));
682 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_UPDATED, port);
683 #ifdef USE_SNMP
684 agent_notify(hardware, NEIGHBOR_CHANGE_UPDATED, port);
685 #endif
686 } else {
687 TRACE(LLDPD_NEIGHBOR_NEW(hardware->h_ifname,
688 chassis->c_name,
689 port->p_descr,
690 i));
691 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_ADDED, port);
692 #ifdef USE_SNMP
693 agent_notify(hardware, NEIGHBOR_CHANGE_ADDED, port);
694 #endif
695 }
696
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;
705 }
706
707 levent_schedule_pdu(hardware);
708 }
709 #endif
710
711 return;
712 }
713
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 */
717 static char *
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;
722 int pipefd[2];
723
724 log_debug("localchassis", "grab LSB release");
725
726 if (pipe(pipefd)) {
727 log_warn("localchassis", "unable to get a pair of pipes");
728 return NULL;
729 }
730
731 pid = vfork();
732 switch (pid) {
733 case -1:
734 log_warn("localchassis", "unable to fork");
735 return NULL;
736 case 0:
737 /* Child, exec lsb_release */
738 close(pipefd[0]);
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);
746 }
747 _exit(127);
748 break;
749 default:
750 /* Father, read the output from the children */
751 close(pipefd[1]);
752 count = 0;
753 do {
754 status = read(pipefd[0], release+count, sizeof(release)-count);
755 if ((status == -1) && (errno == EINTR)) continue;
756 if (status > 0)
757 count += status;
758 } while (count < sizeof(release) && (status > 0));
759 if (status < 0) {
760 log_info("localchassis", "unable to read from lsb_release");
761 close(pipefd[0]);
762 waitpid(pid, &status, 0);
763 return NULL;
764 }
765 close(pipefd[0]);
766 if (count >= sizeof(release)) {
767 log_info("localchassis", "output of lsb_release is too large");
768 waitpid(pid, &status, 0);
769 return NULL;
770 }
771 status = -1;
772 if (waitpid(pid, &status, 0) != pid)
773 return NULL;
774 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
775 log_info("localchassis", "lsb_release information not available");
776 return NULL;
777 }
778 if (!count) {
779 log_info("localchassis", "lsb_release returned an empty string");
780 return NULL;
781 }
782 release[count] = '\0';
783 return release;
784 }
785 /* Should not be here */
786 return NULL;
787 }
788
789 /* Same like lldpd_get_lsb_release but reads /etc/os-release for PRETTY_NAME=. */
790 static char *
791 lldpd_get_os_release() {
792 static char release[1024];
793 char line[1024];
794 char *key, *val;
795 char *ptr1 = release;
796
797 log_debug("localchassis", "grab OS release");
798 FILE *fp = fopen("/etc/os-release", "r");
799 if (!fp) {
800 log_debug("localchassis", "could not open /etc/os-release");
801 fp = fopen("/usr/lib/os-release", "r");
802 }
803 if (!fp) {
804 log_info("localchassis",
805 "could not open either /etc/os-release or /usr/lib/os-release");
806 return NULL;
807 }
808
809 while ((fgets(line, sizeof(line), fp) != NULL)) {
810 key = strtok(line, "=");
811 val = strtok(NULL, "=");
812
813 if (strncmp(key, "PRETTY_NAME", sizeof(line)) == 0) {
814 strlcpy(release, val, sizeof(line));
815 break;
816 }
817 }
818 fclose(fp);
819
820 /* Remove trailing newline and all " in the string. */
821 ptr1 = release + strlen(release) - 1;
822 while (ptr1 != release &&
823 ((*ptr1 == '"') || (*ptr1 == '\n'))) {
824 *ptr1 = '\0';
825 ptr1--;
826 }
827 if (release[0] == '"')
828 return release+1;
829 return release;
830 }
831
832 static void
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];
836 char buffer[256];
837 int i, j, k, found;
838 unsigned int min;
839
840 log_debug("smartfilter", "apply smart filter for port %s",
841 hardware->h_ifname);
842
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]++;
847
848 /* Turn the protocols[] array into an array of
849 enabled/disabled protocols. 1 means enabled, 0
850 means disabled. */
851 min = (unsigned int)-1;
852 for (i = 0; i <= LLDPD_MODE_MAX; i++)
853 if (protocols[i] && (protocols[i] < min))
854 min = protocols[i];
855 found = 0;
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))
862 found = 1;
863 protocols[i] = 1;
864 } else protocols[i] = 0;
865
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;
870 else
871 port->p_hidden_in = protocols[port->p_protocol]?0:1;
872 }
873
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)) {
877 found = 0;
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)
882 found = 1;
883 }
884 if (mask == SMART_INCOMING) {
885 if (found) port->p_hidden_in = 1;
886 if (!port->p_hidden_in)
887 found = 1;
888 }
889 }
890 }
891
892 /* Print a debug message summarizing the operation */
893 for (i = 0; i <= LLDPD_MODE_MAX; i++) protocols[i] = 0;
894 k = j = 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))) {
898 k++;
899 protocols[port->p_protocol] = 1;
900 }
901 j++;
902 }
903 buffer[0] = '\0';
904 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
905 if (cfg->g_protocols[i].enabled && protocols[cfg->g_protocols[i].mode]) {
906 if (strlen(buffer) +
907 strlen(cfg->g_protocols[i].name) + 3 > sizeof(buffer)) {
908 /* Unlikely, our buffer is too small */
909 memcpy(buffer + sizeof(buffer) - 4, "...", 4);
910 break;
911 }
912 if (buffer[0])
913 strncat(buffer, ", ", 2);
914 strncat(buffer, cfg->g_protocols[i].name, strlen(cfg->g_protocols[i].name));
915 }
916 }
917 log_debug("smartfilter", "%s: %s: %d visible neighbors (out of %d)",
918 hardware->h_ifname,
919 (mask == SMART_OUTGOING)?"out filter":"in filter",
920 k, j);
921 log_debug("smartfilter", "%s: protocols: %s",
922 hardware->h_ifname, buffer[0]?buffer:"(none)");
923 }
924
925 /* Hide unwanted ports depending on smart mode set by the user */
926 static void
927 lldpd_hide_all(struct lldpd *cfg)
928 {
929 struct lldpd_hardware *hardware;
930
931 if (!cfg->g_config.c_smart)
932 return;
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);
939 }
940 }
941
942 void
943 lldpd_recv(struct lldpd *cfg, struct lldpd_hardware *hardware, int fd)
944 {
945 char *buffer = NULL;
946 int n;
947 log_debug("receive", "receive a frame on %s",
948 hardware->h_ifname);
949 if ((buffer = (char *)malloc(hardware->h_mtu)) == NULL) {
950 log_warn("receive", "failed to alloc reception buffer");
951 return;
952 }
953 if ((n = hardware->h_ops->recv(cfg, hardware,
954 fd, buffer,
955 hardware->h_mtu)) == -1) {
956 log_debug("receive", "discard frame received on %s",
957 hardware->h_ifname);
958 free(buffer);
959 return;
960 }
961 if (hardware->h_lport.p_disable_rx) {
962 log_debug("receive", "RX disabled, ignore the frame on %s",
963 hardware->h_ifname);
964 free(buffer);
965 return;
966 }
967 if (cfg->g_config.c_paused) {
968 log_debug("receive", "paused, ignore the frame on %s",
969 hardware->h_ifname);
970 free(buffer);
971 return;
972 }
973 hardware->h_rx_cnt++;
974 log_debug("receive", "decode received frame on %s",
975 hardware->h_ifname);
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);
980 free(buffer);
981 }
982
983 static void
984 lldpd_send_shutdown(struct lldpd_hardware *hardware)
985 {
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)
990 return;
991
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",
996 hardware->h_ifname);
997 }
998
999 void
1000 lldpd_send(struct lldpd_hardware *hardware)
1001 {
1002 struct lldpd *cfg = hardware->h_cfg;
1003 struct lldpd_port *port;
1004 int i, sent;
1005
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)
1009 return;
1010
1011 log_debug("send", "send PDU on %s", hardware->h_ifname);
1012 sent = 0;
1013 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
1014 if (!cfg->g_protocols[i].enabled)
1015 continue;
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);
1020 sent++;
1021 continue;
1022 }
1023 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
1024 /* If this remote port is disabled, we don't
1025 * consider it */
1026 if (port->p_hidden_out)
1027 continue;
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",
1033 hardware->h_ifname,
1034 cfg->g_protocols[i].name);
1035 cfg->g_protocols[i].send(cfg,
1036 hardware);
1037 sent++;
1038 break;
1039 }
1040 }
1041 }
1042
1043 if (!sent) {
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,
1053 hardware);
1054 break;
1055 }
1056 if (cfg->g_protocols[i].mode == 0)
1057 log_warnx("send", "no protocol enabled, dunno what to send");
1058 }
1059 }
1060
1061 #ifdef ENABLE_LLDPMED
1062 static void
1063 lldpd_med(struct lldpd_chassis *chassis)
1064 {
1065 static short int once = 0;
1066 if (!once) {
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();
1073 once = 1;
1074 }
1075 }
1076 #endif
1077
1078 static int
1079 lldpd_routing_enabled(struct lldpd *cfg)
1080 {
1081 int routing;
1082
1083 if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_ROUTER) == 0)
1084 return 0;
1085
1086 if ((routing = interfaces_routing_enabled(cfg)) == -1) {
1087 log_debug("localchassis", "unable to check if routing is enabled");
1088 return 0;
1089 }
1090 return routing;
1091 }
1092
1093 static void
1094 lldpd_update_localchassis(struct lldpd *cfg)
1095 {
1096 struct utsname un;
1097 char *hp;
1098
1099 log_debug("localchassis", "update information for local chassis");
1100 assert(LOCAL_CHASSIS(cfg) != NULL);
1101
1102 /* Set system name and description */
1103 if (uname(&un) < 0)
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;
1108 } else {
1109 if ((hp = priv_gethostname()) == NULL)
1110 fatal("localchassis", "failed to get system name");
1111 }
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");
1121 } else {
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)
1127 == -1)
1128 fatal("localchassis", "failed to set full system description");
1129 } else {
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");
1134 }
1135 }
1136 if (cfg->g_config.c_platform == NULL)
1137 cfg->g_config.c_platform = strdup(un.sysname);
1138
1139 /* Check routing */
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;
1143 } else
1144 LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_ROUTER;
1145
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);
1153 else
1154 LOCAL_CHASSIS(cfg)->c_med_sw = strdup("Unknown");
1155 #endif
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;
1159
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)
1163 */
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;
1170 }
1171 }
1172
1173 void
1174 lldpd_update_localports(struct lldpd *cfg)
1175 {
1176 struct lldpd_hardware *hardware;
1177
1178 log_debug("localchassis", "update information for local ports");
1179
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;
1185
1186 TRACE(LLDPD_INTERFACES_UPDATE());
1187 interfaces_update(cfg);
1188 lldpd_cleanup(cfg);
1189 lldpd_reset_timer(cfg);
1190 }
1191
1192 void
1193 lldpd_loop(struct lldpd *cfg)
1194 {
1195 /* Main loop.
1196 1. Update local ports information
1197 2. Update local chassis information
1198 */
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);
1209 }
1210
1211 static void
1212 lldpd_exit(struct lldpd *cfg)
1213 {
1214 struct lldpd_hardware *hardware, *hardware_next;
1215 log_debug("main", "exit lldpd");
1216
1217 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
1218 lldpd_send_shutdown(hardware);
1219
1220 close(cfg->g_ctl);
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);
1229 }
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);
1235 }
1236
1237 /**
1238 * Run lldpcli to configure lldpd.
1239 *
1240 * @return PID of running lldpcli or -1 if error.
1241 */
1242 static pid_t
1243 lldpd_configure(int use_syslog, int debug, const char *path, const char *ctlname)
1244 {
1245 pid_t lldpcli = vfork();
1246 int devnull;
1247
1248 char sdebug[debug + 4];
1249 if (use_syslog)
1250 strlcpy(sdebug, "-s", 3);
1251 else {
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';
1258 }
1259 log_debug("main", "invoke %s %s", path, sdebug);
1260
1261 switch (lldpcli) {
1262 case -1:
1263 log_warn("main", "unable to fork");
1264 return -1;
1265 case 0:
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);
1271
1272 execl(path, "lldpcli", sdebug,
1273 "-u", ctlname,
1274 "-c", SYSCONFDIR "/lldpd.conf",
1275 "-c", SYSCONFDIR "/lldpd.d",
1276 "resume",
1277 (char *)NULL);
1278 log_warn("main", "unable to execute %s", path);
1279 log_warnx("main", "configuration is incomplete, lldpd needs to be unpaused");
1280 }
1281 _exit(127);
1282 break;
1283 default:
1284 /* Father, don't do anything stupid */
1285 return lldpcli;
1286 }
1287 /* Should not be here */
1288 return -1;
1289 }
1290
1291 struct intint { int a; int b; };
1292 static const struct intint filters[] = {
1293 { 0, 0 },
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 },
1324 { -1, 0 }
1325 };
1326
1327 #ifndef HOST_OS_OSX
1328 /**
1329 * Tell if we have been started by upstart.
1330 */
1331 static int
1332 lldpd_started_by_upstart()
1333 {
1334 #ifdef HOST_OS_LINUX
1335 const char *upstartjob = getenv("UPSTART_JOB");
1336 if (!(upstartjob && !strcmp(upstartjob, "lldpd")))
1337 return 0;
1338 log_debug("main", "running with upstart, don't fork but stop");
1339 raise(SIGSTOP);
1340 unsetenv("UPSTART_JOB");
1341 return 1;
1342 #else
1343 return 0;
1344 #endif
1345 }
1346
1347 /**
1348 * Tell if we have been started by systemd.
1349 */
1350 static int
1351 lldpd_started_by_systemd()
1352 {
1353 #ifdef HOST_OS_LINUX
1354 int fd = -1;
1355 const char *notifysocket = getenv("NOTIFY_SOCKET");
1356 if (!notifysocket ||
1357 !strchr("@/", notifysocket[0]) ||
1358 strlen(notifysocket) < 2)
1359 return 0;
1360
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",
1364 notifysocket);
1365 return 0;
1366 }
1367
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;
1371
1372 struct iovec iov = {
1373 .iov_base = "READY=1",
1374 .iov_len = strlen("READY=1")
1375 };
1376 struct msghdr hdr = {
1377 .msg_name = &su,
1378 .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(notifysocket),
1379 .msg_iov = &iov,
1380 .msg_iovlen = 1
1381 };
1382 unsetenv("NOTIFY_SOCKET");
1383 if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
1384 log_warn("main", "unable to send notification to systemd");
1385 close(fd);
1386 return 0;
1387 }
1388 close(fd);
1389 return 1;
1390 #else
1391 return 0;
1392 #endif
1393 }
1394 #endif
1395
1396 #ifdef HOST_OS_LINUX
1397 static void
1398 version_convert(const char *sversion, unsigned iversion[], size_t n)
1399 {
1400 const char *p = sversion;
1401 char *end;
1402 for (size_t i = 0; i < n; i++) {
1403 iversion[i] = strtol(p, &end, 10);
1404 if (*end != '.') break;
1405 p = end + 1;
1406 }
1407 }
1408
1409 static void
1410 version_check(void)
1411 {
1412 struct utsname uts;
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");
1427 #endif
1428 }
1429 }
1430 #else
1431 static void version_check(void) {}
1432 #endif
1433
1434 int
1435 lldpd_main(int argc, char *argv[], char *envp[])
1436 {
1437 struct lldpd *cfg;
1438 struct lldpd_chassis *lchassis;
1439 int ch, debug = 0, use_syslog = 1, daemonize = 1;
1440 const char *errstr;
1441 #ifdef USE_SNMP
1442 int snmp = 0;
1443 const char *agentx = NULL; /* AgentX socket */
1444 #endif
1445 const char *ctlname = NULL;
1446 char *mgmtp = NULL;
1447 char *cidp = 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;
1458 #endif
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;
1464 int smart = 15;
1465 int receiveonly = 0, version = 0;
1466 int ctl;
1467
1468 #ifdef ENABLE_PRIVSEP
1469 /* Non privileged user */
1470 struct passwd *user;
1471 struct group *group;
1472 uid_t uid;
1473 gid_t gid;
1474 #endif
1475
1476 saved_argv = argv;
1477
1478 #if HAVE_SETPROCTITLE_INIT
1479 setproctitle_init(argc, argv, envp);
1480 #endif
1481
1482 /*
1483 * Get and parse command line options
1484 */
1485 if ((popt = strchr(opts, '@')) != NULL) {
1486 for (i=0;
1487 protos[i].mode != 0 && *popt != '\0';
1488 i++)
1489 *(popt++) = protos[i].arg;
1490 *popt = '\0';
1491 }
1492 while ((ch = getopt(argc, argv, opts)) != -1) {
1493 switch (ch) {
1494 case 'h':
1495 usage();
1496 break;
1497 case 'v':
1498 version++;
1499 break;
1500 case 'd':
1501 if (daemonize)
1502 daemonize = 0;
1503 else if (use_syslog)
1504 use_syslog = 0;
1505 else
1506 debug++;
1507 break;
1508 case 'D':
1509 log_accept(optarg);
1510 break;
1511 case 'p':
1512 pidfile = optarg;
1513 break;
1514 case 'r':
1515 receiveonly = 1;
1516 break;
1517 case 'm':
1518 if (mgmtp) {
1519 fprintf(stderr, "-m can only be used once\n");
1520 usage();
1521 }
1522 mgmtp = strdup(optarg);
1523 break;
1524 case 'u':
1525 if (ctlname) {
1526 fprintf(stderr, "-u can only be used once\n");
1527 usage();
1528 }
1529 ctlname = optarg;
1530 break;
1531 case 'I':
1532 if (interfaces) {
1533 fprintf(stderr, "-I can only be used once\n");
1534 usage();
1535 }
1536 interfaces = strdup(optarg);
1537 break;
1538 case 'C':
1539 if (cidp) {
1540 fprintf(stderr, "-C can only be used once\n");
1541 usage();
1542 }
1543 cidp = strdup(optarg);
1544 break;
1545 case 'L':
1546 if (strlen(optarg)) lldpcli = optarg;
1547 else lldpcli = NULL;
1548 break;
1549 case 'k':
1550 advertise_version = 0;
1551 break;
1552 #ifdef ENABLE_LLDPMED
1553 case 'M':
1554 lldpmed = strtonum(optarg, 1, 4, &errstr);
1555 if (errstr) {
1556 fprintf(stderr, "-M requires an argument between 1 and 4\n");
1557 usage();
1558 }
1559 break;
1560 case 'i':
1561 noinventory = 1;
1562 break;
1563 #else
1564 case 'M':
1565 case 'i':
1566 fprintf(stderr, "LLDP-MED support is not built-in\n");
1567 usage();
1568 break;
1569 #endif
1570 #ifdef USE_SNMP
1571 case 'x':
1572 snmp = 1;
1573 break;
1574 case 'X':
1575 if (agentx) {
1576 fprintf(stderr, "-X can only be used once\n");
1577 usage();
1578 }
1579 snmp = 1;
1580 agentx = optarg;
1581 break;
1582 #else
1583 case 'x':
1584 case 'X':
1585 fprintf(stderr, "SNMP support is not built-in\n");
1586 usage();
1587 #endif
1588 break;
1589 case 'S':
1590 if (descr_override) {
1591 fprintf(stderr, "-S can only be used once\n");
1592 usage();
1593 }
1594 descr_override = strdup(optarg);
1595 break;
1596 case 'P':
1597 if (platform_override) {
1598 fprintf(stderr, "-P can only be used once\n");
1599 usage();
1600 }
1601 platform_override = strdup(optarg);
1602 break;
1603 case 'H':
1604 smart = strtonum(optarg, 0, sizeof(filters)/sizeof(filters[0]),
1605 &errstr);
1606 if (errstr) {
1607 fprintf(stderr, "-H requires an int between 0 and %zu\n",
1608 sizeof(filters)/sizeof(filters[0]));
1609 usage();
1610 }
1611 break;
1612 default:
1613 found = 0;
1614 for (i=0; protos[i].mode != 0; i++) {
1615 if (ch == protos[i].arg) {
1616 found = 1;
1617 protos[i].enabled++;
1618 }
1619 }
1620 if (!found)
1621 usage();
1622 }
1623 }
1624
1625 if (version) {
1626 version_display(stdout, "lldpd", version > 1);
1627 exit(0);
1628 }
1629
1630 if (ctlname == NULL) ctlname = LLDPD_CTL_SOCKET;
1631
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");
1636 usage();
1637 }
1638 smart = filters[i].b;
1639
1640 log_init(use_syslog, debug, __progname);
1641 tzset(); /* Get timezone info before chroot */
1642
1643 log_debug("main", "lldpd " PACKAGE_VERSION " starting...");
1644 version_check();
1645
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");
1650 uid = user->pw_uid;
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;
1654 #endif
1655
1656 /* Create and setup socket */
1657 int retry = 1;
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 */
1662 int tfd;
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 */
1667 close(tfd);
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);
1674 continue;
1675 }
1676 log_warn("main", "cannot determine if another daemon is already running");
1677 fatalx("main", "giving up");
1678 }
1679 log_warn("main", "unable to create control socket at %s", ctlname);
1680 fatalx("main", "giving up");
1681 }
1682 #ifdef ENABLE_PRIVSEP
1683 if (chown(ctlname, uid, gid) == -1)
1684 log_warn("main", "unable to chown control socket");
1685 if (chmod(ctlname,
1686 S_IRUSR | S_IWUSR | S_IXUSR |
1687 S_IRGRP | S_IWGRP | S_IXGRP) == -1)
1688 log_warn("main", "unable to chmod control socket");
1689 #endif
1690
1691 /* Disable SIGPIPE */
1692 signal(SIGPIPE, SIG_IGN);
1693
1694 /* Disable SIGHUP, until handlers are installed */
1695 signal(SIGHUP, SIG_IGN);
1696
1697 /* Daemonization, unless started by upstart, systemd or launchd or debug */
1698 #ifndef HOST_OS_OSX
1699 if (daemonize &&
1700 !lldpd_started_by_upstart() && !lldpd_started_by_systemd()) {
1701 int pid;
1702 char *spid;
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)");
1716 free(spid);
1717 close(pid);
1718 }
1719 #endif
1720
1721 /* Configuration with lldpcli */
1722 if (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");
1726 }
1727
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();
1732 if (!lsb_release) {
1733 lsb_release = lldpd_get_lsb_release();
1734 }
1735
1736 log_debug("main", "initialize privilege separation");
1737 #ifdef ENABLE_PRIVSEP
1738 priv_init(PRIVSEP_CHROOT, ctl, uid, gid);
1739 #else
1740 priv_init(PRIVSEP_CHROOT, ctl, 0, 0);
1741 #endif
1742
1743 /* Initialization of global configuration */
1744 if ((cfg = (struct lldpd *)
1745 calloc(1, sizeof(struct lldpd))) == NULL)
1746 fatal("main", NULL);
1747
1748 lldpd_alloc_default_local_port(cfg);
1749 cfg->g_ctlname = ctlname;
1750 cfg->g_ctl = ctl;
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;
1755 if (lldpcli)
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;
1765 #endif
1766 #ifdef USE_SNMP
1767 cfg->g_snmp = snmp;
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;
1772
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");
1777
1778 /* Description */
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;
1783 if (descr_override)
1784 cfg->g_config.c_description = descr_override;
1785
1786 if (platform_override)
1787 cfg->g_config.c_platform = platform_override;
1788
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
1800 if (lldpmed > 0) {
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;
1808 } else
1809 cfg->g_config.c_noinventory = 1;
1810 #endif
1811
1812 /* Set TTL */
1813 lchassis->c_ttl = cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold;
1814
1815 log_debug("main", "initialize protocols");
1816 cfg->g_protocols = protos;
1817 for (i=0; protos[i].mode != 0; i++) {
1818
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;
1825 }
1826 /* With -cc force CDPV1, enable CDPV2 */
1827 if (protos[i].mode == LLDPD_MODE_CDPV2 && protos[i].enabled == 2) {
1828 protos[i].enabled = 1;
1829 }
1830
1831 /* With -cccc disable CDPV1, enable CDPV2 */
1832 if (protos[i].mode == LLDPD_MODE_CDPV1 && protos[i].enabled >= 4) {
1833 protos[i].enabled = 0;
1834 }
1835
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;
1839 }
1840
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);
1845 else
1846 log_info("main", "protocol %s disabled", protos[i].name);
1847 }
1848
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 */
1853
1854 /* Main loop */
1855 log_debug("main", "start main loop");
1856 levent_loop(cfg);
1857 lchassis->c_refcount--;
1858 lldpd_exit(cfg);
1859 free(cfg);
1860
1861 return (0);
1862 }