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