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>
51 int lldpd_iface_init(struct lldpd
*, struct lldpd_hardware
*);
52 int lldpd_iface_init_vlan(struct lldpd
*, struct lldpd_vif
*);
53 void lldpd_iface_init_mtu(struct lldpd
*, struct lldpd_hardware
*);
54 int lldpd_iface_close(struct lldpd
*, struct lldpd_hardware
*);
55 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 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 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 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 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 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 struct sock_filter lldpd_filter_any_f
[] = { LLDPD_FILTER_ANY_F
};
134 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 int lldpd_iface_switchto(struct lldpd
*, short int,
161 struct lldpd_hardware
*);
162 struct lldpd_hardware
*lldpd_port_add(struct lldpd
*, struct ifaddrs
*);
163 void lldpd_loop(struct lldpd
*);
164 void lldpd_shutdown(int);
166 void lldpd_send_all(struct lldpd
*);
167 void lldpd_recv_all(struct lldpd
*);
168 int lldpd_guess_type(struct lldpd
*, char *, int);
169 void lldpd_decode(struct lldpd
*, char *, int,
170 struct lldpd_hardware
*, int);
171 #ifdef ENABLE_LLDPMED
172 void lldpd_med(struct lldpd_chassis
*);
180 extern const char *__progname
;
181 fprintf(stderr
, "usage: %s [options]\n", __progname
);
182 fprintf(stderr
, "see manual page lldpd(8) for more information\n");
187 lldpd_iface_init_mtu(struct lldpd
*global
, struct lldpd_hardware
*hardware
)
192 memset(&ifr
, 0, sizeof(ifr
));
193 strlcpy(ifr
.ifr_name
, hardware
->h_ifname
, sizeof(ifr
.ifr_name
));
194 if (ioctl(global
->g_sock
, SIOCGIFMTU
, (char*)&ifr
) == -1) {
195 LLOG_WARN("unable to get MTU of %s, using 1500", hardware
->h_ifname
);
196 hardware
->h_mtu
= 1500;
198 hardware
->h_mtu
= hardware
->h_lport
.p_mfs
= ifr
.ifr_mtu
;
202 lldpd_iface_init_vlan(struct lldpd
*global
, struct lldpd_vif
*vif
)
207 lldpd_iface_init_mtu(global
, (struct lldpd_hardware
*)vif
);
208 status
= priv_iface_init((struct lldpd_hardware
*)vif
, -1);
213 filter
= LLDPD_MODE_ANY
;
215 filter
= LLDPD_MODE_LLDP
;
217 if (lldpd_iface_switchto(global
, filter
,
218 (struct lldpd_hardware
*)vif
) == -1) {
219 LLOG_WARNX("unable to apply filter");
223 lldpd_iface_multicast(global
, vif
->vif_ifname
, 0);
225 LLOG_DEBUG("vlan interface %s initialized (fd=%d)", vif
->vif_ifname
,
231 lldpd_iface_init(struct lldpd
*global
, struct lldpd_hardware
*hardware
)
233 int master
; /* Bond device */
234 char if_bond
[IFNAMSIZ
];
238 lldpd_iface_init_mtu(global
, hardware
);
239 status
= priv_iface_init(hardware
, -1);
243 if ((master
= iface_is_enslaved(global
, hardware
->h_ifname
)) != -1) {
244 /* With bonding device, we need to listen on the bond ! */
245 if (if_indextoname(master
, if_bond
) == NULL
) {
246 LLOG_WARN("unable to get index for interface %d (master of %s)",
247 master
, hardware
->h_ifname
);
250 hardware
->h_raw_real
= hardware
->h_raw
;
251 hardware
->h_master
= master
;
252 hardware
->h_raw
= -1;
253 status
= priv_iface_init(hardware
, master
);
255 close(hardware
->h_raw_real
);
256 if (hardware
->h_raw
!= -1)
257 close(hardware
->h_raw
);
263 filter
= LLDPD_MODE_ANY
;
265 filter
= LLDPD_MODE_LLDP
;
266 if (lldpd_iface_switchto(global
, filter
, hardware
) == -1) {
267 LLOG_WARNX("unable to apply filter");
272 lldpd_iface_multicast(global
, if_bond
, 0);
273 lldpd_iface_multicast(global
, hardware
->h_ifname
, 0);
275 LLOG_DEBUG("interface %s initialized (fd=%d)", hardware
->h_ifname
,
281 lldpd_iface_multicast(struct lldpd
*global
, const char *name
, int remove
)
285 for (i
=0; global
->g_protocols
[i
].mode
!= 0; i
++) {
286 if (!global
->g_protocols
[i
].enabled
) continue;
287 if ((rc
= priv_iface_multicast(name
,
288 global
->g_protocols
[i
].mac
, !remove
)) != 0) {
291 LLOG_INFO("unable to %s %s address to multicast filter for %s",
292 (remove
)?"delete":"add",
293 global
->g_protocols
[i
].name
,
300 lldpd_iface_close(struct lldpd
*global
, struct lldpd_hardware
*hardware
)
302 char listen
[IFNAMSIZ
];
304 close(hardware
->h_raw
);
305 hardware
->h_raw
= -1;
307 if (hardware
->h_raw_real
> 0) {
308 if (if_indextoname(hardware
->h_master
, listen
) == NULL
) {
309 LLOG_WARN("unable to get index for interface %d",
311 strlcpy(listen
, hardware
->h_ifname
, sizeof(listen
));
313 close(hardware
->h_raw_real
);
314 lldpd_iface_multicast(global
, listen
, 1);
316 strlcpy(listen
, hardware
->h_ifname
, sizeof(listen
));
317 lldpd_iface_multicast(global
, listen
, 1);
319 hardware
->h_raw_real
= -1;
324 lldpd_iface_switchto(struct lldpd
*cfg
, short int filter
, struct lldpd_hardware
*hardware
)
326 struct sock_fprog prog
;
329 memset(&prog
, 0, sizeof(prog
));
330 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
331 if (!cfg
->g_protocols
[i
].enabled
) continue;
332 if (cfg
->g_protocols
[i
].mode
== filter
)
335 prog
.filter
= cfg
->g_protocols
[i
].filter
;
336 prog
.len
= cfg
->g_protocols
[i
].filterlen
/ sizeof(struct sock_filter
);
337 if (setsockopt(hardware
->h_raw
, SOL_SOCKET
, SO_ATTACH_FILTER
,
338 &prog
, sizeof(prog
)) < 0) {
339 LLOG_WARN("unable to change filter for %s", hardware
->h_ifname
);
342 if ((hardware
->h_raw_real
> 0) &&
343 (setsockopt(hardware
->h_raw_real
, SOL_SOCKET
, SO_ATTACH_FILTER
,
344 &prog
, sizeof(prog
)) < 0)) {
345 LLOG_WARN("unable to change filter for real device %s", hardware
->h_ifname
);
353 lldpd_vlan_cleanup(struct lldpd_port
*port
)
355 struct lldpd_vlan
*vlan
, *vlan_next
;
356 for (vlan
= TAILQ_FIRST(&port
->p_vlans
);
360 vlan_next
= TAILQ_NEXT(vlan
, v_entries
);
361 TAILQ_REMOVE(&port
->p_vlans
, vlan
, v_entries
);
368 lldpd_port_cleanup(struct lldpd_port
*port
)
370 #ifdef ENABLE_LLDPMED
372 for (i
=0; i
< LLDPMED_LOCFORMAT_LAST
; i
++)
373 free(port
->p_med_location
[i
].data
);
376 lldpd_vlan_cleanup(port
);
384 lldpd_chassis_cleanup(struct lldpd_chassis
*chassis
)
386 #ifdef ENABLE_LLDPMED
387 free(chassis
->c_med_hw
);
388 free(chassis
->c_med_fw
);
389 free(chassis
->c_med_sn
);
390 free(chassis
->c_med_manuf
);
391 free(chassis
->c_med_model
);
392 free(chassis
->c_med_asset
);
395 free(chassis
->c_name
);
396 free(chassis
->c_descr
);
401 lldpd_remote_cleanup(struct lldpd
*cfg
, struct lldpd_hardware
*hardware
, int reset
)
403 if (hardware
->h_rport
!= NULL
) {
404 lldpd_port_cleanup(hardware
->h_rport
);
405 hardware
->h_rport
= NULL
;
407 if (hardware
->h_rchassis
!= NULL
) {
408 lldpd_chassis_cleanup(hardware
->h_rchassis
);
409 hardware
->h_rchassis
= NULL
;
411 hardware
->h_rlastchange
= hardware
->h_rlastupdate
= 0;
412 free(hardware
->h_rlastframe
);
413 hardware
->h_rlastframe
= NULL
;
414 if (reset
&& cfg
->g_multi
) {
415 hardware
->h_mode
= LLDPD_MODE_ANY
;
416 memset(hardware
->h_proto_macs
, 0, ETH_ALEN
*(cfg
->g_multi
+1));
417 hardware
->h_start_probe
= 0;
418 lldpd_iface_switchto(cfg
, LLDPD_MODE_ANY
, hardware
);
423 lldpd_hardware_cleanup(struct lldpd_hardware
*hardware
)
426 lldpd_vlan_cleanup(&hardware
->h_lport
);
428 free(hardware
->h_proto_macs
);
429 free(hardware
->h_llastframe
);
434 lldpd_cleanup(struct lldpd
*cfg
)
436 struct lldpd_hardware
*hardware
, *hardware_next
;
437 struct lldpd_vif
*vif
, *vif_next
;
439 for (hardware
= TAILQ_FIRST(&cfg
->g_hardware
); hardware
!= NULL
;
440 hardware
= hardware_next
) {
441 hardware_next
= TAILQ_NEXT(hardware
, h_entries
);
442 if (hardware
->h_flags
== 0) {
443 TAILQ_REMOVE(&cfg
->g_hardware
, hardware
, h_entries
);
444 lldpd_iface_close(cfg
, hardware
);
445 lldpd_remote_cleanup(cfg
, hardware
, 1);
446 lldpd_hardware_cleanup(hardware
);
447 } else if (hardware
->h_rchassis
!= NULL
) {
448 if (time(NULL
) - hardware
->h_rlastupdate
>
449 hardware
->h_rchassis
->c_ttl
) {
450 lldpd_remote_cleanup(cfg
, hardware
, 1);
451 hardware
->h_rx_ageout_cnt
++;
455 for (vif
= TAILQ_FIRST(&cfg
->g_vif
); vif
!= NULL
;
457 vif_next
= TAILQ_NEXT(vif
, vif_entries
);
458 if (vif
->vif_flags
== 0) {
459 TAILQ_REMOVE(&cfg
->g_vif
, vif
, vif_entries
);
460 lldpd_iface_close(cfg
, (struct lldpd_hardware
*)vif
);
467 lldpd_port_add_vlan(struct lldpd
*cfg
, struct ifaddrs
*ifa
)
469 struct lldpd_vif
*vif
;
470 struct lldpd_hardware
*hardware
;
471 struct vlan_ioctl_args ifv
;
473 TAILQ_FOREACH(vif
, &cfg
->g_vif
, vif_entries
) {
474 if (strcmp(vif
->vif_ifname
, ifa
->ifa_name
) == 0)
479 if ((vif
= (struct lldpd_vif
*)
480 calloc(1, sizeof(struct lldpd_vif
))) == NULL
)
483 vif
->vif_raw_real
= -1;
485 strlcpy(vif
->vif_ifname
, ifa
->ifa_name
, sizeof(vif
->vif_ifname
));
486 vif
->vif_flags
= ifa
->ifa_flags
;
488 if (vif
->vif_raw
== -1) {
490 if (lldpd_iface_init_vlan(cfg
, vif
) != 0) {
495 /* Find the real interface */
496 vif
->vif_real
= NULL
;
497 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
498 memset(&ifv
, 0, sizeof(ifv
));
499 ifv
.cmd
= GET_VLAN_REALDEV_NAME_CMD
;
500 strlcpy(ifv
.device1
, ifa
->ifa_name
, sizeof(ifv
.device1
));
501 if ((ioctl(cfg
->g_sock
, SIOCGIFVLAN
, &ifv
) >= 0) &&
502 (strncmp(hardware
->h_ifname
,
504 sizeof(ifv
.u
.device2
)) == 0))
505 vif
->vif_real
= hardware
;
507 if (vif
->vif_real
== NULL
) {
508 LLOG_WARNX("unable to find real interface for %s",
514 TAILQ_INSERT_TAIL(&cfg
->g_vif
, vif
, vif_entries
);
520 struct lldpd_hardware
*
521 lldpd_port_add(struct lldpd
*cfg
, struct ifaddrs
*ifa
)
523 #if defined (ENABLE_DOT1) || defined (ENABLE_DOT3)
524 struct ifaddrs
*oifap
, *oifa
;
526 struct lldpd_hardware
*hardware
;
527 struct lldpd_port
*port
;
529 struct lldpd_vlan
*vlan
;
530 struct vlan_ioctl_args ifv
;
533 struct ethtool_cmd ethc
;
537 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
538 if (strcmp(hardware
->h_ifname
, ifa
->ifa_name
) == 0)
542 if (hardware
== NULL
) {
543 if ((hardware
= (struct lldpd_hardware
*)
544 calloc(1, sizeof(struct lldpd_hardware
))) == NULL
)
546 hardware
->h_raw
= -1;
547 hardware
->h_raw_real
= -1;
548 hardware
->h_start_probe
= 0;
549 hardware
->h_proto_macs
= (u_int8_t
*)calloc(cfg
->g_multi
+1, ETH_ALEN
);
550 #ifdef ENABLE_LLDPMED
551 hardware
->h_lport
.p_med_cap_enabled
= LLDPMED_CAP_CAP
;
552 if (!cfg
->g_noinventory
)
553 hardware
->h_lport
.p_med_cap_enabled
|= LLDPMED_CAP_IV
;
556 TAILQ_INIT(&hardware
->h_lport
.p_vlans
);
558 lldpd_vlan_cleanup(&hardware
->h_lport
);
562 port
= &hardware
->h_lport
;
563 hardware
->h_flags
= ifa
->ifa_flags
;
565 strlcpy(hardware
->h_ifname
, ifa
->ifa_name
, sizeof(hardware
->h_ifname
));
566 lladdr
= (u_int8_t
*)(((struct sockaddr_ll
*)ifa
->ifa_addr
)->sll_addr
);
567 memcpy(&hardware
->h_lladdr
, lladdr
, sizeof(hardware
->h_lladdr
));
568 iface_get_permanent_mac(cfg
, hardware
);
569 port
->p_id_subtype
= LLDP_PORTID_SUBTYPE_LLADDR
;
570 if ((port
->p_id
= calloc(1, sizeof(hardware
->h_lladdr
))) == NULL
)
572 memcpy(port
->p_id
, hardware
->h_lladdr
, sizeof(hardware
->h_lladdr
));
573 port
->p_id_len
= sizeof(hardware
->h_lladdr
);
574 port
->p_descr
= hardware
->h_ifname
;
576 if (cfg
->g_lchassis
.c_id
== NULL
) {
577 /* Use the first port's l2 addr as the chassis ID */
578 if ((cfg
->g_lchassis
.c_id
= malloc(sizeof(hardware
->h_lladdr
))) == NULL
)
580 cfg
->g_lchassis
.c_id_subtype
= LLDP_CHASSISID_SUBTYPE_LLADDR
;
581 cfg
->g_lchassis
.c_id_len
= sizeof(hardware
->h_lladdr
);
582 memcpy(cfg
->g_lchassis
.c_id
,
583 hardware
->h_lladdr
, sizeof(hardware
->h_lladdr
));
586 /* Get VLANS and aggregation status */
587 #if defined (ENABLE_DOT3) || defined (ENABLE_DOT1)
588 if (getifaddrs(&oifap
) != 0)
589 fatal("lldpd_port_add: failed to get interface list");
590 for (oifa
= oifap
; oifa
!= NULL
; oifa
= oifa
->ifa_next
) {
592 /* Check if we already have checked this one */
594 TAILQ_FOREACH(vlan
, &port
->p_vlans
, v_entries
) {
595 if (strcmp(vlan
->v_name
, oifa
->ifa_name
) == 0)
601 /* Aggregation check */
603 if (iface_is_bond_slave(cfg
, hardware
->h_ifname
, oifa
->ifa_name
, NULL
))
604 port
->p_aggregid
= if_nametoindex(oifa
->ifa_name
);
609 memset(&ifv
, 0, sizeof(ifv
));
610 ifv
.cmd
= GET_VLAN_REALDEV_NAME_CMD
;
611 strlcpy(ifv
.device1
, oifa
->ifa_name
, sizeof(ifv
.device1
));
612 if ((ioctl(cfg
->g_sock
, SIOCGIFVLAN
, &ifv
) >= 0) &&
613 ((iface_is_bond_slave(cfg
, hardware
->h_ifname
, ifv
.u
.device2
, NULL
)) ||
614 (strncmp(hardware
->h_ifname
, ifv
.u
.device2
, sizeof(ifv
.u
.device2
)) == 0))) {
615 if ((vlan
= (struct lldpd_vlan
*)
616 calloc(1, sizeof(struct lldpd_vlan
))) == NULL
)
618 if ((vlan
->v_name
= strdup(oifa
->ifa_name
)) == NULL
) {
622 memset(&ifv
, 0, sizeof(ifv
));
623 ifv
.cmd
= GET_VLAN_VID_CMD
;
624 strlcpy(ifv
.device1
, oifa
->ifa_name
, sizeof(ifv
.device1
));
625 if (ioctl(cfg
->g_sock
, SIOCGIFVLAN
, &ifv
) < 0) {
626 /* Dunno what happened */
630 vlan
->v_vid
= ifv
.u
.VID
;
631 TAILQ_INSERT_TAIL(&port
->p_vlans
, vlan
, v_entries
);
641 if (priv_ethtool(hardware
->h_ifname
, ðc
) == 0) {
643 int advertised_ethtool_to_rfc3636
[][2] = {
644 {ADVERTISED_10baseT_Half
, LLDP_DOT3_LINK_AUTONEG_10BASE_T
},
645 {ADVERTISED_10baseT_Full
, LLDP_DOT3_LINK_AUTONEG_10BASET_FD
},
646 {ADVERTISED_100baseT_Half
, LLDP_DOT3_LINK_AUTONEG_100BASE_TX
},
647 {ADVERTISED_100baseT_Full
, LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD
},
648 {ADVERTISED_1000baseT_Half
, LLDP_DOT3_LINK_AUTONEG_1000BASE_T
},
649 {ADVERTISED_1000baseT_Full
, LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD
},
650 {ADVERTISED_10000baseT_Full
, LLDP_DOT3_LINK_AUTONEG_OTHER
},
651 {ADVERTISED_Pause
, LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE
},
652 {ADVERTISED_Asym_Pause
, LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE
},
653 {ADVERTISED_2500baseX_Full
, LLDP_DOT3_LINK_AUTONEG_OTHER
},
656 port
->p_autoneg_support
= (ethc
.supported
& SUPPORTED_Autoneg
) ? 1 : 0;
657 port
->p_autoneg_enabled
= (ethc
.autoneg
== AUTONEG_DISABLE
) ? 0 : 1;
658 for (j
=0; advertised_ethtool_to_rfc3636
[j
][0]; j
++) {
659 if (ethc
.advertising
& advertised_ethtool_to_rfc3636
[j
][0])
660 port
->p_autoneg_advertised
|= advertised_ethtool_to_rfc3636
[j
][1];
662 switch (ethc
.speed
) {
664 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
665 LLDP_DOT3_MAU_10BASETFD
: LLDP_DOT3_MAU_10BASETHD
;
666 if (ethc
.port
== PORT_BNC
) port
->p_mau_type
= LLDP_DOT3_MAU_10BASE2
;
667 if (ethc
.port
== PORT_FIBRE
)
668 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
669 LLDP_DOT3_MAU_10BASEFLDF
: LLDP_DOT3_MAU_10BASEFLHD
;
672 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
673 LLDP_DOT3_MAU_100BASETXFD
: LLDP_DOT3_MAU_100BASETXHD
;
674 if (ethc
.port
== PORT_BNC
)
675 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
676 LLDP_DOT3_MAU_100BASET2DF
: LLDP_DOT3_MAU_100BASET2HD
;
677 if (ethc
.port
== PORT_FIBRE
)
678 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
679 LLDP_DOT3_MAU_100BASEFXFD
: LLDP_DOT3_MAU_100BASEFXHD
;
682 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
683 LLDP_DOT3_MAU_1000BASETFD
: LLDP_DOT3_MAU_1000BASETHD
;
684 if (ethc
.port
== PORT_FIBRE
)
685 port
->p_mau_type
= (ethc
.duplex
== DUPLEX_FULL
) ? \
686 LLDP_DOT3_MAU_1000BASEXFD
: LLDP_DOT3_MAU_1000BASEXHD
;
689 port
->p_mau_type
= (ethc
.port
== PORT_FIBRE
) ? \
690 LLDP_DOT3_MAU_10GIGBASEX
: LLDP_DOT3_MAU_10GIGBASER
;
693 if (ethc
.port
== PORT_AUI
) port
->p_mau_type
= LLDP_DOT3_MAU_AUI
;
695 LLOG_DEBUG("unable to get eth info for %s", hardware
->h_ifname
);
698 if (!INTERFACE_OPENED(hardware
)) {
700 if (lldpd_iface_init(cfg
, hardware
) != 0) {
701 LLOG_WARN("unable to initialize %s", hardware
->h_ifname
);
702 lldpd_hardware_cleanup(hardware
);
706 TAILQ_INSERT_TAIL(&cfg
->g_hardware
, hardware
, h_entries
);
713 lldpd_guess_type(struct lldpd
*cfg
, char *frame
, int s
)
718 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
719 if (!cfg
->g_protocols
[i
].enabled
)
721 if (cfg
->g_protocols
[i
].guess
== NULL
) {
722 if (memcmp(frame
, cfg
->g_protocols
[i
].mac
, ETH_ALEN
) == 0)
723 return cfg
->g_protocols
[i
].mode
;
725 if (cfg
->g_protocols
[i
].guess(frame
, s
))
726 return cfg
->g_protocols
[i
].mode
;
733 lldpd_decode(struct lldpd
*cfg
, char *frame
, int s
,
734 struct lldpd_hardware
*hardware
, int bond
)
736 int result
= 0, i
, j
, candidatetonull
;
737 u_int8_t nullmac
[ETH_ALEN
] = {0,0,0,0,0,0};
738 u_int8_t broadcastmac
[ETH_ALEN
] = {0xff,0xff,0xff,0xff,0xff,0xff};
739 struct lldpd_chassis
*chassis
;
740 struct lldpd_port
*port
;
741 struct lldpd_hardware
*ohardware
, *firstnull
= NULL
, *older
= NULL
;
742 int guess
= LLDPD_MODE_LLDP
;
744 /* Discard VLAN frames */
745 if ((s
>= sizeof(struct ieee8023
)) &&
746 (((struct ieee8023
*)frame
)->size
== htons(ETHERTYPE_VLAN
)))
749 if ((hardware
->h_rlastframe
!= NULL
) &&
750 (hardware
->h_rlastframe
->size
== s
) &&
751 (memcmp(hardware
->h_rlastframe
->frame
, frame
, s
) == 0)) {
752 /* Already received the same frame */
753 hardware
->h_rlastupdate
= time(NULL
);
758 if (hardware
->h_mode
== LLDPD_MODE_ANY
)
759 guess
= lldpd_guess_type(cfg
, frame
, s
);
761 guess
= hardware
->h_mode
;
762 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
763 if (!cfg
->g_protocols
[i
].enabled
)
765 if (cfg
->g_protocols
[i
].mode
== guess
) {
766 if ((result
= cfg
->g_protocols
[i
].decode(cfg
, frame
,
767 s
, hardware
, &chassis
, &port
)) == -1)
772 if (cfg
->g_protocols
[i
].mode
== 0) {
773 LLOG_INFO("unable to guess frame type");
776 } else if (cfg
->g_protocols
[0].decode(cfg
, frame
, s
, hardware
,
777 &chassis
, &port
) == -1)
778 /* Nothing has been received */
782 /* Eh, wait ! The frame we just received was for a bonding
783 * device. We need to attach it to a real device. What is the
784 * best candidate? Drum rolling... */
785 TAILQ_FOREACH(ohardware
, &cfg
->g_hardware
, h_entries
) {
786 if (ohardware
->h_master
== hardware
->h_master
) {
788 if (ohardware
->h_rchassis
== NULL
) {
791 (ohardware
->h_mode
== LLDPD_MODE_ANY
)) {
793 cfg
->g_protocols
[i
].mode
!= 0;
795 if (!cfg
->g_protocols
[i
].enabled
)
797 if ((cfg
->g_protocols
[i
].mode
== guess
) &&
798 (memcmp(frame
+ ETH_ALEN
,
799 ohardware
->h_proto_macs
+ ETH_ALEN
*j
,
801 hardware
= ohardware
;
808 if (firstnull
!= NULL
) {
810 cfg
->g_protocols
[i
].mode
!= 0;
812 if (!cfg
->g_protocols
[i
].enabled
)
814 if ((cfg
->g_protocols
[i
].mode
== guess
) &&
816 ohardware
->h_proto_macs
+
829 /* Ok, this is the first candidate if we
830 * don't find a matching chassis/port */
831 if (candidatetonull
) firstnull
= ohardware
;
834 if ((older
== NULL
) ||
835 (older
->h_rlastupdate
> ohardware
->h_rlastupdate
))
836 /* If there is no matching chassis/port
837 * and no free hardware, we will use
840 if ((chassis
->c_id_subtype
!=
841 ohardware
->h_rchassis
->c_id_subtype
) ||
842 (chassis
->c_id_len
!= ohardware
->h_rchassis
->c_id_len
) ||
843 (memcmp(chassis
->c_id
, ohardware
->h_rchassis
->c_id
,
844 chassis
->c_id_len
) != 0) ||
845 (port
->p_id_subtype
!= ohardware
->h_rport
->p_id_subtype
) ||
846 (port
->p_id_len
!= ohardware
->h_rport
->p_id_len
) ||
847 (memcmp(port
->p_id
, ohardware
->h_rport
->p_id
,
848 port
->p_id_len
) != 0))
850 /* We got a match! */
851 hardware
= ohardware
; /* We switch hardware */
858 if (firstnull
!= NULL
)
859 hardware
= firstnull
;
860 else hardware
= older
;
865 (hardware
->h_mode
== LLDPD_MODE_ANY
)) {
870 for (i
=j
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
871 if (!cfg
->g_protocols
[i
].enabled
)
873 if (cfg
->g_protocols
[i
].mode
== guess
) {
874 mac
= hardware
->h_proto_macs
+ ETH_ALEN
*j
;
875 modename
= cfg
->g_protocols
[i
].name
;
876 filter
= cfg
->g_protocols
[i
].mode
;
881 if (cfg
->g_protocols
[i
].mode
== 0) {
882 LLOG_WARNX("should not be there");
886 if (hardware
->h_start_probe
== 0)
887 hardware
->h_start_probe
= time(NULL
) - 1;
888 /* Handle switching respecting probe time */
889 if ((memcmp(mac
, frame
+ ETH_ALEN
, ETH_ALEN
) == 0) &&
890 ((time(NULL
) - hardware
->h_start_probe
) > cfg
->g_probe_time
) &&
891 /* Don't switch to this protocol if not LLDP and LLDP is
892 * a valid candidate */
893 ((filter
== LLDPD_MODE_LLDP
) ||
894 (memcmp(hardware
->h_proto_macs
,
895 broadcastmac
, ETH_ALEN
) == 0) ||
896 (memcmp(hardware
->h_proto_macs
,
897 nullmac
, ETH_ALEN
) == 0))) {
898 LLOG_INFO("switching to %s on port %s", modename
,
900 hardware
->h_mode
= guess
;
901 lldpd_iface_switchto(cfg
, filter
, hardware
);
903 /* Wait twice probe time to be able to receive packets of all kind */
904 if ((time(NULL
) - hardware
->h_start_probe
) > cfg
->g_probe_time
* 2) {
905 LLOG_DEBUG("probe expired on %s, retry", hardware
->h_ifname
);
906 hardware
->h_start_probe
= 0;
907 memset(hardware
->h_proto_macs
, 0, ETH_ALEN
*(cfg
->g_multi
+1));
910 if (memcmp(mac
, broadcastmac
, ETH_ALEN
) == 0)
912 LLOG_INFO("received a %s frame on %s but wait for %d sec",
913 modename
, hardware
->h_ifname
, cfg
->g_probe_time
- time(NULL
) +
914 hardware
->h_start_probe
);
915 if (memcmp(mac
, frame
+ ETH_ALEN
, ETH_ALEN
) == 0)
917 if (memcmp(mac
, nullmac
, ETH_ALEN
) == 0) {
918 memcpy(mac
, frame
+ ETH_ALEN
, ETH_ALEN
);
921 LLOG_INFO("several MAC for %s on %s, discarding %s for this interface",
922 modename
, hardware
->h_ifname
, modename
);
923 memcpy(mac
, broadcastmac
, ETH_ALEN
);
929 if ((hardware
->h_rchassis
== NULL
) ||
930 (chassis
->c_id_subtype
!= hardware
->h_rchassis
->c_id_subtype
) ||
931 (chassis
->c_id_len
!= hardware
->h_rchassis
->c_id_len
) ||
932 (memcmp(chassis
->c_id
, hardware
->h_rchassis
->c_id
,
933 chassis
->c_id_len
) != 0))
936 /* We have our new frame */
937 lldpd_remote_cleanup(cfg
, hardware
, 0);
938 hardware
->h_rport
= port
;
939 hardware
->h_rchassis
= chassis
;
940 hardware
->h_rlastchange
= hardware
->h_rlastupdate
= time(NULL
);
942 /* We remember this frame */
943 free(hardware
->h_rlastframe
);
944 if ((hardware
->h_rlastframe
= (struct lldpd_frame
*)malloc(s
+
945 sizeof(int))) != NULL
) {
946 hardware
->h_rlastframe
->size
= s
;
947 memcpy(hardware
->h_rlastframe
->frame
, frame
, s
);
951 /* This is a new remote system */
952 LLOG_DEBUG("we discovered a new remote system on %s",
954 /* Do we already know this remote system? */
955 TAILQ_FOREACH(ohardware
, &cfg
->g_hardware
, h_entries
) {
956 if ((ohardware
->h_ifname
!= hardware
->h_ifname
) &&
957 (ohardware
->h_rchassis
!= NULL
) &&
958 (ohardware
->h_rchassis
->c_id_subtype
==
959 chassis
->c_id_subtype
) &&
960 (ohardware
->h_rchassis
->c_id_len
==
961 chassis
->c_id_len
) &&
962 (memcmp(ohardware
->h_rchassis
->c_id
,
963 chassis
->c_id
, chassis
->c_id_len
) == 0)) {
964 LLOG_DEBUG("but it was already on %s",
965 ohardware
->h_ifname
);
966 hardware
->h_rid
= ohardware
->h_rid
;
970 hardware
->h_rid
= ++cfg
->g_lastrid
;
975 lldpd_chassis_cleanup(chassis
);
976 lldpd_port_cleanup(port
);
981 lldpd_recv_all(struct lldpd
*cfg
)
983 struct lldpd_hardware
*hardware
;
984 struct lldpd_vif
*vif
;
985 struct lldpd_client
*client
, *client_next
;
988 struct sockaddr_ll from
;
993 struct timeval
*tvp
= &tv
;
995 int rc
, nfds
, n
, bond
;
999 tv
.tv_sec
= cfg
->g_delay
- (time(NULL
) - cfg
->g_lastsent
);
1001 tv
.tv_sec
= LLDPD_TX_DELAY
;
1002 if (tv
.tv_sec
>= cfg
->g_delay
)
1003 tv
.tv_sec
= cfg
->g_delay
;
1009 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
1010 /* Ignore if interface is down */
1011 if ((hardware
->h_flags
& IFF_UP
) == 0)
1013 FD_SET(hardware
->h_raw
, &rfds
);
1014 if (nfds
< hardware
->h_raw
)
1015 nfds
= hardware
->h_raw
;
1016 /* Listen to real interface too. In 2.6.27, we can
1017 * receive packets if this is the slave interface. */
1018 if (hardware
->h_raw_real
> 0) {
1019 FD_SET(hardware
->h_raw_real
, &rfds
);
1020 if (nfds
< hardware
->h_raw_real
)
1021 nfds
= hardware
->h_raw_real
;
1024 TAILQ_FOREACH(vif
, &cfg
->g_vif
, vif_entries
) {
1025 if ((vif
->vif_flags
& IFF_UP
) == 0)
1027 FD_SET(vif
->vif_raw
, &rfds
);
1028 if (nfds
< vif
->vif_raw
)
1029 nfds
= vif
->vif_raw
;
1031 TAILQ_FOREACH(client
, &cfg
->g_clients
, next
) {
1032 FD_SET(client
->fd
, &rfds
);
1033 if (nfds
< client
->fd
)
1036 FD_SET(cfg
->g_ctl
, &rfds
);
1037 if (nfds
< cfg
->g_ctl
)
1042 snmp_select_info(&nfds
, &rfds
, tvp
, &fakeblock
);
1043 #endif /* USE_SNMP */
1045 sleep(cfg
->g_delay
);
1049 rc
= select(nfds
+ 1, &rfds
, NULL
, NULL
, &tv
);
1053 LLOG_WARN("failure on select");
1063 #endif /* USE_SNMP */
1064 TAILQ_FOREACH(vif
, &cfg
->g_vif
, vif_entries
) {
1065 if (!FD_ISSET(vif
->vif_raw
, &rfds
))
1067 if ((buffer
= (char *)malloc(
1068 vif
->vif_mtu
)) == NULL
) {
1069 LLOG_WARN("failed to alloc reception buffer");
1072 fromlen
= sizeof(from
);
1073 if ((n
= recvfrom(vif
->vif_raw
,
1076 (struct sockaddr
*)&from
,
1078 LLOG_WARN("error while receiving frame on vlan %s",
1080 vif
->vif_real
->h_rx_discarded_cnt
++;
1084 if (from
.sll_pkttype
== PACKET_OUTGOING
) {
1088 if (!((cfg
->g_multi
) &&
1089 (vif
->vif_real
->h_mode
!= LLDPD_MODE_ANY
) &&
1090 (lldpd_guess_type(cfg
, buffer
, n
) !=
1091 vif
->vif_real
->h_mode
))) {
1092 vif
->vif_real
->h_rx_cnt
++;
1093 lldpd_decode(cfg
, buffer
, n
, vif
->vif_real
, 0);
1098 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
1099 /* We could have received something on _real_
1100 * interface. However, even in this case, this could be
1101 * just an outgoing packet. We will try to handle both
1102 * cases, but maybe not in the same select. */
1103 onreal
= ((hardware
->h_raw_real
> 0) &&
1104 (FD_ISSET(hardware
->h_raw_real
, &rfds
)));
1105 if (onreal
|| (FD_ISSET(hardware
->h_raw
, &rfds
))) {
1106 if ((buffer
= (char *)malloc(
1107 hardware
->h_mtu
)) == NULL
) {
1108 LLOG_WARN("failed to alloc reception buffer");
1111 fromlen
= sizeof(from
);
1113 onreal
?hardware
->h_raw_real
:hardware
->h_raw
,
1116 (struct sockaddr
*)&from
,
1118 LLOG_WARN("error while receiving frame on %s",
1119 hardware
->h_ifname
);
1120 hardware
->h_rx_discarded_cnt
++;
1124 if (from
.sll_pkttype
== PACKET_OUTGOING
) {
1129 /* If received on real interface, we act like if
1130 * this is not a bond! */
1131 if (!onreal
&& (hardware
->h_raw_real
> 0)) {
1132 /* Bonding. Is it for the correct
1133 * physical interface ? */
1134 if (from
.sll_ifindex
== hardware
->h_master
) {
1135 /* It seems that we don't know from
1136 which physical interface it comes
1137 (kernel < 2.6.24 ?) */
1139 } else if (from
.sll_ifindex
!=
1140 if_nametoindex(hardware
->h_ifname
)) {
1145 hardware
->h_rx_cnt
++;
1146 lldpd_decode(cfg
, buffer
, n
, hardware
, bond
);
1151 if (FD_ISSET(cfg
->g_ctl
, &rfds
)) {
1152 if (ctl_accept(cfg
, cfg
->g_ctl
) == -1)
1153 LLOG_WARN("unable to accept new client");
1155 for (client
= TAILQ_FIRST(&cfg
->g_clients
);
1157 client
= client_next
) {
1158 client_next
= TAILQ_NEXT(client
, next
);
1159 if (FD_ISSET(client
->fd
, &rfds
)) {
1161 if ((buffer
= (char *)malloc(MAX_HMSGSIZE
)) ==
1163 LLOG_WARN("failed to alloc reception buffer");
1166 if ((n
= recv(client
->fd
, buffer
,
1167 MAX_HMSGSIZE
, 0)) == -1) {
1168 LLOG_WARN("error while receiving message");
1173 client_handle_client(cfg
, client
, buffer
, n
);
1175 ctl_close(cfg
, client
->fd
); /* Will use TAILQ_REMOVE ! */
1183 netsnmp_check_outstanding_agent_requests();
1185 #endif /* USE_SNMP */
1186 } while ((rc
!= 0) || (time(NULL
) - cfg
->g_lastsent
< cfg
->g_delay
));
1190 lldpd_send_all(struct lldpd
*cfg
)
1192 struct lldpd_hardware
*hardware
;
1193 u_int8_t saved_lladdr
[ETHER_ADDR_LEN
];
1196 cfg
->g_lastsent
= time(NULL
);
1197 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
1198 /* Ignore if interface is down */
1199 if ((hardware
->h_flags
& IFF_UP
) == 0)
1202 /* When sending on inactive slaves, just send using a 0:0:0:0:0:0 address */
1204 if ((hardware
->h_raw_real
> 0) &&
1205 (!iface_is_slave_active(cfg
, hardware
->h_master
,
1206 hardware
->h_ifname
))) {
1208 memcpy(saved_lladdr
, hardware
->h_lladdr
, ETHER_ADDR_LEN
);
1209 memset(hardware
->h_lladdr
, 0, ETHER_ADDR_LEN
);
1212 for (i
=0; cfg
->g_protocols
[i
].mode
!= 0; i
++) {
1213 if (!cfg
->g_protocols
[i
].enabled
)
1215 if ((hardware
->h_mode
== cfg
->g_protocols
[i
].mode
) ||
1216 (cfg
->g_protocols
[i
].mode
== LLDPD_MODE_LLDP
))
1217 cfg
->g_protocols
[i
].send(cfg
, &cfg
->g_lchassis
, hardware
);
1219 /* Restore MAC if needed */
1221 memcpy(hardware
->h_lladdr
, saved_lladdr
, ETHER_ADDR_LEN
);
1225 #ifdef ENABLE_LLDPMED
1227 lldpd_med(struct lldpd_chassis
*chassis
)
1229 free(chassis
->c_med_hw
);
1230 free(chassis
->c_med_fw
);
1231 free(chassis
->c_med_sn
);
1232 free(chassis
->c_med_manuf
);
1233 free(chassis
->c_med_model
);
1234 free(chassis
->c_med_asset
);
1235 chassis
->c_med_hw
= dmi_hw();
1236 chassis
->c_med_fw
= dmi_fw();
1237 chassis
->c_med_sn
= dmi_sn();
1238 chassis
->c_med_manuf
= dmi_manuf();
1239 chassis
->c_med_model
= dmi_model();
1240 chassis
->c_med_asset
= dmi_asset();
1245 lldpd_loop(struct lldpd
*cfg
)
1247 struct ifaddrs
*ifap
, *ifa
;
1248 struct sockaddr_ll
*sdl
;
1249 struct lldpd_hardware
*hardware
;
1250 struct lldpd_vif
*vif
;
1256 /* Set system name and description */
1257 if ((un
= (struct utsname
*)malloc(sizeof(struct utsname
))) == NULL
)
1260 fatal("failed to get system information");
1261 if ((hp
= priv_gethostbyname()) == NULL
)
1262 fatal("failed to get system name");
1263 free(cfg
->g_lchassis
.c_name
);
1264 free(cfg
->g_lchassis
.c_descr
);
1265 if ((cfg
->g_lchassis
.c_name
= strdup(hp
)) == NULL
)
1267 if (asprintf(&cfg
->g_lchassis
.c_descr
, "%s %s %s %s",
1268 un
->sysname
, un
->release
, un
->version
, un
->machine
) == -1)
1269 fatal("failed to set system description");
1271 /* Check forwarding */
1272 cfg
->g_lchassis
.c_cap_enabled
= 0;
1273 if ((f
= priv_open("/proc/sys/net/ipv4/ip_forward")) >= 0) {
1274 if ((read(f
, &status
, 1) == 1) && (status
== '1')) {
1275 cfg
->g_lchassis
.c_cap_enabled
= LLDP_CAP_ROUTER
;
1279 #ifdef ENABLE_LLDPMED
1280 if (cfg
->g_lchassis
.c_cap_available
& LLDP_CAP_TELEPHONE
)
1281 cfg
->g_lchassis
.c_cap_enabled
|= LLDP_CAP_TELEPHONE
;
1282 lldpd_med(&cfg
->g_lchassis
);
1283 free(cfg
->g_lchassis
.c_med_sw
);
1284 cfg
->g_lchassis
.c_med_sw
= strdup(un
->release
);
1288 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
)
1289 hardware
->h_flags
= 0;
1290 TAILQ_FOREACH(vif
, &cfg
->g_vif
, vif_entries
)
1293 if (getifaddrs(&ifap
) != 0)
1294 fatal("lldpd_loop: failed to get interface list");
1296 cfg
->g_lchassis
.c_mgmt
.s_addr
= INADDR_ANY
;
1297 for (ifa
= ifap
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
1298 if (cfg
->g_lchassis
.c_mgmt
.s_addr
== INADDR_ANY
)
1299 /* Get management address, if available */
1300 if ((ifa
->ifa_addr
!= NULL
) &&
1301 (ifa
->ifa_addr
->sa_family
== AF_INET
)) {
1302 struct sockaddr_in
*sa
;
1303 sa
= (struct sockaddr_in
*)ifa
->ifa_addr
;
1304 if ((ntohl(*(u_int32_t
*)&sa
->sin_addr
) != INADDR_LOOPBACK
) &&
1305 (cfg
->g_mgmt_pattern
== NULL
)) {
1306 memcpy(&cfg
->g_lchassis
.c_mgmt
,
1308 sizeof(struct in_addr
));
1309 cfg
->g_lchassis
.c_mgmt_if
= if_nametoindex(ifa
->ifa_name
);
1311 else if (cfg
->g_mgmt_pattern
!= NULL
) {
1313 ip
= inet_ntoa(sa
->sin_addr
);
1314 if (fnmatch(cfg
->g_mgmt_pattern
,
1316 memcpy(&cfg
->g_lchassis
.c_mgmt
,
1318 sizeof(struct in_addr
));
1319 cfg
->g_lchassis
.c_mgmt_if
=
1320 if_nametoindex(ifa
->ifa_name
);
1325 if (ifa
->ifa_addr
== NULL
||
1326 ifa
->ifa_addr
->sa_family
!= PF_PACKET
)
1329 sdl
= (struct sockaddr_ll
*)ifa
->ifa_addr
;
1330 if (sdl
->sll_hatype
!= ARPHRD_ETHER
|| !sdl
->sll_halen
)
1333 if (iface_is_bridge(cfg
, ifa
->ifa_name
)) {
1334 cfg
->g_lchassis
.c_cap_enabled
|= LLDP_CAP_BRIDGE
;
1338 if ((iface_is_vlan(cfg
, ifa
->ifa_name
)) ||
1339 (iface_is_bond(cfg
, ifa
->ifa_name
)))
1342 if (!(ifa
->ifa_flags
& IFF_MULTICAST
))
1345 if (iface_is_wireless(cfg
, ifa
->ifa_name
))
1346 cfg
->g_lchassis
.c_cap_enabled
|= LLDP_CAP_WLAN
;
1348 if (lldpd_port_add(cfg
, ifa
) == NULL
)
1349 LLOG_WARNX("failed to allocate port %s, skip it",
1354 if (cfg
->g_listen_vlans
) {
1355 for (ifa
= ifap
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
1356 if ((iface_is_vlan(cfg
, ifa
->ifa_name
)) &&
1357 (lldpd_port_add_vlan(cfg
, ifa
) == NULL
)) {
1358 LLOG_WARNX("unable to allocate vlan %s, skip it",
1368 lldpd_send_all(cfg
);
1369 lldpd_recv_all(cfg
);
1373 lldpd_shutdown(int sig
)
1375 LLOG_INFO("signal received, exiting");
1379 /* For signal handling */
1380 struct lldpd
*gcfg
= NULL
;
1385 struct lldpd_hardware
*hardware
;
1386 struct lldpd_vif
*vif
;
1389 TAILQ_FOREACH(hardware
, &gcfg
->g_hardware
, h_entries
) {
1390 if (INTERFACE_OPENED(hardware
))
1391 lldpd_iface_close(gcfg
, hardware
);
1393 TAILQ_FOREACH(vif
, &gcfg
->g_vif
, vif_entries
) {
1394 if (vif
->vif_raw
!= -1)
1395 lldpd_iface_close(gcfg
, (struct lldpd_hardware
*)vif
);
1400 #endif /* USE_SNMP */
1404 main(int argc
, char *argv
[])
1412 char *popt
, opts
[] = "vdxm:p:M:i@ ";
1413 int probe
= 0, i
, found
, vlan
= 0;
1414 #ifdef ENABLE_LLDPMED
1415 int lldpmed
= 0, noinventory
= 0;
1421 * Get and parse command line options
1423 popt
= index(opts
, '@');
1424 for (i
=0; protos
[i
].mode
!= 0; i
++) {
1425 if (protos
[i
].enabled
== 1) continue;
1426 *(popt
++) = protos
[i
].arg
;
1429 while ((ch
= getopt(argc
, argv
, opts
)) != -1) {
1440 #ifdef ENABLE_LLDPMED
1442 lldpmed
= atoi(optarg
);
1443 if ((lldpmed
< 1) || (lldpmed
> 4)) {
1444 fprintf(stderr
, "-M requires an argument between 1 and 4\n");
1455 fprintf(stderr
, "LLDP-MED support is not built-in\n");
1460 probe
= atoi(optarg
);
1466 fprintf(stderr
, "SNMP support is not built-in\n");
1472 for (i
=0; protos
[i
].mode
!= 0; i
++) {
1473 if (protos
[i
].enabled
) continue;
1474 if (ch
== protos
[i
].arg
) {
1475 protos
[i
].enabled
= 1;
1489 if (daemon(0, 0) != 0)
1490 fatal("failed to detach daemon");
1491 if ((pid
= open(LLDPD_PID_FILE
,
1492 O_TRUNC
| O_CREAT
| O_WRONLY
, 0644)) == -1)
1493 fatal("unable to open pid file " LLDPD_PID_FILE
);
1494 if (asprintf(&spid
, "%d\n", getpid()) == -1)
1495 fatal("unable to create pid file " LLDPD_PID_FILE
);
1496 if (write(pid
, spid
, strlen(spid
)) == -1)
1497 fatal("unable to write pid file " LLDPD_PID_FILE
);
1502 priv_init(PRIVSEP_CHROOT
);
1504 if (probe
== 0) probe
= LLDPD_TTL
;
1506 if ((cfg
= (struct lldpd
*)
1507 calloc(1, sizeof(struct lldpd
))) == NULL
)
1510 cfg
->g_mgmt_pattern
= mgmtp
;
1511 cfg
->g_listen_vlans
= vlan
;
1513 /* Get ioctl socket */
1514 if ((cfg
->g_sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
1515 fatal("failed to get ioctl socket");
1516 cfg
->g_delay
= LLDPD_TX_DELAY
;
1518 /* Set system capabilities */
1519 cfg
->g_lchassis
.c_cap_available
= LLDP_CAP_BRIDGE
| LLDP_CAP_WLAN
|
1521 #ifdef ENABLE_LLDPMED
1523 if (lldpmed
== LLDPMED_CLASS_III
)
1524 cfg
->g_lchassis
.c_cap_available
|= LLDP_CAP_TELEPHONE
;
1525 cfg
->g_lchassis
.c_med_type
= lldpmed
;
1526 cfg
->g_lchassis
.c_med_cap_available
= LLDPMED_CAP_CAP
|
1527 LLDPMED_CAP_IV
| LLDPMED_CAP_LOCATION
;
1528 cfg
->g_noinventory
= noinventory
;
1533 cfg
->g_lchassis
.c_ttl
= LLDPD_TTL
;
1535 cfg
->g_protocols
= protos
;
1536 cfg
->g_probe_time
= probe
;
1537 for (i
=0; protos
[i
].mode
!= 0; i
++)
1538 if (protos
[i
].enabled
) {
1540 LLOG_INFO("protocol %s enabled", protos
[i
].name
);
1542 LLOG_INFO("protocol %s disabled", protos
[i
].name
);
1545 TAILQ_INIT(&cfg
->g_hardware
);
1546 TAILQ_INIT(&cfg
->g_vif
);
1551 agent_init(cfg
, debug
);
1553 #endif /* USE_SNMP */
1556 if ((cfg
->g_ctl
= priv_ctl_create(cfg
)) == -1)
1557 fatalx("unable to create control socket " LLDPD_CTL_SOCKET
);
1558 TAILQ_INIT(&cfg
->g_clients
);
1561 if (atexit(lldpd_exit
) != 0) {
1564 fatal("unable to set exit function");
1567 /* Signal handling */
1568 signal(SIGHUP
, lldpd_shutdown
);
1569 signal(SIGINT
, lldpd_shutdown
);
1570 signal(SIGTERM
, lldpd_shutdown
);