]> git.ipfire.org Git - thirdparty/lldpd.git/blobdiff - src/daemon/lldpd.c
lldp: don't use chassis TTL anymore
[thirdparty/lldpd.git] / src / daemon / lldpd.c
index 829520a46374e4dd8c32c0e1ab276412ab0281e4..798bd602518ca986f70232ee0a1f0126b1c75aec 100644 (file)
@@ -44,7 +44,9 @@ static void            usage(void);
 static struct protocol protos[] =
 {
        { LLDPD_MODE_LLDP, 1, "LLDP", 'l', lldp_send, lldp_decode, NULL,
-         LLDP_MULTICAST_ADDR },
+         LLDP_ADDR_NEAREST_BRIDGE,
+         LLDP_ADDR_NEAREST_NONTPMR_BRIDGE,
+         LLDP_ADDR_NEAREST_CUSTOMER_BRIDGE },
 #ifdef ENABLE_CDP
        { LLDPD_MODE_CDPV1, 0, "CDPv1", 'c', cdpv1_send, cdp_decode, cdpv1_guess,
          CDP_MULTICAST_ADDR },
@@ -485,7 +487,9 @@ lldpd_guess_type(struct lldpd *cfg, char *frame, int s)
                if (!cfg->g_protocols[i].enabled)
                        continue;
                if (cfg->g_protocols[i].guess == NULL) {
-                       if (memcmp(frame, cfg->g_protocols[i].mac, ETHER_ADDR_LEN) == 0) {
+                       if (memcmp(frame, cfg->g_protocols[i].mac1, ETHER_ADDR_LEN) == 0 ||
+                           memcmp(frame, cfg->g_protocols[i].mac2, ETHER_ADDR_LEN) == 0 ||
+                           memcmp(frame, cfg->g_protocols[i].mac3, ETHER_ADDR_LEN) == 0) {
                                log_debug("decode", "guessed protocol is %s (from MAC address)",
                                    cfg->g_protocols[i].name);
                                return cfg->g_protocols[i].mode;
@@ -513,9 +517,11 @@ lldpd_decode(struct lldpd *cfg, char *frame, int s,
        log_debug("decode", "decode a received frame on %s",
            hardware->h_ifname);
 
-       if (s < sizeof(struct ether_header) + 4)
+       if (s < sizeof(struct ether_header) + 4) {
                /* Too short, just discard it */
+               hardware->h_rx_discarded_cnt++;
                return;
+       }
 
        /* Decapsulate VLAN frames */
        struct ether_header eheader;
@@ -549,6 +555,7 @@ lldpd_decode(struct lldpd *cfg, char *frame, int s,
                                s, hardware, &chassis, &port) == -1) {
                                log_debug("decode", "function for %s protocol did not decode this frame",
                                    cfg->g_protocols[i].name);
+                               hardware->h_rx_discarded_cnt++;
                                return;
                        }
                        chassis->c_protocol = port->p_protocol =
@@ -1228,6 +1235,7 @@ lldpd_exit(struct lldpd *cfg)
        lldpd_all_chassis_cleanup(cfg);
        free(cfg->g_default_local_port);
        free(cfg->g_config.c_platform);
+       levent_shutdown(cfg);
 }
 
 /**
@@ -1267,8 +1275,8 @@ lldpd_configure(int use_syslog, int debug, const char *path, const char *ctlname
 
                        execl(path, "lldpcli", sdebug,
                            "-u", ctlname,
-                           "-c", SYSCONFDIR "/lldpd.conf",
-                           "-c", SYSCONFDIR "/lldpd.d",
+                           "-C", SYSCONFDIR "/lldpd.conf",
+                           "-C", SYSCONFDIR "/lldpd.d",
                            "resume",
                            (char *)NULL);
                        log_warn("main", "unable to execute %s", path);
@@ -1413,7 +1421,8 @@ version_check(void)
        version_convert(MIN_LINUX_KERNEL_VERSION, version_min, 3);
        if (version_min[0] > version_cur[0] ||
            (version_min[0] == version_cur[0] && version_min[1] > version_cur[1]) ||
-           (version_min[1] == version_cur[1] && version_min[2] > version_cur[2])) {
+           (version_min[0] == version_cur[0] && version_min[1] == version_cur[1] &&
+               version_min[2] > version_cur[2])) {
                log_warnx("lldpd", "minimal kernel version required is %s, got %s",
                    MIN_LINUX_KERNEL_VERSION, uts.release);
                log_warnx("lldpd", "lldpd may be unable to detect bonds and bridges correctly");
@@ -1432,6 +1441,7 @@ lldpd_main(int argc, char *argv[], char *envp[])
        struct lldpd *cfg;
        struct lldpd_chassis *lchassis;
        int ch, debug = 0, use_syslog = 1, daemonize = 1;
+       const char *errstr;
 #ifdef USE_SNMP
        int snmp = 0;
        const char *agentx = NULL;      /* AgentX socket */
@@ -1444,7 +1454,7 @@ lldpd_main(int argc, char *argv[], char *envp[])
         * unless there is a very good reason. Most command-line options will
         * get deprecated at some point. */
        char *popt, opts[] =
-               "H:vhkrdD:xX:m:u:4:6:I:C:p:M:P:S:iL:@                    ";
+               "H:vhkrdD:p:xX:m:u:4:6:I:C:p:M:P:S:iL:@                    ";
        int i, found, advertise_version = 1;
 #ifdef ENABLE_LLDPMED
        int lldpmed = 0, noinventory = 0;
@@ -1454,6 +1464,7 @@ lldpd_main(int argc, char *argv[], char *envp[])
        char *platform_override = NULL;
        char *lsb_release = NULL;
        const char *lldpcli = LLDPCLI_PATH;
+       const char *pidfile = LLDPD_PID_FILE;
        int smart = 15;
        int receiveonly = 0, version = 0;
        int ctl;
@@ -1501,6 +1512,9 @@ lldpd_main(int argc, char *argv[], char *envp[])
                case 'D':
                        log_accept(optarg);
                        break;
+               case 'p':
+                       pidfile = optarg;
+                       break;
                case 'r':
                        receiveonly = 1;
                        break;
@@ -1541,8 +1555,8 @@ lldpd_main(int argc, char *argv[], char *envp[])
                        break;
 #ifdef ENABLE_LLDPMED
                case 'M':
-                       lldpmed = atoi(optarg);
-                       if ((lldpmed < 1) || (lldpmed > 4)) {
+                       lldpmed = strtonum(optarg, 1, 4, &errstr);
+                       if (errstr) {
                                fprintf(stderr, "-M requires an argument between 1 and 4\n");
                                usage();
                        }
@@ -1591,7 +1605,13 @@ lldpd_main(int argc, char *argv[], char *envp[])
                        platform_override = strdup(optarg);
                        break;
                case 'H':
-                       smart = atoi(optarg);
+                       smart = strtonum(optarg, 0, sizeof(filters)/sizeof(filters[0]),
+                           &errstr);
+                       if (errstr) {
+                               fprintf(stderr, "-H requires an int between 0 and %zu\n",
+                                   sizeof(filters)/sizeof(filters[0]));
+                               usage();
+                       }
                        break;
                default:
                        found = 0;
@@ -1623,17 +1643,27 @@ lldpd_main(int argc, char *argv[], char *envp[])
 
        log_init(use_syslog, debug, __progname);
        tzset();                /* Get timezone info before chroot */
-
+       if (use_syslog && daemonize) {
+               /* So, we use syslog and we daemonize (or we are started by
+                * upstart/systemd). No need to continue writing to stdout. */
+               int fd;
+               if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
+                       dup2(fd, STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       dup2(fd, STDERR_FILENO);
+                       if (fd > 2) close(fd);
+               }
+       }
        log_debug("main", "lldpd " PACKAGE_VERSION " starting...");
        version_check();
 
        /* Grab uid and gid to use for priv sep */
 #ifdef ENABLE_PRIVSEP
        if ((user = getpwnam(PRIVSEP_USER)) == NULL)
-               fatal("main", "no " PRIVSEP_USER " user for privilege separation");
+               fatalx("main", "no " PRIVSEP_USER " user for privilege separation, please create it");
        uid = user->pw_uid;
        if ((group = getgrnam(PRIVSEP_GROUP)) == NULL)
-               fatal("main", "no " PRIVSEP_GROUP " group for privilege separation");
+               fatalx("main", "no " PRIVSEP_GROUP " group for privilege separation, please create it");
        gid = group->gr_gid;
 #endif
 
@@ -1660,7 +1690,7 @@ lldpd_main(int argc, char *argv[], char *envp[])
                        log_warn("main", "cannot determine if another daemon is already running");
                        fatalx("main", "giving up");
                }
-               log_warn("main", "unable to create control socket");
+               log_warn("main", "unable to create control socket at %s", ctlname);
                fatalx("main", "giving up");
        }
 #ifdef ENABLE_PRIVSEP
@@ -1678,34 +1708,37 @@ lldpd_main(int argc, char *argv[], char *envp[])
        /* Disable SIGHUP, until handlers are installed */
        signal(SIGHUP, SIG_IGN);
 
-       /* Configuration with lldpcli */
-       if (lldpcli) {
-               log_debug("main", "invoking lldpcli for configuration");
-               if (lldpd_configure(use_syslog, debug, lldpcli, ctlname) == -1)
-                       fatal("main", "unable to spawn lldpcli");
-       }
-
        /* Daemonization, unless started by upstart, systemd or launchd or debug */
 #ifndef HOST_OS_OSX
        if (daemonize &&
            !lldpd_started_by_upstart() && !lldpd_started_by_systemd()) {
                int pid;
                char *spid;
-               log_debug("main", "daemonize");
-               if (daemon(0, 0) != 0)
+               log_info("main", "going into background");
+               if (daemon(0, 1) != 0)
                        fatal("main", "failed to detach daemon");
-               if ((pid = open(LLDPD_PID_FILE,
+               if ((pid = open(pidfile,
                            O_TRUNC | O_CREAT | O_WRONLY, 0666)) == -1)
-                       fatal("main", "unable to open pid file " LLDPD_PID_FILE);
+                       fatal("main", "unable to open pid file " LLDPD_PID_FILE
+                           " (or the specified one)");
                if (asprintf(&spid, "%d\n", getpid()) == -1)
-                       fatal("main", "unable to create pid file " LLDPD_PID_FILE);
+                       fatal("main", "unable to create pid file " LLDPD_PID_FILE
+                           " (or the specified one)");
                if (write(pid, spid, strlen(spid)) == -1)
-                       fatal("main", "unable to write pid file " LLDPD_PID_FILE);
+                       fatal("main", "unable to write pid file " LLDPD_PID_FILE
+                           " (or the specified one)");
                free(spid);
                close(pid);
        }
 #endif
 
+       /* Configuration with lldpcli */
+       if (lldpcli) {
+               log_debug("main", "invoking lldpcli for configuration");
+               if (lldpd_configure(use_syslog, debug, lldpcli, ctlname) == -1)
+                       fatal("main", "unable to spawn lldpcli");
+       }
+
        /* Try to read system information from /etc/os-release if possible.
           Fall back to lsb_release for compatibility. */
        log_debug("main", "get OS/LSB release information");
@@ -1738,6 +1771,7 @@ lldpd_main(int argc, char *argv[], char *envp[])
        cfg->g_config.c_receiveonly = receiveonly;
        cfg->g_config.c_tx_interval = LLDPD_TX_INTERVAL;
        cfg->g_config.c_tx_hold = LLDPD_TX_HOLD;
+       cfg->g_config.c_ttl = cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold;
        cfg->g_config.c_max_neighbors = LLDPD_MAX_NEIGHBORS;
 #ifdef ENABLE_LLDPMED
        cfg->g_config.c_enable_fast_start = enable_fast_start;
@@ -1790,9 +1824,6 @@ lldpd_main(int argc, char *argv[], char *envp[])
                cfg->g_config.c_noinventory = 1;
 #endif
 
-       /* Set TTL */
-       lchassis->c_ttl = cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold;
-
        log_debug("main", "initialize protocols");
        cfg->g_protocols = protos;
        for (i=0; protos[i].mode != 0; i++) {