1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2012 Vincent Bernat <bernat@luffy.cx>
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 #include <sys/param.h>
25 #include <sys/sysctl.h>
26 #include <sys/ioctl.h>
28 #include <net/if_types.h>
29 #include <net/if_media.h>
30 #include <net/if_dl.h>
31 #if defined HOST_OS_FREEBSD
32 # include <net/if_vlan_var.h>
33 # include <net/if_bridgevar.h>
34 # include <net/if_lagg.h>
35 #elif defined HOST_OS_DRAGONFLY
36 # include <net/vlan/if_vlan_var.h>
37 # include <net/bridge/if_bridgevar.h>
38 #elif defined HOST_OS_OPENBSD
39 # include <net/if_vlan_var.h>
40 # include <net/if_bridge.h>
41 # include <net/if_trunk.h>
42 #elif defined HOST_OS_NETBSD
43 # include <net/if_vlanvar.h>
44 # include <net/if_bridgevar.h>
45 # include <net/agr/if_agrioctl.h>
46 #elif defined HOST_OS_OSX
47 # include <osx/if_vlan_var.h>
48 # include <osx/if_bridgevar.h>
49 # include <osx/if_bond_var.h>
53 #define IFDESCRSIZE 64
57 ifbsd_check_wireless(struct lldpd
*cfg
,
58 struct ifaddrs
*ifaddr
,
59 struct interfaces_device
*iface
)
61 struct ifmediareq ifmr
= {};
62 strlcpy(ifmr
.ifm_name
, iface
->name
, sizeof(ifmr
.ifm_name
));
63 if (ioctl(cfg
->g_sock
, SIOCGIFMEDIA
, (caddr_t
)&ifmr
) < 0 ||
64 IFM_TYPE(ifmr
.ifm_current
) != IFM_IEEE80211
)
65 return 0; /* Not wireless either */
66 iface
->type
|= IFACE_WIRELESS_T
| IFACE_PHYSICAL_T
;
71 ifbsd_check_bridge(struct lldpd
*cfg
,
72 struct interfaces_device_list
*interfaces
,
73 struct interfaces_device
*master
)
75 struct ifbreq req
[64];
76 struct ifbifconf bifc
= {
77 .ifbic_len
= sizeof(req
),
81 #if defined HOST_OS_FREEBSD || defined HOST_OS_NETBSD || defined HOST_OS_OSX || HOST_OS_DRAGONFLY
84 .ifd_len
= sizeof(bifc
),
88 strlcpy(ifd
.ifd_name
, master
->name
, sizeof(ifd
.ifd_name
));
89 if (ioctl(cfg
->g_sock
, SIOCGDRVSPEC
, (caddr_t
)&ifd
) < 0) {
90 log_debug("interfaces",
91 "%s is not a bridge", master
->name
);
94 #elif defined HOST_OS_OPENBSD
95 strlcpy(bifc
.ifbic_name
, master
->name
, sizeof(bifc
.ifbic_name
));
96 if (ioctl(cfg
->g_sock
, SIOCBRDGIFS
, (caddr_t
)&bifc
) < 0) {
97 log_debug("interfaces",
98 "%s is not a bridge", master
->name
);
102 # error Unsupported OS
104 if (bifc
.ifbic_len
>= sizeof(req
)) {
105 log_warnx("interfaces",
106 "%s is a bridge too big. Please, report the problem",
110 for (int i
= 0; i
< bifc
.ifbic_len
/ sizeof(*req
); i
++) {
111 struct interfaces_device
*slave
=
112 interfaces_nametointerface(interfaces
,
113 req
[i
].ifbr_ifsname
);
115 log_warnx("interfaces",
116 "%s should be bridged to %s but we don't know %s",
117 req
[i
].ifbr_ifsname
, master
->name
, req
[i
].ifbr_ifsname
);
120 log_debug("interfaces",
121 "%s is bridged to %s",
122 slave
->name
, master
->name
);
123 slave
->upper
= master
;
125 master
->type
|= IFACE_BRIDGE_T
;
129 ifbsd_check_bond(struct lldpd
*cfg
,
130 struct interfaces_device_list
*interfaces
,
131 struct interfaces_device
*master
)
133 #if defined HOST_OS_OPENBSD
134 /* OpenBSD is the same as FreeBSD, just lagg->trunk */
135 # define lagg_reqport trunk_reqport
136 # define lagg_reqall trunk_reqall
137 # define SIOCGLAGG SIOCGTRUNK
138 # define LAGG_MAX_PORTS TRUNK_MAX_PORTS
140 #if defined HOST_OS_OPENBSD || defined HOST_OS_FREEBSD
141 struct lagg_reqport rpbuf
[LAGG_MAX_PORTS
];
142 struct lagg_reqall ra
= {
143 .ra_size
= sizeof(rpbuf
),
146 strlcpy(ra
.ra_ifname
, master
->name
, IFNAMSIZ
);
147 if (ioctl(cfg
->g_sock
, SIOCGLAGG
, (caddr_t
)&ra
) < 0) {
148 log_debug("interfaces",
149 "%s is not a bond", master
->name
);
153 for (int i
= 0; i
< ra
.ra_ports
; i
++) {
154 struct interfaces_device
*slave
;
155 slave
= interfaces_nametointerface(interfaces
,
156 rpbuf
[i
].rp_portname
);
158 log_warnx("interfaces",
159 "%s should be enslaved to %s but we don't know %s",
160 rpbuf
[i
].rp_portname
, master
->name
,
161 rpbuf
[i
].rp_portname
);
164 log_debug("interfaces",
165 "%s is enslaved to bond %s",
166 slave
->name
, master
->name
);
167 slave
->upper
= master
;
169 master
->type
|= IFACE_BOND_T
;
170 #elif defined HOST_OS_NETBSD
171 /* No max, we consider a maximum of 24 ports */
172 char buf
[sizeof(struct agrportinfo
)*24] = {};
173 size_t buflen
= sizeof(buf
);
175 .ar_version
= AGRREQ_VERSION
,
176 .ar_cmd
= AGRCMD_PORTLIST
,
183 struct agrportlist
*apl
= (void *)buf
;
184 struct agrportinfo
*api
= (void *)(apl
+ 1);
185 strlcpy(ifr
.ifr_name
, master
->name
, sizeof(ifr
.ifr_name
));
186 if (ioctl(cfg
->g_sock
, SIOCGETAGR
, &ifr
) == -1) {
187 if (errno
== E2BIG
) {
188 log_warnx("interfaces",
189 "%s is a too big aggregate. Please, report the problem",
192 log_debug("interfaces",
193 "%s is not an aggregate", master
->name
);
197 for (int i
= 0; i
< apl
->apl_nports
; i
++, api
++) {
198 struct interfaces_device
*slave
;
199 slave
= interfaces_nametointerface(interfaces
,
202 log_warnx("interfaces",
203 "%s should be enslaved to %s but we don't know %s",
204 api
->api_ifname
, master
->name
, api
->api_ifname
);
207 log_debug("interfaces",
208 "%s is enslaved to bond %s",
209 slave
->name
, master
->name
);
210 slave
->upper
= master
;
212 master
->type
|= IFACE_BOND_T
;
213 #elif defined HOST_OS_OSX
214 struct if_bond_req ibr
= {
215 .ibr_op
= IF_BOND_OP_GET_STATUS
,
217 .ibru_status
= { .ibsr_version
= IF_BOND_STATUS_REQ_VERSION
}
221 .ifr_data
= (caddr_t
)&ibr
223 strlcpy(ifr
.ifr_name
, master
->name
, sizeof(ifr
.ifr_name
));
224 if (ioctl(cfg
->g_sock
, SIOCGIFBOND
, (caddr_t
)&ifr
) < 0) {
225 log_debug("interfaces",
226 "%s is not an aggregate", master
->name
);
229 master
->type
|= IFACE_BOND_T
;
230 if (ibr
.ibr_ibru
.ibru_status
.ibsr_total
== 0) {
231 log_debug("interfaces", "no members for bond %s",
236 struct if_bond_status_req
*ibsr_p
= &ibr
.ibr_ibru
.ibru_status
;
237 ibsr_p
->ibsr_buffer
=
238 malloc(sizeof(struct if_bond_status
)*ibsr_p
->ibsr_total
);
239 if (ibsr_p
->ibsr_buffer
== NULL
) {
240 log_warnx("interfaces", "not enough memory to check bond members");
243 ibsr_p
->ibsr_count
= ibsr_p
->ibsr_total
;
244 if (ioctl(cfg
->g_sock
, SIOCGIFBOND
, (caddr_t
)&ifr
) < 0) {
245 log_warn("interfaces",
246 "unable to get members for bond %s", master
->name
);
250 struct if_bond_status
*ibs_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
;
251 for (int i
= 0; i
< ibsr_p
->ibsr_total
; i
++, ibs_p
++) {
252 struct interfaces_device
*slave
;
253 slave
= interfaces_nametointerface(interfaces
,
256 log_warnx("interfaces",
257 "%s should be enslaved to %s but we don't know %s",
258 ibs_p
->ibs_if_name
, master
->name
, ibs_p
->ibs_if_name
);
261 log_debug("interfaces", "%s is enslaved to bond %s",
262 slave
->name
, master
->name
);
263 slave
->upper
= master
;
266 free(ibsr_p
->ibsr_buffer
);
267 #elif defined HOST_OS_DRAGONFLY
268 log_debug("interfaces", "DragonFly BSD does not support link aggregation");
270 # error Unsupported OS
275 ifbsd_check_vlan(struct lldpd
*cfg
,
276 struct interfaces_device_list
*interfaces
,
277 struct interfaces_device
*vlan
)
279 struct interfaces_device
*lower
;
280 struct vlanreq vreq
= {};
282 .ifr_data
= (caddr_t
)&vreq
284 strlcpy(ifr
.ifr_name
, vlan
->name
, sizeof(ifr
.ifr_name
));
285 if (ioctl(cfg
->g_sock
, SIOCGETVLAN
, (caddr_t
)&ifr
) < 0) {
286 log_debug("interfaces",
287 "%s is not a VLAN", vlan
->name
);
290 if (strlen(vreq
.vlr_parent
) == 0) {
291 log_debug("interfaces",
292 "%s is a VLAN but has no lower interface",
295 vlan
->type
|= IFACE_VLAN_T
;
298 lower
= interfaces_nametointerface(interfaces
,
301 log_warnx("interfaces",
302 "%s should be a VLAN of %s but %s does not exist",
303 vlan
->name
, vreq
.vlr_parent
, vreq
.vlr_parent
);
306 log_debug("interfaces",
307 "%s is VLAN %d of %s",
308 vlan
->name
, vreq
.vlr_tag
, lower
->name
);
310 bitmap_set(vlan
->vlan_bmap
, vreq
.vlr_tag
);
311 vlan
->type
|= IFACE_VLAN_T
;
315 ifbsd_check_physical(struct lldpd
*cfg
,
316 struct interfaces_device_list
*interfaces
,
317 struct interfaces_device
*iface
)
319 if (iface
->type
& (IFACE_VLAN_T
|
320 IFACE_BOND_T
|IFACE_BRIDGE_T
|IFACE_PHYSICAL_T
))
323 if (!(iface
->flags
& (IFF_MULTICAST
|IFF_BROADCAST
))) {
324 log_debug("interfaces", "skip %s: not able to do multicast nor broadcast",
328 log_debug("interfaces",
329 "%s is a physical interface",
331 iface
->type
|= IFACE_PHYSICAL_T
;
334 /* Blacklist any dangerous interface. Currently, only p2p0 is blacklisted as it
335 * triggers some AirDrop functionality when we send something on it.
336 * See: https://github.com/vincentbernat/lldpd/issues/61
339 ifbsd_blacklist(struct lldpd
*cfg
,
340 struct interfaces_device_list
*interfaces
)
343 struct interfaces_device
*iface
= NULL
;
344 TAILQ_FOREACH(iface
, interfaces
, next
) {
346 if (strncmp(iface
->name
, "p2p", 3)) continue;
347 if (strlen(iface
->name
) < 4) continue;
349 iface
->name
[i
] != '\0' && isdigit(iface
->name
[i
]);
351 if (iface
->name
[i
] == '\0') {
352 log_debug("interfaces", "skip %s: AirDrop interface",
360 static struct interfaces_device
*
361 ifbsd_extract_device(struct lldpd
*cfg
,
362 struct ifaddrs
*ifaddr
)
364 struct interfaces_device
*iface
= NULL
;
365 struct sockaddr_dl
*saddrdl
= ALIGNED_CAST(struct sockaddr_dl
*, ifaddr
->ifa_addr
);
366 if ((saddrdl
->sdl_type
!= IFT_BRIDGE
) &&
367 (saddrdl
->sdl_type
!= IFT_L2VLAN
) &&
368 (saddrdl
->sdl_type
!= IFT_ETHER
)) {
369 log_debug("interfaces", "skip %s: not an ethernet device (%d)",
370 ifaddr
->ifa_name
, saddrdl
->sdl_type
);
373 if ((iface
= calloc(1, sizeof(struct interfaces_device
))) == NULL
) {
374 log_warn("interfaces", "unable to allocate memory for %s",
379 iface
->index
= saddrdl
->sdl_index
;
380 iface
->name
= strdup(ifaddr
->ifa_name
);
381 iface
->flags
= ifaddr
->ifa_flags
;
384 iface
->address
= malloc(ETHER_ADDR_LEN
);
386 memcpy(iface
->address
, LLADDR(saddrdl
), ETHER_ADDR_LEN
);
388 /* Grab description */
390 #if defined HOST_OS_FREEBSD || defined HOST_OS_OPENBSD
391 iface
->alias
= malloc(IFDESCRSIZE
);
393 #if defined HOST_OS_FREEBSD
395 .ifr_buffer
= { .buffer
= iface
->alias
,
396 .length
= IFDESCRSIZE
}
400 .ifr_data
= (caddr_t
)iface
->alias
403 strlcpy(ifr
.ifr_name
, ifaddr
->ifa_name
, sizeof(ifr
.ifr_name
));
404 if (ioctl(cfg
->g_sock
, SIOCGIFDESCR
, (caddr_t
)&ifr
) < 0) {
410 #endif /* SIOCGIFDESCR */
412 if (ifbsd_check_wireless(cfg
, ifaddr
, iface
) == -1) {
413 interfaces_free_device(iface
);
421 ifbsd_extract(struct lldpd
*cfg
,
422 struct interfaces_device_list
*interfaces
,
423 struct interfaces_address_list
*addresses
,
424 struct ifaddrs
*ifaddr
)
426 struct interfaces_address
*address
= NULL
;
427 struct interfaces_device
*device
= NULL
;
428 if (!ifaddr
->ifa_name
) return;
429 if (!ifaddr
->ifa_addr
) return;
430 switch (ifaddr
->ifa_addr
->sa_family
) {
432 log_debug("interfaces",
433 "grabbing information on interface %s",
435 device
= ifbsd_extract_device(cfg
, ifaddr
);
437 TAILQ_INSERT_TAIL(interfaces
, device
, next
);
441 log_debug("interfaces",
442 "got an IP address on %s",
444 address
= malloc(sizeof(struct interfaces_address
));
445 if (address
== NULL
) {
446 log_warn("interfaces",
447 "not enough memory for a new IP address on %s",
451 address
->flags
= ifaddr
->ifa_flags
;
452 address
->index
= if_nametoindex(ifaddr
->ifa_name
);
453 memcpy(&address
->address
,
455 (ifaddr
->ifa_addr
->sa_family
== AF_INET
)?
456 sizeof(struct sockaddr_in
):
457 sizeof(struct sockaddr_in6
));
458 TAILQ_INSERT_TAIL(addresses
, address
, next
);
461 log_debug("interfaces", "unhandled family %d for interface %s",
462 ifaddr
->ifa_addr
->sa_family
,
468 ifbsd_macphy(struct lldpd
*cfg
,
469 struct lldpd_hardware
*hardware
)
472 struct ifmediareq ifmr
= {};
474 typeof(ifmr
.ifm_ulist
[0]) media_list
[32] = {};
476 int media_list
[32] = {};
478 ifmr
.ifm_ulist
= media_list
;
480 struct lldpd_port
*port
= &hardware
->h_lport
;
483 int advertised_ifmedia_to_rfc3636
[][3] = {
485 LLDP_DOT3_LINK_AUTONEG_10BASE_T
,
486 LLDP_DOT3_LINK_AUTONEG_10BASET_FD
},
488 LLDP_DOT3_LINK_AUTONEG_10BASE_T
,
489 LLDP_DOT3_LINK_AUTONEG_10BASET_FD
},
491 LLDP_DOT3_LINK_AUTONEG_100BASE_TX
,
492 LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD
},
494 LLDP_DOT3_LINK_AUTONEG_100BASE_T4
,
495 LLDP_DOT3_LINK_AUTONEG_100BASE_T4
},
497 LLDP_DOT3_LINK_AUTONEG_100BASE_T2
,
498 LLDP_DOT3_LINK_AUTONEG_100BASE_T2FD
},
500 LLDP_DOT3_LINK_AUTONEG_1000BASE_X
,
501 LLDP_DOT3_LINK_AUTONEG_1000BASE_XFD
},
503 LLDP_DOT3_LINK_AUTONEG_1000BASE_X
,
504 LLDP_DOT3_LINK_AUTONEG_1000BASE_XFD
},
506 LLDP_DOT3_LINK_AUTONEG_1000BASE_X
,
507 LLDP_DOT3_LINK_AUTONEG_1000BASE_XFD
},
509 LLDP_DOT3_LINK_AUTONEG_1000BASE_T
,
510 LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD
},
513 int current_ifmedia_to_rfc3636
[][3] = {
515 LLDP_DOT3_MAU_10BASETHD
, LLDP_DOT3_MAU_10BASETFD
},
517 LLDP_DOT3_MAU_10BASETHD
, LLDP_DOT3_MAU_10BASETFD
},
519 LLDP_DOT3_MAU_10BASE2
, LLDP_DOT3_MAU_10BASE2
},
521 LLDP_DOT3_MAU_10BASE5
, LLDP_DOT3_MAU_10BASE5
},
523 LLDP_DOT3_MAU_100BASETXHD
, LLDP_DOT3_MAU_100BASETXFD
},
525 LLDP_DOT3_MAU_100BASEFXHD
, LLDP_DOT3_MAU_100BASEFXFD
},
527 LLDP_DOT3_MAU_100BASET2HD
, LLDP_DOT3_MAU_100BASET2FD
},
529 LLDP_DOT3_MAU_1000BASESXHD
, LLDP_DOT3_MAU_1000BASESXFD
},
531 LLDP_DOT3_MAU_10BASEFLHD
, LLDP_DOT3_MAU_10BASEFLFD
},
533 LLDP_DOT3_MAU_1000BASELXHD
, LLDP_DOT3_MAU_1000BASELXFD
},
535 LLDP_DOT3_MAU_1000BASECXHD
, LLDP_DOT3_MAU_1000BASECXFD
},
537 LLDP_DOT3_MAU_1000BASETHD
, LLDP_DOT3_MAU_1000BASETFD
},
539 LLDP_DOT3_MAU_10GIGBASELR
, LLDP_DOT3_MAU_10GIGBASELR
},
541 LLDP_DOT3_MAU_10GIGBASESR
, LLDP_DOT3_MAU_10GIGBASESR
},
543 LLDP_DOT3_MAU_10GIGBASELX4
, LLDP_DOT3_MAU_10GIGBASELX4
},
546 LLDP_DOT3_MAU_10GIGBASECX4
, LLDP_DOT3_MAU_10GIGBASECX4
},
548 #ifdef IFM_10G_TWINAX
550 LLDP_DOT3_MAU_10GIGBASECX4
, LLDP_DOT3_MAU_10GIGBASECX4
},
552 #ifdef IFM_10G_TWINAX_LONG
553 {IFM_10G_TWINAX_LONG
,
554 LLDP_DOT3_MAU_10GIGBASECX4
, LLDP_DOT3_MAU_10GIGBASECX4
},
558 LLDP_DOT3_MAU_10GIGBASELR
, LLDP_DOT3_MAU_10GIGBASELR
},
560 #ifdef IFM_10G_SFP_CU
562 LLDP_DOT3_MAU_10GIGBASECX4
, LLDP_DOT3_MAU_10GIGBASECX4
},
567 log_debug("interfaces", "get MAC/phy for %s",
569 strlcpy(ifmr
.ifm_name
, hardware
->h_ifname
, sizeof(ifmr
.ifm_name
));
570 if (ioctl(cfg
->g_sock
, SIOCGIFMEDIA
, (caddr_t
)&ifmr
) < 0) {
571 log_debug("interfaces",
572 "unable to get media information from %s",
576 if (IFM_TYPE(ifmr
.ifm_current
) != IFM_ETHER
) {
577 log_warnx("interfaces",
578 "cannot get media information from %s: not an ethernet device",
582 if ((ifmr
.ifm_status
& IFM_ACTIVE
) == 0) {
583 log_debug("interfaces",
584 "interface %s is now down, skip",
588 if (ifmr
.ifm_count
== 0) {
589 log_warnx("interfaces", "no media information available on %s",
593 port
->p_macphy
.autoneg_support
=
594 port
->p_macphy
.autoneg_enabled
= 0;
595 for (int m
= 0; m
< ifmr
.ifm_count
; m
++) {
596 media
= IFM_SUBTYPE(ifmr
.ifm_ulist
[m
]);
597 duplex
= !!(IFM_OPTIONS(ifmr
.ifm_ulist
[m
]) &
599 if (media
== IFM_AUTO
) {
600 port
->p_macphy
.autoneg_support
= 1;
601 port
->p_macphy
.autoneg_enabled
=
602 (IFM_SUBTYPE(ifmr
.ifm_current
) == IFM_AUTO
);
607 for (int j
= 0; advertised_ifmedia_to_rfc3636
[j
][0]; j
++) {
608 if (advertised_ifmedia_to_rfc3636
[j
][0] == media
) {
609 port
->p_macphy
.autoneg_advertised
|=
610 advertised_ifmedia_to_rfc3636
[j
][1 + duplex
];
615 if (!found
) port
->p_macphy
.autoneg_advertised
|= \
616 LLDP_DOT3_LINK_AUTONEG_OTHER
;
619 port
->p_macphy
.mau_type
= 0;
620 media
= IFM_SUBTYPE(ifmr
.ifm_active
);
621 duplex
= !!(IFM_OPTIONS(ifmr
.ifm_active
) & IFM_FDX
);
622 for (int j
= 0; current_ifmedia_to_rfc3636
[j
][0]; j
++) {
623 if (current_ifmedia_to_rfc3636
[j
][0] == media
) {
624 port
->p_macphy
.mau_type
=
625 current_ifmedia_to_rfc3636
[j
][1 + duplex
];
632 extern struct lldpd_ops bpf_ops
;
634 interfaces_update(struct lldpd
*cfg
)
636 struct lldpd_hardware
*hardware
;
637 struct interfaces_device
*iface
;
638 struct interfaces_device_list
*interfaces
;
639 struct interfaces_address_list
*addresses
;
640 struct ifaddrs
*ifaddrs
= NULL
, *ifaddr
;
642 interfaces
= malloc(sizeof(struct interfaces_device_list
));
643 addresses
= malloc(sizeof(struct interfaces_address_list
));
644 if (interfaces
== NULL
|| addresses
== NULL
) {
645 log_warnx("interfaces", "unable to allocate memory");
648 TAILQ_INIT(interfaces
);
649 TAILQ_INIT(addresses
);
650 if (getifaddrs(&ifaddrs
) < 0) {
651 log_warnx("interfaces", "unable to get list of interfaces");
655 for (ifaddr
= ifaddrs
;
657 ifaddr
= ifaddr
->ifa_next
) {
658 ifbsd_extract(cfg
, interfaces
, addresses
, ifaddr
);
660 /* Link interfaces together if needed */
661 TAILQ_FOREACH(iface
, interfaces
, next
) {
662 ifbsd_check_bridge(cfg
, interfaces
, iface
);
663 ifbsd_check_bond(cfg
, interfaces
, iface
);
664 ifbsd_check_vlan(cfg
, interfaces
, iface
);
665 ifbsd_check_physical(cfg
, interfaces
, iface
);
668 ifbsd_blacklist(cfg
, interfaces
);
669 interfaces_helper_whitelist(cfg
, interfaces
);
670 interfaces_helper_physical(cfg
, interfaces
,
671 &bpf_ops
, ifbpf_phys_init
);
673 interfaces_helper_vlan(cfg
, interfaces
);
675 interfaces_helper_mgmt(cfg
, addresses
, interfaces
);
676 interfaces_helper_chassis(cfg
, interfaces
);
679 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
680 if (!hardware
->h_flags
) continue;
681 ifbsd_macphy(cfg
, hardware
);
682 interfaces_helper_promisc(cfg
, hardware
);
685 if (cfg
->g_iface_event
== NULL
) {
687 log_debug("interfaces", "subscribe to route socket notifications");
688 if ((s
= socket(PF_ROUTE
, SOCK_RAW
, 0)) < 0) {
689 log_warn("interfaces", "unable to open route socket");
693 #ifdef ROUTE_MSGFILTER
694 unsigned int rtfilter
;
695 rtfilter
= ROUTE_FILTER(RTM_IFINFO
);
696 if (setsockopt(s
, PF_ROUTE
, ROUTE_MSGFILTER
,
697 &rtfilter
, sizeof(rtfilter
)) == -1)
698 log_warn("interfaces", "unable to set filter for interface updates");
701 if (levent_iface_subscribe(cfg
, s
) == -1)
706 interfaces_free_devices(interfaces
);
707 interfaces_free_addresses(addresses
);
708 if (ifaddrs
) freeifaddrs(ifaddrs
);
712 interfaces_cleanup(struct lldpd
*cfg
)