]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/daemon/lldpd.c
lldpd: correctly increase discarded count
[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 hardware->h_rx_discarded_cnt++;
523 return;
524 }
525
526 /* Decapsulate VLAN frames */
527 struct ether_header eheader;
528 memcpy(&eheader, frame, sizeof(struct ether_header));
529 if (eheader.ether_type == htons(ETHERTYPE_VLAN)) {
530 /* VLAN decapsulation means to shift 4 bytes left the frame from
531 * offset 2*ETHER_ADDR_LEN */
532 memmove(frame + 2*ETHER_ADDR_LEN, frame + 2*ETHER_ADDR_LEN + 4, s - 2*ETHER_ADDR_LEN);
533 s -= 4;
534 }
535
536 TAILQ_FOREACH(oport, &hardware->h_rports, p_entries) {
537 if ((oport->p_lastframe != NULL) &&
538 (oport->p_lastframe->size == s) &&
539 (memcmp(oport->p_lastframe->frame, frame, s) == 0)) {
540 /* Already received the same frame */
541 log_debug("decode", "duplicate frame, no need to decode");
542 oport->p_lastupdate = time(NULL);
543 return;
544 }
545 }
546
547 guess = lldpd_guess_type(cfg, frame, s);
548 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
549 if (!cfg->g_protocols[i].enabled)
550 continue;
551 if (cfg->g_protocols[i].mode == guess) {
552 log_debug("decode", "using decode function for %s protocol",
553 cfg->g_protocols[i].name);
554 if (cfg->g_protocols[i].decode(cfg, frame,
555 s, hardware, &chassis, &port) == -1) {
556 log_debug("decode", "function for %s protocol did not decode this frame",
557 cfg->g_protocols[i].name);
558 hardware->h_rx_discarded_cnt++;
559 return;
560 }
561 chassis->c_protocol = port->p_protocol =
562 cfg->g_protocols[i].mode;
563 break;
564 }
565 }
566 if (cfg->g_protocols[i].mode == 0) {
567 log_debug("decode", "unable to guess frame type on %s",
568 hardware->h_ifname);
569 return;
570 }
571 TRACE(LLDPD_FRAME_DECODED(
572 hardware->h_ifname,
573 cfg->g_protocols[i].name,
574 chassis->c_name,
575 port->p_descr));
576
577 /* Do we already have the same MSAP somewhere? */
578 int count = 0;
579 log_debug("decode", "search for the same MSAP");
580 TAILQ_FOREACH(oport, &hardware->h_rports, p_entries) {
581 if (port->p_protocol == oport->p_protocol) {
582 count++;
583 if ((port->p_id_subtype == oport->p_id_subtype) &&
584 (port->p_id_len == oport->p_id_len) &&
585 (memcmp(port->p_id, oport->p_id, port->p_id_len) == 0) &&
586 (chassis->c_id_subtype == oport->p_chassis->c_id_subtype) &&
587 (chassis->c_id_len == oport->p_chassis->c_id_len) &&
588 (memcmp(chassis->c_id, oport->p_chassis->c_id,
589 chassis->c_id_len) == 0)) {
590 ochassis = oport->p_chassis;
591 log_debug("decode", "MSAP is already known");
592 break;
593 }
594 }
595 }
596 /* Do we have room for a new MSAP? */
597 if (!oport && cfg->g_config.c_max_neighbors) {
598 if (count == (cfg->g_config.c_max_neighbors - 1)) {
599 log_debug("decode",
600 "max neighbors %d reached for port %s, "
601 "dropping any new ones silently",
602 cfg->g_config.c_max_neighbors,
603 hardware->h_ifname);
604 } else if (count > cfg->g_config.c_max_neighbors - 1) {
605 log_debug("decode",
606 "too many neighbors for port %s, drop this new one",
607 hardware->h_ifname);
608 lldpd_port_cleanup(port, 1);
609 lldpd_chassis_cleanup(chassis, 1);
610 free(port);
611 return;
612 }
613 }
614 /* No, but do we already know the system? */
615 if (!oport) {
616 log_debug("decode", "MSAP is unknown, search for the chassis");
617 TAILQ_FOREACH(ochassis, &cfg->g_chassis, c_entries) {
618 if ((chassis->c_protocol == ochassis->c_protocol) &&
619 (chassis->c_id_subtype == ochassis->c_id_subtype) &&
620 (chassis->c_id_len == ochassis->c_id_len) &&
621 (memcmp(chassis->c_id, ochassis->c_id,
622 chassis->c_id_len) == 0))
623 break;
624 }
625 }
626
627 if (oport) {
628 /* The port is known, remove it before adding it back */
629 TAILQ_REMOVE(&hardware->h_rports, oport, p_entries);
630 lldpd_port_cleanup(oport, 1);
631 free(oport);
632 }
633 if (ochassis) {
634 lldpd_move_chassis(ochassis, chassis);
635 chassis = ochassis;
636 } else {
637 /* Chassis not known, add it */
638 log_debug("decode", "unknown chassis, add it to the list");
639 chassis->c_index = ++cfg->g_lastrid;
640 chassis->c_refcount = 0;
641 TAILQ_INSERT_TAIL(&cfg->g_chassis, chassis, c_entries);
642 i = 0; TAILQ_FOREACH(ochassis, &cfg->g_chassis, c_entries) i++;
643 log_debug("decode", "%d different systems are known", i);
644 }
645 /* Add port */
646 port->p_lastchange = port->p_lastupdate = time(NULL);
647 if ((port->p_lastframe = (struct lldpd_frame *)malloc(s +
648 sizeof(struct lldpd_frame))) != NULL) {
649 port->p_lastframe->size = s;
650 memcpy(port->p_lastframe->frame, frame, s);
651 }
652 TAILQ_INSERT_TAIL(&hardware->h_rports, port, p_entries);
653 port->p_chassis = chassis;
654 port->p_chassis->c_refcount++;
655 /* Several cases are possible :
656 1. chassis is new, its refcount was 0. It is now attached
657 to this port, its refcount is 1.
658 2. chassis already exists and was attached to another
659 port, we increase its refcount accordingly.
660 3. chassis already exists and was attached to the same
661 port, its refcount was decreased with
662 lldpd_port_cleanup() and is now increased again.
663
664 In all cases, if the port already existed, it has been
665 freed with lldpd_port_cleanup() and therefore, the refcount
666 of the chassis that was attached to it is decreased.
667 */
668 /* coverity[use_after_free]
669 TAILQ_REMOVE does the right thing */
670 i = 0; TAILQ_FOREACH(aport, &hardware->h_rports, p_entries)
671 i++;
672 log_debug("decode", "%d neighbors for %s", i,
673 hardware->h_ifname);
674
675 if (!oport) hardware->h_insert_cnt++;
676
677 /* Notify */
678 log_debug("decode", "send notifications for changes on %s",
679 hardware->h_ifname);
680 if (oport) {
681 TRACE(LLDPD_NEIGHBOR_UPDATE(hardware->h_ifname,
682 chassis->c_name,
683 port->p_descr,
684 i));
685 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_UPDATED, port);
686 #ifdef USE_SNMP
687 agent_notify(hardware, NEIGHBOR_CHANGE_UPDATED, port);
688 #endif
689 } else {
690 TRACE(LLDPD_NEIGHBOR_NEW(hardware->h_ifname,
691 chassis->c_name,
692 port->p_descr,
693 i));
694 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_ADDED, port);
695 #ifdef USE_SNMP
696 agent_notify(hardware, NEIGHBOR_CHANGE_ADDED, port);
697 #endif
698 }
699
700 #ifdef ENABLE_LLDPMED
701 if (!oport && port->p_chassis->c_med_type) {
702 /* New neighbor, fast start */
703 if (hardware->h_cfg->g_config.c_enable_fast_start &&
704 !hardware->h_tx_fast) {
705 log_debug("decode", "%s: entering fast start due to "
706 "new neighbor", hardware->h_ifname);
707 hardware->h_tx_fast = hardware->h_cfg->g_config.c_tx_fast_init;
708 }
709
710 levent_schedule_pdu(hardware);
711 }
712 #endif
713
714 return;
715 }
716
717 /* Get the output of lsb_release -s -d. This is a slow function. It should be
718 called once. It return NULL if any problem happens. Otherwise, this is a
719 statically allocated buffer. The result includes the trailing \n */
720 static char *
721 lldpd_get_lsb_release() {
722 static char release[1024];
723 char *const command[] = { "lsb_release", "-s", "-d", NULL };
724 int pid, status, devnull, count;
725 int pipefd[2];
726
727 log_debug("localchassis", "grab LSB release");
728
729 if (pipe(pipefd)) {
730 log_warn("localchassis", "unable to get a pair of pipes");
731 return NULL;
732 }
733
734 pid = vfork();
735 switch (pid) {
736 case -1:
737 log_warn("localchassis", "unable to fork");
738 return NULL;
739 case 0:
740 /* Child, exec lsb_release */
741 close(pipefd[0]);
742 if ((devnull = open("/dev/null", O_RDWR, 0)) != -1) {
743 dup2(devnull, STDIN_FILENO);
744 dup2(devnull, STDERR_FILENO);
745 dup2(pipefd[1], STDOUT_FILENO);
746 if (devnull > 2) close(devnull);
747 if (pipefd[1] > 2) close(pipefd[1]);
748 execvp("lsb_release", command);
749 }
750 _exit(127);
751 break;
752 default:
753 /* Father, read the output from the children */
754 close(pipefd[1]);
755 count = 0;
756 do {
757 status = read(pipefd[0], release+count, sizeof(release)-count);
758 if ((status == -1) && (errno == EINTR)) continue;
759 if (status > 0)
760 count += status;
761 } while (count < sizeof(release) && (status > 0));
762 if (status < 0) {
763 log_info("localchassis", "unable to read from lsb_release");
764 close(pipefd[0]);
765 waitpid(pid, &status, 0);
766 return NULL;
767 }
768 close(pipefd[0]);
769 if (count >= sizeof(release)) {
770 log_info("localchassis", "output of lsb_release is too large");
771 waitpid(pid, &status, 0);
772 return NULL;
773 }
774 status = -1;
775 if (waitpid(pid, &status, 0) != pid)
776 return NULL;
777 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
778 log_info("localchassis", "lsb_release information not available");
779 return NULL;
780 }
781 if (!count) {
782 log_info("localchassis", "lsb_release returned an empty string");
783 return NULL;
784 }
785 release[count] = '\0';
786 return release;
787 }
788 /* Should not be here */
789 return NULL;
790 }
791
792 /* Same like lldpd_get_lsb_release but reads /etc/os-release for PRETTY_NAME=. */
793 static char *
794 lldpd_get_os_release() {
795 static char release[1024];
796 char line[1024];
797 char *key, *val;
798 char *ptr1 = release;
799
800 log_debug("localchassis", "grab OS release");
801 FILE *fp = fopen("/etc/os-release", "r");
802 if (!fp) {
803 log_debug("localchassis", "could not open /etc/os-release");
804 fp = fopen("/usr/lib/os-release", "r");
805 }
806 if (!fp) {
807 log_info("localchassis",
808 "could not open either /etc/os-release or /usr/lib/os-release");
809 return NULL;
810 }
811
812 while ((fgets(line, sizeof(line), fp) != NULL)) {
813 key = strtok(line, "=");
814 val = strtok(NULL, "=");
815
816 if (strncmp(key, "PRETTY_NAME", sizeof(line)) == 0) {
817 strlcpy(release, val, sizeof(line));
818 break;
819 }
820 }
821 fclose(fp);
822
823 /* Remove trailing newline and all " in the string. */
824 ptr1 = release + strlen(release) - 1;
825 while (ptr1 != release &&
826 ((*ptr1 == '"') || (*ptr1 == '\n'))) {
827 *ptr1 = '\0';
828 ptr1--;
829 }
830 if (release[0] == '"')
831 return release+1;
832 return release;
833 }
834
835 static void
836 lldpd_hide_ports(struct lldpd *cfg, struct lldpd_hardware *hardware, int mask) {
837 struct lldpd_port *port;
838 int protocols[LLDPD_MODE_MAX+1];
839 char buffer[256];
840 int i, j, k, found;
841 unsigned int min;
842
843 log_debug("smartfilter", "apply smart filter for port %s",
844 hardware->h_ifname);
845
846 /* Compute the number of occurrences of each protocol */
847 for (i = 0; i <= LLDPD_MODE_MAX; i++) protocols[i] = 0;
848 TAILQ_FOREACH(port, &hardware->h_rports, p_entries)
849 protocols[port->p_protocol]++;
850
851 /* Turn the protocols[] array into an array of
852 enabled/disabled protocols. 1 means enabled, 0
853 means disabled. */
854 min = (unsigned int)-1;
855 for (i = 0; i <= LLDPD_MODE_MAX; i++)
856 if (protocols[i] && (protocols[i] < min))
857 min = protocols[i];
858 found = 0;
859 for (i = 0; i <= LLDPD_MODE_MAX; i++)
860 if ((protocols[i] == min) && !found) {
861 /* If we need a tie breaker, we take
862 the first protocol only */
863 if (cfg->g_config.c_smart & mask &
864 (SMART_OUTGOING_ONE_PROTO | SMART_INCOMING_ONE_PROTO))
865 found = 1;
866 protocols[i] = 1;
867 } else protocols[i] = 0;
868
869 /* We set the p_hidden flag to 1 if the protocol is disabled */
870 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
871 if (mask == SMART_OUTGOING)
872 port->p_hidden_out = protocols[port->p_protocol]?0:1;
873 else
874 port->p_hidden_in = protocols[port->p_protocol]?0:1;
875 }
876
877 /* If we want only one neighbor, we take the first one */
878 if (cfg->g_config.c_smart & mask &
879 (SMART_OUTGOING_ONE_NEIGH | SMART_INCOMING_ONE_NEIGH)) {
880 found = 0;
881 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
882 if (mask == SMART_OUTGOING) {
883 if (found) port->p_hidden_out = 1;
884 if (!port->p_hidden_out)
885 found = 1;
886 }
887 if (mask == SMART_INCOMING) {
888 if (found) port->p_hidden_in = 1;
889 if (!port->p_hidden_in)
890 found = 1;
891 }
892 }
893 }
894
895 /* Print a debug message summarizing the operation */
896 for (i = 0; i <= LLDPD_MODE_MAX; i++) protocols[i] = 0;
897 k = j = 0;
898 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
899 if (!(((mask == SMART_OUTGOING) && port->p_hidden_out) ||
900 ((mask == SMART_INCOMING) && port->p_hidden_in))) {
901 k++;
902 protocols[port->p_protocol] = 1;
903 }
904 j++;
905 }
906 buffer[0] = '\0';
907 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
908 if (cfg->g_protocols[i].enabled && protocols[cfg->g_protocols[i].mode]) {
909 if (strlen(buffer) +
910 strlen(cfg->g_protocols[i].name) + 3 > sizeof(buffer)) {
911 /* Unlikely, our buffer is too small */
912 memcpy(buffer + sizeof(buffer) - 4, "...", 4);
913 break;
914 }
915 if (buffer[0])
916 strncat(buffer, ", ", 2);
917 strncat(buffer, cfg->g_protocols[i].name, strlen(cfg->g_protocols[i].name));
918 }
919 }
920 log_debug("smartfilter", "%s: %s: %d visible neighbors (out of %d)",
921 hardware->h_ifname,
922 (mask == SMART_OUTGOING)?"out filter":"in filter",
923 k, j);
924 log_debug("smartfilter", "%s: protocols: %s",
925 hardware->h_ifname, buffer[0]?buffer:"(none)");
926 }
927
928 /* Hide unwanted ports depending on smart mode set by the user */
929 static void
930 lldpd_hide_all(struct lldpd *cfg)
931 {
932 struct lldpd_hardware *hardware;
933
934 if (!cfg->g_config.c_smart)
935 return;
936 log_debug("smartfilter", "apply smart filter results on all ports");
937 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
938 if (cfg->g_config.c_smart & SMART_INCOMING_FILTER)
939 lldpd_hide_ports(cfg, hardware, SMART_INCOMING);
940 if (cfg->g_config.c_smart & SMART_OUTGOING_FILTER)
941 lldpd_hide_ports(cfg, hardware, SMART_OUTGOING);
942 }
943 }
944
945 void
946 lldpd_recv(struct lldpd *cfg, struct lldpd_hardware *hardware, int fd)
947 {
948 char *buffer = NULL;
949 int n;
950 log_debug("receive", "receive a frame on %s",
951 hardware->h_ifname);
952 if ((buffer = (char *)malloc(hardware->h_mtu)) == NULL) {
953 log_warn("receive", "failed to alloc reception buffer");
954 return;
955 }
956 if ((n = hardware->h_ops->recv(cfg, hardware,
957 fd, buffer,
958 hardware->h_mtu)) == -1) {
959 log_debug("receive", "discard frame received on %s",
960 hardware->h_ifname);
961 free(buffer);
962 return;
963 }
964 if (hardware->h_lport.p_disable_rx) {
965 log_debug("receive", "RX disabled, ignore the frame on %s",
966 hardware->h_ifname);
967 free(buffer);
968 return;
969 }
970 if (cfg->g_config.c_paused) {
971 log_debug("receive", "paused, ignore the frame on %s",
972 hardware->h_ifname);
973 free(buffer);
974 return;
975 }
976 hardware->h_rx_cnt++;
977 log_debug("receive", "decode received frame on %s",
978 hardware->h_ifname);
979 TRACE(LLDPD_FRAME_RECEIVED(hardware->h_ifname, buffer, (size_t)n));
980 lldpd_decode(cfg, buffer, n, hardware);
981 lldpd_hide_all(cfg); /* Immediatly hide */
982 lldpd_count_neighbors(cfg);
983 free(buffer);
984 }
985
986 static void
987 lldpd_send_shutdown(struct lldpd_hardware *hardware)
988 {
989 struct lldpd *cfg = hardware->h_cfg;
990 if (cfg->g_config.c_receiveonly || cfg->g_config.c_paused) return;
991 if (hardware->h_lport.p_disable_tx) return;
992 if ((hardware->h_flags & IFF_RUNNING) == 0)
993 return;
994
995 /* It's safe to call `lldp_send_shutdown()` because shutdown LLDPU will
996 * only be emitted if LLDP was sent on that port. */
997 if (lldp_send_shutdown(hardware->h_cfg, hardware) != 0)
998 log_warnx("send", "unable to send shutdown LLDPDU on %s",
999 hardware->h_ifname);
1000 }
1001
1002 void
1003 lldpd_send(struct lldpd_hardware *hardware)
1004 {
1005 struct lldpd *cfg = hardware->h_cfg;
1006 struct lldpd_port *port;
1007 int i, sent;
1008
1009 if (cfg->g_config.c_receiveonly || cfg->g_config.c_paused) return;
1010 if (hardware->h_lport.p_disable_tx) return;
1011 if ((hardware->h_flags & IFF_RUNNING) == 0)
1012 return;
1013
1014 log_debug("send", "send PDU on %s", hardware->h_ifname);
1015 sent = 0;
1016 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
1017 if (!cfg->g_protocols[i].enabled)
1018 continue;
1019 /* We send only if we have at least one remote system
1020 * speaking this protocol or if the protocol is forced */
1021 if (cfg->g_protocols[i].enabled > 1) {
1022 cfg->g_protocols[i].send(cfg, hardware);
1023 sent++;
1024 continue;
1025 }
1026 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
1027 /* If this remote port is disabled, we don't
1028 * consider it */
1029 if (port->p_hidden_out)
1030 continue;
1031 if (port->p_protocol ==
1032 cfg->g_protocols[i].mode) {
1033 TRACE(LLDPD_FRAME_SEND(hardware->h_ifname,
1034 cfg->g_protocols[i].name));
1035 log_debug("send", "send PDU on %s with protocol %s",
1036 hardware->h_ifname,
1037 cfg->g_protocols[i].name);
1038 cfg->g_protocols[i].send(cfg,
1039 hardware);
1040 sent++;
1041 break;
1042 }
1043 }
1044 }
1045
1046 if (!sent) {
1047 /* Nothing was sent for this port, let's speak the first
1048 * available protocol. */
1049 for (i = 0; cfg->g_protocols[i].mode != 0; i++) {
1050 if (!cfg->g_protocols[i].enabled) continue;
1051 TRACE(LLDPD_FRAME_SEND(hardware->h_ifname,
1052 cfg->g_protocols[i].name));
1053 log_debug("send", "fallback to protocol %s for %s",
1054 cfg->g_protocols[i].name, hardware->h_ifname);
1055 cfg->g_protocols[i].send(cfg,
1056 hardware);
1057 break;
1058 }
1059 if (cfg->g_protocols[i].mode == 0)
1060 log_warnx("send", "no protocol enabled, dunno what to send");
1061 }
1062 }
1063
1064 #ifdef ENABLE_LLDPMED
1065 static void
1066 lldpd_med(struct lldpd_chassis *chassis)
1067 {
1068 static short int once = 0;
1069 if (!once) {
1070 chassis->c_med_hw = dmi_hw();
1071 chassis->c_med_fw = dmi_fw();
1072 chassis->c_med_sn = dmi_sn();
1073 chassis->c_med_manuf = dmi_manuf();
1074 chassis->c_med_model = dmi_model();
1075 chassis->c_med_asset = dmi_asset();
1076 once = 1;
1077 }
1078 }
1079 #endif
1080
1081 static int
1082 lldpd_routing_enabled(struct lldpd *cfg)
1083 {
1084 int routing;
1085
1086 if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_ROUTER) == 0)
1087 return 0;
1088
1089 if ((routing = interfaces_routing_enabled(cfg)) == -1) {
1090 log_debug("localchassis", "unable to check if routing is enabled");
1091 return 0;
1092 }
1093 return routing;
1094 }
1095
1096 static void
1097 lldpd_update_localchassis(struct lldpd *cfg)
1098 {
1099 struct utsname un;
1100 char *hp;
1101
1102 log_debug("localchassis", "update information for local chassis");
1103 assert(LOCAL_CHASSIS(cfg) != NULL);
1104
1105 /* Set system name and description */
1106 if (uname(&un) < 0)
1107 fatal("localchassis", "failed to get system information");
1108 if (cfg->g_config.c_hostname) {
1109 log_debug("localchassis", "use overridden system name `%s`", cfg->g_config.c_hostname);
1110 hp = cfg->g_config.c_hostname;
1111 } else {
1112 if ((hp = priv_gethostname()) == NULL)
1113 fatal("localchassis", "failed to get system name");
1114 }
1115 free(LOCAL_CHASSIS(cfg)->c_name);
1116 free(LOCAL_CHASSIS(cfg)->c_descr);
1117 if ((LOCAL_CHASSIS(cfg)->c_name = strdup(hp)) == NULL)
1118 fatal("localchassis", NULL);
1119 if (cfg->g_config.c_description) {
1120 log_debug("localchassis", "use overridden description `%s`", cfg->g_config.c_description);
1121 if (asprintf(&LOCAL_CHASSIS(cfg)->c_descr, "%s",
1122 cfg->g_config.c_description) == -1)
1123 fatal("localchassis", "failed to set full system description");
1124 } else {
1125 if (cfg->g_config.c_advertise_version) {
1126 log_debug("localchassis", "advertise system version");
1127 if (asprintf(&LOCAL_CHASSIS(cfg)->c_descr, "%s %s %s %s %s",
1128 cfg->g_lsb_release?cfg->g_lsb_release:"",
1129 un.sysname, un.release, un.version, un.machine)
1130 == -1)
1131 fatal("localchassis", "failed to set full system description");
1132 } else {
1133 log_debug("localchassis", "do not advertise system version");
1134 if (asprintf(&LOCAL_CHASSIS(cfg)->c_descr, "%s",
1135 cfg->g_lsb_release?cfg->g_lsb_release:un.sysname) == -1)
1136 fatal("localchassis", "failed to set minimal system description");
1137 }
1138 }
1139 if (cfg->g_config.c_platform == NULL)
1140 cfg->g_config.c_platform = strdup(un.sysname);
1141
1142 /* Check routing */
1143 if (lldpd_routing_enabled(cfg)) {
1144 log_debug("localchassis", "routing is enabled, enable router capability");
1145 LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_ROUTER;
1146 } else
1147 LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_ROUTER;
1148
1149 #ifdef ENABLE_LLDPMED
1150 if (LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_TELEPHONE)
1151 LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_TELEPHONE;
1152 lldpd_med(LOCAL_CHASSIS(cfg));
1153 free(LOCAL_CHASSIS(cfg)->c_med_sw);
1154 if (cfg->g_config.c_advertise_version)
1155 LOCAL_CHASSIS(cfg)->c_med_sw = strdup(un.release);
1156 else
1157 LOCAL_CHASSIS(cfg)->c_med_sw = strdup("Unknown");
1158 #endif
1159 if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) &&
1160 (LOCAL_CHASSIS(cfg)->c_cap_enabled == 0))
1161 LOCAL_CHASSIS(cfg)->c_cap_enabled = LLDP_CAP_STATION;
1162
1163 /* Set chassis ID if needed. This is only done if chassis ID
1164 has not been set previously (with the MAC address of an
1165 interface for example)
1166 */
1167 if (LOCAL_CHASSIS(cfg)->c_id == NULL) {
1168 log_debug("localchassis", "no chassis ID is currently set, use chassis name");
1169 if (!(LOCAL_CHASSIS(cfg)->c_id = strdup(LOCAL_CHASSIS(cfg)->c_name)))
1170 fatal("localchassis", NULL);
1171 LOCAL_CHASSIS(cfg)->c_id_len = strlen(LOCAL_CHASSIS(cfg)->c_name);
1172 LOCAL_CHASSIS(cfg)->c_id_subtype = LLDP_CHASSISID_SUBTYPE_LOCAL;
1173 }
1174 }
1175
1176 void
1177 lldpd_update_localports(struct lldpd *cfg)
1178 {
1179 struct lldpd_hardware *hardware;
1180
1181 log_debug("localchassis", "update information for local ports");
1182
1183 /* h_flags is set to 0 for each port. If the port is updated, h_flags
1184 * will be set to a non-zero value. This will allow us to clean up any
1185 * non up-to-date port */
1186 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
1187 hardware->h_flags = 0;
1188
1189 TRACE(LLDPD_INTERFACES_UPDATE());
1190 interfaces_update(cfg);
1191 lldpd_cleanup(cfg);
1192 lldpd_reset_timer(cfg);
1193 }
1194
1195 void
1196 lldpd_loop(struct lldpd *cfg)
1197 {
1198 /* Main loop.
1199 1. Update local ports information
1200 2. Update local chassis information
1201 */
1202 log_debug("loop", "start new loop");
1203 LOCAL_CHASSIS(cfg)->c_cap_enabled = 0;
1204 /* Information for local ports is triggered even when it is possible to
1205 * update them on some other event because we want to refresh them if we
1206 * missed something. */
1207 log_debug("loop", "update information for local ports");
1208 lldpd_update_localports(cfg);
1209 log_debug("loop", "update information for local chassis");
1210 lldpd_update_localchassis(cfg);
1211 lldpd_count_neighbors(cfg);
1212 }
1213
1214 static void
1215 lldpd_exit(struct lldpd *cfg)
1216 {
1217 struct lldpd_hardware *hardware, *hardware_next;
1218 log_debug("main", "exit lldpd");
1219
1220 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
1221 lldpd_send_shutdown(hardware);
1222
1223 close(cfg->g_ctl);
1224 priv_ctl_cleanup(cfg->g_ctlname);
1225 log_debug("main", "cleanup hardware information");
1226 for (hardware = TAILQ_FIRST(&cfg->g_hardware); hardware != NULL;
1227 hardware = hardware_next) {
1228 hardware_next = TAILQ_NEXT(hardware, h_entries);
1229 log_debug("main", "cleanup interface %s", hardware->h_ifname);
1230 lldpd_remote_cleanup(hardware, NULL, 1);
1231 lldpd_hardware_cleanup(cfg, hardware);
1232 }
1233 interfaces_cleanup(cfg);
1234 lldpd_port_cleanup(cfg->g_default_local_port, 1);
1235 lldpd_all_chassis_cleanup(cfg);
1236 free(cfg->g_default_local_port);
1237 free(cfg->g_config.c_platform);
1238 levent_shutdown(cfg);
1239 }
1240
1241 /**
1242 * Run lldpcli to configure lldpd.
1243 *
1244 * @return PID of running lldpcli or -1 if error.
1245 */
1246 static pid_t
1247 lldpd_configure(int use_syslog, int debug, const char *path, const char *ctlname)
1248 {
1249 pid_t lldpcli = vfork();
1250 int devnull;
1251
1252 char sdebug[debug + 4];
1253 if (use_syslog)
1254 strlcpy(sdebug, "-s", 3);
1255 else {
1256 /* debug = 0 -> -sd */
1257 /* debug = 1 -> -sdd */
1258 /* debug = 2 -> -sddd */
1259 memset(sdebug, 'd', sizeof(sdebug));
1260 sdebug[debug + 3] = '\0';
1261 sdebug[0] = '-'; sdebug[1] = 's';
1262 }
1263 log_debug("main", "invoke %s %s", path, sdebug);
1264
1265 switch (lldpcli) {
1266 case -1:
1267 log_warn("main", "unable to fork");
1268 return -1;
1269 case 0:
1270 /* Child, exec lldpcli */
1271 if ((devnull = open("/dev/null", O_RDWR, 0)) != -1) {
1272 dup2(devnull, STDIN_FILENO);
1273 dup2(devnull, STDOUT_FILENO);
1274 if (devnull > 2) close(devnull);
1275
1276 execl(path, "lldpcli", sdebug,
1277 "-u", ctlname,
1278 "-C", SYSCONFDIR "/lldpd.conf",
1279 "-C", SYSCONFDIR "/lldpd.d",
1280 "resume",
1281 (char *)NULL);
1282 log_warn("main", "unable to execute %s", path);
1283 log_warnx("main", "configuration is incomplete, lldpd needs to be unpaused");
1284 }
1285 _exit(127);
1286 break;
1287 default:
1288 /* Father, don't do anything stupid */
1289 return lldpcli;
1290 }
1291 /* Should not be here */
1292 return -1;
1293 }
1294
1295 struct intint { int a; int b; };
1296 static const struct intint filters[] = {
1297 { 0, 0 },
1298 { 1, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1299 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1300 { 2, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO },
1301 { 3, SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1302 { 4, SMART_INCOMING_FILTER | SMART_OUTGOING_FILTER },
1303 { 5, SMART_INCOMING_FILTER },
1304 { 6, SMART_OUTGOING_FILTER },
1305 { 7, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_INCOMING_ONE_NEIGH |
1306 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1307 { 8, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_INCOMING_ONE_NEIGH },
1308 { 9, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH |
1309 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1310 { 10, SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1311 { 11, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH },
1312 { 12, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH |
1313 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1314 { 13, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH |
1315 SMART_OUTGOING_FILTER },
1316 { 14, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1317 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1318 { 15, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1319 SMART_OUTGOING_FILTER },
1320 { 16, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_INCOMING_ONE_NEIGH |
1321 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1322 { 17, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_INCOMING_ONE_NEIGH |
1323 SMART_OUTGOING_FILTER },
1324 { 18, SMART_INCOMING_FILTER |
1325 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1326 { 19, SMART_INCOMING_FILTER |
1327 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1328 { -1, 0 }
1329 };
1330
1331 #ifndef HOST_OS_OSX
1332 /**
1333 * Tell if we have been started by upstart.
1334 */
1335 static int
1336 lldpd_started_by_upstart()
1337 {
1338 #ifdef HOST_OS_LINUX
1339 const char *upstartjob = getenv("UPSTART_JOB");
1340 if (!(upstartjob && !strcmp(upstartjob, "lldpd")))
1341 return 0;
1342 log_debug("main", "running with upstart, don't fork but stop");
1343 raise(SIGSTOP);
1344 unsetenv("UPSTART_JOB");
1345 return 1;
1346 #else
1347 return 0;
1348 #endif
1349 }
1350
1351 /**
1352 * Tell if we have been started by systemd.
1353 */
1354 static int
1355 lldpd_started_by_systemd()
1356 {
1357 #ifdef HOST_OS_LINUX
1358 int fd = -1;
1359 const char *notifysocket = getenv("NOTIFY_SOCKET");
1360 if (!notifysocket ||
1361 !strchr("@/", notifysocket[0]) ||
1362 strlen(notifysocket) < 2)
1363 return 0;
1364
1365 log_debug("main", "running with systemd, don't fork but signal ready");
1366 if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
1367 log_warn("main", "unable to open systemd notification socket %s",
1368 notifysocket);
1369 return 0;
1370 }
1371
1372 struct sockaddr_un su = { .sun_family = AF_UNIX };
1373 strlcpy(su.sun_path, notifysocket, sizeof(su.sun_path));
1374 if (notifysocket[0] == '@') su.sun_path[0] = 0;
1375
1376 struct iovec iov = {
1377 .iov_base = "READY=1",
1378 .iov_len = strlen("READY=1")
1379 };
1380 struct msghdr hdr = {
1381 .msg_name = &su,
1382 .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(notifysocket),
1383 .msg_iov = &iov,
1384 .msg_iovlen = 1
1385 };
1386 unsetenv("NOTIFY_SOCKET");
1387 if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
1388 log_warn("main", "unable to send notification to systemd");
1389 close(fd);
1390 return 0;
1391 }
1392 close(fd);
1393 return 1;
1394 #else
1395 return 0;
1396 #endif
1397 }
1398 #endif
1399
1400 #ifdef HOST_OS_LINUX
1401 static void
1402 version_convert(const char *sversion, unsigned iversion[], size_t n)
1403 {
1404 const char *p = sversion;
1405 char *end;
1406 for (size_t i = 0; i < n; i++) {
1407 iversion[i] = strtol(p, &end, 10);
1408 if (*end != '.') break;
1409 p = end + 1;
1410 }
1411 }
1412
1413 static void
1414 version_check(void)
1415 {
1416 struct utsname uts;
1417 if (uname(&uts) == -1) return;
1418 unsigned version_min[3] = {};
1419 unsigned version_cur[3] = {};
1420 version_convert(uts.release, version_cur, 3);
1421 version_convert(MIN_LINUX_KERNEL_VERSION, version_min, 3);
1422 if (version_min[0] > version_cur[0] ||
1423 (version_min[0] == version_cur[0] && version_min[1] > version_cur[1]) ||
1424 (version_min[0] == version_cur[0] && version_min[1] == version_cur[1] &&
1425 version_min[2] > version_cur[2])) {
1426 log_warnx("lldpd", "minimal kernel version required is %s, got %s",
1427 MIN_LINUX_KERNEL_VERSION, uts.release);
1428 log_warnx("lldpd", "lldpd may be unable to detect bonds and bridges correctly");
1429 #ifndef ENABLE_OLDIES
1430 log_warnx("lldpd", "consider recompiling with --enable-oldies option");
1431 #endif
1432 }
1433 }
1434 #else
1435 static void version_check(void) {}
1436 #endif
1437
1438 int
1439 lldpd_main(int argc, char *argv[], char *envp[])
1440 {
1441 struct lldpd *cfg;
1442 struct lldpd_chassis *lchassis;
1443 int ch, debug = 0, use_syslog = 1, daemonize = 1;
1444 const char *errstr;
1445 #ifdef USE_SNMP
1446 int snmp = 0;
1447 const char *agentx = NULL; /* AgentX socket */
1448 #endif
1449 const char *ctlname = NULL;
1450 char *mgmtp = NULL;
1451 char *cidp = NULL;
1452 char *interfaces = NULL;
1453 /* We do not want more options here. Please add them in lldpcli instead
1454 * unless there is a very good reason. Most command-line options will
1455 * get deprecated at some point. */
1456 char *popt, opts[] =
1457 "H:vhkrdD:p:xX:m:u:4:6:I:C:p:M:P:S:iL:@ ";
1458 int i, found, advertise_version = 1;
1459 #ifdef ENABLE_LLDPMED
1460 int lldpmed = 0, noinventory = 0;
1461 int enable_fast_start = 1;
1462 #endif
1463 char *descr_override = NULL;
1464 char *platform_override = NULL;
1465 char *lsb_release = NULL;
1466 const char *lldpcli = LLDPCLI_PATH;
1467 const char *pidfile = LLDPD_PID_FILE;
1468 int smart = 15;
1469 int receiveonly = 0, version = 0;
1470 int ctl;
1471
1472 #ifdef ENABLE_PRIVSEP
1473 /* Non privileged user */
1474 struct passwd *user;
1475 struct group *group;
1476 uid_t uid;
1477 gid_t gid;
1478 #endif
1479
1480 saved_argv = argv;
1481
1482 #if HAVE_SETPROCTITLE_INIT
1483 setproctitle_init(argc, argv, envp);
1484 #endif
1485
1486 /*
1487 * Get and parse command line options
1488 */
1489 if ((popt = strchr(opts, '@')) != NULL) {
1490 for (i=0;
1491 protos[i].mode != 0 && *popt != '\0';
1492 i++)
1493 *(popt++) = protos[i].arg;
1494 *popt = '\0';
1495 }
1496 while ((ch = getopt(argc, argv, opts)) != -1) {
1497 switch (ch) {
1498 case 'h':
1499 usage();
1500 break;
1501 case 'v':
1502 version++;
1503 break;
1504 case 'd':
1505 if (daemonize)
1506 daemonize = 0;
1507 else if (use_syslog)
1508 use_syslog = 0;
1509 else
1510 debug++;
1511 break;
1512 case 'D':
1513 log_accept(optarg);
1514 break;
1515 case 'p':
1516 pidfile = optarg;
1517 break;
1518 case 'r':
1519 receiveonly = 1;
1520 break;
1521 case 'm':
1522 if (mgmtp) {
1523 fprintf(stderr, "-m can only be used once\n");
1524 usage();
1525 }
1526 mgmtp = strdup(optarg);
1527 break;
1528 case 'u':
1529 if (ctlname) {
1530 fprintf(stderr, "-u can only be used once\n");
1531 usage();
1532 }
1533 ctlname = optarg;
1534 break;
1535 case 'I':
1536 if (interfaces) {
1537 fprintf(stderr, "-I can only be used once\n");
1538 usage();
1539 }
1540 interfaces = strdup(optarg);
1541 break;
1542 case 'C':
1543 if (cidp) {
1544 fprintf(stderr, "-C can only be used once\n");
1545 usage();
1546 }
1547 cidp = strdup(optarg);
1548 break;
1549 case 'L':
1550 if (strlen(optarg)) lldpcli = optarg;
1551 else lldpcli = NULL;
1552 break;
1553 case 'k':
1554 advertise_version = 0;
1555 break;
1556 #ifdef ENABLE_LLDPMED
1557 case 'M':
1558 lldpmed = strtonum(optarg, 1, 4, &errstr);
1559 if (errstr) {
1560 fprintf(stderr, "-M requires an argument between 1 and 4\n");
1561 usage();
1562 }
1563 break;
1564 case 'i':
1565 noinventory = 1;
1566 break;
1567 #else
1568 case 'M':
1569 case 'i':
1570 fprintf(stderr, "LLDP-MED support is not built-in\n");
1571 usage();
1572 break;
1573 #endif
1574 #ifdef USE_SNMP
1575 case 'x':
1576 snmp = 1;
1577 break;
1578 case 'X':
1579 if (agentx) {
1580 fprintf(stderr, "-X can only be used once\n");
1581 usage();
1582 }
1583 snmp = 1;
1584 agentx = optarg;
1585 break;
1586 #else
1587 case 'x':
1588 case 'X':
1589 fprintf(stderr, "SNMP support is not built-in\n");
1590 usage();
1591 #endif
1592 break;
1593 case 'S':
1594 if (descr_override) {
1595 fprintf(stderr, "-S can only be used once\n");
1596 usage();
1597 }
1598 descr_override = strdup(optarg);
1599 break;
1600 case 'P':
1601 if (platform_override) {
1602 fprintf(stderr, "-P can only be used once\n");
1603 usage();
1604 }
1605 platform_override = strdup(optarg);
1606 break;
1607 case 'H':
1608 smart = strtonum(optarg, 0, sizeof(filters)/sizeof(filters[0]),
1609 &errstr);
1610 if (errstr) {
1611 fprintf(stderr, "-H requires an int between 0 and %zu\n",
1612 sizeof(filters)/sizeof(filters[0]));
1613 usage();
1614 }
1615 break;
1616 default:
1617 found = 0;
1618 for (i=0; protos[i].mode != 0; i++) {
1619 if (ch == protos[i].arg) {
1620 found = 1;
1621 protos[i].enabled++;
1622 }
1623 }
1624 if (!found)
1625 usage();
1626 }
1627 }
1628
1629 if (version) {
1630 version_display(stdout, "lldpd", version > 1);
1631 exit(0);
1632 }
1633
1634 if (ctlname == NULL) ctlname = LLDPD_CTL_SOCKET;
1635
1636 /* Set correct smart mode */
1637 for (i=0; (filters[i].a != -1) && (filters[i].a != smart); i++);
1638 if (filters[i].a == -1) {
1639 fprintf(stderr, "Incorrect mode for -H\n");
1640 usage();
1641 }
1642 smart = filters[i].b;
1643
1644 log_init(use_syslog, debug, __progname);
1645 tzset(); /* Get timezone info before chroot */
1646 if (use_syslog && daemonize) {
1647 /* So, we use syslog and we daemonize (or we are started by
1648 * upstart/systemd). No need to continue writing to stdout. */
1649 int fd;
1650 if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
1651 dup2(fd, STDIN_FILENO);
1652 dup2(fd, STDOUT_FILENO);
1653 dup2(fd, STDERR_FILENO);
1654 if (fd > 2) close(fd);
1655 }
1656 }
1657 log_debug("main", "lldpd " PACKAGE_VERSION " starting...");
1658 version_check();
1659
1660 /* Grab uid and gid to use for priv sep */
1661 #ifdef ENABLE_PRIVSEP
1662 if ((user = getpwnam(PRIVSEP_USER)) == NULL)
1663 fatalx("main", "no " PRIVSEP_USER " user for privilege separation, please create it");
1664 uid = user->pw_uid;
1665 if ((group = getgrnam(PRIVSEP_GROUP)) == NULL)
1666 fatalx("main", "no " PRIVSEP_GROUP " group for privilege separation, please create it");
1667 gid = group->gr_gid;
1668 #endif
1669
1670 /* Create and setup socket */
1671 int retry = 1;
1672 log_debug("main", "creating control socket");
1673 while ((ctl = ctl_create(ctlname)) == -1) {
1674 if (retry-- && errno == EADDRINUSE) {
1675 /* Check if a daemon is really listening */
1676 int tfd;
1677 log_info("main", "unable to create control socket because it already exists");
1678 log_info("main", "check if another instance is running");
1679 if ((tfd = ctl_connect(ctlname)) != -1) {
1680 /* Another instance is running */
1681 close(tfd);
1682 log_warnx("main", "another instance is running, please stop it");
1683 fatalx("main", "giving up");
1684 } else if (errno == ECONNREFUSED) {
1685 /* Nobody is listening */
1686 log_info("main", "old control socket is present, clean it");
1687 ctl_cleanup(ctlname);
1688 continue;
1689 }
1690 log_warn("main", "cannot determine if another daemon is already running");
1691 fatalx("main", "giving up");
1692 }
1693 log_warn("main", "unable to create control socket at %s", ctlname);
1694 fatalx("main", "giving up");
1695 }
1696 #ifdef ENABLE_PRIVSEP
1697 if (chown(ctlname, uid, gid) == -1)
1698 log_warn("main", "unable to chown control socket");
1699 if (chmod(ctlname,
1700 S_IRUSR | S_IWUSR | S_IXUSR |
1701 S_IRGRP | S_IWGRP | S_IXGRP) == -1)
1702 log_warn("main", "unable to chmod control socket");
1703 #endif
1704
1705 /* Disable SIGPIPE */
1706 signal(SIGPIPE, SIG_IGN);
1707
1708 /* Disable SIGHUP, until handlers are installed */
1709 signal(SIGHUP, SIG_IGN);
1710
1711 /* Daemonization, unless started by upstart, systemd or launchd or debug */
1712 #ifndef HOST_OS_OSX
1713 if (daemonize &&
1714 !lldpd_started_by_upstart() && !lldpd_started_by_systemd()) {
1715 int pid;
1716 char *spid;
1717 log_info("main", "going into background");
1718 if (daemon(0, 1) != 0)
1719 fatal("main", "failed to detach daemon");
1720 if ((pid = open(pidfile,
1721 O_TRUNC | O_CREAT | O_WRONLY, 0666)) == -1)
1722 fatal("main", "unable to open pid file " LLDPD_PID_FILE
1723 " (or the specified one)");
1724 if (asprintf(&spid, "%d\n", getpid()) == -1)
1725 fatal("main", "unable to create pid file " LLDPD_PID_FILE
1726 " (or the specified one)");
1727 if (write(pid, spid, strlen(spid)) == -1)
1728 fatal("main", "unable to write pid file " LLDPD_PID_FILE
1729 " (or the specified one)");
1730 free(spid);
1731 close(pid);
1732 }
1733 #endif
1734
1735 /* Configuration with lldpcli */
1736 if (lldpcli) {
1737 log_debug("main", "invoking lldpcli for configuration");
1738 if (lldpd_configure(use_syslog, debug, lldpcli, ctlname) == -1)
1739 fatal("main", "unable to spawn lldpcli");
1740 }
1741
1742 /* Try to read system information from /etc/os-release if possible.
1743 Fall back to lsb_release for compatibility. */
1744 log_debug("main", "get OS/LSB release information");
1745 lsb_release = lldpd_get_os_release();
1746 if (!lsb_release) {
1747 lsb_release = lldpd_get_lsb_release();
1748 }
1749
1750 log_debug("main", "initialize privilege separation");
1751 #ifdef ENABLE_PRIVSEP
1752 priv_init(PRIVSEP_CHROOT, ctl, uid, gid);
1753 #else
1754 priv_init(PRIVSEP_CHROOT, ctl, 0, 0);
1755 #endif
1756
1757 /* Initialization of global configuration */
1758 if ((cfg = (struct lldpd *)
1759 calloc(1, sizeof(struct lldpd))) == NULL)
1760 fatal("main", NULL);
1761
1762 lldpd_alloc_default_local_port(cfg);
1763 cfg->g_ctlname = ctlname;
1764 cfg->g_ctl = ctl;
1765 cfg->g_config.c_mgmt_pattern = mgmtp;
1766 cfg->g_config.c_cid_pattern = cidp;
1767 cfg->g_config.c_iface_pattern = interfaces;
1768 cfg->g_config.c_smart = smart;
1769 if (lldpcli)
1770 cfg->g_config.c_paused = 1;
1771 cfg->g_config.c_receiveonly = receiveonly;
1772 cfg->g_config.c_tx_interval = LLDPD_TX_INTERVAL;
1773 cfg->g_config.c_tx_hold = LLDPD_TX_HOLD;
1774 cfg->g_config.c_max_neighbors = LLDPD_MAX_NEIGHBORS;
1775 #ifdef ENABLE_LLDPMED
1776 cfg->g_config.c_enable_fast_start = enable_fast_start;
1777 cfg->g_config.c_tx_fast_init = LLDPD_FAST_INIT;
1778 cfg->g_config.c_tx_fast_interval = LLDPD_FAST_TX_INTERVAL;
1779 #endif
1780 #ifdef USE_SNMP
1781 cfg->g_snmp = snmp;
1782 cfg->g_snmp_agentx = agentx;
1783 #endif /* USE_SNMP */
1784 cfg->g_config.c_bond_slave_src_mac_type = \
1785 LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED;
1786
1787 /* Get ioctl socket */
1788 log_debug("main", "get an ioctl socket");
1789 if ((cfg->g_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1790 fatal("main", "failed to get ioctl socket");
1791
1792 /* Description */
1793 if (!(cfg->g_config.c_advertise_version = advertise_version) &&
1794 lsb_release && lsb_release[strlen(lsb_release) - 1] == '\n')
1795 lsb_release[strlen(lsb_release) - 1] = '\0';
1796 cfg->g_lsb_release = lsb_release;
1797 if (descr_override)
1798 cfg->g_config.c_description = descr_override;
1799
1800 if (platform_override)
1801 cfg->g_config.c_platform = platform_override;
1802
1803 /* Set system capabilities */
1804 log_debug("main", "set system capabilities");
1805 if ((lchassis = (struct lldpd_chassis*)
1806 calloc(1, sizeof(struct lldpd_chassis))) == NULL)
1807 fatal("localchassis", NULL);
1808 cfg->g_config.c_cap_advertise = 1;
1809 lchassis->c_cap_available = LLDP_CAP_BRIDGE | LLDP_CAP_WLAN |
1810 LLDP_CAP_ROUTER | LLDP_CAP_STATION;
1811 cfg->g_config.c_mgmt_advertise = 1;
1812 TAILQ_INIT(&lchassis->c_mgmt);
1813 #ifdef ENABLE_LLDPMED
1814 if (lldpmed > 0) {
1815 if (lldpmed == LLDP_MED_CLASS_III)
1816 lchassis->c_cap_available |= LLDP_CAP_TELEPHONE;
1817 lchassis->c_med_type = lldpmed;
1818 lchassis->c_med_cap_available = LLDP_MED_CAP_CAP |
1819 LLDP_MED_CAP_IV | LLDP_MED_CAP_LOCATION |
1820 LLDP_MED_CAP_POLICY | LLDP_MED_CAP_MDI_PSE | LLDP_MED_CAP_MDI_PD;
1821 cfg->g_config.c_noinventory = noinventory;
1822 } else
1823 cfg->g_config.c_noinventory = 1;
1824 #endif
1825
1826 /* Set TTL */
1827 lchassis->c_ttl = cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold;
1828
1829 log_debug("main", "initialize protocols");
1830 cfg->g_protocols = protos;
1831 for (i=0; protos[i].mode != 0; i++) {
1832
1833 /* With -ll, disable LLDP */
1834 if (protos[i].mode == LLDPD_MODE_LLDP)
1835 protos[i].enabled %= 3;
1836 /* With -ccc force CDPV2, enable CDPV1 */
1837 if (protos[i].mode == LLDPD_MODE_CDPV1 && protos[i].enabled == 3) {
1838 protos[i].enabled = 1;
1839 }
1840 /* With -cc force CDPV1, enable CDPV2 */
1841 if (protos[i].mode == LLDPD_MODE_CDPV2 && protos[i].enabled == 2) {
1842 protos[i].enabled = 1;
1843 }
1844
1845 /* With -cccc disable CDPV1, enable CDPV2 */
1846 if (protos[i].mode == LLDPD_MODE_CDPV1 && protos[i].enabled >= 4) {
1847 protos[i].enabled = 0;
1848 }
1849
1850 /* With -cccc disable CDPV1, enable CDPV2; -ccccc will force CDPv2 */
1851 if (protos[i].mode == LLDPD_MODE_CDPV2 && protos[i].enabled == 4) {
1852 protos[i].enabled = 1;
1853 }
1854
1855 if (protos[i].enabled > 1)
1856 log_info("main", "protocol %s enabled and forced", protos[i].name);
1857 else if (protos[i].enabled)
1858 log_info("main", "protocol %s enabled", protos[i].name);
1859 else
1860 log_info("main", "protocol %s disabled", protos[i].name);
1861 }
1862
1863 TAILQ_INIT(&cfg->g_hardware);
1864 TAILQ_INIT(&cfg->g_chassis);
1865 TAILQ_INSERT_TAIL(&cfg->g_chassis, lchassis, c_entries);
1866 lchassis->c_refcount++; /* We should always keep a reference to local chassis */
1867
1868 /* Main loop */
1869 log_debug("main", "start main loop");
1870 levent_loop(cfg);
1871 lchassis->c_refcount--;
1872 lldpd_exit(cfg);
1873 free(cfg);
1874
1875 return (0);
1876 }