# Checks for header files.
AC_HEADER_RESOLV
AC_CHECK_HEADERS([valgrind/valgrind.h])
+lldp_CHECK_STDINT
AC_CACHE_SAVE
lldp_DEFINE_OS(openbsd*, OpenBSD, OPENBSD)
lldp_DEFINE_OS(netbsd*, NetBSD, NETBSD)
lldp_DEFINE_OS(darwin*, [Mac OS X], OSX)
+ lldp_DEFINE_OS(solaris*, Solaris, SOLARIS)
if test x"$os" = x; then
AC_MSG_RESULT(no)
--- /dev/null
+#
+# lldp_CHECK_STDINT
+#
+AC_DEFUN([lldp_CHECK_STDINT], [
+ AC_CHECK_TYPES([u_int32_t, uint32_t])
+ if test "_$ac_cv_type_uint32_t" = _yes; then
+ if test "_$ac_cv_type_u_int32_t" = _no; then
+ AC_DEFINE(u_int8_t, uint8_t, [Compatibility with Linux u_int8_t])
+ AC_DEFINE(u_int16_t, uint16_t, [Compatibility with Linux u_int16_t])
+ AC_DEFINE(u_int32_t, uint32_t, [Compatibility with Linux u_int32_t])
+ AC_DEFINE(u_int64_t, uint64_t, [Compatibility with Linux u_int64_t])
+ fi
+ fi])
#define _GNU_SOURCE
#include <stdio.h>
-#include <sys/cdefs.h>
#include <sys/types.h>
#include <string.h>
#define LLDPD_CTL_SOCKET "/var/run/lldpd.socket"
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include <stdint.h>
#include "marshal.h"
if HOST_OS_LINUX
liblldpd_la_SOURCES += \
+ forward-linux.c \
interfaces-linux.c \
netlink.c \
dmi-linux.c
endif
if HOST_OS_DRAGONFLY
liblldpd_la_SOURCES += \
+ forward-bsd.c \
+ interfaces-bpf.c \
interfaces-bsd.c \
dmi-dummy.c
endif
if HOST_OS_FREEBSD
liblldpd_la_SOURCES += \
+ forward-bsd.c \
+ interfaces-bpf.c \
interfaces-bsd.c \
dmi-freebsd.c
endif
if HOST_OS_OPENBSD
liblldpd_la_SOURCES += \
+ interfaces-bpf.c \
+ forward-bsd.c \
interfaces-bsd.c \
dmi-openbsd.c
endif
if HOST_OS_NETBSD
liblldpd_la_SOURCES += \
+ forward-bsd.c \
+ interfaces-bpf.c \
interfaces-bsd.c \
dmi-dummy.c
endif
if HOST_OS_OSX
liblldpd_la_SOURCES += \
+ forward-bsd.c \
+ interfaces-bpf.c \
interfaces-bsd.c \
dmi-osx.c
liblldpd_la_LDFLAGS = -framework Foundation
liblldpd_la_LDFLAGS += -framework CoreFoundation -framework IOKit
liblldpd_la_LDFLAGS += -framework IOKit
endif
+if HOST_OS_SOLARIS
+liblldpd_la_SOURCES += \
+ forward-solaris.c \
+ interfaces-bpf.c \
+ interfaces-solaris.c \
+ dmi-dummy.c
+endif
# Add SNMP support if needed
if USE_SNMP
--- /dev/null
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2013 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "lldpd.h"
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+int
+interfaces_routing_enabled(struct lldpd *cfg) {
+ (void)cfg;
+ int n, mib[4] = {
+ CTL_NET,
+ PF_INET,
+ IPPROTO_IP,
+ IPCTL_FORWARDING
+ };
+ size_t len = sizeof(int);
+ if (sysctl(mib, 4, &n, &len, NULL, 0) != -1)
+ return (n == 1);
+ return -1;
+}
--- /dev/null
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2013 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "lldpd.h"
+
+#include <unistd.h>
+
+int
+interfaces_routing_enabled(struct lldpd *cfg) {
+ (void)cfg;
+ int f;
+ char status;
+ int rc;
+ if ((f = priv_open("/proc/sys/net/ipv4/ip_forward")) >= 0) {
+ if (read(f, &status, 1) == 1) {
+ rc = (status == '1');
+ } else rc = -1;
+ close(f);
+ return rc;
+ }
+ return -1;
+}
--- /dev/null
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2013 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "lldpd.h"
+#include <unistd.h>
+#include <stropts.h>
+#include <inet/tunables.h>
+#include <sys/sockio.h>
+
+int
+interfaces_routing_enabled(struct lldpd *cfg) {
+ int rc;
+ size_t iocsize = sizeof(mod_ioc_prop_t) + 1;
+ mod_ioc_prop_t *mip = calloc(1, iocsize);
+ if (mip == NULL) {
+ log_warn("interfaces", "unable to allocate memory for ioctl");
+ return -1;
+ }
+ mip->mpr_version = MOD_PROP_VERSION;
+ mip->mpr_flags = MOD_PROP_ACTIVE;
+ mip->mpr_proto = MOD_PROTO_IPV4;
+ mip->mpr_valsize = iocsize + 1 - sizeof(mod_ioc_prop_t);
+ strlcpy(mip->mpr_name, "forwarding", sizeof(mip->mpr_name));
+ struct strioctl ioc = {
+ .ic_cmd = SIOCGETPROP,
+ .ic_timout = 0,
+ .ic_len = iocsize,
+ .ic_dp = (char*)mip
+ };
+ if (ioctl(cfg->g_sock, I_STR, &ioc) == -1) {
+ free(mip);
+ log_debug("interfaces", "unable to get value for IPv4 forwarding");
+ return -1;
+ }
+
+ rc = (*mip->mpr_val == '1');
+ free(mip);
+ return rc;
+}
--- /dev/null
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2013 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "lldpd.h"
+#include <unistd.h>
+#include <net/bpf.h>
+
+struct bpf_buffer {
+ size_t len; /* Total length of the buffer */
+ char data[0]; /* Data */
+};
+
+int
+ifbpf_phys_init(struct lldpd *cfg,
+ struct lldpd_hardware *hardware)
+{
+ struct bpf_buffer *buffer = NULL;
+ int fd = -1;
+
+ log_debug("interfaces", "initialize ethernet device %s",
+ hardware->h_ifname);
+ if ((fd = priv_iface_init(hardware->h_ifindex, hardware->h_ifname)) == -1)
+ return -1;
+
+ /* Allocate receive buffer */
+ hardware->h_data = buffer =
+ malloc(ETHER_MAX_LEN + sizeof(struct bpf_buffer));
+ if (buffer == NULL) {
+ log_warn("interfaces",
+ "unable to allocate buffer space for BPF on %s",
+ hardware->h_ifname);
+ goto end;
+ }
+ buffer->len = ETHER_MAX_LEN;
+
+ /* Setup multicast */
+ interfaces_setup_multicast(cfg, hardware->h_ifname, 0);
+
+ hardware->h_sendfd = fd; /* Send */
+
+ levent_hardware_add_fd(hardware, fd); /* Receive */
+ log_debug("interfaces", "interface %s initialized (fd=%d)", hardware->h_ifname,
+ fd);
+ return 0;
+
+end:
+ if (fd >= 0) close(fd);
+ free(buffer);
+ hardware->h_data = NULL;
+ return -1;
+}
+
+/* Ethernet send/receive through BPF */
+static int
+ifbpf_eth_send(struct lldpd *cfg, struct lldpd_hardware *hardware,
+ char *buffer, size_t size)
+{
+ log_debug("interfaces", "send PDU to ethernet device %s (fd=%d)",
+ hardware->h_ifname, hardware->h_sendfd);
+ return write(hardware->h_sendfd,
+ buffer, size);
+}
+
+static int
+ifbpf_eth_recv(struct lldpd *cfg,
+ struct lldpd_hardware *hardware,
+ int fd, char *buffer, size_t size)
+{
+ struct bpf_buffer *bpfbuf = hardware->h_data;
+ struct bpf_hdr *bh;
+ log_debug("interfaces", "receive PDU from ethernet device %s",
+ hardware->h_ifname);
+
+ /* We assume we have only receive one packet (unbuffered mode). Dunno if
+ * this is correct. */
+ if (read(fd, bpfbuf->data, bpfbuf->len) == -1) {
+ log_warn("interfaces", "error while receiving frame on %s",
+ hardware->h_ifname);
+ hardware->h_rx_discarded_cnt++;
+ return -1;
+ }
+ bh = (struct bpf_hdr*)bpfbuf->data;
+ if (bh->bh_caplen < size)
+ size = bh->bh_caplen;
+ memcpy(buffer, bpfbuf->data + bh->bh_hdrlen, size);
+
+ return size;
+}
+
+static int
+ifbpf_eth_close(struct lldpd *cfg, struct lldpd_hardware *hardware)
+{
+ log_debug("interfaces", "close ethernet device %s",
+ hardware->h_ifname);
+ interfaces_setup_multicast(cfg, hardware->h_ifname, 1);
+ return 0;
+}
+
+struct lldpd_ops bpf_ops = {
+ .send = ifbpf_eth_send,
+ .recv = ifbpf_eth_recv,
+ .cleanup = ifbpf_eth_close,
+};
#endif
}
-struct bpf_buffer {
- size_t len; /* Total length of the buffer */
- char data[0]; /* Data */
-};
-
-static int
-ifbsd_phys_init(struct lldpd *cfg,
- struct lldpd_hardware *hardware)
-{
- struct bpf_buffer *buffer = NULL;
- int fd = -1;
-
- log_debug("interfaces", "initialize ethernet device %s",
- hardware->h_ifname);
- if ((fd = priv_iface_init(hardware->h_ifindex, hardware->h_ifname)) == -1)
- return -1;
-
- /* Allocate receive buffer */
- hardware->h_data = buffer =
- malloc(ETHER_MAX_LEN + sizeof(struct bpf_buffer));
- if (buffer == NULL) {
- log_warn("interfaces",
- "unable to allocate buffer space for BPF on %s",
- hardware->h_ifname);
- goto end;
- }
- buffer->len = ETHER_MAX_LEN;
-
- /* Setup multicast */
- interfaces_setup_multicast(cfg, hardware->h_ifname, 0);
-
- hardware->h_sendfd = fd; /* Send */
-
- levent_hardware_add_fd(hardware, fd); /* Receive */
- log_debug("interfaces", "interface %s initialized (fd=%d)", hardware->h_ifname,
- fd);
- return 0;
-
-end:
- if (fd >= 0) close(fd);
- free(buffer);
- hardware->h_data = NULL;
- return -1;
-}
-
-/* Ethernet send/receive through BPF */
-static int
-ifbsd_eth_send(struct lldpd *cfg, struct lldpd_hardware *hardware,
- char *buffer, size_t size)
-{
- log_debug("interfaces", "send PDU to ethernet device %s (fd=%d)",
- hardware->h_ifname, hardware->h_sendfd);
- return write(hardware->h_sendfd,
- buffer, size);
-}
-
-static int
-ifbsd_eth_recv(struct lldpd *cfg,
- struct lldpd_hardware *hardware,
- int fd, char *buffer, size_t size)
-{
- struct bpf_buffer *bpfbuf = hardware->h_data;
- struct bpf_hdr *bh;
- log_debug("interfaces", "receive PDU from ethernet device %s",
- hardware->h_ifname);
-
- /* We assume we have only receive one packet (unbuffered mode). Dunno if
- * this is correct. */
- if (read(fd, bpfbuf->data, bpfbuf->len) == -1) {
- log_warn("interfaces", "error while receiving frame on %s",
- hardware->h_ifname);
- hardware->h_rx_discarded_cnt++;
- return -1;
- }
- bh = (struct bpf_hdr*)bpfbuf->data;
- if (bh->bh_caplen < size)
- size = bh->bh_caplen;
- memcpy(buffer, bpfbuf->data + bh->bh_hdrlen, size);
-
- return size;
-}
-
-static int
-ifbsd_eth_close(struct lldpd *cfg, struct lldpd_hardware *hardware)
-{
- log_debug("interfaces", "close ethernet device %s",
- hardware->h_ifname);
- interfaces_setup_multicast(cfg, hardware->h_ifname, 1);
- return 0;
-}
-
-static struct lldpd_ops eth_ops = {
- .send = ifbsd_eth_send,
- .recv = ifbsd_eth_recv,
- .cleanup = ifbsd_eth_close,
-};
-
+extern struct lldpd_ops bpf_ops;
void
interfaces_update(struct lldpd *cfg)
{
interfaces_helper_whitelist(cfg, interfaces);
interfaces_helper_physical(cfg, interfaces,
- ð_ops, ifbsd_phys_init);
+ &bpf_ops, ifbpf_phys_init);
#ifdef ENABLE_DOT1
interfaces_helper_vlan(cfg, interfaces);
#endif
--- /dev/null
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2013 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "lldpd.h"
+
+#include <unistd.h>
+#include <sys/sockio.h>
+#include <net/if_types.h>
+
+/* Solaris comes with libdladm which seems to be handy to get all the necessary
+ * information. Unfortunately, this library needs a special device file and a
+ * Unix socket to a daemon. This is a bit difficult to use it in a
+ * privilege-separated daemon. Therefore, we keep using ioctl(). This should
+ * also improve compatibility with older versions of Solaris.
+ */
+
+static void
+ifsolaris_extract(struct lldpd *cfg,
+ struct interfaces_device_list *interfaces,
+ struct interfaces_address_list *addresses,
+ struct lifreq *lifr) {
+ int flags = 0;
+ int index = 0;
+ struct interfaces_address *address = NULL;
+ struct interfaces_device *device = NULL;
+
+ sa_family_t lifr_af = lifr->lifr_addr.ss_family;
+ struct lifreq lifrl = { .lifr_name = {} };
+ strlcpy(lifrl.lifr_name, lifr->lifr_name, sizeof(lifrl.lifr_name));
+
+ /* Flags */
+ if (ioctl(cfg->g_sock, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0) {
+ log_warn("interfaces", "unable to get flags for %s",
+ lifrl.lifr_name);
+ return;
+ }
+ flags = lifrl.lifr_flags;
+ if (!((flags & IFF_UP) && (flags & IFF_RUNNING))) {
+ log_debug("interfaces",
+ "skip %s: down", lifrl.lifr_name);
+ return;
+ }
+
+ /* Index */
+ if (ioctl(cfg->g_sock, SIOCGLIFINDEX, (caddr_t)&lifrl) < 0) {
+ log_warn("interfaces", "unable to get index for %s",
+ lifrl.lifr_name);
+ return;
+ }
+ index = lifrl.lifr_index;
+
+ /* Record the address */
+ if ((address = malloc(sizeof(struct interfaces_address))) == NULL) {
+ log_warn("interfaces",
+ "not enough memory for a new IP address on %s",
+ lifrl.lifr_name);
+ return;
+ }
+ address->flags = flags;
+ address->index = index;
+ memcpy(&address->address,
+ &lifr->lifr_addr,
+ (lifr_af == AF_INET)?
+ sizeof(struct sockaddr_in):
+ sizeof(struct sockaddr_in6));
+ TAILQ_INSERT_TAIL(addresses, address, next);
+
+ /* Hardware address */
+ if (ioctl(cfg->g_sock, SIOCGLIFHWADDR, (caddr_t)&lifrl) < 0) {
+ log_debug("interfaces", "unable to get hardware address for %s",
+ lifrl.lifr_name);
+ return;
+ }
+ struct sockaddr_dl *saddrdl = (struct sockaddr_dl*)&lifrl.lifr_addr;
+ if (saddrdl->sdl_type != 4) {
+ log_debug("interfaces", "skip %s: not an ethernet device (%d)",
+ lifrl.lifr_name, saddrdl->sdl_type);
+ return;
+ }
+
+ /* Handle the interface */
+ if ((device = calloc(1, sizeof(struct interfaces_device))) == NULL) {
+ log_warn("interfaces", "unable to allocate memory for %s",
+ lifrl.lifr_name);
+ return;
+ }
+
+ device->name = strdup(lifrl.lifr_name);
+ device->flags = flags;
+ device->index = index;
+ device->type = IFACE_PHYSICAL_T;
+ device->address = malloc(ETHER_ADDR_LEN);
+ if (device->address)
+ memcpy(device->address, LLADDR(saddrdl), ETHER_ADDR_LEN);
+
+ /* MTU */
+ if (ioctl(cfg->g_sock, SIOCGLIFMTU, (caddr_t)&lifrl) < 0) {
+ log_debug("interfaces", "unable to get MTU for %s",
+ lifrl.lifr_name);
+ } else device->mtu = lifrl.lifr_mtu;
+
+ TAILQ_INSERT_TAIL(interfaces, device, next);
+}
+
+extern struct lldpd_ops bpf_ops;
+void
+interfaces_update(struct lldpd *cfg) {
+ caddr_t buffer = NULL;
+ struct interfaces_device_list *interfaces;
+ struct interfaces_address_list *addresses;
+ interfaces = malloc(sizeof(struct interfaces_device_list));
+ addresses = malloc(sizeof(struct interfaces_address_list));
+ if (interfaces == NULL || addresses == NULL) {
+ log_warnx("interfaces", "unable to allocate memory");
+ goto end;
+ }
+ TAILQ_INIT(interfaces);
+ TAILQ_INIT(addresses);
+
+ struct lifnum lifn = {
+ .lifn_family = AF_UNSPEC,
+ .lifn_flags = LIFC_ENABLED
+ };
+ if (ioctl(cfg->g_sock, SIOCGLIFNUM, &lifn) < 0) {
+ log_warn("interfaces", "unable to get the number of interfaces");
+ goto end;
+ }
+
+ size_t bufsize = lifn.lifn_count * sizeof(struct lifreq);
+ if ((buffer = malloc(bufsize)) == NULL) {
+ log_warn("interfaces", "unable to allocate buffer to get interfaces");
+ goto end;
+ }
+
+ struct lifconf lifc = {
+ .lifc_family = AF_UNSPEC,
+ .lifc_flags = LIFC_ENABLED,
+ .lifc_len = bufsize,
+ .lifc_buf = buffer
+ };
+ if (ioctl(cfg->g_sock, SIOCGLIFCONF, (char *)&lifc) < 0) {
+ log_warn("interfaces", "unable to get the network interfaces");
+ goto end;
+ }
+
+ int num = lifc.lifc_len / sizeof (struct lifreq);
+ if (num > lifn.lifn_count) num = lifn.lifn_count;
+ log_debug("interfaces", "got %d interfaces", num);
+
+ struct lifreq *lifrp = (struct lifreq *)buffer;
+ for (int n = 0; n < num; n++, lifrp++)
+ ifsolaris_extract(cfg, interfaces, addresses, lifrp);
+
+ interfaces_helper_whitelist(cfg, interfaces);
+ interfaces_helper_physical(cfg, interfaces,
+ &bpf_ops, ifbpf_phys_init);
+ interfaces_helper_mgmt(cfg, addresses);
+ interfaces_helper_chassis(cfg, interfaces);
+
+end:
+ free(buffer);
+ interfaces_free_devices(interfaces);
+ interfaces_free_addresses(addresses);
+}
#ifndef IN_IS_ADDR_LOOPBACK
#define IN_IS_ADDR_LOOPBACK(a) ((a)->s_addr == htonl(INADDR_LOOPBACK))
#endif
+#ifndef IN_IS_ADDR_ANY
+#define IN_IS_ADDR_ANY(a) ((a)->s_addr == htonl(INADDR_ANY))
+#endif
#ifndef IN_IS_ADDR_GLOBAL
-#define IN_IS_ADDR_GLOBAL(a) (!IN_IS_ADDR_LOOPBACK(a))
+#define IN_IS_ADDR_GLOBAL(a) (!IN_IS_ADDR_LOOPBACK(a) && !IN_IS_ADDR_ANY(a))
#endif
#ifndef IN6_IS_ADDR_GLOBAL
#define IN6_IS_ADDR_GLOBAL(a) \
#include <netinet/if_ether.h>
#include <pwd.h>
#include <grp.h>
-#if defined HOST_OS_FREEBSD || \
- defined HOST_OS_DRAGONFLY || \
- defined HOST_OS_OPENBSD || \
- defined HOST_OS_NETBSD || \
- defined HOST_OS_OSX
-# include <sys/param.h>
-# include <sys/sysctl.h>
-#endif
static void usage(void);
#endif
static int
-lldpd_forwarding_enabled(void)
+lldpd_routing_enabled(struct lldpd *cfg)
{
- int rc = 0;
-#if defined HOST_OS_LINUX
- int f;
- char status;
- if ((f = priv_open("/proc/sys/net/ipv4/ip_forward")) >= 0) {
- if ((read(f, &status, 1) == 1) && (status == '1'))
- rc = 1;
- close(f);
+ int routing;
+ if ((routing = interfaces_routing_enabled(cfg)) == -1) {
+ log_debug("localchassis", "unable to check if routing is enabled");
+ return 0;
}
-#elif defined HOST_OS_FREEBSD || defined HOST_OS_OPENBSD || defined HOST_OS_NETBSD || defined HOST_OS_OSX || defined HOST_OS_DRAGONFLY
- int n, mib[4] = {
- CTL_NET,
- PF_INET,
- IPPROTO_IP,
- IPCTL_FORWARDING
- };
- size_t len = sizeof(int);
- if (sysctl(mib, 4, &n, &len, NULL, 0) != -1)
- rc = (n == 1);
-#else
-#error Unsupported OS
-#endif
- else log_debug("localchassis", "unable to check if forwarding is enabled");
- return rc;
+ return routing;
}
static void
assert(LOCAL_CHASSIS(cfg) != NULL);
/* Set system name and description */
- if (uname(&un) != 0)
+ if (uname(&un) < 0)
fatal("localchassis", "failed to get system information");
if ((hp = priv_gethostbyname()) == NULL)
fatal("localchassis", "failed to get system name");
}
}
- /* Check forwarding */
- if (lldpd_forwarding_enabled()) {
- log_debug("localchassis", "forwarding is enabled, enable router capability");
+ /* Check routing */
+ if (lldpd_routing_enabled(cfg)) {
+ log_debug("localchassis", "routing is enabled, enable router capability");
LOCAL_CHASSIS(cfg)->c_cap_enabled |= LLDP_CAP_ROUTER;
} else
LOCAL_CHASSIS(cfg)->c_cap_enabled &= ~LLDP_CAP_ROUTER;
#endif
void interfaces_setup_multicast(struct lldpd *, const char *, int);
+int interfaces_routing_enabled(struct lldpd *);
#ifdef HOST_OS_LINUX
/* netlink.c */
int netlink_subscribe_changes(void);
#endif
+#ifndef HOST_OS_LINUX
+int ifbpf_phys_init(struct lldpd *, struct lldpd_hardware *);
+#endif
+
#endif /* _LLDPD_H */
HOST_OS_DRAGONFLY || \
HOST_OS_NETBSD || \
HOST_OS_OPENBSD || \
- HOST_OS_OSX
+ HOST_OS_OSX || \
+ HOST_OS_SOLARIS
# include <net/bpf.h>
#endif
#if defined HOST_OS_FREEBSD || HOST_OS_OSX || HOST_OS_DRAGONFLY
# include <net/if_dl.h>
#endif
+#if defined HOST_OS_SOLARIS
+# include <sys/sockio.h>
+#endif
#include <netinet/if_ether.h>
/* Use resolv.h */
struct utsname un;
struct hostent *hp;
int len;
- if (uname(&un) != 0)
+ if (uname(&un) < 0)
fatal("privsep", "failed to get system information");
if ((hp = gethostbyname(un.nodename)) == NULL) {
log_info("privsep", "unable to get system name");
defined HOST_OS_DRAGONFLY || \
defined HOST_OS_OPENBSD || \
defined HOST_OS_NETBSD || \
- defined HOST_OS_OSX
- int n = 0;
+ defined HOST_OS_OSX || \
+ defined HOST_OS_SOLARIS
int enable, required;
- char dev[20];
struct bpf_insn filter[] = { LLDPD_FILTER_F };
- struct ifreq ifr = {};
+ struct ifreq ifr = { .ifr_name = {} };
struct bpf_program fprog = {
.bf_insns = filter,
.bf_len = sizeof(filter)/sizeof(struct bpf_insn)
};
+#ifndef HOST_OS_SOLARIS
+ int n = 0;
+ char dev[20];
do {
snprintf(dev, sizeof(dev), "/dev/bpf%d", n++);
fd = open(dev, O_RDWR);
} while (fd < 0 && errno == EBUSY);
+#else
+ fd = open("/dev/bpf", O_RDWR);
+#endif
if (fd < 0) {
rc = errno;
log_warn("privsep", "unable to find a free BPF");
asroot_iface_multicast()
{
int add, rc = 0;
- struct ifreq ifr = {};
+ struct ifreq ifr = { .ifr_name = {} };
must_read(remote, ifr.ifr_name, IFNAMSIZ);
#if defined HOST_OS_LINUX
must_read(remote, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
dlp->sdl_alen = ETHER_ADDR_LEN;
dlp->sdl_slen = 0;
must_read(remote, LLADDR(dlp), ETHER_ADDR_LEN);
-#elif defined HOST_OS_OPENBSD || defined HOST_OS_NETBSD
+#elif defined HOST_OS_OPENBSD || defined HOST_OS_NETBSD || defined HOST_OS_SOLARIS
struct sockaddr *sap = (struct sockaddr *)&ifr.ifr_addr;
+#if ! defined HOST_OS_SOLARIS
sap->sa_len = sizeof(struct sockaddr);
+#endif
sap->sa_family = AF_UNSPEC;
must_read(remote, sap->sa_data, ETHER_ADDR_LEN);
#else
* POSSIBILITY OF SUCH DAMAGE.
*/
+/* The following are needed by Solaris. The first to get CMSG_* and the second
+ * to keep IFNAMSIZ */
+#define _XOPEN_SOURCE 600
+#define __EXTENSIONS__
#include "lldpd.h"
#include <sys/param.h>