]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
solaris: preliminary support
authorVincent Bernat <bernat@luffy.cx>
Mon, 6 May 2013 19:31:42 +0000 (21:31 +0200)
committerVincent Bernat <bernat@luffy.cx>
Wed, 8 May 2013 21:27:02 +0000 (23:27 +0200)
Basic functionalities are present. However, the interface support is
very poor. There is no way to detect bridges, VLAN and
aggregates. There is no MAC/PHY support. There is no detection of
wireless devices.

The code to detect IP forwarding is here but does not work inside the
chroot.

17 files changed:
configure.ac
m4/os.m4
m4/stdint.m4 [new file with mode: 0644]
src/compat/fgetln.c
src/ctl.h
src/daemon/Makefile.am
src/daemon/forward-bsd.c [new file with mode: 0644]
src/daemon/forward-linux.c [new file with mode: 0644]
src/daemon/forward-solaris.c [new file with mode: 0644]
src/daemon/interfaces-bpf.c [new file with mode: 0644]
src/daemon/interfaces-bsd.c
src/daemon/interfaces-solaris.c [new file with mode: 0644]
src/daemon/interfaces.c
src/daemon/lldpd.c
src/daemon/lldpd.h
src/daemon/priv.c
src/daemon/privsep_fdpass.c

index 570031bc8f666f5830a57640c82fcbca5bb6bbda..5689c9e4cca9d9a3018908d9ec1b011335a0c5f4 100644 (file)
@@ -84,6 +84,7 @@ AC_CACHE_SAVE
 # Checks for header files.
 AC_HEADER_RESOLV
 AC_CHECK_HEADERS([valgrind/valgrind.h])
+lldp_CHECK_STDINT
 
 AC_CACHE_SAVE
 
index 28ab16863f63f3b8c4256bfd4ec6177614125611..584e9d5642ad0fb23ffedc5ae262034f209853e2 100644 (file)
--- a/m4/os.m4
+++ b/m4/os.m4
@@ -23,6 +23,7 @@ AC_DEFUN([lldp_CHECK_OS], [
   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)
diff --git a/m4/stdint.m4 b/m4/stdint.m4
new file mode 100644 (file)
index 0000000..96558be
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# 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])
index 45e63f49b09553884038cfe82b0150e46cae9b33..0490469b40f25f861f63218c253b63527420ba20 100644 (file)
@@ -27,7 +27,6 @@
 
 #define _GNU_SOURCE
 #include <stdio.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
 #include <string.h>
 
index 9d019bd7cd1fb63756f90cdd22c451c511b72be0..9dc65e3f577dd25be61ea0a4e2428f18ee6c682a 100644 (file)
--- a/src/ctl.h
+++ b/src/ctl.h
 
 #define LLDPD_CTL_SOCKET       "/var/run/lldpd.socket"
 
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include <stdint.h>
 #include "marshal.h"
 
index bcf79b585f5acfc4c9e75f20fd7b640a467c9185..86ea9039612f50a548bbd72c260445f2d00edb9c 100644 (file)
@@ -24,38 +24,56 @@ liblldpd_la_LIBADD   = \
 
 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
diff --git a/src/daemon/forward-bsd.c b/src/daemon/forward-bsd.c
new file mode 100644 (file)
index 0000000..e22a45d
--- /dev/null
@@ -0,0 +1,36 @@
+/* -*- 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;
+}
diff --git a/src/daemon/forward-linux.c b/src/daemon/forward-linux.c
new file mode 100644 (file)
index 0000000..c7d9f73
--- /dev/null
@@ -0,0 +1,36 @@
+/* -*- 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;
+}
diff --git a/src/daemon/forward-solaris.c b/src/daemon/forward-solaris.c
new file mode 100644 (file)
index 0000000..d2fca55
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*- 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;
+}
diff --git a/src/daemon/interfaces-bpf.c b/src/daemon/interfaces-bpf.c
new file mode 100644 (file)
index 0000000..a03a11b
--- /dev/null
@@ -0,0 +1,117 @@
+/* -*- 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,
+};
index 9d1cb1a4544c3e6091b0a7272c9136c3f62c0d46..ee4e378d032e9a882f870c9a642ec3c5ddd04663 100644 (file)
@@ -580,103 +580,7 @@ ifbsd_macphy(struct lldpd *cfg,
 #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)
 {
@@ -714,7 +618,7 @@ interfaces_update(struct lldpd *cfg)
 
        interfaces_helper_whitelist(cfg, interfaces);
        interfaces_helper_physical(cfg, interfaces,
-           &eth_ops, ifbsd_phys_init);
+           &bpf_ops, ifbpf_phys_init);
 #ifdef ENABLE_DOT1
        interfaces_helper_vlan(cfg, interfaces);
 #endif
diff --git a/src/daemon/interfaces-solaris.c b/src/daemon/interfaces-solaris.c
new file mode 100644 (file)
index 0000000..304f71c
--- /dev/null
@@ -0,0 +1,178 @@
+/* -*- 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);
+}
index 2392b86aca87826b0327d00f72b208868335b57b..3f80c12d94bcbc6e3f1336a70cc5ced530a10e9a 100644 (file)
@@ -360,8 +360,11 @@ interfaces_helper_chassis(struct lldpd *cfg,
 #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) \
index c7b8ecf10aa5d5370bfa59bb827cd08cbd761b5d..17aa30d03dec89705547b4b06bc085cc02d86bc4 100644 (file)
 #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);
 
@@ -877,32 +869,14 @@ lldpd_med(struct lldpd_chassis *chassis)
 #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
@@ -915,7 +889,7 @@ lldpd_update_localchassis(struct lldpd *cfg)
        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");
@@ -944,9 +918,9 @@ lldpd_update_localchassis(struct lldpd *cfg)
                }
         }
 
-       /* 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;
index 8e436ed36ca1039f961ae30a30d0dfb8e790f0d6..2afb3b87105b3007ff87bd41c41608913c3ddadd 100644 (file)
@@ -341,6 +341,7 @@ void interfaces_helper_vlan(struct lldpd *,
 #endif
 
 void interfaces_setup_multicast(struct lldpd *, const char *, int);
+int interfaces_routing_enabled(struct lldpd *);
 
 #ifdef HOST_OS_LINUX
 /* netlink.c */
@@ -349,4 +350,8 @@ struct interfaces_address_list *netlink_get_addresses(void);
 int netlink_subscribe_changes(void);
 #endif
 
+#ifndef HOST_OS_LINUX
+int ifbpf_phys_init(struct lldpd *, struct lldpd_hardware *);
+#endif
+
 #endif /* _LLDPD_H */
index fc3e5a56433a706e0c956938249d2ad9eed6ca22..4737077a5dd049840b8ac0f4356fe3afd0f66a27 100644 (file)
            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 */
@@ -237,7 +241,7 @@ asroot_gethostbyname()
        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");
@@ -408,21 +412,26 @@ asroot_iface_init()
       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");
@@ -526,7 +535,7 @@ static void
 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);
@@ -540,9 +549,11 @@ asroot_iface_multicast()
        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
index 0e09f0853ff1f6775893e79ab8e785f3db159a31..cb6bc9eaeecca6760060f56a37fdf1dfde6ae5ea 100644 (file)
  * 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>