Coverage Report

Created: 2026-09-01 06:14

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