]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/daemon/lldpd.c
lldpd: add an option to keep some specified ports
[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 <limits.h>
25 #include <signal.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <time.h>
29 #include <libgen.h>
30 #include <assert.h>
31 #include <sys/utsname.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <sys/socket.h>
35 #include <sys/select.h>
36 #include <sys/time.h>
37 #include <sys/ioctl.h>
38 #include <arpa/inet.h>
39 #include <netinet/if_ether.h>
40 #include <pwd.h>
41 #include <grp.h>
42
43 #if HAVE_VFORK_H
44 # include <vfork.h>
45 #endif
46 #if HAVE_WORKING_FORK
47 # define vfork fork
48 #endif
49
50 static void usage(void);
51
52 static struct protocol protos[] =
53 {
54 { LLDPD_MODE_LLDP, 1, "LLDP", 'l', lldp_send, lldp_decode, NULL,
55 LLDP_ADDR_NEAREST_BRIDGE,
56 LLDP_ADDR_NEAREST_NONTPMR_BRIDGE,
57 LLDP_ADDR_NEAREST_CUSTOMER_BRIDGE },
58 #ifdef ENABLE_CDP
59 { LLDPD_MODE_CDPV1, 0, "CDPv1", 'c', cdpv1_send, cdp_decode, cdpv1_guess,
60 CDP_MULTICAST_ADDR },
61 { LLDPD_MODE_CDPV2, 0, "CDPv2", 'c', cdpv2_send, cdp_decode, cdpv2_guess,
62 CDP_MULTICAST_ADDR },
63 #endif
64 #ifdef ENABLE_SONMP
65 { LLDPD_MODE_SONMP, 0, "SONMP", 's', sonmp_send, sonmp_decode, NULL,
66 SONMP_MULTICAST_ADDR },
67 #endif
68 #ifdef ENABLE_EDP
69 { LLDPD_MODE_EDP, 0, "EDP", 'e', edp_send, edp_decode, NULL,
70 EDP_MULTICAST_ADDR },
71 #endif
72 #ifdef ENABLE_FDP
73 { LLDPD_MODE_FDP, 0, "FDP", 'f', fdp_send, cdp_decode, NULL,
74 FDP_MULTICAST_ADDR },
75 #endif
76 { 0, 0, "any", ' ', NULL, NULL, NULL,
77 {0,0,0,0,0,0} }
78 };
79
80 static char **saved_argv;
81 #ifdef HAVE___PROGNAME
82 extern const char *__progname;
83 #else
84 # define __progname "lldpd"
85 #endif
86
87 static void
88 usage(void)
89 {
90 fprintf(stderr, "Usage: %s [OPTIONS ...]\n", __progname);
91 fprintf(stderr, "Version: %s\n", PACKAGE_STRING);
92
93 fprintf(stderr, "\n");
94
95 fprintf(stderr, "-d Do not daemonize.\n");
96 fprintf(stderr, "-r Receive-only mode\n");
97 fprintf(stderr, "-i Disable LLDP-MED inventory TLV transmission.\n");
98 fprintf(stderr, "-k Disable advertising of kernel release, version, machine.\n");
99 fprintf(stderr, "-S descr Override the default system description.\n");
100 fprintf(stderr, "-P name Override the default hardware platform.\n");
101 fprintf(stderr, "-m IP Specify the IP management addresses of this system.\n");
102 fprintf(stderr, "-u file Specify the Unix-domain socket used for communication with lldpctl(8).\n");
103 fprintf(stderr, "-H mode Specify the behaviour when detecting multiple neighbors.\n");
104 fprintf(stderr, "-I iface Limit interfaces to use.\n");
105 fprintf(stderr, "-C iface Limit interfaces to use for computing chassis ID.\n");
106 fprintf(stderr, "-L path Override path for lldpcli command.\n");
107 fprintf(stderr, "-O file Override default configuration locations processed by lldpcli(8) at start.\n");
108 #ifdef ENABLE_LLDPMED
109 fprintf(stderr, "-M class Enable emission of LLDP-MED frame. 'class' should be one of:\n");
110 fprintf(stderr, " 1 Generic Endpoint (Class I)\n");
111 fprintf(stderr, " 2 Media Endpoint (Class II)\n");
112 fprintf(stderr, " 3 Communication Device Endpoints (Class III)\n");
113 fprintf(stderr, " 4 Network Connectivity Device\n");
114 #endif
115 #ifdef USE_SNMP
116 fprintf(stderr, "-x Enable SNMP subagent.\n");
117 fprintf(stderr, "-X sock Specify the SNMP subagent socket.\n");
118 #endif
119 fprintf(stderr, "\n");
120
121 #if defined ENABLE_CDP || defined ENABLE_EDP || defined ENABLE_FDP || defined ENABLE_SONMP
122 fprintf(stderr, "Additional protocol support.\n");
123 #ifdef ENABLE_CDP
124 fprintf(stderr, "-c Enable the support of CDP protocol. (Cisco)\n");
125 #endif
126 #ifdef ENABLE_EDP
127 fprintf(stderr, "-e Enable the support of EDP protocol. (Extreme)\n");
128 #endif
129 #ifdef ENABLE_FDP
130 fprintf(stderr, "-f Enable the support of FDP protocol. (Foundry)\n");
131 #endif
132 #ifdef ENABLE_SONMP
133 fprintf(stderr, "-s Enable the support of SONMP protocol. (Nortel)\n");
134 #endif
135
136 fprintf(stderr, "\n");
137 #endif
138
139 fprintf(stderr, "see manual page lldpd(8) for more information\n");
140 exit(1);
141 }
142
143 struct lldpd_hardware *
144 lldpd_get_hardware(struct lldpd *cfg, char *name, int index)
145 {
146 struct lldpd_hardware *hardware;
147 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
148 if (strcmp(hardware->h_ifname, name) == 0) {
149 if (hardware->h_flags == 0) {
150 hardware->h_ifindex = index;
151 break;
152 }
153 if (hardware->h_ifindex == index)
154 break;
155 }
156 }
157 return hardware;
158 }
159
160 /**
161 * Allocate the default local port. This port will be cloned each time we need a
162 * new local port.
163 */
164 static void
165 lldpd_alloc_default_local_port(struct lldpd *cfg)
166 {
167 struct lldpd_port *port;
168
169 if ((port = (struct lldpd_port *)
170 calloc(1, sizeof(struct lldpd_port))) == NULL)
171 fatal("main", NULL);
172
173 #ifdef ENABLE_DOT1
174 TAILQ_INIT(&port->p_vlans);
175 TAILQ_INIT(&port->p_ppvids);
176 TAILQ_INIT(&port->p_pids);
177 #endif
178 #ifdef ENABLE_CUSTOM
179 TAILQ_INIT(&port->p_custom_list);
180 #endif
181 cfg->g_default_local_port = port;
182 }
183
184 /**
185 * Clone a given port. The destination needs to be already allocated.
186 */
187 static int
188 lldpd_clone_port(struct lldpd_port *destination, struct lldpd_port *source)
189 {
190
191 u_int8_t *output = NULL;
192 ssize_t output_len;
193 struct lldpd_port *cloned = NULL;
194 output_len = lldpd_port_serialize(source, (void**)&output);
195 if (output_len == -1 ||
196 lldpd_port_unserialize(output, output_len, &cloned) <= 0) {
197 log_warnx("alloc", "unable to clone default port");
198 free(output);
199 return -1;
200 }
201 memcpy(destination, cloned, sizeof(struct lldpd_port));
202 free(cloned);
203 free(output);
204 #ifdef ENABLE_DOT1
205 marshal_repair_tailq(lldpd_vlan, &destination->p_vlans, v_entries);
206 marshal_repair_tailq(lldpd_ppvid, &destination->p_ppvids, p_entries);
207 marshal_repair_tailq(lldpd_pi, &destination->p_pids, p_entries);
208 #endif
209 #ifdef ENABLE_CUSTOM
210 marshal_repair_tailq(lldpd_custom, &destination->p_custom_list, next);
211 #endif
212 return 0;
213 }
214
215 struct lldpd_hardware *
216 lldpd_alloc_hardware(struct lldpd *cfg, char *name, int index)
217 {
218 struct lldpd_hardware *hardware;
219
220 log_debug("alloc", "allocate a new local port (%s)", name);
221
222 if ((hardware = (struct lldpd_hardware *)
223 calloc(1, sizeof(struct lldpd_hardware))) == NULL)
224 return NULL;
225
226 /* Clone default local port */
227 if (lldpd_clone_port(&hardware->h_lport, cfg->g_default_local_port) == -1) {
228 log_warnx("alloc", "unable to clone default port");
229 free(hardware);
230 return NULL;
231 }
232
233 hardware->h_cfg = cfg;
234 strlcpy(hardware->h_ifname, name, sizeof(hardware->h_ifname));
235 hardware->h_ifindex = index;
236 hardware->h_lport.p_chassis = LOCAL_CHASSIS(cfg);
237 hardware->h_lport.p_chassis->c_refcount++;
238 TAILQ_INIT(&hardware->h_rports);
239
240 #ifdef ENABLE_LLDPMED
241 if (LOCAL_CHASSIS(cfg)->c_med_cap_available) {
242 hardware->h_lport.p_med_cap_enabled = LLDP_MED_CAP_CAP;
243 if (!cfg->g_config.c_noinventory)
244 hardware->h_lport.p_med_cap_enabled |= LLDP_MED_CAP_IV;
245 }
246 #endif
247
248 levent_hardware_init(hardware);
249 return hardware;
250 }
251
252 struct lldpd_mgmt *
253 lldpd_alloc_mgmt(int family, void *addrptr, size_t addrsize, u_int32_t iface)
254 {
255 struct lldpd_mgmt *mgmt;
256
257 log_debug("alloc", "allocate a new management address (family: %d)", family);
258
259 if (family <= LLDPD_AF_UNSPEC || family >= LLDPD_AF_LAST) {
260 errno = EAFNOSUPPORT;
261 return NULL;
262 }
263 if (addrsize > LLDPD_MGMT_MAXADDRSIZE) {
264 errno = EOVERFLOW;
265 return NULL;
266 }
267 mgmt = calloc(1, sizeof(struct lldpd_mgmt));
268 if (mgmt == NULL) {
269 errno = ENOMEM;
270 return NULL;
271 }
272 mgmt->m_family = family;
273 memcpy(&mgmt->m_addr, addrptr, addrsize);
274 mgmt->m_addrsize = addrsize;
275 mgmt->m_iface = iface;
276 return mgmt;
277 }
278
279 void
280 lldpd_hardware_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware)
281 {
282 log_debug("alloc", "cleanup hardware port %s", hardware->h_ifname);
283
284 free(hardware->h_lport_previous);
285 free(hardware->h_lchassis_previous_id);
286 free(hardware->h_lport_previous_id);
287 lldpd_port_cleanup(&hardware->h_lport, 1);
288 if (hardware->h_ops && hardware->h_ops->cleanup)
289 hardware->h_ops->cleanup(cfg, hardware);
290 levent_hardware_release(hardware);
291 free(hardware);
292 }
293
294 static void
295 lldpd_display_neighbors(struct lldpd *cfg)
296 {
297 if (!cfg->g_config.c_set_ifdescr) return;
298 struct lldpd_hardware *hardware;
299 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
300 struct lldpd_port *port;
301 char *description;
302 const char *neighbor = NULL;
303 unsigned neighbors = 0;
304 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
305 if (SMART_HIDDEN(port)) continue;
306 neighbors++;
307 neighbor = port->p_chassis->c_name;
308 }
309 if (neighbors == 0)
310 priv_iface_description(hardware->h_ifname,
311 "");
312 else if (neighbors == 1 && neighbor && *neighbor != '\0') {
313 if (asprintf(&description, "%s",
314 neighbor) != -1) {
315 priv_iface_description(hardware->h_ifname, description);
316 free(description);
317 }
318 } else {
319 if (asprintf(&description, "%d neighbor%s",
320 neighbors, (neighbors > 1)?"s":"") != -1) {
321 priv_iface_description(hardware->h_ifname,
322 description);
323 free(description);
324 }
325 }
326 }
327 }
328
329 static void
330 lldpd_count_neighbors(struct lldpd *cfg)
331 {
332 #if HAVE_SETPROCTITLE
333 struct lldpd_chassis *chassis;
334 const char *neighbor;
335 unsigned neighbors = 0;
336 TAILQ_FOREACH(chassis, &cfg->g_chassis, c_entries) {
337 neighbors++;
338 neighbor = chassis->c_name;
339 }
340 neighbors--;
341 if (neighbors == 0)
342 setproctitle("no neighbor.");
343 else if (neighbors == 1 && neighbor && *neighbor != '\0')
344 setproctitle("connected to %s.", neighbor);
345 else
346 setproctitle("%d neighbor%s.", neighbors,
347 (neighbors > 1)?"s":"");
348 #endif
349 lldpd_display_neighbors(cfg);
350 }
351
352 static void
353 notify_clients_deletion(struct lldpd_hardware *hardware,
354 struct lldpd_port *rport)
355 {
356 TRACE(LLDPD_NEIGHBOR_DELETE(hardware->h_ifname,
357 rport->p_chassis->c_name,
358 rport->p_descr));
359 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_DELETED,
360 rport);
361 #ifdef USE_SNMP
362 agent_notify(hardware, NEIGHBOR_CHANGE_DELETED, rport);
363 #endif
364 }
365
366 static void
367 lldpd_reset_timer(struct lldpd *cfg)
368 {
369 /* Reset timer for ports that have been changed. */
370 struct lldpd_hardware *hardware;
371 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
372 /* We keep a flat copy of the local port to see if there is any
373 * change. To do this, we zero out fields that are not
374 * significant, marshal the port, then restore. */
375 struct lldpd_port *port = &hardware->h_lport;
376 /* Take the current flags into account to detect a change. */
377 port->_p_hardware_flags = hardware->h_flags;
378 u_int8_t *output = NULL;
379 ssize_t output_len;
380 char save[LLDPD_PORT_START_MARKER];
381 memcpy(save, port, sizeof(save));
382 /* coverity[suspicious_sizeof]
383 We intentionally partially memset port */
384 memset(port, 0, sizeof(save));
385 output_len = lldpd_port_serialize(port, (void**)&output);
386 memcpy(port, save, sizeof(save));
387 if (output_len == -1) {
388 log_warnx("localchassis",
389 "unable to serialize local port %s to check for differences",
390 hardware->h_ifname);
391 continue;
392 }
393
394 /* Compare with the previous value */
395 if (hardware->h_lport_previous &&
396 output_len == hardware->h_lport_previous_len &&
397 !memcmp(output, hardware->h_lport_previous, output_len)) {
398 log_debug("localchassis",
399 "no change detected for port %s",
400 hardware->h_ifname);
401 } else {
402 log_debug("localchassis",
403 "change detected for port %s, resetting its timer",
404 hardware->h_ifname);
405 levent_schedule_pdu(hardware);
406 }
407
408 /* Update the value */
409 free(hardware->h_lport_previous);
410 hardware->h_lport_previous = output;
411 hardware->h_lport_previous_len = output_len;
412 }
413 }
414
415 static void
416 lldpd_all_chassis_cleanup(struct lldpd *cfg)
417 {
418 struct lldpd_chassis *chassis, *chassis_next;
419 log_debug("localchassis", "cleanup all chassis");
420
421 for (chassis = TAILQ_FIRST(&cfg->g_chassis); chassis;
422 chassis = chassis_next) {
423 chassis_next = TAILQ_NEXT(chassis, c_entries);
424 if (chassis->c_refcount == 0) {
425 TAILQ_REMOVE(&cfg->g_chassis, chassis, c_entries);
426 lldpd_chassis_cleanup(chassis, 1);
427 }
428 }
429 }
430
431 void
432 lldpd_cleanup(struct lldpd *cfg)
433 {
434 struct lldpd_hardware *hardware, *hardware_next;
435
436 log_debug("localchassis", "cleanup all ports");
437
438 for (hardware = TAILQ_FIRST(&cfg->g_hardware); hardware != NULL;
439 hardware = hardware_next) {
440 hardware_next = TAILQ_NEXT(hardware, h_entries);
441 if (!hardware->h_flags) {
442 int m = cfg->g_config.c_perm_ifaces?
443 pattern_match(hardware->h_ifname, cfg->g_config.c_perm_ifaces, 0):
444 0;
445 switch (m) {
446 case 0:
447 log_debug("localchassis", "delete non-permanent interface %s",
448 hardware->h_ifname);
449 TRACE(LLDPD_INTERFACES_DELETE(hardware->h_ifname));
450 TAILQ_REMOVE(&cfg->g_hardware, hardware, h_entries);
451 lldpd_remote_cleanup(hardware, notify_clients_deletion, 1);
452 lldpd_hardware_cleanup(cfg, hardware);
453 break;
454 case 1:
455 case 2:
456 log_debug("localchassis", "do not delete %s, permanent",
457 hardware->h_ifname);
458 break;
459 }
460 } else {
461 lldpd_remote_cleanup(hardware, notify_clients_deletion,
462 !(hardware->h_flags & IFF_RUNNING));
463 }
464 }
465
466 levent_schedule_cleanup(cfg);
467 lldpd_all_chassis_cleanup(cfg);
468 lldpd_count_neighbors(cfg);
469 }
470
471 /* Update chassis `ochassis' with values from `chassis'. The later one is not
472 expected to be part of a list! It will also be wiped from memory. */
473 static void
474 lldpd_move_chassis(struct lldpd_chassis *ochassis,
475 struct lldpd_chassis *chassis) {
476 struct lldpd_mgmt *mgmt, *mgmt_next;
477
478 /* We want to keep refcount, index and list stuff from the current
479 * chassis */
480 TAILQ_ENTRY(lldpd_chassis) entries;
481 int refcount = ochassis->c_refcount;
482 int index = ochassis->c_index;
483 memcpy(&entries, &ochassis->c_entries,
484 sizeof(entries));
485 lldpd_chassis_cleanup(ochassis, 0);
486
487 /* Make the copy. */
488 /* WARNING: this is a kludgy hack, we need in-place copy and cannot use
489 * marshaling. */
490 memcpy(ochassis, chassis, sizeof(struct lldpd_chassis));
491 TAILQ_INIT(&ochassis->c_mgmt);
492
493 /* Copy of management addresses */
494 for (mgmt = TAILQ_FIRST(&chassis->c_mgmt);
495 mgmt != NULL;
496 mgmt = mgmt_next) {
497 mgmt_next = TAILQ_NEXT(mgmt, m_entries);
498 TAILQ_REMOVE(&chassis->c_mgmt, mgmt, m_entries);
499 TAILQ_INSERT_TAIL(&ochassis->c_mgmt, mgmt, m_entries);
500 }
501
502 /* Restore saved values */
503 ochassis->c_refcount = refcount;
504 ochassis->c_index = index;
505 memcpy(&ochassis->c_entries, &entries, sizeof(entries));
506
507 /* Get rid of the new chassis */
508 free(chassis);
509 }
510
511 static int
512 lldpd_guess_type(struct lldpd *cfg, char *frame, int s)
513 {
514 int i;
515 if (s < ETHER_ADDR_LEN)
516 return -1;
517 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
518 if (!cfg->g_protocols[i].enabled)
519 continue;
520 if (cfg->g_protocols[i].guess == NULL) {
521 if (memcmp(frame, cfg->g_protocols[i].mac1, ETHER_ADDR_LEN) == 0 ||
522 memcmp(frame, cfg->g_protocols[i].mac2, ETHER_ADDR_LEN) == 0 ||
523 memcmp(frame, cfg->g_protocols[i].mac3, ETHER_ADDR_LEN) == 0) {
524 log_debug("decode", "guessed protocol is %s (from MAC address)",
525 cfg->g_protocols[i].name);
526 return cfg->g_protocols[i].mode;
527 }
528 } else {
529 if (cfg->g_protocols[i].guess(frame, s)) {
530 log_debug("decode", "guessed protocol is %s (from detector function)",
531 cfg->g_protocols[i].name);
532 return cfg->g_protocols[i].mode;
533 }
534 }
535 }
536 return -1;
537 }
538
539 static void
540 lldpd_decode(struct lldpd *cfg, char *frame, int s,
541 struct lldpd_hardware *hardware)
542 {
543 int i;
544 struct lldpd_chassis *chassis, *ochassis = NULL;
545 struct lldpd_port *port, *oport = NULL, *aport;
546 int guess = LLDPD_MODE_LLDP;
547
548 log_debug("decode", "decode a received frame on %s",
549 hardware->h_ifname);
550
551 if (s < sizeof(struct ether_header) + 4) {
552 /* Too short, just discard it */
553 hardware->h_rx_discarded_cnt++;
554 return;
555 }
556
557 /* Decapsulate VLAN frames */
558 struct ether_header eheader;
559 memcpy(&eheader, frame, sizeof(struct ether_header));
560 if (eheader.ether_type == htons(ETHERTYPE_VLAN)) {
561 /* VLAN decapsulation means to shift 4 bytes left the frame from
562 * offset 2*ETHER_ADDR_LEN */
563 memmove(frame + 2*ETHER_ADDR_LEN, frame + 2*ETHER_ADDR_LEN + 4, s - 2*ETHER_ADDR_LEN);
564 s -= 4;
565 }
566
567 TAILQ_FOREACH(oport, &hardware->h_rports, p_entries) {
568 if ((oport->p_lastframe != NULL) &&
569 (oport->p_lastframe->size == s) &&
570 (memcmp(oport->p_lastframe->frame, frame, s) == 0)) {
571 /* Already received the same frame */
572 log_debug("decode", "duplicate frame, no need to decode");
573 oport->p_lastupdate = time(NULL);
574 return;
575 }
576 }
577
578 guess = lldpd_guess_type(cfg, frame, s);
579 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
580 if (!cfg->g_protocols[i].enabled)
581 continue;
582 if (cfg->g_protocols[i].mode == guess) {
583 log_debug("decode", "using decode function for %s protocol",
584 cfg->g_protocols[i].name);
585 if (cfg->g_protocols[i].decode(cfg, frame,
586 s, hardware, &chassis, &port) == -1) {
587 log_debug("decode", "function for %s protocol did not decode this frame",
588 cfg->g_protocols[i].name);
589 hardware->h_rx_discarded_cnt++;
590 return;
591 }
592 chassis->c_protocol = port->p_protocol =
593 cfg->g_protocols[i].mode;
594 break;
595 }
596 }
597 if (cfg->g_protocols[i].mode == 0) {
598 log_debug("decode", "unable to guess frame type on %s",
599 hardware->h_ifname);
600 return;
601 }
602 TRACE(LLDPD_FRAME_DECODED(
603 hardware->h_ifname,
604 cfg->g_protocols[i].name,
605 chassis->c_name,
606 port->p_descr));
607
608 /* Do we already have the same MSAP somewhere? */
609 int count = 0;
610 log_debug("decode", "search for the same MSAP");
611 TAILQ_FOREACH(oport, &hardware->h_rports, p_entries) {
612 if (port->p_protocol == oport->p_protocol) {
613 count++;
614 if ((port->p_id_subtype == oport->p_id_subtype) &&
615 (port->p_id_len == oport->p_id_len) &&
616 (memcmp(port->p_id, oport->p_id, port->p_id_len) == 0) &&
617 (chassis->c_id_subtype == oport->p_chassis->c_id_subtype) &&
618 (chassis->c_id_len == oport->p_chassis->c_id_len) &&
619 (memcmp(chassis->c_id, oport->p_chassis->c_id,
620 chassis->c_id_len) == 0)) {
621 ochassis = oport->p_chassis;
622 log_debug("decode", "MSAP is already known");
623 break;
624 }
625 }
626 }
627 /* Do we have room for a new MSAP? */
628 if (!oport && cfg->g_config.c_max_neighbors) {
629 if (count == (cfg->g_config.c_max_neighbors - 1)) {
630 log_debug("decode",
631 "max neighbors %d reached for port %s, "
632 "dropping any new ones silently",
633 cfg->g_config.c_max_neighbors,
634 hardware->h_ifname);
635 } else if (count > cfg->g_config.c_max_neighbors - 1) {
636 log_debug("decode",
637 "too many neighbors for port %s, drop this new one",
638 hardware->h_ifname);
639 lldpd_port_cleanup(port, 1);
640 lldpd_chassis_cleanup(chassis, 1);
641 free(port);
642 return;
643 }
644 }
645 /* No, but do we already know the system? */
646 if (!oport) {
647 log_debug("decode", "MSAP is unknown, search for the chassis");
648 TAILQ_FOREACH(ochassis, &cfg->g_chassis, c_entries) {
649 if ((chassis->c_protocol == ochassis->c_protocol) &&
650 (chassis->c_id_subtype == ochassis->c_id_subtype) &&
651 (chassis->c_id_len == ochassis->c_id_len) &&
652 (memcmp(chassis->c_id, ochassis->c_id,
653 chassis->c_id_len) == 0))
654 break;
655 }
656 }
657
658 if (oport) {
659 /* The port is known, remove it before adding it back */
660 TAILQ_REMOVE(&hardware->h_rports, oport, p_entries);
661 lldpd_port_cleanup(oport, 1);
662 free(oport);
663 }
664 if (ochassis) {
665 lldpd_move_chassis(ochassis, chassis);
666 chassis = ochassis;
667 } else {
668 /* Chassis not known, add it */
669 log_debug("decode", "unknown chassis, add it to the list");
670 chassis->c_index = ++cfg->g_lastrid;
671 chassis->c_refcount = 0;
672 TAILQ_INSERT_TAIL(&cfg->g_chassis, chassis, c_entries);
673 i = 0; TAILQ_FOREACH(ochassis, &cfg->g_chassis, c_entries) i++;
674 log_debug("decode", "%d different systems are known", i);
675 }
676 /* Add port */
677 port->p_lastchange = port->p_lastupdate = time(NULL);
678 if ((port->p_lastframe = (struct lldpd_frame *)malloc(s +
679 sizeof(struct lldpd_frame))) != NULL) {
680 port->p_lastframe->size = s;
681 memcpy(port->p_lastframe->frame, frame, s);
682 }
683 TAILQ_INSERT_TAIL(&hardware->h_rports, port, p_entries);
684 port->p_chassis = chassis;
685 port->p_chassis->c_refcount++;
686 /* Several cases are possible :
687 1. chassis is new, its refcount was 0. It is now attached
688 to this port, its refcount is 1.
689 2. chassis already exists and was attached to another
690 port, we increase its refcount accordingly.
691 3. chassis already exists and was attached to the same
692 port, its refcount was decreased with
693 lldpd_port_cleanup() and is now increased again.
694
695 In all cases, if the port already existed, it has been
696 freed with lldpd_port_cleanup() and therefore, the refcount
697 of the chassis that was attached to it is decreased.
698 */
699 /* coverity[use_after_free]
700 TAILQ_REMOVE does the right thing */
701 i = 0; TAILQ_FOREACH(aport, &hardware->h_rports, p_entries)
702 i++;
703 log_debug("decode", "%d neighbors for %s", i,
704 hardware->h_ifname);
705
706 if (!oport) hardware->h_insert_cnt++;
707
708 /* Notify */
709 log_debug("decode", "send notifications for changes on %s",
710 hardware->h_ifname);
711 if (oport) {
712 TRACE(LLDPD_NEIGHBOR_UPDATE(hardware->h_ifname,
713 chassis->c_name,
714 port->p_descr,
715 i));
716 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_UPDATED, port);
717 #ifdef USE_SNMP
718 agent_notify(hardware, NEIGHBOR_CHANGE_UPDATED, port);
719 #endif
720 } else {
721 TRACE(LLDPD_NEIGHBOR_NEW(hardware->h_ifname,
722 chassis->c_name,
723 port->p_descr,
724 i));
725 levent_ctl_notify(hardware->h_ifname, NEIGHBOR_CHANGE_ADDED, port);
726 #ifdef USE_SNMP
727 agent_notify(hardware, NEIGHBOR_CHANGE_ADDED, port);
728 #endif
729 }
730
731 #ifdef ENABLE_LLDPMED
732 if (!oport && port->p_chassis->c_med_type) {
733 /* New neighbor, fast start */
734 if (hardware->h_cfg->g_config.c_enable_fast_start &&
735 !hardware->h_tx_fast) {
736 log_debug("decode", "%s: entering fast start due to "
737 "new neighbor", hardware->h_ifname);
738 hardware->h_tx_fast = hardware->h_cfg->g_config.c_tx_fast_init;
739 }
740
741 levent_schedule_pdu(hardware);
742 }
743 #endif
744
745 return;
746 }
747
748 /* Get the output of lsb_release -s -d. This is a slow function. It should be
749 called once. It return NULL if any problem happens. Otherwise, this is a
750 statically allocated buffer. The result includes the trailing \n */
751 static char *
752 lldpd_get_lsb_release() {
753 static char release[1024];
754 char *const command[] = { "lsb_release", "-s", "-d", NULL };
755 int pid, status, devnull, count;
756 int pipefd[2];
757
758 log_debug("localchassis", "grab LSB release");
759
760 if (pipe(pipefd)) {
761 log_warn("localchassis", "unable to get a pair of pipes");
762 return NULL;
763 }
764
765 pid = vfork();
766 switch (pid) {
767 case -1:
768 log_warn("localchassis", "unable to fork");
769 return NULL;
770 case 0:
771 /* Child, exec lsb_release */
772 close(pipefd[0]);
773 if ((devnull = open("/dev/null", O_RDWR, 0)) != -1) {
774 dup2(devnull, STDIN_FILENO);
775 dup2(devnull, STDERR_FILENO);
776 dup2(pipefd[1], STDOUT_FILENO);
777 if (devnull > 2) close(devnull);
778 if (pipefd[1] > 2) close(pipefd[1]);
779 execvp("lsb_release", command);
780 }
781 _exit(127);
782 break;
783 default:
784 /* Father, read the output from the children */
785 close(pipefd[1]);
786 count = 0;
787 do {
788 status = read(pipefd[0], release+count, sizeof(release)-count);
789 if ((status == -1) && (errno == EINTR)) continue;
790 if (status > 0)
791 count += status;
792 } while (count < sizeof(release) && (status > 0));
793 if (status < 0) {
794 log_info("localchassis", "unable to read from lsb_release");
795 close(pipefd[0]);
796 waitpid(pid, &status, 0);
797 return NULL;
798 }
799 close(pipefd[0]);
800 if (count >= sizeof(release)) {
801 log_info("localchassis", "output of lsb_release is too large");
802 waitpid(pid, &status, 0);
803 return NULL;
804 }
805 status = -1;
806 if (waitpid(pid, &status, 0) != pid)
807 return NULL;
808 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
809 log_info("localchassis", "lsb_release information not available");
810 return NULL;
811 }
812 if (!count) {
813 log_info("localchassis", "lsb_release returned an empty string");
814 return NULL;
815 }
816 release[count] = '\0';
817 return release;
818 }
819 /* Should not be here */
820 return NULL;
821 }
822
823 /* Same like lldpd_get_lsb_release but reads /etc/os-release for PRETTY_NAME=. */
824 static char *
825 lldpd_get_os_release() {
826 static char release[1024];
827 char line[1024];
828 char *key, *val;
829 char *ptr1 = release;
830
831 log_debug("localchassis", "grab OS release");
832 FILE *fp = fopen("/etc/os-release", "r");
833 if (!fp) {
834 log_debug("localchassis", "could not open /etc/os-release");
835 fp = fopen("/usr/lib/os-release", "r");
836 }
837 if (!fp) {
838 log_info("localchassis",
839 "could not open either /etc/os-release or /usr/lib/os-release");
840 return NULL;
841 }
842
843 while ((fgets(line, sizeof(line), fp) != NULL)) {
844 key = strtok(line, "=");
845 val = strtok(NULL, "=");
846
847 if (strncmp(key, "PRETTY_NAME", sizeof(line)) == 0) {
848 strlcpy(release, val, sizeof(line));
849 break;
850 }
851 }
852 fclose(fp);
853
854 /* Remove trailing newline and all " in the string. */
855 ptr1 = release + strlen(release) - 1;
856 while (ptr1 != release &&
857 ((*ptr1 == '"') || (*ptr1 == '\n'))) {
858 *ptr1 = '\0';
859 ptr1--;
860 }
861 if (release[0] == '"')
862 return release+1;
863 return release;
864 }
865
866 static void
867 lldpd_hide_ports(struct lldpd *cfg, struct lldpd_hardware *hardware, int mask) {
868 struct lldpd_port *port;
869 int protocols[LLDPD_MODE_MAX+1];
870 char buffer[256];
871 int i, j, k, found;
872 unsigned int min;
873
874 log_debug("smartfilter", "apply smart filter for port %s",
875 hardware->h_ifname);
876
877 /* Compute the number of occurrences of each protocol */
878 for (i = 0; i <= LLDPD_MODE_MAX; i++) protocols[i] = 0;
879 TAILQ_FOREACH(port, &hardware->h_rports, p_entries)
880 protocols[port->p_protocol]++;
881
882 /* Turn the protocols[] array into an array of
883 enabled/disabled protocols. 1 means enabled, 0
884 means disabled. */
885 min = (unsigned int)-1;
886 for (i = 0; i <= LLDPD_MODE_MAX; i++)
887 if (protocols[i] && (protocols[i] < min))
888 min = protocols[i];
889 found = 0;
890 for (i = 0; i <= LLDPD_MODE_MAX; i++)
891 if ((protocols[i] == min) && !found) {
892 /* If we need a tie breaker, we take
893 the first protocol only */
894 if (cfg->g_config.c_smart & mask &
895 (SMART_OUTGOING_ONE_PROTO | SMART_INCOMING_ONE_PROTO))
896 found = 1;
897 protocols[i] = 1;
898 } else protocols[i] = 0;
899
900 /* We set the p_hidden flag to 1 if the protocol is disabled */
901 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
902 if (mask == SMART_OUTGOING)
903 port->p_hidden_out = protocols[port->p_protocol]?0:1;
904 else
905 port->p_hidden_in = protocols[port->p_protocol]?0:1;
906 }
907
908 /* If we want only one neighbor, we take the first one */
909 if (cfg->g_config.c_smart & mask &
910 (SMART_OUTGOING_ONE_NEIGH | SMART_INCOMING_ONE_NEIGH)) {
911 found = 0;
912 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
913 if (mask == SMART_OUTGOING) {
914 if (found) port->p_hidden_out = 1;
915 if (!port->p_hidden_out)
916 found = 1;
917 }
918 if (mask == SMART_INCOMING) {
919 if (found) port->p_hidden_in = 1;
920 if (!port->p_hidden_in)
921 found = 1;
922 }
923 }
924 }
925
926 /* Print a debug message summarizing the operation */
927 for (i = 0; i <= LLDPD_MODE_MAX; i++) protocols[i] = 0;
928 k = j = 0;
929 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
930 if (!(((mask == SMART_OUTGOING) && port->p_hidden_out) ||
931 ((mask == SMART_INCOMING) && port->p_hidden_in))) {
932 k++;
933 protocols[port->p_protocol] = 1;
934 }
935 j++;
936 }
937 buffer[0] = '\0';
938 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
939 if (cfg->g_protocols[i].enabled && protocols[cfg->g_protocols[i].mode]) {
940 if (strlen(buffer) +
941 strlen(cfg->g_protocols[i].name) + 3 > sizeof(buffer)) {
942 /* Unlikely, our buffer is too small */
943 memcpy(buffer + sizeof(buffer) - 4, "...", 4);
944 break;
945 }
946 if (buffer[0])
947 strncat(buffer, ", ", 2);
948 strncat(buffer, cfg->g_protocols[i].name, strlen(cfg->g_protocols[i].name));
949 }
950 }
951 log_debug("smartfilter", "%s: %s: %d visible neighbors (out of %d)",
952 hardware->h_ifname,
953 (mask == SMART_OUTGOING)?"out filter":"in filter",
954 k, j);
955 log_debug("smartfilter", "%s: protocols: %s",
956 hardware->h_ifname, buffer[0]?buffer:"(none)");
957 }
958
959 /* Hide unwanted ports depending on smart mode set by the user */
960 static void
961 lldpd_hide_all(struct lldpd *cfg)
962 {
963 struct lldpd_hardware *hardware;
964
965 if (!cfg->g_config.c_smart)
966 return;
967 log_debug("smartfilter", "apply smart filter results on all ports");
968 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
969 if (cfg->g_config.c_smart & SMART_INCOMING_FILTER)
970 lldpd_hide_ports(cfg, hardware, SMART_INCOMING);
971 if (cfg->g_config.c_smart & SMART_OUTGOING_FILTER)
972 lldpd_hide_ports(cfg, hardware, SMART_OUTGOING);
973 }
974 }
975
976 /* If PD device and PSE allocated power, echo back this change. If we have
977 * several LLDP neighbors, we use the latest updated. */
978 static void
979 lldpd_dot3_power_pd_pse(struct lldpd_hardware *hardware)
980 {
981 #ifdef ENABLE_DOT3
982 struct lldpd_port *port, *selected_port = NULL;
983 /* Are we a PD device? */
984 if (hardware->h_lport.p_power.devicetype != LLDP_DOT3_POWER_PD)
985 return;
986 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
987 if (port->p_hidden_in)
988 continue;
989 if (port->p_protocol != LLDPD_MODE_LLDP)
990 continue;
991 if (port->p_power.devicetype != LLDP_DOT3_POWER_PSE)
992 continue;
993 if (!selected_port || port->p_lastupdate > selected_port->p_lastupdate)
994 selected_port = port;
995 }
996 if (selected_port && selected_port->p_power.allocated != hardware->h_lport.p_power.allocated) {
997 log_info("receive", "for %s, PSE told us allocated is now %d instead of %d",
998 hardware->h_ifname,
999 selected_port->p_power.allocated,
1000 hardware->h_lport.p_power.allocated);
1001 hardware->h_lport.p_power.allocated = selected_port->p_power.allocated;
1002 levent_schedule_pdu(hardware);
1003 }
1004 #endif
1005 }
1006
1007 void
1008 lldpd_recv(struct lldpd *cfg, struct lldpd_hardware *hardware, int fd)
1009 {
1010 char *buffer = NULL;
1011 int n;
1012 log_debug("receive", "receive a frame on %s",
1013 hardware->h_ifname);
1014 if ((buffer = (char *)malloc(hardware->h_mtu)) == NULL) {
1015 log_warn("receive", "failed to alloc reception buffer");
1016 return;
1017 }
1018 if ((n = hardware->h_ops->recv(cfg, hardware,
1019 fd, buffer,
1020 hardware->h_mtu)) == -1) {
1021 log_debug("receive", "discard frame received on %s",
1022 hardware->h_ifname);
1023 free(buffer);
1024 return;
1025 }
1026 if (hardware->h_lport.p_disable_rx) {
1027 log_debug("receive", "RX disabled, ignore the frame on %s",
1028 hardware->h_ifname);
1029 free(buffer);
1030 return;
1031 }
1032 if (cfg->g_config.c_paused) {
1033 log_debug("receive", "paused, ignore the frame on %s",
1034 hardware->h_ifname);
1035 free(buffer);
1036 return;
1037 }
1038 hardware->h_rx_cnt++;
1039 log_debug("receive", "decode received frame on %s",
1040 hardware->h_ifname);
1041 TRACE(LLDPD_FRAME_RECEIVED(hardware->h_ifname, buffer, (size_t)n));
1042 lldpd_decode(cfg, buffer, n, hardware);
1043 lldpd_hide_all(cfg); /* Immediatly hide */
1044 lldpd_dot3_power_pd_pse(hardware);
1045 lldpd_count_neighbors(cfg);
1046 free(buffer);
1047 }
1048
1049 static void
1050 lldpd_send_shutdown(struct lldpd_hardware *hardware)
1051 {
1052 struct lldpd *cfg = hardware->h_cfg;
1053 if (cfg->g_config.c_receiveonly || cfg->g_config.c_paused) return;
1054 if (hardware->h_lport.p_disable_tx) return;
1055 if ((hardware->h_flags & IFF_RUNNING) == 0)
1056 return;
1057
1058 /* It's safe to call `lldp_send_shutdown()` because shutdown LLDPU will
1059 * only be emitted if LLDP was sent on that port. */
1060 if (lldp_send_shutdown(hardware->h_cfg, hardware) != 0)
1061 log_warnx("send", "unable to send shutdown LLDPDU on %s",
1062 hardware->h_ifname);
1063 }
1064
1065 void
1066 lldpd_send(struct lldpd_hardware *hardware)
1067 {
1068 struct lldpd *cfg = hardware->h_cfg;
1069 struct lldpd_port *port;
1070 int i, sent;
1071
1072 if (cfg->g_config.c_receiveonly || cfg->g_config.c_paused) return;
1073 if (hardware->h_lport.p_disable_tx) return;
1074 if ((hardware->h_flags & IFF_RUNNING) == 0)
1075 return;
1076
1077 log_debug("send", "send PDU on %s", hardware->h_ifname);
1078 sent = 0;
1079 for (i=0; cfg->g_protocols[i].mode != 0; i++) {
1080 if (!cfg->g_protocols[i].enabled)
1081 continue;
1082 /* We send only if we have at least one remote system
1083 * speaking this protocol or if the protocol is forced */
1084 if (cfg->g_protocols[i].enabled > 1) {
1085 cfg->g_protocols[i].send(cfg, hardware);
1086 sent++;
1087 continue;
1088 }
1089 TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
1090 /* If this remote port is disabled, we don't
1091 * consider it */
1092 if (port->p_hidden_out)
1093 continue;
1094 if (port->p_protocol ==
1095 cfg->g_protocols[i].mode) {
1096 TRACE(LLDPD_FRAME_SEND(hardware->h_ifname,
1097 cfg->g_protocols[i].name));
1098 log_debug("send", "send PDU on %s with protocol %s",
1099 hardware->h_ifname,
1100 cfg->g_protocols[i].name);
1101 cfg->g_protocols[i].send(cfg,
1102 hardware);
1103 hardware->h_lport.p_protocol = cfg->g_protocols[i].mode;
1104 sent++;
1105 break;
1106 }
1107 }
1108 }
1109
1110 if (!sent) {
1111 /* Nothing was sent for this port, let's speak the first
1112 * available protocol. */
1113 for (i = 0; cfg->g_protocols[i].mode != 0; i++) {
1114 if (!cfg->g_protocols[i].enabled) continue;
1115 TRACE(LLDPD_FRAME_SEND(hardware->h_ifname,
1116 cfg->g_protocols[i].name));
1117 log_debug("send", "fallback to protocol %s for %s",
1118 cfg->g_protocols[i].name, hardware->h_ifname);
1119 cfg->g_protocols[i].send(cfg,
1120 hardware);
1121 break;
1122 }
1123 if (cfg->g_protocols[i].mode == 0)
1124 log_warnx("send", "no protocol enabled, dunno what to send");
1125 }
1126 }
1127
1128 #ifdef ENABLE_LLDPMED
1129 static void
1130 lldpd_med(struct lldpd_chassis *chassis)
1131 {
1132 static short int once = 0;
1133 if (!once) {
1134 chassis->c_med_hw = dmi_hw();
1135 chassis->c_med_fw = dmi_fw();
1136 chassis->c_med_sn = dmi_sn();
1137 chassis->c_med_manuf = dmi_manuf();
1138 chassis->c_med_model = dmi_model();
1139 chassis->c_med_asset = dmi_asset();
1140 once = 1;
1141 }
1142 }
1143 #endif
1144
1145 static int
1146 lldpd_routing_enabled(struct lldpd *cfg)
1147 {
1148 int routing;
1149
1150 if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_ROUTER) == 0)
1151 return 0;
1152
1153 if ((routing = interfaces_routing_enabled(cfg)) == -1) {
1154 log_debug("localchassis", "unable to check if routing is enabled");
1155 return 0;
1156 }
1157 return routing;
1158 }
1159
1160 void
1161 lldpd_update_localchassis(struct lldpd *cfg)
1162 {
1163 struct utsname un;
1164 char *hp;
1165
1166 log_debug("localchassis", "update information for local chassis");
1167 assert(LOCAL_CHASSIS(cfg) != NULL);
1168
1169 /* Set system name and description */
1170 if (uname(&un) < 0)
1171 fatal("localchassis", "failed to get system information");
1172 if (cfg->g_config.c_hostname) {
1173 log_debug("localchassis", "use overridden system name `%s`", cfg->g_config.c_hostname);
1174 hp = cfg->g_config.c_hostname;
1175 } else {
1176 if ((hp = priv_gethostname()) == NULL)
1177 fatal("localchassis", "failed to get system name");
1178 }
1179 free(LOCAL_CHASSIS(cfg)->c_name);
1180 free(LOCAL_CHASSIS(cfg)->c_descr);
1181 if ((LOCAL_CHASSIS(cfg)->c_name = strdup(hp)) == NULL)
1182 fatal("localchassis", NULL);
1183 if (cfg->g_config.c_description) {
1184 log_debug("localchassis", "use overridden description `%s`", cfg->g_config.c_description);
1185 if (asprintf(&LOCAL_CHASSIS(cfg)->c_descr, "%s",
1186 cfg->g_config.c_description) == -1)
1187 fatal("localchassis", "failed to set full system description");
1188 } else {
1189 if (cfg->g_config.c_advertise_version) {
1190 log_debug("localchassis", "advertise system version");
1191 if (asprintf(&LOCAL_CHASSIS(cfg)->c_descr, "%s %s %s %s %s",
1192 cfg->g_lsb_release?cfg->g_lsb_release:"",
1193 un.sysname, un.release, un.version, un.machine)
1194 == -1)
1195 fatal("localchassis", "failed to set full system description");
1196 } else {
1197 log_debug("localchassis", "do not advertise system version");
1198 if (asprintf(&LOCAL_CHASSIS(cfg)->c_descr, "%s",
1199 cfg->g_lsb_release?cfg->g_lsb_release:un.sysname) == -1)
1200 fatal("localchassis", "failed to set minimal system description");
1201 }
1202 }
1203 if (cfg->g_config.c_platform == NULL)
1204 cfg->g_config.c_platform = strdup(un.sysname);
1205
1206 /* Check routing */
1207 if (lldpd_routing_enabled(cfg)) {
1208 log_debug("localchassis", "routing is enabled, enable router capability");
1209 LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_ROUTER;
1210 } else
1211 LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_ROUTER;
1212
1213 #ifdef ENABLE_LLDPMED
1214 if (LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_TELEPHONE)
1215 LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_TELEPHONE;
1216 lldpd_med(LOCAL_CHASSIS(cfg));
1217 free(LOCAL_CHASSIS(cfg)->c_med_sw);
1218 if (cfg->g_config.c_advertise_version)
1219 LOCAL_CHASSIS(cfg)->c_med_sw = strdup(un.release);
1220 else
1221 LOCAL_CHASSIS(cfg)->c_med_sw = strdup("Unknown");
1222 #endif
1223 if ((LOCAL_CHASSIS(cfg)->c_cap_available & LLDP_CAP_STATION) &&
1224 (LOCAL_CHASSIS(cfg)->c_cap_enabled == 0))
1225 LOCAL_CHASSIS(cfg)->c_cap_enabled = LLDP_CAP_STATION;
1226 else if (LOCAL_CHASSIS(cfg)->c_cap_enabled != LLDP_CAP_STATION)
1227 LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_STATION;
1228
1229 /* Set chassis ID if needed. This is only done if chassis ID
1230 has not been set previously (with the MAC address of an
1231 interface for example)
1232 */
1233 if (cfg->g_config.c_cid_string != NULL) {
1234 log_debug("localchassis", "use specified chassis ID string");
1235 free(LOCAL_CHASSIS(cfg)->c_id);
1236 if (!(LOCAL_CHASSIS(cfg)->c_id = strdup(cfg->g_config.c_cid_string)))
1237 fatal("localchassis", NULL);
1238 LOCAL_CHASSIS(cfg)->c_id_len = strlen(cfg->g_config.c_cid_string);
1239 LOCAL_CHASSIS(cfg)->c_id_subtype = LLDP_CHASSISID_SUBTYPE_LOCAL;
1240 }
1241 if (LOCAL_CHASSIS(cfg)->c_id == NULL) {
1242 log_debug("localchassis", "no chassis ID is currently set, use chassis name");
1243 if (!(LOCAL_CHASSIS(cfg)->c_id = strdup(LOCAL_CHASSIS(cfg)->c_name)))
1244 fatal("localchassis", NULL);
1245 LOCAL_CHASSIS(cfg)->c_id_len = strlen(LOCAL_CHASSIS(cfg)->c_name);
1246 LOCAL_CHASSIS(cfg)->c_id_subtype = LLDP_CHASSISID_SUBTYPE_LOCAL;
1247 }
1248 }
1249
1250 void
1251 lldpd_update_localports(struct lldpd *cfg)
1252 {
1253 struct lldpd_hardware *hardware;
1254
1255 log_debug("localchassis", "update information for local ports");
1256
1257 /* h_flags is set to 0 for each port. If the port is updated, h_flags
1258 * will be set to a non-zero value. This will allow us to clean up any
1259 * non up-to-date port */
1260 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
1261 hardware->h_flags = 0;
1262
1263 TRACE(LLDPD_INTERFACES_UPDATE());
1264 interfaces_update(cfg);
1265 lldpd_cleanup(cfg);
1266 lldpd_reset_timer(cfg);
1267 }
1268
1269 void
1270 lldpd_loop(struct lldpd *cfg)
1271 {
1272 /* Main loop.
1273 1. Update local ports information
1274 2. Update local chassis information
1275 */
1276 log_debug("loop", "start new loop");
1277 LOCAL_CHASSIS(cfg)->c_cap_enabled = 0;
1278 /* Information for local ports is triggered even when it is possible to
1279 * update them on some other event because we want to refresh them if we
1280 * missed something. */
1281 log_debug("loop", "update information for local ports");
1282 lldpd_update_localports(cfg);
1283 log_debug("loop", "update information for local chassis");
1284 lldpd_update_localchassis(cfg);
1285 lldpd_count_neighbors(cfg);
1286 }
1287
1288 static void
1289 lldpd_exit(struct lldpd *cfg)
1290 {
1291 struct lldpd_hardware *hardware, *hardware_next;
1292 log_debug("main", "exit lldpd");
1293
1294 TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
1295 lldpd_send_shutdown(hardware);
1296
1297 close(cfg->g_ctl);
1298 priv_ctl_cleanup(cfg->g_ctlname);
1299 log_debug("main", "cleanup hardware information");
1300 for (hardware = TAILQ_FIRST(&cfg->g_hardware); hardware != NULL;
1301 hardware = hardware_next) {
1302 hardware_next = TAILQ_NEXT(hardware, h_entries);
1303 log_debug("main", "cleanup interface %s", hardware->h_ifname);
1304 lldpd_remote_cleanup(hardware, NULL, 1);
1305 lldpd_hardware_cleanup(cfg, hardware);
1306 }
1307 interfaces_cleanup(cfg);
1308 lldpd_port_cleanup(cfg->g_default_local_port, 1);
1309 lldpd_all_chassis_cleanup(cfg);
1310 free(cfg->g_default_local_port);
1311 free(cfg->g_config.c_platform);
1312 levent_shutdown(cfg);
1313 }
1314
1315 /**
1316 * Run lldpcli to configure lldpd.
1317 *
1318 * @return PID of running lldpcli or -1 if error.
1319 */
1320 static pid_t
1321 lldpd_configure(int use_syslog, int debug, const char *path, const char *ctlname, const char *config_path)
1322 {
1323 pid_t lldpcli = vfork();
1324 int devnull;
1325
1326 char sdebug[debug + 4];
1327 if (use_syslog)
1328 strlcpy(sdebug, "-s", 3);
1329 else {
1330 /* debug = 0 -> -sd */
1331 /* debug = 1 -> -sdd */
1332 /* debug = 2 -> -sddd */
1333 memset(sdebug, 'd', sizeof(sdebug));
1334 sdebug[debug + 3] = '\0';
1335 sdebug[0] = '-'; sdebug[1] = 's';
1336 }
1337 log_debug("main", "invoke %s %s", path, sdebug);
1338
1339 switch (lldpcli) {
1340 case -1:
1341 log_warn("main", "unable to fork");
1342 return -1;
1343 case 0:
1344 /* Child, exec lldpcli */
1345 if ((devnull = open("/dev/null", O_RDWR, 0)) != -1) {
1346 dup2(devnull, STDIN_FILENO);
1347 dup2(devnull, STDOUT_FILENO);
1348 if (devnull > 2) close(devnull);
1349
1350 if (config_path) {
1351 execl(path, "lldpcli", sdebug,
1352 "-u", ctlname,
1353 "-C", config_path,
1354 "resume",
1355 (char *)NULL);
1356 } else {
1357 execl(path, "lldpcli", sdebug,
1358 "-u", ctlname,
1359 "-C", SYSCONFDIR "/lldpd.conf",
1360 "-C", SYSCONFDIR "/lldpd.d",
1361 "resume",
1362 (char *)NULL);
1363 }
1364
1365 log_warn("main", "unable to execute %s", path);
1366 log_warnx("main", "configuration is incomplete, lldpd needs to be unpaused");
1367 }
1368 _exit(127);
1369 break;
1370 default:
1371 /* Father, don't do anything stupid */
1372 return lldpcli;
1373 }
1374 /* Should not be here */
1375 return -1;
1376 }
1377
1378 struct intint { int a; int b; };
1379 static const struct intint filters[] = {
1380 { 0, 0 },
1381 { 1, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1382 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1383 { 2, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO },
1384 { 3, SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1385 { 4, SMART_INCOMING_FILTER | SMART_OUTGOING_FILTER },
1386 { 5, SMART_INCOMING_FILTER },
1387 { 6, SMART_OUTGOING_FILTER },
1388 { 7, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_INCOMING_ONE_NEIGH |
1389 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1390 { 8, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_INCOMING_ONE_NEIGH },
1391 { 9, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH |
1392 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1393 { 10, SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1394 { 11, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH },
1395 { 12, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH |
1396 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1397 { 13, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_NEIGH |
1398 SMART_OUTGOING_FILTER },
1399 { 14, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1400 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1401 { 15, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO |
1402 SMART_OUTGOING_FILTER },
1403 { 16, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_INCOMING_ONE_NEIGH |
1404 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1405 { 17, SMART_INCOMING_FILTER | SMART_INCOMING_ONE_PROTO | SMART_INCOMING_ONE_NEIGH |
1406 SMART_OUTGOING_FILTER },
1407 { 18, SMART_INCOMING_FILTER |
1408 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_NEIGH },
1409 { 19, SMART_INCOMING_FILTER |
1410 SMART_OUTGOING_FILTER | SMART_OUTGOING_ONE_PROTO },
1411 { -1, 0 }
1412 };
1413
1414 #ifndef HOST_OS_OSX
1415 /**
1416 * Tell if we have been started by systemd.
1417 */
1418 static int
1419 lldpd_started_by_systemd()
1420 {
1421 #ifdef HOST_OS_LINUX
1422 int fd = -1;
1423 const char *notifysocket = getenv("NOTIFY_SOCKET");
1424 if (!notifysocket ||
1425 !strchr("@/", notifysocket[0]) ||
1426 strlen(notifysocket) < 2)
1427 return 0;
1428
1429 log_debug("main", "running with systemd, don't fork but signal ready");
1430 if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
1431 log_warn("main", "unable to open systemd notification socket %s",
1432 notifysocket);
1433 return 0;
1434 }
1435
1436 struct sockaddr_un su = { .sun_family = AF_UNIX };
1437 strlcpy(su.sun_path, notifysocket, sizeof(su.sun_path));
1438 if (notifysocket[0] == '@') su.sun_path[0] = 0;
1439
1440 struct iovec iov = {
1441 .iov_base = "READY=1",
1442 .iov_len = strlen("READY=1")
1443 };
1444 struct msghdr hdr = {
1445 .msg_name = &su,
1446 .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(notifysocket),
1447 .msg_iov = &iov,
1448 .msg_iovlen = 1
1449 };
1450 unsetenv("NOTIFY_SOCKET");
1451 if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
1452 log_warn("main", "unable to send notification to systemd");
1453 close(fd);
1454 return 0;
1455 }
1456 close(fd);
1457 return 1;
1458 #else
1459 return 0;
1460 #endif
1461 }
1462 #endif
1463
1464 #ifdef HOST_OS_LINUX
1465 static void
1466 version_convert(const char *sversion, unsigned iversion[], size_t n)
1467 {
1468 const char *p = sversion;
1469 char *end;
1470 for (size_t i = 0; i < n; i++) {
1471 iversion[i] = strtol(p, &end, 10);
1472 if (*end != '.') break;
1473 p = end + 1;
1474 }
1475 }
1476
1477 static void
1478 version_check(void)
1479 {
1480 struct utsname uts;
1481 if (uname(&uts) == -1) return;
1482 unsigned version_min[3] = {};
1483 unsigned version_cur[3] = {};
1484 version_convert(uts.release, version_cur, 3);
1485 version_convert(MIN_LINUX_KERNEL_VERSION, version_min, 3);
1486 if (version_min[0] > version_cur[0] ||
1487 (version_min[0] == version_cur[0] && version_min[1] > version_cur[1]) ||
1488 (version_min[0] == version_cur[0] && version_min[1] == version_cur[1] &&
1489 version_min[2] > version_cur[2])) {
1490 log_warnx("lldpd", "minimal kernel version required is %s, got %s",
1491 MIN_LINUX_KERNEL_VERSION, uts.release);
1492 log_warnx("lldpd", "lldpd may be unable to detect bonds and bridges correctly");
1493 #ifndef ENABLE_OLDIES
1494 log_warnx("lldpd", "consider recompiling with --enable-oldies option");
1495 #endif
1496 }
1497 }
1498 #else
1499 static void version_check(void) {}
1500 #endif
1501
1502 int
1503 lldpd_main(int argc, char *argv[], char *envp[])
1504 {
1505 struct lldpd *cfg;
1506 struct lldpd_chassis *lchassis;
1507 int ch, debug = 0, use_syslog = 1, daemonize = 1;
1508 const char *errstr;
1509 #ifdef USE_SNMP
1510 int snmp = 0;
1511 const char *agentx = NULL; /* AgentX socket */
1512 #endif
1513 const char *ctlname = NULL;
1514 char *mgmtp = NULL;
1515 char *cidp = NULL;
1516 char *interfaces = NULL;
1517 /* We do not want more options here. Please add them in lldpcli instead
1518 * unless there is a very good reason. Most command-line options will
1519 * get deprecated at some point. */
1520 char *popt, opts[] =
1521 "H:vhkrdD:p:xX:m:u:4:6:I:C:p:M:P:S:iL:O:@ ";
1522 int i, found, advertise_version = 1;
1523 #ifdef ENABLE_LLDPMED
1524 int lldpmed = 0, noinventory = 0;
1525 int enable_fast_start = 1;
1526 #endif
1527 char *descr_override = NULL;
1528 char *platform_override = NULL;
1529 char *lsb_release = NULL;
1530 const char *lldpcli = LLDPCLI_PATH;
1531 const char *pidfile = LLDPD_PID_FILE;
1532 int smart = 15;
1533 int receiveonly = 0, version = 0;
1534 int ctl;
1535 const char *config_file = NULL;
1536
1537 #ifdef ENABLE_PRIVSEP
1538 /* Non privileged user */
1539 struct passwd *user;
1540 struct group *group;
1541 uid_t uid;
1542 gid_t gid;
1543 #endif
1544
1545 saved_argv = argv;
1546
1547 #if HAVE_SETPROCTITLE_INIT
1548 setproctitle_init(argc, argv, envp);
1549 #endif
1550
1551 /*
1552 * Get and parse command line options
1553 */
1554 if ((popt = strchr(opts, '@')) != NULL) {
1555 for (i=0;
1556 protos[i].mode != 0 && *popt != '\0';
1557 i++)
1558 *(popt++) = protos[i].arg;
1559 *popt = '\0';
1560 }
1561 while ((ch = getopt(argc, argv, opts)) != -1) {
1562 switch (ch) {
1563 case 'h':
1564 usage();
1565 break;
1566 case 'v':
1567 version++;
1568 break;
1569 case 'd':
1570 if (daemonize)
1571 daemonize = 0;
1572 else if (use_syslog)
1573 use_syslog = 0;
1574 else
1575 debug++;
1576 break;
1577 case 'D':
1578 log_accept(optarg);
1579 break;
1580 case 'p':
1581 pidfile = optarg;
1582 break;
1583 case 'r':
1584 receiveonly = 1;
1585 break;
1586 case 'm':
1587 if (mgmtp) {
1588 fprintf(stderr, "-m can only be used once\n");
1589 usage();
1590 }
1591 mgmtp = strdup(optarg);
1592 break;
1593 case 'u':
1594 if (ctlname) {
1595 fprintf(stderr, "-u can only be used once\n");
1596 usage();
1597 }
1598 ctlname = optarg;
1599 break;
1600 case 'I':
1601 if (interfaces) {
1602 fprintf(stderr, "-I can only be used once\n");
1603 usage();
1604 }
1605 interfaces = strdup(optarg);
1606 break;
1607 case 'C':
1608 if (cidp) {
1609 fprintf(stderr, "-C can only be used once\n");
1610 usage();
1611 }
1612 cidp = strdup(optarg);
1613 break;
1614 case 'L':
1615 if (strlen(optarg)) lldpcli = optarg;
1616 else lldpcli = NULL;
1617 break;
1618 case 'k':
1619 advertise_version = 0;
1620 break;
1621 #ifdef ENABLE_LLDPMED
1622 case 'M':
1623 lldpmed = strtonum(optarg, 1, 4, &errstr);
1624 if (errstr) {
1625 fprintf(stderr, "-M requires an argument between 1 and 4\n");
1626 usage();
1627 }
1628 break;
1629 case 'i':
1630 noinventory = 1;
1631 break;
1632 #else
1633 case 'M':
1634 case 'i':
1635 fprintf(stderr, "LLDP-MED support is not built-in\n");
1636 usage();
1637 break;
1638 #endif
1639 #ifdef USE_SNMP
1640 case 'x':
1641 snmp = 1;
1642 break;
1643 case 'X':
1644 if (agentx) {
1645 fprintf(stderr, "-X can only be used once\n");
1646 usage();
1647 }
1648 snmp = 1;
1649 agentx = optarg;
1650 break;
1651 #else
1652 case 'x':
1653 case 'X':
1654 fprintf(stderr, "SNMP support is not built-in\n");
1655 usage();
1656 #endif
1657 break;
1658 case 'S':
1659 if (descr_override) {
1660 fprintf(stderr, "-S can only be used once\n");
1661 usage();
1662 }
1663 descr_override = strdup(optarg);
1664 break;
1665 case 'P':
1666 if (platform_override) {
1667 fprintf(stderr, "-P can only be used once\n");
1668 usage();
1669 }
1670 platform_override = strdup(optarg);
1671 break;
1672 case 'H':
1673 smart = strtonum(optarg, 0, sizeof(filters)/sizeof(filters[0]),
1674 &errstr);
1675 if (errstr) {
1676 fprintf(stderr, "-H requires an int between 0 and %zu\n",
1677 sizeof(filters)/sizeof(filters[0]));
1678 usage();
1679 }
1680 break;
1681 case 'O':
1682 if (config_file) {
1683 fprintf(stderr, "-O can only be used once\n");
1684 usage();
1685 }
1686 config_file = optarg;
1687 break;
1688 default:
1689 found = 0;
1690 for (i=0; protos[i].mode != 0; i++) {
1691 if (ch == protos[i].arg) {
1692 found = 1;
1693 protos[i].enabled++;
1694 }
1695 }
1696 if (!found)
1697 usage();
1698 }
1699 }
1700
1701 if (version) {
1702 version_display(stdout, "lldpd", version > 1);
1703 exit(0);
1704 }
1705
1706 if (ctlname == NULL) ctlname = LLDPD_CTL_SOCKET;
1707
1708 /* Set correct smart mode */
1709 for (i=0; (filters[i].a != -1) && (filters[i].a != smart); i++);
1710 if (filters[i].a == -1) {
1711 fprintf(stderr, "Incorrect mode for -H\n");
1712 usage();
1713 }
1714 smart = filters[i].b;
1715
1716 log_init(use_syslog, debug, __progname);
1717 tzset(); /* Get timezone info before chroot */
1718 if (use_syslog && daemonize) {
1719 /* So, we use syslog and we daemonize (or we are started by
1720 * systemd). No need to continue writing to stdout. */
1721 int fd;
1722 if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
1723 dup2(fd, STDIN_FILENO);
1724 dup2(fd, STDOUT_FILENO);
1725 dup2(fd, STDERR_FILENO);
1726 if (fd > 2) close(fd);
1727 }
1728 }
1729 log_debug("main", "lldpd " PACKAGE_VERSION " starting...");
1730 version_check();
1731
1732 /* Grab uid and gid to use for priv sep */
1733 #ifdef ENABLE_PRIVSEP
1734 if ((user = getpwnam(PRIVSEP_USER)) == NULL)
1735 fatalx("main", "no " PRIVSEP_USER " user for privilege separation, please create it");
1736 uid = user->pw_uid;
1737 if ((group = getgrnam(PRIVSEP_GROUP)) == NULL)
1738 fatalx("main", "no " PRIVSEP_GROUP " group for privilege separation, please create it");
1739 gid = group->gr_gid;
1740 #endif
1741
1742 /* Create and setup socket */
1743 int retry = 1;
1744 log_debug("main", "creating control socket");
1745 while ((ctl = ctl_create(ctlname)) == -1) {
1746 if (retry-- && errno == EADDRINUSE) {
1747 /* Check if a daemon is really listening */
1748 int tfd;
1749 log_info("main", "unable to create control socket because it already exists");
1750 log_info("main", "check if another instance is running");
1751 if ((tfd = ctl_connect(ctlname)) != -1) {
1752 /* Another instance is running */
1753 close(tfd);
1754 log_warnx("main", "another instance is running, please stop it");
1755 fatalx("main", "giving up");
1756 } else if (errno == ECONNREFUSED) {
1757 /* Nobody is listening */
1758 log_info("main", "old control socket is present, clean it");
1759 ctl_cleanup(ctlname);
1760 continue;
1761 }
1762 log_warn("main", "cannot determine if another daemon is already running");
1763 fatalx("main", "giving up");
1764 }
1765 log_warn("main", "unable to create control socket at %s", ctlname);
1766 fatalx("main", "giving up");
1767 }
1768 #ifdef ENABLE_PRIVSEP
1769 if (chown(ctlname, uid, gid) == -1)
1770 log_warn("main", "unable to chown control socket");
1771 if (chmod(ctlname,
1772 S_IRUSR | S_IWUSR | S_IXUSR |
1773 S_IRGRP | S_IWGRP | S_IXGRP) == -1)
1774 log_warn("main", "unable to chmod control socket");
1775 #endif
1776
1777 /* Disable SIGPIPE */
1778 signal(SIGPIPE, SIG_IGN);
1779
1780 /* Disable SIGHUP, until handlers are installed */
1781 signal(SIGHUP, SIG_IGN);
1782
1783 /* Daemonization, unless started by systemd or launchd or debug */
1784 #ifndef HOST_OS_OSX
1785 if (daemonize &&
1786 !lldpd_started_by_systemd()) {
1787 int pid;
1788 char *spid;
1789 log_debug("main", "going into background");
1790 if (daemon(0, 1) != 0)
1791 fatal("main", "failed to detach daemon");
1792 if ((pid = open(pidfile,
1793 O_TRUNC | O_CREAT | O_WRONLY, 0666)) == -1)
1794 fatal("main", "unable to open pid file " LLDPD_PID_FILE
1795 " (or the specified one)");
1796 if (asprintf(&spid, "%d\n", getpid()) == -1)
1797 fatal("main", "unable to create pid file " LLDPD_PID_FILE
1798 " (or the specified one)");
1799 if (write(pid, spid, strlen(spid)) == -1)
1800 fatal("main", "unable to write pid file " LLDPD_PID_FILE
1801 " (or the specified one)");
1802 free(spid);
1803 close(pid);
1804 }
1805 #endif
1806
1807 /* Configuration with lldpcli */
1808 if (lldpcli) {
1809 if (!config_file) {
1810 log_debug("main", "invoking lldpcli for default configuration locations");
1811 } else {
1812 log_debug("main", "invoking lldpcli for user supplied configuration location");
1813 }
1814 if (lldpd_configure(use_syslog, debug, lldpcli, ctlname, config_file) == -1)
1815 fatal("main", "unable to spawn lldpcli");
1816 }
1817
1818 /* Try to read system information from /etc/os-release if possible.
1819 Fall back to lsb_release for compatibility. */
1820 log_debug("main", "get OS/LSB release information");
1821 lsb_release = lldpd_get_os_release();
1822 if (!lsb_release) {
1823 lsb_release = lldpd_get_lsb_release();
1824 }
1825
1826 log_debug("main", "initialize privilege separation");
1827 #ifdef ENABLE_PRIVSEP
1828 priv_init(PRIVSEP_CHROOT, ctl, uid, gid);
1829 #else
1830 priv_init(PRIVSEP_CHROOT, ctl, 0, 0);
1831 #endif
1832
1833 /* Initialization of global configuration */
1834 if ((cfg = (struct lldpd *)
1835 calloc(1, sizeof(struct lldpd))) == NULL)
1836 fatal("main", NULL);
1837
1838 lldpd_alloc_default_local_port(cfg);
1839 cfg->g_ctlname = ctlname;
1840 cfg->g_ctl = ctl;
1841 cfg->g_config.c_mgmt_pattern = mgmtp;
1842 cfg->g_config.c_cid_pattern = cidp;
1843 cfg->g_config.c_iface_pattern = interfaces;
1844 cfg->g_config.c_smart = smart;
1845 if (lldpcli)
1846 cfg->g_config.c_paused = 1;
1847 cfg->g_config.c_receiveonly = receiveonly;
1848 cfg->g_config.c_tx_interval = LLDPD_TX_INTERVAL;
1849 cfg->g_config.c_tx_hold = LLDPD_TX_HOLD;
1850 cfg->g_config.c_ttl = cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold;
1851 cfg->g_config.c_max_neighbors = LLDPD_MAX_NEIGHBORS;
1852 #ifdef ENABLE_LLDPMED
1853 cfg->g_config.c_enable_fast_start = enable_fast_start;
1854 cfg->g_config.c_tx_fast_init = LLDPD_FAST_INIT;
1855 cfg->g_config.c_tx_fast_interval = LLDPD_FAST_TX_INTERVAL;
1856 #endif
1857 #ifdef USE_SNMP
1858 cfg->g_snmp = snmp;
1859 cfg->g_snmp_agentx = agentx;
1860 #endif /* USE_SNMP */
1861 cfg->g_config.c_bond_slave_src_mac_type = \
1862 LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED;
1863
1864 /* Get ioctl socket */
1865 log_debug("main", "get an ioctl socket");
1866 if ((cfg->g_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1867 fatal("main", "failed to get ioctl socket");
1868
1869 /* Description */
1870 if (!(cfg->g_config.c_advertise_version = advertise_version) &&
1871 lsb_release && lsb_release[strlen(lsb_release) - 1] == '\n')
1872 lsb_release[strlen(lsb_release) - 1] = '\0';
1873 cfg->g_lsb_release = lsb_release;
1874 if (descr_override)
1875 cfg->g_config.c_description = descr_override;
1876
1877 if (platform_override)
1878 cfg->g_config.c_platform = platform_override;
1879
1880 /* Set system capabilities */
1881 log_debug("main", "set system capabilities");
1882 if ((lchassis = (struct lldpd_chassis*)
1883 calloc(1, sizeof(struct lldpd_chassis))) == NULL)
1884 fatal("localchassis", NULL);
1885 cfg->g_config.c_cap_advertise = 1;
1886 lchassis->c_cap_available = LLDP_CAP_BRIDGE | LLDP_CAP_WLAN |
1887 LLDP_CAP_ROUTER | LLDP_CAP_STATION;
1888 cfg->g_config.c_mgmt_advertise = 1;
1889 TAILQ_INIT(&lchassis->c_mgmt);
1890 #ifdef ENABLE_LLDPMED
1891 if (lldpmed > 0) {
1892 if (lldpmed == LLDP_MED_CLASS_III)
1893 lchassis->c_cap_available |= LLDP_CAP_TELEPHONE;
1894 lchassis->c_med_type = lldpmed;
1895 lchassis->c_med_cap_available = LLDP_MED_CAP_CAP |
1896 LLDP_MED_CAP_IV | LLDP_MED_CAP_LOCATION |
1897 LLDP_MED_CAP_POLICY | LLDP_MED_CAP_MDI_PSE | LLDP_MED_CAP_MDI_PD;
1898 cfg->g_config.c_noinventory = noinventory;
1899 } else
1900 cfg->g_config.c_noinventory = 1;
1901 #endif
1902
1903 log_debug("main", "initialize protocols");
1904 cfg->g_protocols = protos;
1905 for (i=0; protos[i].mode != 0; i++) {
1906
1907 /* With -ll, disable LLDP */
1908 if (protos[i].mode == LLDPD_MODE_LLDP)
1909 protos[i].enabled %= 3;
1910 /* With -ccc force CDPV2, enable CDPV1 */
1911 if (protos[i].mode == LLDPD_MODE_CDPV1 && protos[i].enabled == 3) {
1912 protos[i].enabled = 1;
1913 }
1914 /* With -cc force CDPV1, enable CDPV2 */
1915 if (protos[i].mode == LLDPD_MODE_CDPV2 && protos[i].enabled == 2) {
1916 protos[i].enabled = 1;
1917 }
1918
1919 /* With -cccc disable CDPV1, enable CDPV2 */
1920 if (protos[i].mode == LLDPD_MODE_CDPV1 && protos[i].enabled >= 4) {
1921 protos[i].enabled = 0;
1922 }
1923
1924 /* With -cccc disable CDPV1, enable CDPV2; -ccccc will force CDPv2 */
1925 if (protos[i].mode == LLDPD_MODE_CDPV2 && protos[i].enabled == 4) {
1926 protos[i].enabled = 1;
1927 }
1928
1929 if (protos[i].enabled > 1)
1930 log_info("main", "protocol %s enabled and forced", protos[i].name);
1931 else if (protos[i].enabled)
1932 log_info("main", "protocol %s enabled", protos[i].name);
1933 else
1934 log_info("main", "protocol %s disabled", protos[i].name);
1935 }
1936
1937 TAILQ_INIT(&cfg->g_hardware);
1938 TAILQ_INIT(&cfg->g_chassis);
1939 TAILQ_INSERT_TAIL(&cfg->g_chassis, lchassis, c_entries);
1940 lchassis->c_refcount++; /* We should always keep a reference to local chassis */
1941
1942 /* Main loop */
1943 log_debug("main", "start main loop");
1944 levent_loop(cfg);
1945 lchassis->c_refcount--;
1946 lldpd_exit(cfg);
1947 free(cfg);
1948
1949 return (0);
1950 }