2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 * Permission to use, copy, modify, and 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>
30 #include <sys/socket.h>
31 #include <sys/select.h>
33 #include <sys/ioctl.h>
34 #include <arpa/inet.h>
36 #include <net/if_arp.h>
37 #include <linux/filter.h>
38 #include <linux/if_vlan.h>
39 #include <linux/if_packet.h>
40 #include <linux/sockios.h>
43 #include <net-snmp/net-snmp-config.h>
44 #include <net-snmp/net-snmp-includes.h>
45 #include <net-snmp/agent/net-snmp-agent-includes.h>
46 #include <net-snmp/agent/snmp_vars.h>
49 static void usage(void);
51 static int lldpd_iface_init(struct lldpd
*, struct lldpd_hardware
*);
52 static int lldpd_iface_init_vlan(struct lldpd
*, struct lldpd_vif
*);
53 static void lldpd_iface_init_mtu(struct lldpd
*, struct lldpd_hardware
*);
54 static int lldpd_iface_close(struct lldpd
*, struct lldpd_hardware
*);
55 static void lldpd_iface_multicast(struct lldpd
*, const char *, int);
57 /* "ether proto 0x88cc and ether dst 01:80:c2:00:00:0e" */
58 #define LLDPD_FILTER_LLDP_F \
59 { 0x28, 0, 0, 0x0000000c }, \
60 { 0x15, 0, 5, 0x000088cc }, \
61 { 0x20, 0, 0, 0x00000002 }, \
62 { 0x15, 0, 3, 0xc200000e }, \
63 { 0x28, 0, 0, 0x00000000 }, \
64 { 0x15, 0, 1, 0x00000180 }, \
65 { 0x6, 0, 0, 0x0000ffff }, \
66 { 0x6, 0, 0, 0x00000000 },
67 static struct sock_filter lldpd_filter_lldp_f
[] = { LLDPD_FILTER_LLDP_F
};
69 /* "ether dst 01:e0:52:cc:cc:cc" */
70 #define LLDPD_FILTER_FDP_F \
71 { 0x20, 0, 0, 0x00000002 }, \
72 { 0x15, 0, 3, 0x52cccccc }, \
73 { 0x28, 0, 0, 0x00000000 }, \
74 { 0x15, 0, 1, 0x000001e0 }, \
75 { 0x6, 0, 0, 0x0000ffff }, \
76 { 0x6, 0, 0, 0x00000000 },
77 static struct sock_filter lldpd_filter_fdp_f
[] = { LLDPD_FILTER_FDP_F
};
78 #endif /* ENABLE_FDP */
80 /* "ether dst 01:00:0c:cc:cc:cc" */
81 #define LLDPD_FILTER_CDP_F \
82 { 0x20, 0, 0, 0x00000002 }, \
83 { 0x15, 0, 3, 0x0ccccccc }, \
84 { 0x28, 0, 0, 0x00000000 }, \
85 { 0x15, 0, 1, 0x00000100 }, \
86 { 0x6, 0, 0, 0x0000ffff }, \
87 { 0x6, 0, 0, 0x00000000 },
88 static struct sock_filter lldpd_filter_cdp_f
[] = { LLDPD_FILTER_CDP_F
};
89 #endif /* ENABLE_CDP */
91 /* "ether dst 01:00:81:00:01:00" */
92 #define LLDPD_FILTER_SONMP_F \
93 { 0x20, 0, 0, 0x00000002 }, \
94 { 0x15, 0, 3, 0x81000100 }, \
95 { 0x28, 0, 0, 0x00000000 }, \
96 { 0x15, 0, 1, 0x00000100 }, \
97 { 0x6, 0, 0, 0x0000ffff }, \
98 { 0x6, 0, 0, 0x00000000 },
99 static struct sock_filter lldpd_filter_sonmp_f
[] = { LLDPD_FILTER_SONMP_F
};
100 #endif /* ENABLE_SONMP */
102 /* "ether dst 00:e0:2b:00:00:00" */
103 #define LLDPD_FILTER_EDP_F \
104 { 0x20, 0, 0, 0x00000002 }, \
105 { 0x15, 0, 3, 0x2b000000 }, \
106 { 0x28, 0, 0, 0x00000000 }, \
107 { 0x15, 0, 1, 0x000000e0 }, \
108 { 0x6, 0, 0, 0x0000ffff }, \
109 { 0x6, 0, 0, 0x00000000 },
110 static struct sock_filter lldpd_filter_edp_f
[] = { LLDPD_FILTER_EDP_F
};
111 #endif /* ENABLE_EDP */
112 #define LLDPD_FILTER_ANY_F \
113 { 0x28, 0, 0, 0x0000000c }, \
114 { 0x15, 0, 4, 0x000088cc }, \
115 { 0x20, 0, 0, 0x00000002 }, \
116 { 0x15, 0, 2, 0xc200000e }, \
117 { 0x28, 0, 0, 0x00000000 }, \
118 { 0x15, 11, 12, 0x00000180 }, \
119 { 0x20, 0, 0, 0x00000002 }, \
120 { 0x15, 0, 2, 0x2b000000 }, \
121 { 0x28, 0, 0, 0x00000000 }, \
122 { 0x15, 7, 8, 0x000000e0 }, \
123 { 0x15, 1, 0, 0x0ccccccc }, \
124 { 0x15, 0, 2, 0x81000100 }, \
125 { 0x28, 0, 0, 0x00000000 }, \
126 { 0x15, 3, 4, 0x00000100 }, \
127 { 0x15, 0, 3, 0x52cccccc }, \
128 { 0x28, 0, 0, 0x00000000 }, \
129 { 0x15, 0, 1, 0x000001e0 }, \
130 { 0x6, 0, 0, 0x0000ffff }, \
131 { 0x6, 0, 0, 0x00000000 },
132 static struct sock_filter lldpd_filter_any_f
[] = { LLDPD_FILTER_ANY_F
};
134 static struct protocol protos
[] =
136 { LLDPD_MODE_LLDP
, 1, "LLDP", ' ', lldp_send
, lldp_decode
, NULL
,
137 LLDP_MULTICAST_ADDR
, lldpd_filter_lldp_f
, sizeof(lldpd_filter_lldp_f
) },
139 { LLDPD_MODE_CDPV1
, 0, "CDPv1", 'c', cdpv1_send
, cdp_decode
, cdpv1_guess
,
140 CDP_MULTICAST_ADDR
, lldpd_filter_cdp_f
, sizeof(lldpd_filter_cdp_f
) },
141 { LLDPD_MODE_CDPV2
, 0, "CDPv2", 'c', cdpv2_send
, cdp_decode
, cdpv2_guess
,
142 CDP_MULTICAST_ADDR
, lldpd_filter_cdp_f
, sizeof(lldpd_filter_cdp_f
) },
145 { LLDPD_MODE_SONMP
, 0, "SONMP", 's', sonmp_send
, sonmp_decode
, NULL
,
146 SONMP_MULTICAST_ADDR
, lldpd_filter_sonmp_f
, sizeof(lldpd_filter_sonmp_f
) },
149 { LLDPD_MODE_EDP
, 0, "EDP", 'e', edp_send
, edp_decode
, NULL
,
150 EDP_MULTICAST_ADDR
, lldpd_filter_edp_f
, sizeof(lldpd_filter_edp_f
) },
153 { LLDPD_MODE_FDP
, 0, "FDP", 'f', fdp_send
, cdp_decode
, NULL
,
154 FDP_MULTICAST_ADDR
, lldpd_filter_fdp_f
, sizeof(lldpd_filter_fdp_f
) },
156 { 0, 0, "any", ' ', NULL
, NULL
, NULL
,
157 {0,0,0,0,0,0}, lldpd_filter_any_f
, sizeof(lldpd_filter_any_f
) }
160 static int lldpd_iface_switchto(struct lldpd
*, short int,
161 struct lldpd_hardware
*);
163 struct lldpd_hardware
*lldpd_port_add(struct lldpd
*, struct ifaddrs
*);
164 static void lldpd_loop(struct lldpd
*);
165 static void lldpd_shutdown(int);
166 static void lldpd_exit();
167 static void lldpd_send_all(struct lldpd
*);
168 static void lldpd_recv_all(struct lldpd
*);
169 static int lldpd_guess_type(struct lldpd
*, char *, int);
170 static void lldpd_decode(struct lldpd
*, char *, int,
171 struct lldpd_hardware
*, int);
172 #ifdef ENABLE_LLDPMED
173 static void lldpd_med(struct lldpd_chassis
*);
176 static char **saved_argv
;
181 extern const char *__progname
;
182 fprintf(stderr
, "usage: %s [options]\n", __progname
);
183 fprintf(stderr
, "see manual page lldpd(8) for more information\n");
188 lldpd_iface_init_mtu(struct lldpd
*global
, struct lldpd_hardware
*hardware
)
193 memset(&ifr
, 0, sizeof(ifr
));
194 strlcpy(ifr
.ifr_name
, hardware
->h_ifname
, sizeof(ifr
.ifr_name
));
195 if (ioctl(global
->g_sock
, SIOCGIFMTU
, (char*)&ifr
) == -1) {
196 LLOG_WARN("unable to get MTU of %s, using 1500", hardware
->h_ifname
);
197 hardware
->h_mtu
= 1500;
199 hardware
->h_mtu
= hardware
->h_lport
.p_mfs
= ifr
.ifr_mtu
;
203 lldpd_iface_init_vlan(struct lldpd
*global
, struct lldpd_vif
*vif
)
208 lldpd_iface_init_mtu(global
, (struct lldpd_hardware
*)vif
);
209 status
= priv_iface_init((struct lldpd_hardware
*)vif
, -1);
214 filter
= LLDPD_MODE_ANY
;
216 filter
= LLDPD_MODE_LLDP
;
218 if (lldpd_iface_switchto(global
, filter
,
219 (struct lldpd_hardware
*)vif
) == -1) {
220 LLOG_WARNX("unable to apply filter");
224 lldpd_iface_multicast(global
, vif
->vif_ifname
, 0);
226 LLOG_DEBUG("vlan interface %s initialized (fd=%d)", vif
->vif_ifname
,
232 lldpd_iface_init(struct lldpd
*global
, struct lldpd_hardware
*hardware
)
234 int master
; /* Bond device */
235 char if_bond
[IFNAMSIZ
];
239 lldpd_iface_init_mtu(global
, hardware
);
240 status
= priv_iface_init(hardware
, -1);
244 if ((master
= iface_is_enslaved(global
, hardware
->h_ifname
)) != -1) {
245 /* With bonding device, we need to listen on the bond ! */
246 if (if_indextoname(master
, if_bond
) == NULL
) {
247 LLOG_WARN("unable to get index for interface %d (master of %s)",
248 master
, hardware
->h_ifname
);
251 hardware
->h_raw_real
= hardware
->h_raw
;
252 hardware
->h_master
= master
;
253 hardware
->h_raw
= -1;
254 status
= priv_iface_init(hardware
, master
);
256 close(hardware
->h_raw_real
);
257 if (hardware
->h_raw
!= -1)
258 close(hardware
->h_raw
);
264 filter
= LLDPD_MODE_ANY
;
266 filter
= LLDPD_MODE_LLDP
;
267 if (lldpd_iface_switchto(global
, filter
, hardware
) == -1) {
268 LLOG_WARNX("unable to apply filter");
273 lldpd_iface_multicast(global
, if_bond
, 0);
274 lldpd_iface_multicast(global
, hardware
->h_ifname
, 0);
276 LLOG_DEBUG("interface %s initialized (fd=%d)", hardware
->h_ifname
,
282 lldpd_iface_multicast(struct lldpd
*global
, const char *name
, int remove
)
286 for (i
=0; global
->g_protocols
[i
].mode
!= 0; i
++) {
287 if (!global
->g_protocols
[i
].enabled
) continue;
288 if ((rc
= priv_iface_multicast(name
,
289 global
->g_protocols
[i
].mac
, !remove
)) != 0) {
292 LLOG_INFO("unable to %s %s address to multicast filter for %s",
293 (remove
)?"delete":"add",
294 global
->g_protocols
[i
].name
,
301 lldpd_iface_close(struct lldpd
*global
, struct lldpd_hardware
*hardware
)
303 char listen
[IFNAMSIZ
];
305 close(hardware
->h_raw
);
306 hardware
->h_raw
= -1;
308 if (hardware
->h_raw_real
> 0) {
309 if (if_indextoname(hardware
->h_master
, listen
) == NULL
) {
310 LLOG_WARN("unable to get index for interface %d",
312 strlcpy(listen
, hardware
->h_ifname
, sizeof(listen
));
314 close(hardware
->h_raw_real
);
315 lldpd_iface_multicast(global
, listen
, 1);
317 memcpy(listen
, hardware
->h_ifname
, IFNAMSIZ
);
318 lldpd_iface_multicast(global
, listen
, 1);
320 hardware
->h_raw_real
= -1;
325 lldpd_iface_switchto(struct lldpd
*cfg
, short int filter
, struct lldpd_hardware
*hardware
)
327 struct sock_fprog prog
;
330 memset(&prog
, 0, sizeof(prog
));
331 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
332 if (!cfg
->g_protocols
[i
].enabled
) continue;
333 if (cfg
->g_protocols
[i
].mode
== filter
)
336 prog
.filter
= cfg
->g_protocols
[i
].filter
;
337 prog
.len
= cfg
->g_protocols
[i
].filterlen
/ sizeof(struct sock_filter
);
338 if (setsockopt(hardware
->h_raw
, SOL_SOCKET
, SO_ATTACH_FILTER
,
339 &prog
, sizeof(prog
)) < 0) {
340 LLOG_WARN("unable to change filter for %s", hardware
->h_ifname
);
343 if ((hardware
->h_raw_real
> 0) &&
344 (setsockopt(hardware
->h_raw_real
, SOL_SOCKET
, SO_ATTACH_FILTER
,
345 &prog
, sizeof(prog
)) < 0)) {
346 LLOG_WARN("unable to change filter for real device %s", hardware
->h_ifname
);
354 lldpd_vlan_cleanup(struct lldpd_port
*port
)
356 struct lldpd_vlan
*vlan
, *vlan_next
;
357 for (vlan
= TAILQ_FIRST(&port
->p_vlans
);
361 vlan_next
= TAILQ_NEXT(vlan
, v_entries
);
362 TAILQ_REMOVE(&port
->p_vlans
, vlan
, v_entries
);
368 /* If `all' is true, clear all information, including information that
369 are not refreshed periodically. If `all' is true, also free the
372 lldpd_port_cleanup(struct lldpd_port
*port
, int all
)
374 #ifdef ENABLE_LLDPMED
377 for (i
=0; i
< LLDPMED_LOCFORMAT_LAST
; i
++)
378 free(port
->p_med_location
[i
].data
);
381 lldpd_vlan_cleanup(port
);
390 lldpd_chassis_cleanup(struct lldpd_chassis
*chassis
)
392 #ifdef ENABLE_LLDPMED
393 free(chassis
->c_med_hw
);
394 free(chassis
->c_med_sw
);
395 free(chassis
->c_med_fw
);
396 free(chassis
->c_med_sn
);
397 free(chassis
->c_med_manuf
);
398 free(chassis
->c_med_model
);
399 free(chassis
->c_med_asset
);
402 free(chassis
->c_name
);
403 free(chassis
->c_descr
);
408 lldpd_remote_cleanup(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
, int reset
)
410 if (hardware
->h_rport
!= NULL
) {
411 lldpd_port_cleanup(hardware
->h_rport
, 1);
412 hardware
->h_rport
= NULL
;
414 if (hardware
->h_rchassis
!= NULL
) {
415 lldpd_chassis_cleanup(hardware
->h_rchassis
);
416 hardware
->h_rchassis
= NULL
;
418 hardware
->h_rlastchange
= hardware
->h_rlastupdate
= 0;
419 free(hardware
->h_rlastframe
);
420 hardware
->h_rlastframe
= NULL
;
421 if (reset
&& cfg
->g_multi
) {
422 hardware
->h_mode
= LLDPD_MODE_ANY
;
423 memset(hardware
->h_proto_macs
, 0, ETH_ALEN
*(cfg
->g_multi
+1));
424 hardware
->h_start_probe
= 0;
425 lldpd_iface_switchto(cfg
, LLDPD_MODE_ANY
, hardware
);
430 lldpd_hardware_cleanup(struct lldpd_hardware
*hardware
)
432 lldpd_port_cleanup(&hardware
->h_lport
, 1);
433 free(hardware
->h_proto_macs
);
434 free(hardware
->h_llastframe
);
439 lldpd_cleanup(struct lldpd
*cfg
)
441 struct lldpd_hardware
*hardware
, *hardware_next
;
442 struct lldpd_vif
*vif
, *vif_next
;
444 for (hardware
= TAILQ_FIRST(&cfg
->g_hardware
); hardware
!= NULL
;
445 hardware
= hardware_next
) {
446 hardware_next
= TAILQ_NEXT(hardware
, h_entries
);
447 if (hardware
->h_flags
== 0) {
448 TAILQ_REMOVE(&cfg
->g_hardware
, hardware
, h_entries
);
449 lldpd_iface_close(cfg
, hardware
);
450 lldpd_remote_cleanup(cfg
, hardware
, 0);
451 lldpd_hardware_cleanup(hardware
);
452 } else if (hardware
->h_rchassis
!= NULL
) {
453 if (time(NULL
) - hardware
->h_rlastupdate
>
454 hardware
->h_rchassis
->c_ttl
) {
455 lldpd_remote_cleanup(cfg
, hardware
, 1);
456 hardware
->h_rx_ageout_cnt
++;
460 for (vif
= TAILQ_FIRST(&cfg
->g_vif
); vif
!= NULL
;
462 vif_next
= TAILQ_NEXT(vif
, vif_entries
);
463 if (vif
->vif_flags
== 0) {
464 TAILQ_REMOVE(&cfg
->g_vif
, vif
, vif_entries
);
465 lldpd_iface_close(cfg
, (struct lldpd_hardware
*)vif
);
471 static struct lldpd_vif
*
472 lldpd_port_add_vlan(struct lldpd
*cfg
, struct ifaddrs
*ifa
)
474 struct lldpd_vif
*vif
;
475 struct lldpd_hardware
*hardware
;
476 struct vlan_ioctl_args ifv
;
478 TAILQ_FOREACH(vif
, &cfg
->g_vif
, vif_entries
) {
479 if (strcmp(vif
->vif_ifname
, ifa
->ifa_name
) == 0)
484 if ((vif
= (struct lldpd_vif
*)
485 calloc(1, sizeof(struct lldpd_vif
))) == NULL
)
488 vif
->vif_raw_real
= -1;
490 strlcpy(vif
->vif_ifname
, ifa
->ifa_name
, sizeof(vif
->vif_ifname
));
491 vif
->vif_flags
= ifa
->ifa_flags
;
493 if (vif
->vif_raw
== -1) {
495 if (lldpd_iface_init_vlan(cfg
, vif
) != 0) {
500 /* Find the real interface */
501 vif
->vif_real
= NULL
;
502 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
503 memset(&ifv
, 0, sizeof(ifv
));
504 ifv
.cmd
= GET_VLAN_REALDEV_NAME_CMD
;
505 strlcpy(ifv
.device1
, ifa
->ifa_name
, sizeof(ifv
.device1
));
506 if ((ioctl(cfg
->g_sock
, SIOCGIFVLAN
, &ifv
) >= 0) &&
507 (strncmp(hardware
->h_ifname
,
509 sizeof(ifv
.u
.device2
)) == 0))
510 vif
->vif_real
= hardware
;
512 if (vif
->vif_real
== NULL
) {
513 LLOG_WARNX("unable to find real interface for %s",
519 TAILQ_INSERT_TAIL(&cfg
->g_vif
, vif
, vif_entries
);
525 static struct lldpd_hardware
*
526 lldpd_port_add(struct lldpd
*cfg
, struct ifaddrs
*ifa
)
528 #if defined (ENABLE_DOT1) || defined (ENABLE_DOT3)
529 struct ifaddrs
*oifap
, *oifa
;
531 struct lldpd_hardware
*hardware
;
532 struct lldpd_port
*port
;
534 struct lldpd_vlan
*vlan
;
535 struct vlan_ioctl_args ifv
;
538 struct ethtool_cmd ethc
;
542 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
543 if (strcmp(hardware
->h_ifname
, ifa
->ifa_name
) == 0)
547 if (hardware
== NULL
) {
548 if ((hardware
= (struct lldpd_hardware
*)
549 calloc(1, sizeof(struct lldpd_hardware
))) == NULL
)
551 hardware
->h_raw
= -1;
552 hardware
->h_raw_real
= -1;
553 hardware
->h_start_probe
= 0;
554 hardware
->h_proto_macs
= (u_int8_t
*)calloc(cfg
->g_multi
+1, ETH_ALEN
);
555 #ifdef ENABLE_LLDPMED
556 hardware
->h_lport
.p_med_cap_enabled
= LLDPMED_CAP_CAP
;
557 if (!cfg
->g_noinventory
)
558 hardware
->h_lport
.p_med_cap_enabled
|= LLDPMED_CAP_IV
;
561 TAILQ_INIT(&hardware
->h_lport
.p_vlans
);
563 lldpd_port_cleanup(&hardware
->h_lport
, 0);
567 port
= &hardware
->h_lport
;
568 hardware
->h_flags
= ifa
->ifa_flags
;
570 strlcpy(hardware
->h_ifname
, ifa
->ifa_name
, sizeof(hardware
->h_ifname
));
571 lladdr
= (u_int8_t
*)(((struct sockaddr_ll
*)ifa
->ifa_addr
)->sll_addr
);
572 memcpy(&hardware
->h_lladdr
, lladdr
, sizeof(hardware
->h_lladdr
));
573 iface_get_permanent_mac(cfg
, hardware
);
574 port
->p_id_subtype
= LLDP_PORTID_SUBTYPE_LLADDR
;
575 if ((port
->p_id
= calloc(1, sizeof(hardware
->h_lladdr
))) == NULL
)
577 memcpy(port
->p_id
, hardware
->h_lladdr
, sizeof(hardware
->h_lladdr
));
578 port
->p_id_len
= sizeof(hardware
->h_lladdr
);
579 port
->p_descr
= strdup(hardware
->h_ifname
);
581 if (cfg
->g_lchassis
.c_id
== NULL
) {
582 /* Use the first port's l2 addr as the chassis ID */
583 if ((cfg
->g_lchassis
.c_id
= malloc(sizeof(hardware
->h_lladdr
))) == NULL
)
585 cfg
->g_lchassis
.c_id_subtype
= LLDP_CHASSISID_SUBTYPE_LLADDR
;
586 cfg
->g_lchassis
.c_id_len
= sizeof(hardware
->h_lladdr
);
587 memcpy(cfg
->g_lchassis
.c_id
,
588 hardware
->h_lladdr
, sizeof(hardware
->h_lladdr
));
591 /* Get VLANS and aggregation status */
592 #if defined (ENABLE_DOT3) || defined (ENABLE_DOT1)
593 if (getifaddrs(&oifap
) != 0)
594 fatal("lldpd_port_add: failed to get interface list");
595 for (oifa
= oifap
; oifa
!= NULL
; oifa
= oifa
->ifa_next
) {
597 /* Check if we already have checked this one */
599 TAILQ_FOREACH(vlan
, &port
->p_vlans
, v_entries
) {
600 if (strcmp(vlan
->v_name
, oifa
->ifa_name
) == 0) {
608 /* Aggregation check */
610 if (iface_is_bond_slave(cfg
, hardware
->h_ifname
, oifa
->ifa_name
, NULL
))
611 port
->p_aggregid
= if_nametoindex(oifa
->ifa_name
);
616 memset(&ifv
, 0, sizeof(ifv
));
617 ifv
.cmd
= GET_VLAN_REALDEV_NAME_CMD
;
618 strlcpy(ifv
.device1
, oifa
->ifa_name
, sizeof(ifv
.device1
));
619 if ((ioctl(cfg
->g_sock
, SIOCGIFVLAN
, &ifv
) >= 0) &&
620 ((iface_is_bond_slave(cfg
, hardware
->h_ifname
, ifv
.u
.device2
, NULL
)) ||
621 (iface_is_bridged_to(cfg
, hardware
->h_ifname
, ifv
.u
.device2
)) ||
622 (strncmp(hardware
->h_ifname
, ifv
.u
.device2
, sizeof(ifv
.u
.device2
)) == 0))) {
623 if ((vlan
= (struct lldpd_vlan
*)
624 calloc(1, sizeof(struct lldpd_vlan
))) == NULL
)
626 if ((vlan
->v_name
= strdup(oifa
->ifa_name
)) == NULL
) {
630 memset(&ifv
, 0, sizeof(ifv
));
631 ifv
.cmd
= GET_VLAN_VID_CMD
;
632 strlcpy(ifv
.device1
, oifa
->ifa_name
, sizeof(ifv
.device1
));
633 if (ioctl(cfg
->g_sock
, SIOCGIFVLAN
, &ifv
) < 0) {
634 /* Dunno what happened */
638 vlan
->v_vid
= ifv
.u
.VID
;
639 TAILQ_INSERT_TAIL(&port
->p_vlans
, vlan
, v_entries
);
649 if (priv_ethtool(hardware
->h_ifname
, ðc
) == 0) {
651 int advertised_ethtool_to_rfc3636
[][2] = {
652 {ADVERTISED_10baseT_Half
, LLDP_DOT3_LINK_AUTONEG_10BASE_T
},
653 {ADVERTISED_10baseT_Full
, LLDP_DOT3_LINK_AUTONEG_10BASET_FD
},
654 {ADVERTISED_100baseT_Half
, LLDP_DOT3_LINK_AUTONEG_100BASE_TX
},
655 {ADVERTISED_100baseT_Full
, LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD
},
656 {ADVERTISED_1000baseT_Half
, LLDP_DOT3_LINK_AUTONEG_1000BASE_T
},
657 {ADVERTISED_1000baseT_Full
, LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD
},
658 {ADVERTISED_10000baseT_Full
, LLDP_DOT3_LINK_AUTONEG_OTHER
},
659 {ADVERTISED_Pause
, LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE
},
660 {ADVERTISED_Asym_Pause
, LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE
},
661 {ADVERTISED_2500baseX_Full
, LLDP_DOT3_LINK_AUTONEG_OTHER
},
664 port
->p_autoneg_support
= (ethc
.supported
& SUPPORTED_Autoneg
) ? 1 : 0;
665 port
->p_autoneg_enabled
= (ethc
.autoneg
== AUTONEG_DISABLE
) ? 0 : 1;
666 for (j
=0; advertised_ethtool_to_rfc3636
[j
][0]; j
++) {
667 if (ethc
.advertising
& advertised_ethtool_to_rfc3636
[j
][0])
668 port
->p_autoneg_advertised
|= advertised_ethtool_to_rfc3636
[j
][1];
670 switch (ethc
.speed
) {
672 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
673 LLDP_DOT3_MAU_10BASETFD
: LLDP_DOT3_MAU_10BASETHD
;
674 if (ethc
.port
== PORT_BNC
) port
->p_mau_type
= LLDP_DOT3_MAU_10BASE2
;
675 if (ethc
.port
== PORT_FIBRE
)
676 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
677 LLDP_DOT3_MAU_10BASEFLDF
: LLDP_DOT3_MAU_10BASEFLHD
;
680 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
681 LLDP_DOT3_MAU_100BASETXFD
: LLDP_DOT3_MAU_100BASETXHD
;
682 if (ethc
.port
== PORT_BNC
)
683 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
684 LLDP_DOT3_MAU_100BASET2DF
: LLDP_DOT3_MAU_100BASET2HD
;
685 if (ethc
.port
== PORT_FIBRE
)
686 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
687 LLDP_DOT3_MAU_100BASEFXFD
: LLDP_DOT3_MAU_100BASEFXHD
;
690 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
691 LLDP_DOT3_MAU_1000BASETFD
: LLDP_DOT3_MAU_1000BASETHD
;
692 if (ethc
.port
== PORT_FIBRE
)
693 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
694 LLDP_DOT3_MAU_1000BASEXFD
: LLDP_DOT3_MAU_1000BASEXHD
;
697 port
->p_mau_type
= (ethc
.port
== PORT_FIBRE
) ? \
698 LLDP_DOT3_MAU_10GIGBASEX
: LLDP_DOT3_MAU_10GIGBASER
;
701 if (ethc
.port
== PORT_AUI
) port
->p_mau_type
= LLDP_DOT3_MAU_AUI
;
703 LLOG_DEBUG("unable to get eth info for %s", hardware
->h_ifname
);
706 if (!INTERFACE_OPENED(hardware
)) {
708 if (lldpd_iface_init(cfg
, hardware
) != 0) {
709 LLOG_WARN("unable to initialize %s", hardware
->h_ifname
);
710 lldpd_hardware_cleanup(hardware
);
714 TAILQ_INSERT_TAIL(&cfg
->g_hardware
, hardware
, h_entries
);
721 lldpd_guess_type(struct lldpd
*cfg
, char *frame
, int s
)
726 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
727 if (!cfg
->g_protocols
[i
].enabled
)
729 if (cfg
->g_protocols
[i
].guess
== NULL
) {
730 if (memcmp(frame
, cfg
->g_protocols
[i
].mac
, ETH_ALEN
) == 0)
731 return cfg
->g_protocols
[i
].mode
;
733 if (cfg
->g_protocols
[i
].guess(frame
, s
))
734 return cfg
->g_protocols
[i
].mode
;
741 lldpd_decode(struct lldpd
*cfg
, char *frame
, int s
,
742 struct lldpd_hardware
*hardware
, int bond
)
744 int result
= 0, i
, j
, candidatetonull
;
745 u_int8_t nullmac
[ETH_ALEN
] = {0,0,0,0,0,0};
746 u_int8_t broadcastmac
[ETH_ALEN
] = {0xff,0xff,0xff,0xff,0xff,0xff};
747 struct lldpd_chassis
*chassis
;
748 struct lldpd_port
*port
;
749 struct lldpd_hardware
*ohardware
, *firstnull
= NULL
, *older
= NULL
;
750 int guess
= LLDPD_MODE_LLDP
;
752 /* Discard VLAN frames */
753 if ((s
>= sizeof(struct ethhdr
)) &&
754 (((struct ethhdr
*)frame
)->h_proto
== htons(ETHERTYPE_VLAN
)))
757 if ((hardware
->h_rlastframe
!= NULL
) &&
758 (hardware
->h_rlastframe
->size
== s
) &&
759 (memcmp(hardware
->h_rlastframe
->frame
, frame
, s
) == 0)) {
760 /* Already received the same frame */
761 hardware
->h_rlastupdate
= time(NULL
);
766 if (hardware
->h_mode
== LLDPD_MODE_ANY
)
767 guess
= lldpd_guess_type(cfg
, frame
, s
);
769 guess
= hardware
->h_mode
;
770 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
771 if (!cfg
->g_protocols
[i
].enabled
)
773 if (cfg
->g_protocols
[i
].mode
== guess
) {
774 if ((result
= cfg
->g_protocols
[i
].decode(cfg
, frame
,
775 s
, hardware
, &chassis
, &port
)) == -1)
780 if (cfg
->g_protocols
[i
].mode
== 0) {
781 LLOG_INFO("unable to guess frame type");
784 } else if (cfg
->g_protocols
[0].decode(cfg
, frame
, s
, hardware
,
785 &chassis
, &port
) == -1)
786 /* Nothing has been received */
790 /* Eh, wait ! The frame we just received was for a bonding
791 * device. We need to attach it to a real device. What is the
792 * best candidate? Drum rolling... */
793 TAILQ_FOREACH(ohardware
, &cfg
->g_hardware
, h_entries
) {
794 if (ohardware
->h_master
== hardware
->h_master
) {
796 if (ohardware
->h_rchassis
== NULL
) {
799 (ohardware
->h_mode
== LLDPD_MODE_ANY
)) {
801 cfg
->g_protocols
[i
].mode
!= 0;
803 if (!cfg
->g_protocols
[i
].enabled
)
805 if ((cfg
->g_protocols
[i
].mode
== guess
) &&
806 (memcmp(frame
+ ETH_ALEN
,
807 ohardware
->h_proto_macs
+ ETH_ALEN
*j
,
809 hardware
= ohardware
;
816 if (firstnull
!= NULL
) {
818 cfg
->g_protocols
[i
].mode
!= 0;
820 if (!cfg
->g_protocols
[i
].enabled
)
822 if ((cfg
->g_protocols
[i
].mode
== guess
) &&
824 ohardware
->h_proto_macs
+
837 /* Ok, this is the first candidate if we
838 * don't find a matching chassis/port */
839 if (candidatetonull
) firstnull
= ohardware
;
842 if ((older
== NULL
) ||
843 (older
->h_rlastupdate
> ohardware
->h_rlastupdate
))
844 /* If there is no matching chassis/port
845 * and no free hardware, we will use
848 if ((chassis
->c_id_subtype
!=
849 ohardware
->h_rchassis
->c_id_subtype
) ||
850 (chassis
->c_id_len
!= ohardware
->h_rchassis
->c_id_len
) ||
851 (memcmp(chassis
->c_id
, ohardware
->h_rchassis
->c_id
,
852 chassis
->c_id_len
) != 0) ||
853 (port
->p_id_subtype
!= ohardware
->h_rport
->p_id_subtype
) ||
854 (port
->p_id_len
!= ohardware
->h_rport
->p_id_len
) ||
855 (memcmp(port
->p_id
, ohardware
->h_rport
->p_id
,
856 port
->p_id_len
) != 0))
858 /* We got a match! */
859 hardware
= ohardware
; /* We switch hardware */
866 if (firstnull
!= NULL
)
867 hardware
= firstnull
;
868 else hardware
= older
;
873 (hardware
->h_mode
== LLDPD_MODE_ANY
)) {
878 for (i
=j
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
879 if (!cfg
->g_protocols
[i
].enabled
)
881 if (cfg
->g_protocols
[i
].mode
== guess
) {
882 mac
= hardware
->h_proto_macs
+ ETH_ALEN
*j
;
883 modename
= cfg
->g_protocols
[i
].name
;
884 filter
= cfg
->g_protocols
[i
].mode
;
889 if (cfg
->g_protocols
[i
].mode
== 0) {
890 LLOG_WARNX("should not be there");
894 if (hardware
->h_start_probe
== 0)
895 hardware
->h_start_probe
= time(NULL
) - 1;
896 /* Handle switching respecting probe time */
897 if ((memcmp(mac
, frame
+ ETH_ALEN
, ETH_ALEN
) == 0) &&
898 ((time(NULL
) - hardware
->h_start_probe
) > cfg
->g_probe_time
) &&
899 /* Don't switch to this protocol if not LLDP and LLDP is
900 * a valid candidate */
901 ((filter
== LLDPD_MODE_LLDP
) ||
902 (memcmp(hardware
->h_proto_macs
,
903 broadcastmac
, ETH_ALEN
) == 0) ||
904 (memcmp(hardware
->h_proto_macs
,
905 nullmac
, ETH_ALEN
) == 0))) {
906 LLOG_INFO("switching to %s on port %s", modename
,
908 hardware
->h_mode
= guess
;
909 lldpd_iface_switchto(cfg
, filter
, hardware
);
911 /* Wait twice probe time to be able to receive packets of all kind */
912 if ((time(NULL
) - hardware
->h_start_probe
) > cfg
->g_probe_time
* 2) {
913 LLOG_DEBUG("probe expired on %s, retry", hardware
->h_ifname
);
914 hardware
->h_start_probe
= 0;
915 memset(hardware
->h_proto_macs
, 0, ETH_ALEN
*(cfg
->g_multi
+1));
918 if (memcmp(mac
, broadcastmac
, ETH_ALEN
) == 0)
920 LLOG_INFO("received a %s frame on %s but wait for %d sec",
921 modename
, hardware
->h_ifname
, cfg
->g_probe_time
- time(NULL
) +
922 hardware
->h_start_probe
);
923 if (memcmp(mac
, frame
+ ETH_ALEN
, ETH_ALEN
) == 0)
925 if (memcmp(mac
, nullmac
, ETH_ALEN
) == 0) {
926 memcpy(mac
, frame
+ ETH_ALEN
, ETH_ALEN
);
929 LLOG_INFO("several MAC for %s on %s, discarding %s for this interface",
930 modename
, hardware
->h_ifname
, modename
);
931 memcpy(mac
, broadcastmac
, ETH_ALEN
);
937 if ((hardware
->h_rchassis
== NULL
) ||
938 (chassis
->c_id_subtype
!= hardware
->h_rchassis
->c_id_subtype
) ||
939 (chassis
->c_id_len
!= hardware
->h_rchassis
->c_id_len
) ||
940 (memcmp(chassis
->c_id
, hardware
->h_rchassis
->c_id
,
941 chassis
->c_id_len
) != 0))
944 /* We have our new frame */
945 lldpd_remote_cleanup(cfg
, hardware
, 0);
946 hardware
->h_rport
= port
;
947 hardware
->h_rchassis
= chassis
;
948 hardware
->h_rlastchange
= hardware
->h_rlastupdate
= time(NULL
);
950 /* We remember this frame */
951 free(hardware
->h_rlastframe
);
952 if ((hardware
->h_rlastframe
= (struct lldpd_frame
*)malloc(s
+
953 sizeof(int))) != NULL
) {
954 hardware
->h_rlastframe
->size
= s
;
955 memcpy(hardware
->h_rlastframe
->frame
, frame
, s
);
959 /* This is a new remote system */
960 LLOG_DEBUG("we discovered a new remote system on %s",
962 /* Do we already know this remote system? */
963 TAILQ_FOREACH(ohardware
, &cfg
->g_hardware
, h_entries
) {
964 if ((ohardware
->h_ifname
!= hardware
->h_ifname
) &&
965 (ohardware
->h_rchassis
!= NULL
) &&
966 (ohardware
->h_rchassis
->c_id_subtype
==
967 chassis
->c_id_subtype
) &&
968 (ohardware
->h_rchassis
->c_id_len
==
969 chassis
->c_id_len
) &&
970 (memcmp(ohardware
->h_rchassis
->c_id
,
971 chassis
->c_id
, chassis
->c_id_len
) == 0)) {
972 LLOG_DEBUG("but it was already on %s",
973 ohardware
->h_ifname
);
974 hardware
->h_rid
= ohardware
->h_rid
;
978 hardware
->h_rid
= ++cfg
->g_lastrid
;
983 lldpd_chassis_cleanup(chassis
);
984 lldpd_port_cleanup(port
, 1);
989 lldpd_recv_all(struct lldpd
*cfg
)
991 struct lldpd_hardware
*hardware
;
992 struct lldpd_vif
*vif
;
993 struct lldpd_client
*client
, *client_next
;
996 struct sockaddr_ll from
;
1001 struct timeval
*tvp
= &tv
;
1003 int rc
, nfds
, n
, bond
;
1007 tv
.tv_sec
= cfg
->g_delay
- (time(NULL
) - cfg
->g_lastsent
);
1009 tv
.tv_sec
= LLDPD_TX_DELAY
;
1010 if (tv
.tv_sec
>= cfg
->g_delay
)
1011 tv
.tv_sec
= cfg
->g_delay
;
1017 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
1018 /* Ignore if interface is down */
1019 if (((hardware
->h_flags
& IFF_UP
) == 0) ||
1020 ((hardware
->h_flags
& IFF_RUNNING
) == 0))
1022 FD_SET(hardware
->h_raw
, &rfds
);
1023 if (nfds
< hardware
->h_raw
)
1024 nfds
= hardware
->h_raw
;
1025 /* Listen to real interface too. In 2.6.27, we can
1026 * receive packets if this is the slave interface. */
1027 if (hardware
->h_raw_real
> 0) {
1028 FD_SET(hardware
->h_raw_real
, &rfds
);
1029 if (nfds
< hardware
->h_raw_real
)
1030 nfds
= hardware
->h_raw_real
;
1033 TAILQ_FOREACH(vif
, &cfg
->g_vif
, vif_entries
) {
1034 if (((vif
->vif_flags
& IFF_UP
) == 0) ||
1035 ((vif
->vif_flags
& IFF_RUNNING
) == 0))
1037 FD_SET(vif
->vif_raw
, &rfds
);
1038 if (nfds
< vif
->vif_raw
)
1039 nfds
= vif
->vif_raw
;
1041 TAILQ_FOREACH(client
, &cfg
->g_clients
, next
) {
1042 FD_SET(client
->fd
, &rfds
);
1043 if (nfds
< client
->fd
)
1046 FD_SET(cfg
->g_ctl
, &rfds
);
1047 if (nfds
< cfg
->g_ctl
)
1052 snmp_select_info(&nfds
, &rfds
, tvp
, &fakeblock
);
1053 #endif /* USE_SNMP */
1055 sleep(cfg
->g_delay
);
1059 rc
= select(nfds
+ 1, &rfds
, NULL
, NULL
, &tv
);
1063 LLOG_WARN("failure on select");
1073 #endif /* USE_SNMP */
1074 TAILQ_FOREACH(vif
, &cfg
->g_vif
, vif_entries
) {
1075 if (!FD_ISSET(vif
->vif_raw
, &rfds
))
1077 if ((buffer
= (char *)malloc(
1078 vif
->vif_mtu
)) == NULL
) {
1079 LLOG_WARN("failed to alloc reception buffer");
1082 fromlen
= sizeof(from
);
1083 if ((n
= recvfrom(vif
->vif_raw
,
1086 (struct sockaddr
*)&from
,
1088 LLOG_WARN("error while receiving frame on vlan %s",
1090 vif
->vif_real
->h_rx_discarded_cnt
++;
1094 if (from
.sll_pkttype
== PACKET_OUTGOING
) {
1098 if (!((cfg
->g_multi
) &&
1099 (vif
->vif_real
->h_mode
!= LLDPD_MODE_ANY
) &&
1100 (lldpd_guess_type(cfg
, buffer
, n
) !=
1101 vif
->vif_real
->h_mode
))) {
1102 vif
->vif_real
->h_rx_cnt
++;
1103 lldpd_decode(cfg
, buffer
, n
, vif
->vif_real
, 0);
1108 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
1109 /* We could have received something on _real_
1110 * interface. However, even in this case, this could be
1111 * just an outgoing packet. We will try to handle both
1112 * cases, but maybe not in the same select. */
1113 onreal
= ((hardware
->h_raw_real
> 0) &&
1114 (FD_ISSET(hardware
->h_raw_real
, &rfds
)));
1115 if (onreal
|| (FD_ISSET(hardware
->h_raw
, &rfds
))) {
1116 if ((buffer
= (char *)malloc(
1117 hardware
->h_mtu
)) == NULL
) {
1118 LLOG_WARN("failed to alloc reception buffer");
1121 fromlen
= sizeof(from
);
1123 onreal
?hardware
->h_raw_real
:hardware
->h_raw
,
1126 (struct sockaddr
*)&from
,
1128 LLOG_WARN("error while receiving frame on %s",
1129 hardware
->h_ifname
);
1130 hardware
->h_rx_discarded_cnt
++;
1134 if (from
.sll_pkttype
== PACKET_OUTGOING
) {
1139 /* If received on real interface, we act like if
1140 * this is not a bond! */
1141 if (!onreal
&& (hardware
->h_raw_real
> 0)) {
1142 /* Bonding. Is it for the correct
1143 * physical interface ? */
1144 if (from
.sll_ifindex
== hardware
->h_master
) {
1145 /* It seems that we don't know from
1146 which physical interface it comes
1147 (kernel < 2.6.24 ?) */
1149 } else if (from
.sll_ifindex
!=
1150 if_nametoindex(hardware
->h_ifname
)) {
1155 hardware
->h_rx_cnt
++;
1156 lldpd_decode(cfg
, buffer
, n
, hardware
, bond
);
1161 if (FD_ISSET(cfg
->g_ctl
, &rfds
)) {
1162 if (ctl_accept(cfg
, cfg
->g_ctl
) == -1)
1163 LLOG_WARN("unable to accept new client");
1165 for (client
= TAILQ_FIRST(&cfg
->g_clients
);
1167 client
= client_next
) {
1168 client_next
= TAILQ_NEXT(client
, next
);
1169 if (FD_ISSET(client
->fd
, &rfds
)) {
1171 if ((buffer
= (char *)malloc(MAX_HMSGSIZE
)) ==
1173 LLOG_WARN("failed to alloc reception buffer");
1176 if ((n
= recv(client
->fd
, buffer
,
1177 MAX_HMSGSIZE
, 0)) == -1) {
1178 LLOG_WARN("error while receiving message");
1183 client_handle_client(cfg
, client
, buffer
, n
);
1185 ctl_close(cfg
, client
->fd
); /* Will use TAILQ_REMOVE ! */
1193 netsnmp_check_outstanding_agent_requests();
1195 #endif /* USE_SNMP */
1196 } while ((rc
!= 0) || (time(NULL
) - cfg
->g_lastsent
< cfg
->g_delay
));
1200 lldpd_send_all(struct lldpd
*cfg
)
1202 struct lldpd_hardware
*hardware
;
1203 u_int8_t saved_lladdr
[ETHER_ADDR_LEN
];
1206 cfg
->g_lastsent
= time(NULL
);
1207 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
1208 /* Ignore if interface is down */
1209 if (((hardware
->h_flags
& IFF_UP
) == 0) ||
1210 ((hardware
->h_flags
& IFF_RUNNING
) == 0))
1213 /* When sending on inactive slaves, just send using a 0:0:0:0:0:0 address */
1215 if ((hardware
->h_raw_real
> 0) &&
1216 (!iface_is_slave_active(cfg
, hardware
->h_master
,
1217 hardware
->h_ifname
))) {
1219 memcpy(saved_lladdr
, hardware
->h_lladdr
, ETHER_ADDR_LEN
);
1220 memset(hardware
->h_lladdr
, 0, ETHER_ADDR_LEN
);
1223 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
1224 if (!cfg
->g_protocols
[i
].enabled
)
1226 if ((hardware
->h_mode
== cfg
->g_protocols
[i
].mode
) ||
1227 (cfg
->g_protocols
[i
].mode
== LLDPD_MODE_LLDP
))
1228 cfg
->g_protocols
[i
].send(cfg
, &cfg
->g_lchassis
, hardware
);
1230 /* Restore MAC if needed */
1232 memcpy(hardware
->h_lladdr
, saved_lladdr
, ETHER_ADDR_LEN
);
1236 #ifdef ENABLE_LLDPMED
1238 lldpd_med(struct lldpd_chassis
*chassis
)
1240 free(chassis
->c_med_hw
);
1241 free(chassis
->c_med_fw
);
1242 free(chassis
->c_med_sn
);
1243 free(chassis
->c_med_manuf
);
1244 free(chassis
->c_med_model
);
1245 free(chassis
->c_med_asset
);
1246 chassis
->c_med_hw
= dmi_hw();
1247 chassis
->c_med_fw
= dmi_fw();
1248 chassis
->c_med_sn
= dmi_sn();
1249 chassis
->c_med_manuf
= dmi_manuf();
1250 chassis
->c_med_model
= dmi_model();
1251 chassis
->c_med_asset
= dmi_asset();
1256 lldpd_loop(struct lldpd
*cfg
)
1258 struct ifaddrs
*ifap
, *ifa
;
1259 struct sockaddr_ll
*sdl
;
1260 struct lldpd_hardware
*hardware
;
1261 struct lldpd_vif
*vif
;
1267 /* Set system name and description */
1268 if ((un
= (struct utsname
*)malloc(sizeof(struct utsname
))) == NULL
)
1271 fatal("failed to get system information");
1272 if ((hp
= priv_gethostbyname()) == NULL
)
1273 fatal("failed to get system name");
1274 free(cfg
->g_lchassis
.c_name
);
1275 free(cfg
->g_lchassis
.c_descr
);
1276 if ((cfg
->g_lchassis
.c_name
= strdup(hp
)) == NULL
)
1278 if (asprintf(&cfg
->g_lchassis
.c_descr
, "%s %s %s %s",
1279 un
->sysname
, un
->release
, un
->version
, un
->machine
) == -1)
1280 fatal("failed to set system description");
1282 /* Check forwarding */
1283 cfg
->g_lchassis
.c_cap_enabled
= 0;
1284 if ((f
= priv_open("/proc/sys/net/ipv4/ip_forward")) >= 0) {
1285 if ((read(f
, &status
, 1) == 1) && (status
== '1')) {
1286 cfg
->g_lchassis
.c_cap_enabled
= LLDP_CAP_ROUTER
;
1290 #ifdef ENABLE_LLDPMED
1291 if (cfg
->g_lchassis
.c_cap_available
& LLDP_CAP_TELEPHONE
)
1292 cfg
->g_lchassis
.c_cap_enabled
|= LLDP_CAP_TELEPHONE
;
1293 lldpd_med(&cfg
->g_lchassis
);
1294 free(cfg
->g_lchassis
.c_med_sw
);
1295 cfg
->g_lchassis
.c_med_sw
= strdup(un
->release
);
1299 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
1300 hardware
->h_flags
= 0;
1301 TAILQ_FOREACH(vif
, &cfg
->g_vif
, vif_entries
)
1304 if (getifaddrs(&ifap
) != 0)
1305 fatal("lldpd_loop: failed to get interface list");
1307 cfg
->g_lchassis
.c_mgmt
.s_addr
= INADDR_ANY
;
1308 for (ifa
= ifap
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
1309 if (cfg
->g_lchassis
.c_mgmt
.s_addr
== INADDR_ANY
)
1310 /* Get management address, if available */
1311 if ((ifa
->ifa_addr
!= NULL
) &&
1312 (ifa
->ifa_addr
->sa_family
== AF_INET
)) {
1313 struct sockaddr_in
*sa
;
1314 sa
= (struct sockaddr_in
*)ifa
->ifa_addr
;
1315 if ((ntohl(*(u_int32_t
*)&sa
->sin_addr
) != INADDR_LOOPBACK
) &&
1316 (cfg
->g_mgmt_pattern
== NULL
)) {
1317 memcpy(&cfg
->g_lchassis
.c_mgmt
,
1319 sizeof(struct in_addr
));
1320 cfg
->g_lchassis
.c_mgmt_if
= if_nametoindex(ifa
->ifa_name
);
1322 else if (cfg
->g_mgmt_pattern
!= NULL
) {
1324 ip
= inet_ntoa(sa
->sin_addr
);
1325 if (fnmatch(cfg
->g_mgmt_pattern
,
1327 memcpy(&cfg
->g_lchassis
.c_mgmt
,
1329 sizeof(struct in_addr
));
1330 cfg
->g_lchassis
.c_mgmt_if
=
1331 if_nametoindex(ifa
->ifa_name
);
1336 if (ifa
->ifa_addr
== NULL
||
1337 ifa
->ifa_addr
->sa_family
!= PF_PACKET
)
1340 sdl
= (struct sockaddr_ll
*)ifa
->ifa_addr
;
1341 if (sdl
->sll_hatype
!= ARPHRD_ETHER
|| !sdl
->sll_halen
)
1344 if (iface_is_bridge(cfg
, ifa
->ifa_name
)) {
1345 cfg
->g_lchassis
.c_cap_enabled
|= LLDP_CAP_BRIDGE
;
1349 if ((iface_is_vlan(cfg
, ifa
->ifa_name
)) ||
1350 (iface_is_bond(cfg
, ifa
->ifa_name
)))
1353 if (!(ifa
->ifa_flags
& (IFF_MULTICAST
|IFF_BROADCAST
)))
1356 if (iface_is_wireless(cfg
, ifa
->ifa_name
))
1357 cfg
->g_lchassis
.c_cap_enabled
|= LLDP_CAP_WLAN
;
1359 if (lldpd_port_add(cfg
, ifa
) == NULL
)
1360 LLOG_WARNX("failed to allocate port %s, skip it",
1365 if (cfg
->g_listen_vlans
) {
1366 for (ifa
= ifap
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
1367 if ((iface_is_vlan(cfg
, ifa
->ifa_name
)) &&
1368 (lldpd_port_add_vlan(cfg
, ifa
) == NULL
)) {
1369 LLOG_WARNX("unable to allocate vlan %s, skip it",
1379 lldpd_send_all(cfg
);
1380 lldpd_recv_all(cfg
);
1384 lldpd_shutdown(int sig
)
1386 LLOG_INFO("signal received, exiting");
1390 /* For signal handling */
1391 static struct lldpd
*gcfg
= NULL
;
1396 struct lldpd_hardware
*hardware
;
1397 struct lldpd_vif
*vif
;
1400 TAILQ_FOREACH(hardware
, &gcfg
->g_hardware
, h_entries
) {
1401 if (INTERFACE_OPENED(hardware
))
1402 lldpd_iface_close(gcfg
, hardware
);
1404 TAILQ_FOREACH(vif
, &gcfg
->g_vif
, vif_entries
) {
1405 if (vif
->vif_raw
!= -1)
1406 lldpd_iface_close(gcfg
, (struct lldpd_hardware
*)vif
);
1411 #endif /* USE_SNMP */
1415 main(int argc
, char *argv
[])
1423 char *popt
, opts
[] = "vdxm:p:M:i@ ";
1424 int probe
= 0, i
, found
, vlan
= 0;
1425 #ifdef ENABLE_LLDPMED
1426 int lldpmed
= 0, noinventory
= 0;
1432 * Get and parse command line options
1434 popt
= index(opts
, '@');
1435 for (i
=0; protos
[i
].mode
!= 0; i
++) {
1436 if (protos
[i
].enabled
== 1) continue;
1437 *(popt
++) = protos
[i
].arg
;
1440 while ((ch
= getopt(argc
, argv
, opts
)) != -1) {
1451 #ifdef ENABLE_LLDPMED
1453 lldpmed
= atoi(optarg
);
1454 if ((lldpmed
< 1) || (lldpmed
> 4)) {
1455 fprintf(stderr
, "-M requires an argument between 1 and 4\n");
1466 fprintf(stderr
, "LLDP-MED support is not built-in\n");
1471 probe
= atoi(optarg
);
1477 fprintf(stderr
, "SNMP support is not built-in\n");
1483 for (i
=0; protos
[i
].mode
!= 0; i
++) {
1484 if (protos
[i
].enabled
) continue;
1485 if (ch
== protos
[i
].arg
) {
1486 protos
[i
].enabled
= 1;
1500 if (daemon(0, 0) != 0)
1501 fatal("failed to detach daemon");
1502 if ((pid
= open(LLDPD_PID_FILE
,
1503 O_TRUNC
| O_CREAT
| O_WRONLY
, 0644)) == -1)
1504 fatal("unable to open pid file " LLDPD_PID_FILE
);
1505 if (asprintf(&spid
, "%d\n", getpid()) == -1)
1506 fatal("unable to create pid file " LLDPD_PID_FILE
);
1507 if (write(pid
, spid
, strlen(spid
)) == -1)
1508 fatal("unable to write pid file " LLDPD_PID_FILE
);
1513 priv_init(PRIVSEP_CHROOT
);
1515 if (probe
== 0) probe
= LLDPD_TTL
;
1517 if ((cfg
= (struct lldpd
*)
1518 calloc(1, sizeof(struct lldpd
))) == NULL
)
1521 cfg
->g_mgmt_pattern
= mgmtp
;
1522 cfg
->g_listen_vlans
= vlan
;
1524 /* Get ioctl socket */
1525 if ((cfg
->g_sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1526 fatal("failed to get ioctl socket");
1527 cfg
->g_delay
= LLDPD_TX_DELAY
;
1529 /* Set system capabilities */
1530 cfg
->g_lchassis
.c_cap_available
= LLDP_CAP_BRIDGE
| LLDP_CAP_WLAN
|
1532 #ifdef ENABLE_LLDPMED
1534 if (lldpmed
== LLDPMED_CLASS_III
)
1535 cfg
->g_lchassis
.c_cap_available
|= LLDP_CAP_TELEPHONE
;
1536 cfg
->g_lchassis
.c_med_type
= lldpmed
;
1537 cfg
->g_lchassis
.c_med_cap_available
= LLDPMED_CAP_CAP
|
1538 LLDPMED_CAP_IV
| LLDPMED_CAP_LOCATION
;
1539 cfg
->g_noinventory
= noinventory
;
1544 cfg
->g_lchassis
.c_ttl
= LLDPD_TTL
;
1546 cfg
->g_protocols
= protos
;
1547 cfg
->g_probe_time
= probe
;
1548 for (i
=0; protos
[i
].mode
!= 0; i
++)
1549 if (protos
[i
].enabled
) {
1551 LLOG_INFO("protocol %s enabled", protos
[i
].name
);
1553 LLOG_INFO("protocol %s disabled", protos
[i
].name
);
1556 TAILQ_INIT(&cfg
->g_hardware
);
1557 TAILQ_INIT(&cfg
->g_vif
);
1562 agent_init(cfg
, debug
);
1564 #endif /* USE_SNMP */
1567 if ((cfg
->g_ctl
= priv_ctl_create(cfg
)) == -1)
1568 fatalx("unable to create control socket " LLDPD_CTL_SOCKET
);
1569 TAILQ_INIT(&cfg
->g_clients
);
1572 if (atexit(lldpd_exit
) != 0) {
1575 fatal("unable to set exit function");
1578 /* Signal handling */
1579 signal(SIGHUP
, lldpd_shutdown
);
1580 signal(SIGINT
, lldpd_shutdown
);
1581 signal(SIGTERM
, lldpd_shutdown
);