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