2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 #include <sys/utsname.h>
29 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/select.h>
34 #include <sys/ioctl.h>
35 #include <arpa/inet.h>
36 #include <net/if_arp.h>
40 static void usage(void);
42 static struct protocol protos
[] =
44 { LLDPD_MODE_LLDP
, 1, "LLDP", 'l', lldp_send
, lldp_decode
, NULL
,
45 LLDP_MULTICAST_ADDR
},
47 { LLDPD_MODE_CDPV1
, 0, "CDPv1", 'c', cdpv1_send
, cdp_decode
, cdpv1_guess
,
49 { LLDPD_MODE_CDPV2
, 0, "CDPv2", 'c', cdpv2_send
, cdp_decode
, cdpv2_guess
,
53 { LLDPD_MODE_SONMP
, 0, "SONMP", 's', sonmp_send
, sonmp_decode
, NULL
,
54 SONMP_MULTICAST_ADDR
},
57 { LLDPD_MODE_EDP
, 0, "EDP", 'e', edp_send
, edp_decode
, NULL
,
61 { LLDPD_MODE_FDP
, 0, "FDP", 'f', fdp_send
, cdp_decode
, NULL
,
64 { 0, 0, "any", ' ', NULL
, NULL
, NULL
,
68 static char **saved_argv
;
69 #ifdef HAVE___PROGNAME
70 extern const char *__progname
;
72 # define __progname "lldpd"
78 fprintf(stderr
, "Usage: %s [OPTIONS ...]\n", __progname
);
79 fprintf(stderr
, "Version: %s\n", PACKAGE_STRING
);
81 fprintf(stderr
, "\n");
83 fprintf(stderr
, "-d Do not daemonize.\n");
84 fprintf(stderr
, "-r Receive-only mode\n");
85 fprintf(stderr
, "-i Disable LLDP-MED inventory TLV transmission.\n");
86 fprintf(stderr
, "-k Disable advertising of kernel release, version, machine.\n");
87 fprintf(stderr
, "-S descr Override the default system description.\n");
88 fprintf(stderr
, "-P name Override the default hardware platform.\n");
89 fprintf(stderr
, "-m IP Specify the IPv4 management addresses of this system.\n");
90 fprintf(stderr
, "-H mode Specify the behaviour when detecting multiple neighbors.\n");
91 fprintf(stderr
, "-I iface Limit interfaces to use.\n");
93 fprintf(stderr
, "-M class Enable emission of LLDP-MED frame. 'class' should be one of:\n");
94 fprintf(stderr
, " 1 Generic Endpoint (Class I)\n");
95 fprintf(stderr
, " 2 Media Endpoint (Class II)\n");
96 fprintf(stderr
, " 3 Communication Device Endpoints (Class III)\n");
97 fprintf(stderr
, " 4 Network Connectivity Device\n");
100 fprintf(stderr
, "-x Enable SNMP subagent.\n");
102 fprintf(stderr
, "\n");
104 #if defined ENABLE_CDP || defined ENABLE_EDP || defined ENABLE_FDP || defined ENABLE_SONMP
105 fprintf(stderr
, "Additional protocol support.\n");
107 fprintf(stderr
, "-c Enable the support of CDP protocol. (Cisco)\n");
110 fprintf(stderr
, "-e Enable the support of EDP protocol. (Extreme)\n");
113 fprintf(stderr
, "-f Enable the support of FDP protocol. (Foundry)\n");
116 fprintf(stderr
, "-s Enable the support of SONMP protocol. (Nortel)\n");
119 fprintf(stderr
, "\n");
122 fprintf(stderr
, "see manual page lldpd(8) for more information\n");
126 struct lldpd_hardware
*
127 lldpd_get_hardware(struct lldpd
*cfg
, char *name
, int index
, struct lldpd_ops
*ops
)
129 struct lldpd_hardware
*hardware
;
130 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
131 if ((strcmp(hardware
->h_ifname
, name
) == 0) &&
132 (hardware
->h_ifindex
== index
) &&
133 ((!ops
) || (ops
== hardware
->h_ops
)))
139 struct lldpd_hardware
*
140 lldpd_alloc_hardware(struct lldpd
*cfg
, char *name
)
142 struct lldpd_hardware
*hardware
;
144 if ((hardware
= (struct lldpd_hardware
*)
145 calloc(1, sizeof(struct lldpd_hardware
))) == NULL
)
148 hardware
->h_cfg
= cfg
;
149 strlcpy(hardware
->h_ifname
, name
, sizeof(hardware
->h_ifname
));
150 hardware
->h_lport
.p_chassis
= LOCAL_CHASSIS(cfg
);
151 hardware
->h_lport
.p_chassis
->c_refcount
++;
152 TAILQ_INIT(&hardware
->h_rports
);
154 #ifdef ENABLE_LLDPMED
155 if (LOCAL_CHASSIS(cfg
)->c_med_cap_available
) {
156 hardware
->h_lport
.p_med_cap_enabled
= LLDPMED_CAP_CAP
;
157 if (!cfg
->g_noinventory
)
158 hardware
->h_lport
.p_med_cap_enabled
|= LLDPMED_CAP_IV
;
162 TAILQ_INIT(&hardware
->h_lport
.p_vlans
);
163 TAILQ_INIT(&hardware
->h_lport
.p_ppvids
);
164 TAILQ_INIT(&hardware
->h_lport
.p_pids
);
167 levent_hardware_init(hardware
);
173 lldpd_vlan_cleanup(struct lldpd_port
*port
)
175 struct lldpd_vlan
*vlan
, *vlan_next
;
176 for (vlan
= TAILQ_FIRST(&port
->p_vlans
);
180 vlan_next
= TAILQ_NEXT(vlan
, v_entries
);
181 TAILQ_REMOVE(&port
->p_vlans
, vlan
, v_entries
);
187 lldpd_ppvid_cleanup(struct lldpd_port
*port
)
189 struct lldpd_ppvid
*ppvid
, *ppvid_next
;
190 for (ppvid
= TAILQ_FIRST(&port
->p_ppvids
);
192 ppvid
= ppvid_next
) {
193 ppvid_next
= TAILQ_NEXT(ppvid
, p_entries
);
194 TAILQ_REMOVE(&port
->p_ppvids
, ppvid
, p_entries
);
200 lldpd_pi_cleanup(struct lldpd_port
*port
)
202 struct lldpd_pi
*pi
, *pi_next
;
203 for (pi
= TAILQ_FIRST(&port
->p_pids
);
207 pi_next
= TAILQ_NEXT(pi
, p_entries
);
208 TAILQ_REMOVE(&port
->p_pids
, pi
, p_entries
);
214 /* If `all' is true, clear all information, including information that
215 are not refreshed periodically. Port should be freed manually. */
217 lldpd_port_cleanup(struct lldpd
*cfg
, struct lldpd_port
*port
, int all
)
219 #ifdef ENABLE_LLDPMED
222 for (i
=0; i
< LLDPMED_LOCFORMAT_LAST
; i
++)
223 free(port
->p_med_location
[i
].data
);
226 lldpd_vlan_cleanup(port
);
227 lldpd_ppvid_cleanup(port
);
228 lldpd_pi_cleanup(port
);
233 free(port
->p_lastframe
);
234 if (port
->p_chassis
) { /* chassis may not have been attributed, yet */
235 port
->p_chassis
->c_refcount
--;
236 port
->p_chassis
= NULL
;
242 lldpd_alloc_mgmt(int family
, void *addrptr
, size_t addrsize
, u_int32_t iface
)
244 struct lldpd_mgmt
*mgmt
;
246 if (family
<= LLDPD_AF_UNSPEC
|| family
>= LLDPD_AF_LAST
) {
247 errno
= EAFNOSUPPORT
;
250 if (addrsize
> LLDPD_MGMT_MAXADDRSIZE
) {
254 mgmt
= calloc(1, sizeof(struct lldpd_mgmt
));
259 mgmt
->m_family
= family
;
260 assert(addrsize
<= LLDPD_MGMT_MAXADDRSIZE
);
261 memcpy(&mgmt
->m_addr
, addrptr
, addrsize
);
262 mgmt
->m_addrsize
= addrsize
;
263 mgmt
->m_iface
= iface
;
268 lldpd_chassis_mgmt_cleanup(struct lldpd_chassis
*chassis
)
270 struct lldpd_mgmt
*mgmt
, *mgmt_next
;
271 for (mgmt
= TAILQ_FIRST(&chassis
->c_mgmt
);
274 mgmt_next
= TAILQ_NEXT(mgmt
, m_entries
);
275 TAILQ_REMOVE(&chassis
->c_mgmt
, mgmt
, m_entries
);
281 lldpd_chassis_cleanup(struct lldpd_chassis
*chassis
, int all
)
283 #ifdef ENABLE_LLDPMED
284 free(chassis
->c_med_hw
);
285 free(chassis
->c_med_sw
);
286 free(chassis
->c_med_fw
);
287 free(chassis
->c_med_sn
);
288 free(chassis
->c_med_manuf
);
289 free(chassis
->c_med_model
);
290 free(chassis
->c_med_asset
);
293 free(chassis
->c_name
);
294 free(chassis
->c_descr
);
295 lldpd_chassis_mgmt_cleanup(chassis
);
301 lldpd_remote_cleanup(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
, int all
)
303 struct lldpd_port
*port
, *port_next
;
305 for (port
= TAILQ_FIRST(&hardware
->h_rports
);
308 port_next
= TAILQ_NEXT(port
, p_entries
);
311 (time(NULL
) - port
->p_lastupdate
> port
->p_chassis
->c_ttl
)) {
312 hardware
->h_rx_ageout_cnt
++;
316 TAILQ_REMOVE(&hardware
->h_rports
, port
, p_entries
);
317 lldpd_port_cleanup(cfg
, port
, 1);
324 lldpd_hardware_cleanup(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
)
326 lldpd_port_cleanup(cfg
, &hardware
->h_lport
, 1);
327 if (hardware
->h_ops
->cleanup
)
328 hardware
->h_ops
->cleanup(cfg
, hardware
);
329 levent_hardware_release(hardware
);
334 lldpd_cleanup(struct lldpd
*cfg
)
336 struct lldpd_hardware
*hardware
, *hardware_next
;
337 struct lldpd_chassis
*chassis
, *chassis_next
;
339 for (hardware
= TAILQ_FIRST(&cfg
->g_hardware
); hardware
!= NULL
;
340 hardware
= hardware_next
) {
341 hardware_next
= TAILQ_NEXT(hardware
, h_entries
);
342 if (!hardware
->h_flags
) {
343 TAILQ_REMOVE(&cfg
->g_hardware
, hardware
, h_entries
);
344 lldpd_remote_cleanup(cfg
, hardware
, 1);
345 lldpd_hardware_cleanup(cfg
, hardware
);
347 lldpd_remote_cleanup(cfg
, hardware
, 0);
350 for (chassis
= TAILQ_FIRST(&cfg
->g_chassis
); chassis
;
351 chassis
= chassis_next
) {
352 chassis_next
= TAILQ_NEXT(chassis
, c_entries
);
353 if (chassis
->c_refcount
== 0) {
354 TAILQ_REMOVE(&cfg
->g_chassis
, chassis
, c_entries
);
355 lldpd_chassis_cleanup(chassis
, 1);
360 /* Update chassis `ochassis' with values from `chassis'. The later one is not
361 expected to be part of a list! It will also be wiped from memory. */
363 lldpd_move_chassis(struct lldpd_chassis
*ochassis
,
364 struct lldpd_chassis
*chassis
) {
365 struct lldpd_mgmt
*mgmt
, *mgmt_next
;
367 /* We want to keep refcount, index and list stuff from the current
369 TAILQ_ENTRY(lldpd_chassis
) entries
;
370 int refcount
= ochassis
->c_refcount
;
371 int index
= ochassis
->c_index
;
372 memcpy(&entries
, &ochassis
->c_entries
,
374 lldpd_chassis_cleanup(ochassis
, 0);
377 /* WARNING: this is a kludgy hack, we need in-place copy and cannot use
379 memcpy(ochassis
, chassis
, sizeof(struct lldpd_chassis
));
380 TAILQ_INIT(&ochassis
->c_mgmt
);
382 /* Copy of management addresses */
383 for (mgmt
= TAILQ_FIRST(&chassis
->c_mgmt
);
386 mgmt_next
= TAILQ_NEXT(mgmt
, m_entries
);
387 TAILQ_REMOVE(&chassis
->c_mgmt
, mgmt
, m_entries
);
388 TAILQ_INSERT_TAIL(&ochassis
->c_mgmt
, mgmt
, m_entries
);
391 /* Restore saved values */
392 ochassis
->c_refcount
= refcount
;
393 ochassis
->c_index
= index
;
394 memcpy(&ochassis
->c_entries
, &entries
, sizeof(entries
));
396 /* Get rid of the new chassis */
401 lldpd_guess_type(struct lldpd
*cfg
, char *frame
, int s
)
406 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
407 if (!cfg
->g_protocols
[i
].enabled
)
409 if (cfg
->g_protocols
[i
].guess
== NULL
) {
410 if (memcmp(frame
, cfg
->g_protocols
[i
].mac
, ETH_ALEN
) == 0)
411 return cfg
->g_protocols
[i
].mode
;
413 if (cfg
->g_protocols
[i
].guess(frame
, s
))
414 return cfg
->g_protocols
[i
].mode
;
421 lldpd_decode(struct lldpd
*cfg
, char *frame
, int s
,
422 struct lldpd_hardware
*hardware
)
425 struct lldpd_chassis
*chassis
, *ochassis
= NULL
;
426 struct lldpd_port
*port
, *oport
= NULL
;
427 int guess
= LLDPD_MODE_LLDP
;
429 if (s
< sizeof(struct ethhdr
) + 4)
430 /* Too short, just discard it */
432 /* Decapsulate VLAN frames */
433 if (((struct ethhdr
*)frame
)->h_proto
== htons(ETHERTYPE_VLAN
)) {
434 /* VLAN decapsulation means to shift 4 bytes left the frame from
435 * offset 2*ETH_ALEN */
436 memmove(frame
+ 2*ETH_ALEN
, frame
+ 2*ETH_ALEN
+ 4, s
- 2*ETH_ALEN
);
440 TAILQ_FOREACH(oport
, &hardware
->h_rports
, p_entries
) {
441 if ((oport
->p_lastframe
!= NULL
) &&
442 (oport
->p_lastframe
->size
== s
) &&
443 (memcmp(oport
->p_lastframe
->frame
, frame
, s
) == 0)) {
444 /* Already received the same frame */
445 oport
->p_lastupdate
= time(NULL
);
450 guess
= lldpd_guess_type(cfg
, frame
, s
);
451 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
452 if (!cfg
->g_protocols
[i
].enabled
)
454 if (cfg
->g_protocols
[i
].mode
== guess
) {
455 if ((result
= cfg
->g_protocols
[i
].decode(cfg
, frame
,
456 s
, hardware
, &chassis
, &port
)) == -1)
458 chassis
->c_protocol
= port
->p_protocol
=
459 cfg
->g_protocols
[i
].mode
;
463 if (cfg
->g_protocols
[i
].mode
== 0) {
464 LLOG_INFO("unable to guess frame type on %s",
469 /* Do we already have the same MSAP somewhere? */
470 TAILQ_FOREACH(oport
, &hardware
->h_rports
, p_entries
) {
471 if ((port
->p_protocol
== oport
->p_protocol
) &&
472 (port
->p_id_subtype
== oport
->p_id_subtype
) &&
473 (port
->p_id_len
== oport
->p_id_len
) &&
474 (memcmp(port
->p_id
, oport
->p_id
, port
->p_id_len
) == 0) &&
475 (chassis
->c_id_subtype
== oport
->p_chassis
->c_id_subtype
) &&
476 (chassis
->c_id_len
== oport
->p_chassis
->c_id_len
) &&
477 (memcmp(chassis
->c_id
, oport
->p_chassis
->c_id
,
478 chassis
->c_id_len
) == 0)) {
479 ochassis
= oport
->p_chassis
;
483 /* No, but do we already know the system? */
485 TAILQ_FOREACH(ochassis
, &cfg
->g_chassis
, c_entries
) {
486 if ((chassis
->c_protocol
== ochassis
->c_protocol
) &&
487 (chassis
->c_id_subtype
== ochassis
->c_id_subtype
) &&
488 (chassis
->c_id_len
== ochassis
->c_id_len
) &&
489 (memcmp(chassis
->c_id
, ochassis
->c_id
,
490 chassis
->c_id_len
) == 0))
496 /* The port is known, remove it before adding it back */
497 TAILQ_REMOVE(&hardware
->h_rports
, oport
, p_entries
);
498 lldpd_port_cleanup(cfg
, oport
, 1);
502 lldpd_move_chassis(ochassis
, chassis
);
505 /* Chassis not known, add it */
506 chassis
->c_index
= ++cfg
->g_lastrid
;
507 chassis
->c_refcount
= 0;
508 TAILQ_INSERT_TAIL(&cfg
->g_chassis
, chassis
, c_entries
);
509 i
= 0; TAILQ_FOREACH(ochassis
, &cfg
->g_chassis
, c_entries
) i
++;
510 LLOG_DEBUG("Currently, we know %d different systems", i
);
513 port
->p_lastchange
= port
->p_lastupdate
= time(NULL
);
514 if ((port
->p_lastframe
= (struct lldpd_frame
*)malloc(s
+
515 sizeof(int))) != NULL
) {
516 port
->p_lastframe
->size
= s
;
517 memcpy(port
->p_lastframe
->frame
, frame
, s
);
519 TAILQ_INSERT_TAIL(&hardware
->h_rports
, port
, p_entries
);
520 port
->p_chassis
= chassis
;
521 port
->p_chassis
->c_refcount
++;
522 /* Several cases are possible :
523 1. chassis is new, its refcount was 0. It is now attached
524 to this port, its refcount is 1.
525 2. chassis already exists and was attached to another
526 port, we increase its refcount accordingly.
527 3. chassis already exists and was attached to the same
528 port, its refcount was decreased with
529 lldpd_port_cleanup() and is now increased again.
531 In all cases, if the port already existed, it has been
532 freed with lldpd_port_cleanup() and therefore, the refcount
533 of the chassis that was attached to it is decreased.
535 i
= 0; TAILQ_FOREACH(oport
, &hardware
->h_rports
, p_entries
)
537 LLOG_DEBUG("Currently, %s knows %d neighbors",
538 hardware
->h_ifname
, i
);
542 /* Get the output of lsb_release -s -d. This is a slow function. It should be
543 called once. It return NULL if any problem happens. Otherwise, this is a
544 statically allocated buffer. The result includes the trailing \n */
546 lldpd_get_lsb_release() {
547 static char release
[1024];
548 char *const command
[] = { "lsb_release", "-s", "-d", NULL
};
549 int pid
, status
, devnull
, count
;
553 LLOG_WARN("unable to get a pair of pipes");
557 if ((pid
= fork()) < 0) {
558 LLOG_WARN("unable to fork");
563 /* Child, exec lsb_release */
565 if ((devnull
= open("/dev/null", O_RDWR
, 0)) != -1) {
566 dup2(devnull
, STDIN_FILENO
);
567 dup2(devnull
, STDERR_FILENO
);
568 dup2(pipefd
[1], STDOUT_FILENO
);
569 if (devnull
> 2) close(devnull
);
570 if (pipefd
[1] > 2) close(pipefd
[1]);
571 execvp("lsb_release", command
);
576 /* Father, read the output from the children */
580 status
= read(pipefd
[0], release
+count
, sizeof(release
)-count
);
581 if ((status
== -1) && (errno
== EINTR
)) continue;
584 } while (count
< sizeof(release
) && (status
> 0));
586 LLOG_WARN("unable to read from lsb_release");
588 waitpid(pid
, &status
, 0);
592 if (count
>= sizeof(release
)) {
593 LLOG_INFO("output of lsb_release is too large");
594 waitpid(pid
, &status
, 0);
598 if (waitpid(pid
, &status
, 0) != pid
)
600 if (!WIFEXITED(status
) || (WEXITSTATUS(status
) != 0)) {
601 LLOG_INFO("lsb_release information not available");
605 LLOG_INFO("lsb_release returned an empty string");
608 release
[count
] = '\0';
611 /* Should not be here */
615 /* Same like lldpd_get_lsb_release but reads /etc/os-release for PRETTY_NAME=. */
617 lldpd_get_os_release() {
618 static char release
[1024];
621 char *ptr1
= release
;
622 char *ptr2
= release
;
624 FILE *fp
= fopen("/etc/os-release", "r");
626 LLOG_WARN("could not open /etc/os-release");
630 while ((fgets(line
, 1024, fp
) != NULL
)) {
631 key
= strtok(line
, "=");
632 val
= strtok(NULL
, "=");
634 if (strncmp(key
, "PRETTY_NAME", 1024) == 0) {
635 strncpy(release
, val
, 1024);
641 /* Remove trailing newline and all " in the string. */
643 if ((*ptr1
== '"') || (*ptr1
== '\n')) {
655 lldpd_hide_ports(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
, int mask
) {
656 struct lldpd_port
*port
;
657 int protocols
[LLDPD_MODE_MAX
+1];
662 /* Compute the number of occurrences of each protocol */
663 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++) protocols
[i
] = 0;
664 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
)
665 protocols
[port
->p_protocol
]++;
667 /* Turn the protocols[] array into an array of
668 enabled/disabled protocols. 1 means enabled, 0
670 min
= (unsigned int)-1;
671 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++)
672 if (protocols
[i
] && (protocols
[i
] < min
))
675 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++)
676 if ((protocols
[i
] == min
) && !found
) {
677 /* If we need a tie breaker, we take
678 the first protocol only */
679 if (cfg
->g_smart
& mask
&
680 (SMART_OUTGOING_ONE_PROTO
| SMART_INCOMING_ONE_PROTO
))
683 } else protocols
[i
] = 0;
685 /* We set the p_hidden flag to 1 if the protocol is disabled */
686 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
) {
687 if (mask
== SMART_OUTGOING
)
688 port
->p_hidden_out
= protocols
[port
->p_protocol
]?0:1;
690 port
->p_hidden_in
= protocols
[port
->p_protocol
]?0:1;
693 /* If we want only one neighbor, we take the first one */
694 if (cfg
->g_smart
& mask
&
695 (SMART_OUTGOING_ONE_NEIGH
| SMART_INCOMING_ONE_NEIGH
)) {
697 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
) {
698 if (mask
== SMART_OUTGOING
) {
699 if (found
) port
->p_hidden_out
= 1;
700 if (!port
->p_hidden_out
)
703 if (mask
== SMART_INCOMING
) {
704 if (found
) port
->p_hidden_in
= 1;
705 if (!port
->p_hidden_in
)
711 /* Print a debug message summarizing the operation */
712 for (i
= 0; i
<= LLDPD_MODE_MAX
; i
++) protocols
[i
] = 0;
714 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
) {
715 if (!(((mask
== SMART_OUTGOING
) && port
->p_hidden_out
) ||
716 ((mask
== SMART_INCOMING
) && port
->p_hidden_in
))) {
718 protocols
[port
->p_protocol
] = 1;
723 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
724 if (cfg
->g_protocols
[i
].enabled
&& protocols
[cfg
->g_protocols
[i
].mode
]) {
726 strlen(cfg
->g_protocols
[i
].name
) + 3 > sizeof(buffer
)) {
727 /* Unlikely, our buffer is too small */
728 memcpy(buffer
+ sizeof(buffer
) - 4, "...", 4);
732 strcat(buffer
, ", ");
733 strcat(buffer
, cfg
->g_protocols
[i
].name
);
736 LLOG_DEBUG("[%s] %s: %d visible neigh / %d. Protocols: %s.",
737 (mask
== SMART_OUTGOING
)?"out filter":"in filter",
738 hardware
->h_ifname
, k
, j
, buffer
[0]?buffer
:"(none)");
741 /* Hide unwanted ports depending on smart mode set by the user */
743 lldpd_hide_all(struct lldpd
*cfg
)
745 struct lldpd_hardware
*hardware
;
749 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
750 if (cfg
->g_smart
& SMART_INCOMING_FILTER
)
751 lldpd_hide_ports(cfg
, hardware
, SMART_INCOMING
);
752 if (cfg
->g_smart
& SMART_OUTGOING_FILTER
)
753 lldpd_hide_ports(cfg
, hardware
, SMART_OUTGOING
);
758 lldpd_recv(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
, int fd
)
762 if ((buffer
= (char *)malloc(hardware
->h_mtu
)) == NULL
) {
763 LLOG_WARN("failed to alloc reception buffer");
766 if ((n
= hardware
->h_ops
->recv(cfg
, hardware
,
768 hardware
->h_mtu
)) == -1) {
772 hardware
->h_rx_cnt
++;
773 lldpd_decode(cfg
, buffer
, n
, hardware
);
774 lldpd_hide_all(cfg
); /* Immediatly hide */
779 lldpd_send_all(struct lldpd
*cfg
)
781 struct lldpd_hardware
*hardware
;
782 struct lldpd_port
*port
;
785 cfg
->g_lastsent
= time(NULL
);
786 if (cfg
->g_receiveonly
) return;
787 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
788 /* Ignore if interface is down */
789 if ((hardware
->h_flags
& IFF_RUNNING
) == 0)
793 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
794 if (!cfg
->g_protocols
[i
].enabled
)
796 /* We send only if we have at least one remote system
797 * speaking this protocol or if the protocol is forced */
798 if (cfg
->g_protocols
[i
].enabled
> 1) {
799 cfg
->g_protocols
[i
].send(cfg
, hardware
);
803 TAILQ_FOREACH(port
, &hardware
->h_rports
, p_entries
) {
804 /* If this remote port is disabled, we don't
806 if (port
->p_hidden_out
)
808 if (port
->p_protocol
==
809 cfg
->g_protocols
[i
].mode
) {
810 cfg
->g_protocols
[i
].send(cfg
,
819 /* Nothing was sent for this port, let's speak LLDP */
820 cfg
->g_protocols
[0].send(cfg
,
825 #ifdef ENABLE_LLDPMED
827 lldpd_med(struct lldpd_chassis
*chassis
)
829 #if __i386__ || __amd64__
830 static short int once
= 0;
832 chassis
->c_med_hw
= dmi_hw();
833 chassis
->c_med_fw
= dmi_fw();
834 chassis
->c_med_sn
= dmi_sn();
835 chassis
->c_med_manuf
= dmi_manuf();
836 chassis
->c_med_model
= dmi_model();
837 chassis
->c_med_asset
= dmi_asset();
845 lldpd_update_localchassis(struct lldpd
*cfg
)
852 /* Set system name and description */
854 fatal("failed to get system information");
855 if ((hp
= priv_gethostbyname()) == NULL
)
856 fatal("failed to get system name");
857 free(LOCAL_CHASSIS(cfg
)->c_name
);
858 free(LOCAL_CHASSIS(cfg
)->c_descr
);
859 if ((LOCAL_CHASSIS(cfg
)->c_name
= strdup(hp
)) == NULL
)
861 if (cfg
->g_descr_override
) {
862 if (asprintf(&LOCAL_CHASSIS(cfg
)->c_descr
, "%s",
863 cfg
->g_descr_override
) == -1)
864 fatal("failed to set full system description");
866 if (cfg
->g_advertise_version
) {
867 if (asprintf(&LOCAL_CHASSIS(cfg
)->c_descr
, "%s %s %s %s %s",
868 cfg
->g_lsb_release
?cfg
->g_lsb_release
:"",
869 un
.sysname
, un
.release
, un
.version
, un
.machine
)
871 fatal("failed to set full system description");
873 if (asprintf(&LOCAL_CHASSIS(cfg
)->c_descr
, "%s",
874 cfg
->g_lsb_release
?cfg
->g_lsb_release
:un
.sysname
) == -1)
875 fatal("failed to set minimal system description");
879 /* Check forwarding */
880 if ((f
= priv_open("/proc/sys/net/ipv4/ip_forward")) >= 0) {
881 if ((read(f
, &status
, 1) == 1) && (status
== '1'))
882 LOCAL_CHASSIS(cfg
)->c_cap_enabled
|= LLDP_CAP_ROUTER
;
884 LOCAL_CHASSIS(cfg
)->c_cap_enabled
&= ~LLDP_CAP_ROUTER
;
887 #ifdef ENABLE_LLDPMED
888 if (LOCAL_CHASSIS(cfg
)->c_cap_available
& LLDP_CAP_TELEPHONE
)
889 LOCAL_CHASSIS(cfg
)->c_cap_enabled
|= LLDP_CAP_TELEPHONE
;
890 lldpd_med(LOCAL_CHASSIS(cfg
));
891 free(LOCAL_CHASSIS(cfg
)->c_med_sw
);
892 if (cfg
->g_advertise_version
)
893 LOCAL_CHASSIS(cfg
)->c_med_sw
= strdup(un
.release
);
895 LOCAL_CHASSIS(cfg
)->c_med_sw
= strdup("Unknown");
898 /* Set chassis ID if needed. This is only done if chassis ID
899 has not been set previously (with the MAC address of an
900 interface for example)
902 if (LOCAL_CHASSIS(cfg
)->c_id
== NULL
) {
903 if (!(LOCAL_CHASSIS(cfg
)->c_id
= strdup(LOCAL_CHASSIS(cfg
)->c_name
)))
905 LOCAL_CHASSIS(cfg
)->c_id_len
= strlen(LOCAL_CHASSIS(cfg
)->c_name
);
906 LOCAL_CHASSIS(cfg
)->c_id_subtype
= LLDP_CHASSISID_SUBTYPE_LOCAL
;
911 lldpd_update_localports(struct lldpd
*cfg
)
913 struct ifaddrs
*ifap
;
914 struct lldpd_hardware
*hardware
;
915 lldpd_ifhandlers ifhs
[] = {
916 lldpd_ifh_whitelist
, /* Is the interface whitelisted? */
917 lldpd_ifh_bond
, /* Handle bond */
918 lldpd_ifh_eth
, /* Handle classic ethernet interfaces */
920 lldpd_ifh_vlan
, /* Handle VLAN */
922 lldpd_ifh_mgmt
, /* Handle management address (if not already handled) */
923 lldpd_ifh_chassis
, /* Handle chassis ID (if not already handled) */
926 lldpd_ifhandlers
*ifh
;
928 /* h_flags is set to 0 for each port. If the port is updated, h_flags
929 * will be set to a non-zero value. This will allow us to clean up any
930 * non up-to-date port */
931 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
932 hardware
->h_flags
= 0;
934 if (getifaddrs(&ifap
) != 0)
935 fatal("lldpd_update_localports: failed to get interface list");
937 /* We will run the list of interfaces through a list of interface
938 * handlers. Each handler will create or update some hardware port (and
939 * will set h_flags to a non zero value. The handler can use the list of
940 * interfaces but this is not mandatory. If the interface handler
941 * handles an interface from the list, it should set ifa_flags to 0 to
942 * let know the other handlers that it took care of this interface. This
943 * means that more specific handlers should be before less specific
945 for (ifh
= ifhs
; *ifh
!= NULL
; ifh
++)
951 lldpd_loop(struct lldpd
*cfg
)
955 1. Update local ports information
956 2. Clean unwanted (removed) local ports
957 3. Update local chassis information
961 LOCAL_CHASSIS(cfg
)->c_cap_enabled
= 0;
962 lldpd_update_localports(cfg
);
964 lldpd_update_localchassis(cfg
);
969 lldpd_exit(struct lldpd
*cfg
)
971 struct lldpd_hardware
*hardware
, *hardware_next
;
974 for (hardware
= TAILQ_FIRST(&cfg
->g_hardware
); hardware
!= NULL
;
975 hardware
= hardware_next
) {
976 hardware_next
= TAILQ_NEXT(hardware
, h_entries
);
977 lldpd_remote_cleanup(cfg
, hardware
, 1);
978 lldpd_hardware_cleanup(cfg
, hardware
);
982 struct intint
{ int a
; int b
; };
983 static const struct intint filters
[] = {
985 { 1, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
986 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
987 { 2, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
},
988 { 3, SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
989 { 4, SMART_INCOMING_FILTER
| SMART_OUTGOING_FILTER
},
990 { 5, SMART_INCOMING_FILTER
},
991 { 6, SMART_OUTGOING_FILTER
},
992 { 7, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_INCOMING_ONE_NEIGH
|
993 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
994 { 8, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_INCOMING_ONE_NEIGH
},
995 { 9, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
|
996 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
997 { 10, SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
998 { 11, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
},
999 { 12, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
|
1000 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1001 { 13, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_NEIGH
|
1002 SMART_OUTGOING_FILTER
},
1003 { 14, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
1004 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1005 { 15, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
|
1006 SMART_OUTGOING_FILTER
},
1007 { 16, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_INCOMING_ONE_NEIGH
|
1008 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1009 { 17, SMART_INCOMING_FILTER
| SMART_INCOMING_ONE_PROTO
| SMART_INCOMING_ONE_NEIGH
|
1010 SMART_OUTGOING_FILTER
},
1011 { 18, SMART_INCOMING_FILTER
|
1012 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_NEIGH
},
1013 { 19, SMART_INCOMING_FILTER
|
1014 SMART_OUTGOING_FILTER
| SMART_OUTGOING_ONE_PROTO
},
1019 lldpd_main(int argc
, char *argv
[])
1022 struct lldpd_chassis
*lchassis
;
1026 char *agentx
= NULL
; /* AgentX socket */
1030 char *interfaces
= NULL
;
1031 char *popt
, opts
[] =
1032 "H:vhkrdxX:m:4:6:I:C:p:M:P:S:i@ ";
1033 int i
, found
, advertise_version
= 1;
1034 #ifdef ENABLE_LLDPMED
1035 int lldpmed
= 0, noinventory
= 0;
1037 char *descr_override
= NULL
;
1038 char *platform_override
= NULL
;
1039 char *lsb_release
= NULL
;
1041 int receiveonly
= 0;
1044 /* Non privileged user */
1045 struct passwd
*user
;
1046 struct group
*group
;
1053 * Get and parse command line options
1055 popt
= strchr(opts
, '@');
1056 for (i
=0; protos
[i
].mode
!= 0; i
++)
1057 *(popt
++) = protos
[i
].arg
;
1059 while ((ch
= getopt(argc
, argv
, opts
)) != -1) {
1065 fprintf(stdout
, "%s\n", PACKAGE_VERSION
);
1078 interfaces
= optarg
;
1084 advertise_version
= 0;
1086 #ifdef ENABLE_LLDPMED
1088 lldpmed
= atoi(optarg
);
1089 if ((lldpmed
< 1) || (lldpmed
> 4)) {
1090 fprintf(stderr
, "-M requires an argument between 1 and 4\n");
1100 fprintf(stderr
, "LLDP-MED support is not built-in\n");
1115 fprintf(stderr
, "SNMP support is not built-in\n");
1120 descr_override
= strdup(optarg
);
1123 platform_override
= strdup(optarg
);
1126 smart
= atoi(optarg
);
1130 for (i
=0; protos
[i
].mode
!= 0; i
++) {
1131 if (ch
== protos
[i
].arg
) {
1132 protos
[i
].enabled
++;
1133 /* When an argument enable
1134 several protocols, only the
1135 first one can be forced. */
1136 if (found
&& protos
[i
].enabled
> 1)
1137 protos
[i
].enabled
= 1;
1146 /* Set correct smart mode */
1147 for (i
=0; (filters
[i
].a
!= -1) && (filters
[i
].a
!= smart
); i
++);
1148 if (filters
[i
].a
== -1) {
1149 fprintf(stderr
, "Incorrect mode for -H\n");
1152 smart
= filters
[i
].b
;
1154 log_init(debug
, __progname
);
1155 tzset(); /* Get timezone info before chroot */
1157 /* Grab uid and gid to use for priv sep */
1158 if ((user
= getpwnam(PRIVSEP_USER
)) == NULL
)
1159 fatal("no " PRIVSEP_USER
" user for privilege separation");
1161 if ((group
= getgrnam(PRIVSEP_GROUP
)) == NULL
)
1162 fatal("no " PRIVSEP_GROUP
" group for privilege separation");
1163 gid
= group
->gr_gid
;
1165 /* Create and setup socket */
1166 if ((ctl
= ctl_create(LLDPD_CTL_SOCKET
)) == -1) {
1167 LLOG_WARN ("unable to create control socket");
1168 LLOG_WARNX("If another instance is running, please stop it.");
1169 LLOG_WARNX("Otherwise, remove " LLDPD_CTL_SOCKET
);
1170 fatalx("Giving up");
1172 if (chown(LLDPD_CTL_SOCKET
, uid
, gid
) == -1)
1173 LLOG_WARN("unable to chown control socket");
1174 if (chmod(LLDPD_CTL_SOCKET
,
1175 S_IRUSR
| S_IWUSR
| S_IXUSR
|
1176 S_IRGRP
| S_IWGRP
| S_IXGRP
) == -1)
1177 LLOG_WARN("unable to chmod control socket");
1179 /* Detach if needed */
1183 if (daemon(0, 0) != 0)
1184 fatal("failed to detach daemon");
1185 if ((pid
= open(LLDPD_PID_FILE
,
1186 O_TRUNC
| O_CREAT
| O_WRONLY
, 0644)) == -1)
1187 fatal("unable to open pid file " LLDPD_PID_FILE
);
1188 if (asprintf(&spid
, "%d\n", getpid()) == -1)
1189 fatal("unable to create pid file " LLDPD_PID_FILE
);
1190 if (write(pid
, spid
, strlen(spid
)) == -1)
1191 fatal("unable to write pid file " LLDPD_PID_FILE
);
1196 /* Try to read system information from /etc/os-release if possible.
1197 Fall back to lsb_release for compatibility. */
1198 lsb_release
= lldpd_get_os_release();
1200 lsb_release
= lldpd_get_lsb_release();
1203 priv_init(PRIVSEP_CHROOT
, ctl
, uid
, gid
);
1205 /* Initialization of global configuration */
1206 if ((cfg
= (struct lldpd
*)
1207 calloc(1, sizeof(struct lldpd
))) == NULL
)
1211 cfg
->g_mgmt_pattern
= mgmtp
;
1212 cfg
->g_cid_pattern
= cidp
;
1213 cfg
->g_interfaces
= interfaces
;
1214 cfg
->g_smart
= smart
;
1215 cfg
->g_receiveonly
= receiveonly
;
1218 cfg
->g_snmp_agentx
= agentx
;
1219 #endif /* USE_SNMP */
1221 /* Get ioctl socket */
1222 if ((cfg
->g_sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1223 fatal("failed to get ioctl socket");
1224 cfg
->g_delay
= LLDPD_TX_DELAY
;
1227 if (!(cfg
->g_advertise_version
= advertise_version
) && lsb_release
)
1229 lsb_release
[strlen(lsb_release
) - 1] = '\0';
1230 cfg
->g_lsb_release
= lsb_release
;
1232 cfg
->g_descr_override
= descr_override
;
1234 if (platform_override
)
1235 cfg
->g_platform_override
= platform_override
;
1237 /* Set system capabilities */
1238 if ((lchassis
= (struct lldpd_chassis
*)
1239 calloc(1, sizeof(struct lldpd_chassis
))) == NULL
)
1241 lchassis
->c_cap_available
= LLDP_CAP_BRIDGE
| LLDP_CAP_WLAN
|
1243 TAILQ_INIT(&lchassis
->c_mgmt
);
1244 #ifdef ENABLE_LLDPMED
1246 if (lldpmed
== LLDPMED_CLASS_III
)
1247 lchassis
->c_cap_available
|= LLDP_CAP_TELEPHONE
;
1248 lchassis
->c_med_type
= lldpmed
;
1249 lchassis
->c_med_cap_available
= LLDPMED_CAP_CAP
|
1250 LLDPMED_CAP_IV
| LLDPMED_CAP_LOCATION
|
1251 LLDPMED_CAP_POLICY
| LLDPMED_CAP_MDI_PSE
| LLDPMED_CAP_MDI_PD
;
1252 cfg
->g_noinventory
= noinventory
;
1254 cfg
->g_noinventory
= 1;
1258 lchassis
->c_ttl
= LLDPD_TTL
;
1260 cfg
->g_protocols
= protos
;
1261 for (i
=0; protos
[i
].mode
!= 0; i
++)
1262 if (protos
[i
].enabled
> 1)
1263 LLOG_INFO("protocol %s enabled and forced", protos
[i
].name
);
1264 else if (protos
[i
].enabled
)
1265 LLOG_INFO("protocol %s enabled", protos
[i
].name
);
1267 LLOG_INFO("protocol %s disabled", protos
[i
].name
);
1269 TAILQ_INIT(&cfg
->g_hardware
);
1270 TAILQ_INIT(&cfg
->g_chassis
);
1271 TAILQ_INSERT_TAIL(&cfg
->g_chassis
, lchassis
, c_entries
);
1272 lchassis
->c_refcount
++; /* We should always keep a reference to local chassis */