systemd: merge branch 'systemd' into master
authorThomas Haller <thaller@redhat.com>
Mon, 4 Jan 2016 14:22:51 +0000 (15:22 +0100)
committerThomas Haller <thaller@redhat.com>
Mon, 4 Jan 2016 16:03:11 +0000 (17:03 +0100)
72 files changed:
1  2 
src/Makefile.am
src/devices/nm-lldp-listener.c
src/platform/tests/test-address.c
src/systemd/src/basic/alloc-util.c
src/systemd/src/basic/alloc-util.h
src/systemd/src/basic/escape.c
src/systemd/src/basic/escape.h
src/systemd/src/basic/fd-util.c
src/systemd/src/basic/fileio.c
src/systemd/src/basic/fs-util.c
src/systemd/src/basic/fs-util.h
src/systemd/src/basic/hashmap.c
src/systemd/src/basic/hashmap.h
src/systemd/src/basic/hexdecoct.c
src/systemd/src/basic/hexdecoct.h
src/systemd/src/basic/hostname-util.c
src/systemd/src/basic/in-addr-util.c
src/systemd/src/basic/in-addr-util.h
src/systemd/src/basic/io-util.c
src/systemd/src/basic/io-util.h
src/systemd/src/basic/macro.h
src/systemd/src/basic/mempool.c
src/systemd/src/basic/parse-util.c
src/systemd/src/basic/parse-util.h
src/systemd/src/basic/path-util.c
src/systemd/src/basic/path-util.h
src/systemd/src/basic/prioq.c
src/systemd/src/basic/prioq.h
src/systemd/src/basic/random-util.c
src/systemd/src/basic/random-util.h
src/systemd/src/basic/set.h
src/systemd/src/basic/siphash24.c
src/systemd/src/basic/siphash24.h
src/systemd/src/basic/socket-util.h
src/systemd/src/basic/string-table.c
src/systemd/src/basic/string-table.h
src/systemd/src/basic/string-util.c
src/systemd/src/basic/string-util.h
src/systemd/src/basic/strv.c
src/systemd/src/basic/strv.h
src/systemd/src/basic/time-util.c
src/systemd/src/basic/time-util.h
src/systemd/src/basic/utf8.c
src/systemd/src/basic/utf8.h
src/systemd/src/basic/util.c
src/systemd/src/basic/util.h
src/systemd/src/libsystemd-network/dhcp-internal.h
src/systemd/src/libsystemd-network/dhcp-lease-internal.h
src/systemd/src/libsystemd-network/dhcp-option.c
src/systemd/src/libsystemd-network/dhcp-protocol.h
src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
src/systemd/src/libsystemd-network/dhcp6-option.c
src/systemd/src/libsystemd-network/lldp-internal.c
src/systemd/src/libsystemd-network/lldp-tlv.h
src/systemd/src/libsystemd-network/sd-dhcp-client.c
src/systemd/src/libsystemd-network/sd-dhcp-lease.c
src/systemd/src/libsystemd-network/sd-dhcp6-client.c
src/systemd/src/libsystemd-network/sd-ipv4acd.c
src/systemd/src/libsystemd-network/sd-ipv4ll.c
src/systemd/src/libsystemd-network/sd-lldp.c
src/systemd/src/shared/dns-domain.c
src/systemd/src/shared/dns-domain.h
src/systemd/src/systemd/_sd-common.h
src/systemd/src/systemd/sd-dhcp-client.h
src/systemd/src/systemd/sd-dhcp-lease.h
src/systemd/src/systemd/sd-dhcp6-client.h
src/systemd/src/systemd/sd-dhcp6-lease.h
src/systemd/src/systemd/sd-event.h
src/systemd/src/systemd/sd-ipv4acd.h
src/systemd/src/systemd/sd-ipv4ll.h
src/systemd/src/systemd/sd-lldp.h
src/systemd/src/systemd/sd-ndisc.h

diff --cc src/Makefile.am
@@@ -48,143 -48,6 +48,139 @@@ AM_CPPFLAGS =                             
  # primarily for its side effect of removing duplicates.
  AM_CPPFLAGS += $(foreach d,$(sort $(dir $(libNetworkManager_la_SOURCES))),-I$(top_srcdir)/src/$d)
  
-       -I$(top_srcdir)/src/systemd/src/libsystemd/sd-event \
 +noinst_LTLIBRARIES = \
 +      libNetworkManager.la \
 +      libnm-iface-helper.la \
 +      libsystemd-nm.la
 +
 +######################
 +# libsystemd-nm
 +######################
 +
 +SYSTEMD_NM_CFLAGS_PATHS = \
 +      -I$(top_srcdir)/src/systemd/src/systemd \
 +      -I$(top_srcdir)/src/systemd/src/libsystemd-network \
-       systemd/src/libsystemd-network/lldp-util.h \
 +      -I$(top_srcdir)/src/systemd/src/basic \
 +      -I$(top_srcdir)/src/systemd
 +
 +libsystemd_nm_la_SOURCES = \
 +      systemd/nm-sd-adapt.c \
 +      systemd/nm-sd-adapt.h \
 +      systemd/src/basic/alloc-util.c \
 +      systemd/src/basic/alloc-util.h \
 +      systemd/src/basic/async.h \
 +      systemd/src/basic/escape.c \
 +      systemd/src/basic/escape.h \
 +      systemd/src/basic/fd-util.c \
 +      systemd/src/basic/fd-util.h \
 +      systemd/src/basic/fileio.c \
 +      systemd/src/basic/fileio.h \
 +      systemd/src/basic/fs-util.c \
 +      systemd/src/basic/fs-util.h \
 +      systemd/src/basic/hashmap.c \
 +      systemd/src/basic/hashmap.h \
 +      systemd/src/basic/hexdecoct.c \
 +      systemd/src/basic/hexdecoct.h \
 +      systemd/src/basic/hostname-util.c \
 +      systemd/src/basic/hostname-util.h \
 +      systemd/src/basic/in-addr-util.c \
 +      systemd/src/basic/in-addr-util.h \
 +      systemd/src/basic/io-util.c \
 +      systemd/src/basic/io-util.h \
 +      systemd/src/basic/list.h \
 +      systemd/src/basic/log.h \
 +      systemd/src/basic/macro.h \
 +      systemd/src/basic/mempool.c \
 +      systemd/src/basic/mempool.h \
 +      systemd/src/basic/parse-util.c \
 +      systemd/src/basic/parse-util.h \
 +      systemd/src/basic/path-util.c \
 +      systemd/src/basic/path-util.h \
 +      systemd/src/basic/prioq.c \
 +      systemd/src/basic/prioq.h \
 +      systemd/src/basic/random-util.c \
 +      systemd/src/basic/random-util.h \
 +      systemd/src/basic/refcnt.h \
 +      systemd/src/basic/siphash24.c \
 +      systemd/src/basic/siphash24.h \
 +      systemd/src/basic/set.h \
 +      systemd/src/basic/socket-util.h \
 +      systemd/src/basic/sparse-endian.h \
 +      systemd/src/basic/string-table.c \
 +      systemd/src/basic/string-table.h \
 +      systemd/src/basic/string-util.c \
 +      systemd/src/basic/string-util.h \
 +      systemd/src/basic/strv.c \
 +      systemd/src/basic/strv.h \
 +      systemd/src/basic/time-util.c \
 +      systemd/src/basic/time-util.h \
 +      systemd/src/basic/umask-util.h \
 +      systemd/src/basic/unaligned.h \
 +      systemd/src/basic/utf8.c \
 +      systemd/src/basic/utf8.h \
 +      systemd/src/basic/util.c \
 +      systemd/src/basic/util.h \
 +      systemd/src/libsystemd-network/arp-util.c \
 +      systemd/src/libsystemd-network/arp-util.h \
 +      systemd/src/libsystemd-network/dhcp-identifier.c \
 +      systemd/src/libsystemd-network/dhcp-identifier.h \
 +      systemd/src/libsystemd-network/dhcp-internal.h \
 +      systemd/src/libsystemd-network/dhcp-lease-internal.h \
 +      systemd/src/libsystemd-network/dhcp-network.c \
 +      systemd/src/libsystemd-network/dhcp-option.c \
 +      systemd/src/libsystemd-network/dhcp-packet.c \
 +      systemd/src/libsystemd-network/dhcp-protocol.h \
 +      systemd/src/libsystemd-network/dhcp6-internal.h \
 +      systemd/src/libsystemd-network/dhcp6-lease-internal.h \
 +      systemd/src/libsystemd-network/dhcp6-network.c \
 +      systemd/src/libsystemd-network/dhcp6-option.c \
 +      systemd/src/libsystemd-network/dhcp6-protocol.h \
 +      systemd/src/libsystemd-network/lldp.h \
 +      systemd/src/libsystemd-network/lldp-network.h \
 +      systemd/src/libsystemd-network/lldp-network.c \
 +      systemd/src/libsystemd-network/lldp-tlv.c \
 +      systemd/src/libsystemd-network/lldp-tlv.h \
 +      systemd/src/libsystemd-network/lldp-port.c \
 +      systemd/src/libsystemd-network/lldp-port.h \
-       systemd/src/libsystemd/sd-event/event-util.h \
 +      systemd/src/libsystemd-network/lldp-internal.h \
 +      systemd/src/libsystemd-network/lldp-internal.c \
 +      systemd/src/libsystemd-network/network-internal.c \
 +      systemd/src/libsystemd-network/network-internal.h \
 +      systemd/src/libsystemd-network/sd-dhcp-client.c \
 +      systemd/src/libsystemd-network/sd-dhcp-lease.c \
 +      systemd/src/libsystemd-network/sd-dhcp6-client.c \
 +      systemd/src/libsystemd-network/sd-dhcp6-lease.c \
 +      systemd/src/libsystemd-network/sd-ipv4acd.c \
 +      systemd/src/libsystemd-network/sd-ipv4ll.c \
 +      systemd/src/libsystemd-network/sd-lldp.c \
 +      systemd/src/libsystemd/sd-id128/sd-id128.c \
-       systemd/src/systemd/sd-icmp6-nd.h \
 +      systemd/src/shared/dns-domain.c \
 +      systemd/src/shared/dns-domain.h \
 +      systemd/src/systemd/_sd-common.h \
 +      systemd/src/systemd/sd-dhcp-client.h \
 +      systemd/src/systemd/sd-dhcp-lease.h \
 +      systemd/src/systemd/sd-dhcp6-client.h \
 +      systemd/src/systemd/sd-dhcp6-lease.h \
 +      systemd/src/systemd/sd-lldp.h \
 +      systemd/src/systemd/sd-event.h \
 +      systemd/src/systemd/sd-id128.h \
 +      systemd/src/systemd/sd-ipv4acd.h \
 +      systemd/src/systemd/sd-ipv4ll.h \
 +      systemd/src/systemd/sd-ndisc.h
 +
 +libsystemd_nm_la_CPPFLAGS = \
 +      -I$(top_srcdir)/shared \
 +      -I$(top_builddir)/shared \
 +      -I$(top_srcdir)/libnm-core \
 +      -I$(top_builddir)/libnm-core \
 +      $(SYSTEMD_NM_CFLAGS_PATHS) \
 +      -I$(top_srcdir)/src/systemd/src/shared \
 +      -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD \
 +      $(GLIB_CFLAGS)
 +
 +libsystemd_nm_la_LIBADD = \
 +      $(GLIB_LIBS)
 +
  ###########################################
  # NetworkManager
  ###########################################
index 1d30a62,0000000..9118129
mode 100644,000000..100644
--- /dev/null
@@@ -1,648 -1,0 +1,648 @@@
-       sd_lldp_free (priv->lldp_handle);
 +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 +/* NetworkManager -- Network link manager
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
 + * the Free Software Foundation; either version 2 of the License, or
 + * (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + *
 + * Copyright (C) 2015 Red Hat, Inc.
 + */
 +
 +#include "config.h"
 +
 +#include <net/ethernet.h>
 +
 +#include "sd-lldp.h"
 +#include "lldp.h"
 +#include "nm-lldp-listener.h"
 +#include "nm-platform.h"
 +#include "nm-utils.h"
 +
 +#define MAX_NEIGHBORS         4096
 +#define MIN_UPDATE_INTERVAL   2
 +
 +typedef struct {
 +      char         *iface;
 +      int           ifindex;
 +      sd_lldp      *lldp_handle;
 +      GHashTable   *lldp_neighbors;
 +      guint         timer;
 +      guint         num_pending_events;
 +      GVariant     *variant;
 +} NMLldpListenerPrivate;
 +
 +enum {
 +      PROP_0,
 +      PROP_NEIGHBORS,
 +
 +      LAST_PROP
 +};
 +
 +G_DEFINE_TYPE (NMLldpListener, nm_lldp_listener, G_TYPE_OBJECT)
 +
 +#define NM_LLDP_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_LLDP_LISTENER, NMLldpListenerPrivate))
 +
 +typedef struct {
 +      guint8 chassis_id_type;
 +      guint8 port_id_type;
 +      char *chassis_id;
 +      char *port_id;
 +
 +      int dest;
 +
 +      GHashTable *tlvs;
 +} LLDPNeighbor;
 +
 +static void process_lldp_neighbors (NMLldpListener *self);
 +
 +static void
 +gvalue_destroy (gpointer data)
 +{
 +      GValue *value = (GValue *) data;
 +
 +      g_value_unset (value);
 +      g_slice_free (GValue, value);
 +}
 +
 +static GValue *
 +gvalue_new_nstr (const char *str, guint16 len)
 +{
 +      GValue *value;
 +
 +      value = g_slice_new0 (GValue);
 +      g_value_init (value, G_TYPE_STRING);
 +      g_value_take_string (value, strndup (str, len));
 +      return value;
 +}
 +
 +static GValue *
 +gvalue_new_uint (guint val)
 +{
 +      GValue *value;
 +
 +      value = g_slice_new0 (GValue);
 +      g_value_init (value, G_TYPE_UINT);
 +      g_value_set_uint (value, val);
 +      return value;
 +}
 +
 +static guint
 +lldp_neighbor_id_hash (gconstpointer ptr)
 +{
 +      const LLDPNeighbor *neigh = ptr;
 +
 +      return g_str_hash (neigh->chassis_id) ^
 +             g_str_hash (neigh->port_id) ^
 +             neigh->chassis_id_type ^
 +             (neigh->port_id_type * 33);
 +}
 +
 +static gboolean
 +lldp_neighbor_id_equal (gconstpointer a, gconstpointer b)
 +{
 +      const LLDPNeighbor *x = a, *y = b;
 +
 +      return x->chassis_id_type == y->chassis_id_type &&
 +             x->port_id_type == y->port_id_type &&
 +             !g_strcmp0 (x->chassis_id, y->chassis_id) &&
 +             !g_strcmp0 (x->port_id, y->port_id);
 +}
 +
 +static void
 +lldp_neighbor_free (gpointer data)
 +{
 +      LLDPNeighbor *neighbor = data;
 +
 +      if (neighbor) {
 +              g_free (neighbor->chassis_id);
 +              g_free (neighbor->port_id);
 +              g_hash_table_unref (neighbor->tlvs);
 +              g_free (neighbor);
 +      }
 +}
 +
 +static gboolean
 +lldp_neighbor_equal (LLDPNeighbor *a, LLDPNeighbor *b)
 +{
 +      GHashTableIter iter;
 +      gpointer k, v;
 +
 +      g_return_val_if_fail (a && a->tlvs, FALSE);
 +      g_return_val_if_fail (b && b->tlvs, FALSE);
 +
 +      if (   a->chassis_id_type != b->chassis_id_type
 +          || a->port_id_type != b->port_id_type
 +          || a->dest != b->dest
 +          || g_strcmp0 (a->chassis_id, b->chassis_id)
 +          || g_strcmp0 (a->port_id, b->port_id))
 +              return FALSE;
 +
 +      if (g_hash_table_size (a->tlvs) != g_hash_table_size (b->tlvs))
 +              return FALSE;
 +
 +      g_hash_table_iter_init (&iter, a->tlvs);
 +      while (g_hash_table_iter_next (&iter, &k, &v)) {
 +              GValue *value_a, *value_b;
 +
 +              value_a = v;
 +              value_b = g_hash_table_lookup (b->tlvs, k);
 +
 +              if (!value_b)
 +                      return FALSE;
 +
 +              g_return_val_if_fail (G_VALUE_TYPE (value_a) == G_VALUE_TYPE (value_b), FALSE);
 +
 +              if (G_VALUE_HOLDS_STRING (value_a)) {
 +                      if (g_strcmp0 (g_value_get_string (value_a), g_value_get_string (value_b)))
 +                              return FALSE;
 +              } else if (G_VALUE_HOLDS_UINT (value_a)) {
 +                      if (g_value_get_uint (value_a) != g_value_get_uint (value_b))
 +                              return FALSE;
 +              } else
 +                      g_return_val_if_reached (FALSE);
 +      }
 +
 +      return TRUE;
 +}
 +
 +static gboolean
 +lldp_hash_table_equal (GHashTable *a, GHashTable *b)
 +{
 +      GHashTableIter iter;
 +      gpointer val;
 +
 +      g_return_val_if_fail (a, FALSE);
 +      g_return_val_if_fail (b, FALSE);
 +
 +      if (g_hash_table_size (a) != g_hash_table_size (b))
 +              return FALSE;
 +
 +      g_hash_table_iter_init (&iter, a);
 +      while (g_hash_table_iter_next (&iter, NULL, &val)) {
 +              LLDPNeighbor *neigh_a, *neigh_b;
 +
 +              neigh_a = val;
 +              neigh_b = g_hash_table_lookup (b, val);
 +
 +              if (!neigh_b)
 +                      return FALSE;
 +
 +              if (!lldp_neighbor_equal (neigh_a, neigh_b))
 +                      return FALSE;
 +      }
 +
 +      return TRUE;
 +}
 +
 +static gboolean
 +lldp_timeout (gpointer user_data)
 +{
 +      NMLldpListener *self = NM_LLDP_LISTENER (user_data);
 +      NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 +
 +      priv->timer = 0;
 +
 +      if (priv->num_pending_events)
 +              process_lldp_neighbors (self);
 +
 +      return G_SOURCE_REMOVE;
 +}
 +
 +static void
 +process_lldp_neighbors (NMLldpListener *self)
 +{
 +      NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 +      sd_lldp_packet **packets = NULL;
 +      GHashTable *hash;
 +      int num, i;
 +
 +      num = sd_lldp_get_packets (priv->lldp_handle, &packets);
 +      if (num < 0) {
 +              nm_log_dbg (LOGD_DEVICE, "LLDP: error %d retrieving neighbor packets for %s",
 +                          num, priv->iface);
 +              return;
 +      }
 +
 +      hash = g_hash_table_new_full (lldp_neighbor_id_hash, lldp_neighbor_id_equal,
 +                                    lldp_neighbor_free, NULL);
 +
 +      for (i = 0; packets && i < num; i++) {
 +              uint8_t chassis_id_type, port_id_type, *chassis_id, *port_id, data8;
 +              uint16_t chassis_id_len, port_id_len, len, data16;
 +              LLDPNeighbor *neigh;
 +              GValue *value;
 +              char *str;
 +              int r;
 +
 +              if (i >= MAX_NEIGHBORS)
 +                      goto next_packet;
 +
 +              r = sd_lldp_packet_read_chassis_id (packets[i], &chassis_id_type,
 +                                                  &chassis_id, &chassis_id_len);
 +              if (r < 0)
 +                      goto next_packet;
 +
 +              r = sd_lldp_packet_read_port_id (packets[i], &port_id_type,
 +                                               &port_id, &port_id_len);
 +              if (r < 0)
 +                      goto next_packet;
 +
 +              neigh = g_malloc0 (sizeof (LLDPNeighbor));
 +              neigh->tlvs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy);
 +              neigh->chassis_id_type = chassis_id_type;
 +              neigh->port_id_type = port_id_type;
 +              sd_lldp_packet_get_destination_type (packets[i], &neigh->dest);
 +
 +              if (chassis_id_len < 1) {
 +                      lldp_neighbor_free (neigh);
 +                      goto next_packet;
 +              }
 +
 +              switch (chassis_id_type) {
 +              case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS:
 +              case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME:
 +              case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED:
 +              case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT:
 +                      neigh->chassis_id = strndup ((char *) chassis_id, chassis_id_len);
 +                      break;
 +              case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
 +                      neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len);
 +                      break;
 +              default:
 +                      nm_log_dbg (LOGD_DEVICE, "LLDP: unsupported chassis ID type %d", chassis_id_type);
 +                      lldp_neighbor_free (neigh);
 +                      goto next_packet;
 +              }
 +
 +              if (port_id_len < 1) {
 +                      lldp_neighbor_free (neigh);
 +                      goto next_packet;
 +              }
 +
 +              switch (port_id_type) {
 +              case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
 +              case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
 +              case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED:
 +              case LLDP_PORT_SUBTYPE_PORT_COMPONENT:
 +                      neigh->port_id = strndup ((char *) port_id, port_id_len);
 +                      break;
 +              case LLDP_PORT_SUBTYPE_MAC_ADDRESS:
 +                      neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len);
 +                      break;
 +              default:
 +                      nm_log_dbg (LOGD_DEVICE, "LLDP: unsupported port ID type %d", port_id_type);
 +                      lldp_neighbor_free (neigh);
 +                      goto next_packet;
 +              }
 +
 +              if (sd_lldp_packet_read_port_description (packets[i], &str, &len) == 0) {
 +                      value = gvalue_new_nstr (str, len);
 +                      g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_PORT_DESCRIPTION, value);
 +              }
 +
 +              if (sd_lldp_packet_read_system_name (packets[i], &str, &len) == 0) {
 +                      value = gvalue_new_nstr (str, len);
 +                      g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_NAME, value);
 +              }
 +
 +              if (sd_lldp_packet_read_system_description (packets[i], &str, &len) == 0) {
 +                      value = gvalue_new_nstr (str, len);
 +                      g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, value);
 +              }
 +
 +              if (sd_lldp_packet_read_system_capability (packets[i], &data16) == 0) {
 +                      value = gvalue_new_uint (data16);
 +                      g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_CAPABILITIES, value);
 +              }
 +
 +              if (sd_lldp_packet_read_port_vlan_id (packets[i], &data16) == 0) {
 +                      value = gvalue_new_uint (data16);
 +                      g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PVID, value);
 +              }
 +
 +              if (sd_lldp_packet_read_port_protocol_vlan_id (packets[i], &data8, &data16) == 0) {
 +                      value = gvalue_new_uint (data16);
 +                      g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID, value);
 +
 +                      value = gvalue_new_uint (data8);
 +                      g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS, value);
 +              }
 +
 +              if (sd_lldp_packet_read_vlan_name (packets[i], &data16, &str, &len) == 0) {
 +                      value = gvalue_new_uint (data16);
 +                      g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VID, value);
 +
 +                      value = gvalue_new_nstr (str, len);
 +                      g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, value);
 +              }
 +
 +              nm_log_dbg (LOGD_DEVICE, "LLDP: new neigh: CHASSIS='%s' PORT='%s'",
 +                          neigh->chassis_id, neigh->port_id);
 +
 +              g_hash_table_add (hash, neigh);
 +next_packet:
 +              sd_lldp_packet_unref (packets[i]);
 +      }
 +
 +      g_free (packets);
 +
 +      if (lldp_hash_table_equal (priv->lldp_neighbors, hash)) {
 +              g_hash_table_destroy (hash);
 +      } else {
 +              g_hash_table_destroy (priv->lldp_neighbors);
 +              priv->lldp_neighbors = hash;
 +              nm_clear_g_variant (&priv->variant);
 +              g_object_notify (G_OBJECT (self), NM_LLDP_LISTENER_NEIGHBORS);
 +      }
 +
 +      /* Since the processing of the neighbor list is potentially
 +       * expensive when there are many neighbors, coalesce multiple
 +       * events arriving in short time.
 +       */
 +      priv->timer = g_timeout_add_seconds (MIN_UPDATE_INTERVAL, lldp_timeout, self);
 +      priv->num_pending_events = 0;
 +}
 +
 +static void
 +lldp_event_handler (sd_lldp *lldp, int event, void *userdata)
 +{
 +      NMLldpListener *self = userdata;
 +      NMLldpListenerPrivate *priv;
 +
 +      g_return_if_fail (NM_IS_LLDP_LISTENER (self));
 +      priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 +
 +      if (priv->timer > 0) {
 +              priv->num_pending_events++;
 +              return;
 +      }
 +
 +      process_lldp_neighbors (self);
 +}
 +
 +gboolean
 +nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface,
 +                        const guint8 *mac, guint mac_len, GError **error)
 +{
 +      NMLldpListenerPrivate *priv;
 +      int ret;
 +
 +      g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE);
 +      g_return_val_if_fail (ifindex > 0, FALSE);
 +      g_return_val_if_fail (iface, FALSE);
 +      g_return_val_if_fail (!error || !*error, FALSE);
 +
 +      priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 +
 +      if (priv->lldp_handle) {
 +              g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
 +                                   "already running");
 +              return FALSE;
 +      }
 +
 +      if (!mac || mac_len != ETH_ALEN) {
 +              g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
 +                                   "unsupported device");
 +              return FALSE;
 +      }
 +
 +      ret = sd_lldp_new (ifindex, iface, (struct ether_addr *) mac, &priv->lldp_handle);
 +      if (ret) {
 +              g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
 +                                   "initialization failed");
 +              return FALSE;
 +      }
 +
 +      ret = sd_lldp_attach_event (priv->lldp_handle, NULL, 0);
 +      if (ret) {
 +              g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
 +                                   "attach event failed");
 +              goto err_free;
 +      }
 +
 +      ret = sd_lldp_set_callback (priv->lldp_handle, lldp_event_handler, self);
 +      if (ret) {
 +              g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
 +                                   "set callback failed");
 +              goto err;
 +      }
 +
 +      ret = sd_lldp_start (priv->lldp_handle);
 +      if (ret) {
 +              g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
 +                                   "start failed");
 +              goto err;
 +      }
 +
 +      priv->ifindex = ifindex;
 +      priv->iface = strdup (iface);
 +      return TRUE;
 +
 +err:
 +      sd_lldp_detach_event (priv->lldp_handle);
 +err_free:
-               sd_lldp_free (priv->lldp_handle);
++      sd_lldp_unref (priv->lldp_handle);
 +      priv->lldp_handle = NULL;
 +      return FALSE;
 +}
 +
 +void
 +nm_lldp_listener_stop (NMLldpListener *self)
 +{
 +      NMLldpListenerPrivate *priv;
 +      guint size;
 +
 +      g_return_if_fail (NM_IS_LLDP_LISTENER (self));
 +      priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 +
 +      if (priv->lldp_handle) {
 +              sd_lldp_stop (priv->lldp_handle);
 +              sd_lldp_detach_event (priv->lldp_handle);
++              sd_lldp_unref (priv->lldp_handle);
 +              g_clear_pointer (&priv->iface, g_free);
 +              priv->lldp_handle = NULL;
 +
 +              size = g_hash_table_size (priv->lldp_neighbors);
 +              g_hash_table_remove_all (priv->lldp_neighbors);
 +              if (size) {
 +                      nm_clear_g_variant (&priv->variant);
 +                      g_object_notify (G_OBJECT (self), NM_LLDP_LISTENER_NEIGHBORS);
 +              }
 +      }
 +
 +      nm_clear_g_source (&priv->timer);
 +}
 +
 +gboolean
 +nm_lldp_listener_is_running (NMLldpListener *self)
 +{
 +      NMLldpListenerPrivate *priv;
 +
 +      g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE);
 +
 +      priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 +      return !!priv->lldp_handle;
 +}
 +
 +GVariant *
 +nm_lldp_listener_get_neighbors (NMLldpListener *self)
 +{
 +      GVariantBuilder array_builder, neigh_builder;
 +      GHashTableIter iter;
 +      NMLldpListenerPrivate *priv;
 +      LLDPNeighbor *neigh;
 +      char *dest_str = NULL;
 +
 +      priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 +
 +      if (priv->variant)
 +              goto out;
 +
 +      g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
 +      g_hash_table_iter_init (&iter, priv->lldp_neighbors);
 +
 +      while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &neigh)) {
 +              GHashTableIter val_iter;
 +              gpointer key, val;
 +
 +              g_variant_builder_init (&neigh_builder, G_VARIANT_TYPE ("a{sv}"));
 +
 +              g_variant_builder_add (&neigh_builder, "{sv}",
 +                                     NM_LLDP_ATTR_CHASSIS_ID_TYPE,
 +                                     g_variant_new_uint32 (neigh->chassis_id_type));
 +              g_variant_builder_add (&neigh_builder, "{sv}",
 +                                     NM_LLDP_ATTR_CHASSIS_ID,
 +                                     g_variant_new_string (neigh->chassis_id));
 +              g_variant_builder_add (&neigh_builder, "{sv}",
 +                                     NM_LLDP_ATTR_PORT_ID_TYPE,
 +                                     g_variant_new_uint32 (neigh->port_id_type));
 +              g_variant_builder_add (&neigh_builder, "{sv}",
 +                                     NM_LLDP_ATTR_PORT_ID,
 +                                     g_variant_new_string (neigh->port_id));
 +
 +              switch (neigh->dest) {
 +              case SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE:
 +                      dest_str = NM_LLDP_DEST_NEAREST_BRIDGE;
 +                      break;
 +              case SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE:
 +                      dest_str = NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE;
 +                      break;
 +              case SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE:
 +                      dest_str = NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE;
 +                      break;
 +              }
 +
 +              if (dest_str) {
 +                      g_variant_builder_add (&neigh_builder, "{sv}",
 +                                             NM_LLDP_ATTR_DESTINATION,
 +                                             g_variant_new_string (dest_str));
 +              }
 +
 +              g_hash_table_iter_init (&val_iter, neigh->tlvs);
 +              while (g_hash_table_iter_next (&val_iter, &key, &val)) {
 +                      GValue *item = val;
 +
 +                      if (G_VALUE_HOLDS_STRING (item)) {
 +                              g_variant_builder_add (&neigh_builder, "{sv}",
 +                                                     key,
 +                                                     g_variant_new_string (g_value_get_string (item)));
 +                      } else if (G_VALUE_HOLDS_UINT (item)) {
 +                              g_variant_builder_add (&neigh_builder, "{sv}",
 +                                                     key,
 +                                                     g_variant_new_uint32 (g_value_get_uint (item)));
 +                      }
 +              }
 +
 +              g_variant_builder_add (&array_builder, "a{sv}", &neigh_builder);
 +      }
 +
 +      priv->variant = g_variant_ref_sink (g_variant_builder_end (&array_builder));
 +
 +out:
 +      return priv->variant;
 +}
 +
 +static void
 +get_property (GObject *object, guint prop_id,
 +              GValue *value, GParamSpec *pspec)
 +{
 +      NMLldpListener *self = NM_LLDP_LISTENER (object);
 +
 +      switch (prop_id) {
 +      case PROP_NEIGHBORS:
 +              g_value_set_variant (value, nm_lldp_listener_get_neighbors (self));
 +              break;
 +      default:
 +              G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 +              break;
 +      }
 +}
 +
 +static void
 +nm_lldp_listener_init (NMLldpListener *self)
 +{
 +      NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 +
 +      priv->lldp_neighbors = g_hash_table_new_full (lldp_neighbor_id_hash,
 +                                                    lldp_neighbor_id_equal,
 +                                                    lldp_neighbor_free, NULL);
 +}
 +
 +NMLldpListener *
 +nm_lldp_listener_new (void)
 +{
 +      return (NMLldpListener *) g_object_new (NM_TYPE_LLDP_LISTENER, NULL);
 +}
 +
 +static void
 +dispose (GObject *object)
 +{
 +      nm_lldp_listener_stop (NM_LLDP_LISTENER (object));
 +
 +      G_OBJECT_CLASS (nm_lldp_listener_parent_class)->dispose (object);
 +}
 +
 +static void
 +finalize (GObject *object)
 +{
 +      NMLldpListener *self = NM_LLDP_LISTENER (object);
 +      NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
 +
 +      nm_lldp_listener_stop (self);
 +      g_hash_table_unref (priv->lldp_neighbors);
 +
 +      nm_clear_g_variant (&priv->variant);
 +
 +      G_OBJECT_CLASS (nm_lldp_listener_parent_class)->finalize (object);
 +}
 +
 +static void
 +nm_lldp_listener_class_init (NMLldpListenerClass *klass)
 +{
 +      GObjectClass *object_class = G_OBJECT_CLASS (klass);
 +
 +      g_type_class_add_private (klass, sizeof (NMLldpListenerPrivate));
 +
 +      object_class->dispose = dispose;
 +      object_class->finalize = finalize;
 +      object_class->get_property = get_property;
 +
 +      g_object_class_install_property
 +              (object_class, PROP_NEIGHBORS,
 +               g_param_spec_variant (NM_LLDP_LISTENER_NEIGHBORS, "", "",
 +                                     G_VARIANT_TYPE ("aa{sv}"),
 +                                     NULL,
 +                                     G_PARAM_READABLE |
 +                                     G_PARAM_STATIC_STRINGS));
 +}
 +
@@@ -148,10 -153,8 +148,10 @@@ test_ip6_address_general (void
        accept_signal (address_removed);
  
        /* Remove address again */
 -      g_assert (nm_platform_ip6_address_delete (ifindex, addr, IP6_PLEN));
 -      no_error ();
 +      nmtstp_ip6_address_del (EX, ifindex, addr, IP6_PLEN);
 +
-       /* ensure no pending signal. */
++      /* ensure not pending signal. */
 +      accept_signals (address_changed, 0, 1);
  
        free_signal (address_added);
        free_signal (address_changed);
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <stdint.h>
+ #include <string.h>
  #include "alloc-util.h"
+ #include "macro.h"
  #include "util.h"
  
  void* memdup(const void *p, size_t l) {
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <alloca.h>
+ #include <stddef.h>
  #include <stdlib.h>
  #include <string.h>
  
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <string.h>
  #include "alloc-util.h"
  #include "escape.h"
  #include "hexdecoct.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <inttypes.h>
+ #include <stddef.h>
+ #include <stdint.h>
  #include <sys/types.h>
  
+ #include "string-util.h"
  /* What characters are special in the shell? */
  /* must be escaped outside and inside double-quotes */
  #define SHELL_NEED_ESCAPE "\"\\`$"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
- #if 0 /* NM_IGNORED */
- #include "dirent-util.h"
- #endif /* NM_IGNORED */
 +#include "nm-sd-adapt.h"
 +
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <sys/resource.h>
+ #include <sys/socket.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
  #include "fd-util.h"
- #include "parse-util.h"
+ #include "macro.h"
 +#if 0 /* NM_IGNORED */
+ #include "missing.h"
 +#endif /* NM_IGNORED */
+ #include "parse-util.h"
+ #include "path-util.h"
  #include "socket-util.h"
  #include "util.h"
  
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <limits.h>
+ #include <stdarg.h>
+ #include <stdint.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
  #include <unistd.h>
  
  #include "alloc-util.h"
  #include "parse-util.h"
  #include "path-util.h"
  #include "random-util.h"
 +#if 0 /* NM_IGNORED */
  #include "stdio-util.h"
 +#endif /* NM_IGNORED */
  #include "string-util.h"
  #include "strv.h"
+ #include "time-util.h"
  #include "umask-util.h"
  #include "utf8.h"
- #include "util.h"
  
  int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
  
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <dirent.h>
+ #include <errno.h>
+ #include <stddef.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sys/stat.h>
+ #include <time.h>
+ #include <unistd.h>
  #include "alloc-util.h"
 +#if 0 /* NM_IGNORED */
  #include "dirent-util.h"
 +#endif /* NM_IGNORED */
  #include "fd-util.h"
  #include "fileio.h"
  #include "fs-util.h"
+ #include "log.h"
+ #include "macro.h"
 +#if 0 /* NM_IGNORED */
+ #include "missing.h"
  #include "mkdir.h"
 +#endif /* NM_IGNORED */
  #include "parse-util.h"
  #include "path-util.h"
  #include "string-util.h"
  #include "strv.h"
+ #include "time-util.h"
 +#if 0 /* NM_IGNORED */
  #include "user-util.h"
 +#endif /* NM_IGNORED */
  #include "util.h"
  
  int unlink_noerrno(const char *path) {
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <fcntl.h>
  #include <limits.h>
+ #include <stdbool.h>
+ #include <stdint.h>
  #include <sys/inotify.h>
  #include <sys/types.h>
  #include <unistd.h>
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <errno.h>
- #include <pthread.h>
+ #include <stdint.h>
  #include <stdlib.h>
+ #include <string.h>
  
  #include "alloc-util.h"
  #include "hashmap.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <limits.h>
  #include <stdbool.h>
+ #include <stddef.h>
  
  #include "macro.h"
  #include "siphash24.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <ctype.h>
- #include <inttypes.h>
+ #include <errno.h>
+ #include <stdint.h>
+ #include <stdlib.h>
  
  #include "alloc-util.h"
  #include "hexdecoct.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <stdbool.h>
+ #include <stddef.h>
  #include <stdio.h>
  #include <sys/types.h>
  
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
- #include <ctype.h>
 +#include "nm-sd-adapt.h"
 +
+ #include <bits/local_lim.h>
+ #include <errno.h>
+ #include <limits.h>
+ #include <stdio.h>
+ #include <string.h>
  #include <sys/utsname.h>
+ #include <unistd.h>
  
  #include "fd-util.h"
  #include "fileio.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <arpa/inet.h>
+ #include <endian.h>
+ #include <errno.h>
+ #include <stdint.h>
+ #include <stdlib.h>
  
  #include "alloc-util.h"
  #include "in-addr-util.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <netinet/in.h>
+ #include <stddef.h>
+ #include <sys/socket.h>
  
  #include "macro.h"
  #include "util.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <errno.h>
+ #include <limits.h>
  #include <poll.h>
+ #include <stdio.h>
+ #include <time.h>
  #include <unistd.h>
  
  #include "io-util.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <stdbool.h>
+ #include <stddef.h>
+ #include <stdint.h>
  #include <sys/types.h>
  #include <sys/uio.h>
  
@@@ -362,8 -351,7 +362,7 @@@ static inline unsigned long ALIGN_POWER
  /* Define C11 noreturn without <stdnoreturn.h> and even on older gcc
   * compiler versions */
  #ifndef noreturn
--#if __STDC_VERSION__ >= 201112L
++#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
  #define noreturn _Noreturn
  #else
  #define noreturn __attribute__((noreturn))
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <stdint.h>
+ #include <stdlib.h>
  #include "macro.h"
  #include "mempool.h"
  #include "util.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <errno.h>
+ #include <inttypes.h>
+ #include <locale.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <xlocale.h>
  #include "alloc-util.h"
 +#if 0 /* NM_IGNORED */
  #include "extract-word.h"
 +#endif /* NM_IGNORED */
+ #include "macro.h"
  #include "parse-util.h"
  #include "string-util.h"
- #include "util.h"
  
  int parse_boolean(const char *v) {
          assert(v);
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <inttypes.h>
+ #include <limits.h>
+ #include <stddef.h>
+ #include <stdint.h>
  #include <sys/types.h>
  
  #include "macro.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <errno.h>
- #include <fcntl.h>
+ #include <limits.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #undef basename
  
  #include "alloc-util.h"
- #include "fd-util.h"
- #include "fileio.h"
 +#if 0 /* NM_IGNORED */
+ #include "extract-word.h"
++#endif /* NM_IGNORED */
  #include "fs-util.h"
  #include "log.h"
  #include "macro.h"
++#if 0 /* NM_IGNORED */
  #include "missing.h"
- #include "parse-util.h"
 +#endif /* NM_IGNORED */
  #include "path-util.h"
 +#if 0 /* NM_IGNORED */
  #include "stat-util.h"
 +#endif /* NM_IGNORED */
  #include "string-util.h"
- #if 0 /* NM_IGNORED */
  #include "strv.h"
- #endif /* NM_IGNORED */
- #include "util.h"
+ #include "time-util.h"
  
 +#if 0 /* NM_IGNORED */
  bool path_is_absolute(const char *p) {
          return p[0] == '/';
  }
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <alloca.h>
  #include <stdbool.h>
+ #include <stddef.h>
  
  #include "macro.h"
  #include "time-util.h"
   * The underlying algorithm used in this implementation is a Heap.
   */
  
 +#include "nm-sd-adapt.h"
 +
+ #include <errno.h>
+ #include <stdlib.h>
  #include "alloc-util.h"
+ #include "hashmap.h"
  #include "prioq.h"
- #include "util.h"
  
  struct prioq_item {
          void *data;
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <stdbool.h>
  #include "hashmap.h"
+ #include "macro.h"
  
  typedef struct Prioq Prioq;
  
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <elf.h>
  #include <errno.h>
  #include <fcntl.h>
+ #include <stdbool.h>
+ #include <stdlib.h>
+ #include <sys/time.h>
  #include <linux/random.h>
  #include <stdint.h>
  #ifdef HAVE_SYS_AUXV_H
  #include <sys/auxv.h>
  #endif
  
  #include "fd-util.h"
  #include "io-util.h"
 +#if 0 /* NM_IGNORED */
  #include "missing.h"
 +#endif
  #include "random-util.h"
  #include "time-util.h"
- #include "util.h"
  
  int dev_urandom(void *p, size_t n) {
 +#if 0 /* NM_IGNORED */
          static int have_syscall = -1;
  
          _cleanup_close_ int fd = -1;
@@@ -19,8 -19,7 +19,9 @@@
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <stddef.h>
  #include <stdint.h>
  
  int dev_urandom(void *p, size_t n);
Simple merge
      coding style)
  */
  
 +#include "nm-sd-adapt.h"
 +
+ #include "macro.h"
  #include "siphash24.h"
- #include "sparse-endian.h"
  #include "unaligned.h"
- #include "util.h"
  
  static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
          assert(b < 64);
@@@ -1,8 -1,8 +1,10 @@@
  #pragma once
  
 +#include "nm-sd-adapt.h"
 +
  #include <inttypes.h>
+ #include <stddef.h>
+ #include <stdint.h>
  #include <sys/types.h>
  
  struct siphash {
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <netinet/ether.h>
  #include <netinet/in.h>
+ #include <stdbool.h>
+ #include <stddef.h>
  #include <sys/socket.h>
+ #include <sys/types.h>
  #include <sys/un.h>
  #include <linux/netlink.h>
  #include <linux/if_packet.h>
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include "string-table.h"
+ #include "string-util.h"
  
  ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
          size_t i;
@@@ -22,8 -22,7 +22,9 @@@
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <errno.h>
  #include <stddef.h>
  #include <stdio.h>
  #include <string.h>
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <errno.h>
+ #include <stdarg.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <stdlib.h>
  #include "alloc-util.h"
 +#if 0 /* NM_IGNORED */
  #include "gunicode.h"
 +#endif /* NM_IGNORED */
+ #include "macro.h"
  #include "string-util.h"
  #include "utf8.h"
  #include "util.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <alloca.h>
  #include <stdbool.h>
+ #include <stddef.h>
  #include <string.h>
  
  #include "macro.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <errno.h>
+ #include <fnmatch.h>
  #include <stdarg.h>
+ #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  
  #include "alloc-util.h"
  #include "escape.h"
++#if 0 /* NM_IGNORED */
+ #include "extract-word.h"
++#endif /* NM_IGNORED */
  #include "string-util.h"
  #include "strv.h"
  #include "util.h"
  #include <fnmatch.h>
  #include <stdarg.h>
  #include <stdbool.h>
+ #include <stddef.h>
  
+ #include "alloc-util.h"
 +#if 0 /* NM_IGNORED */
  #include "extract-word.h"
 +#endif /* NM_IGNORED */
+ #include "macro.h"
  #include "util.h"
  
  char *strv_find(char **l, const char *name) _pure_;
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
+ #include <errno.h>
+ #include <limits.h>
+ #include <stdlib.h>
  #include <string.h>
+ #include <sys/stat.h>
+ #include <sys/time.h>
  #include <sys/timerfd.h>
  #include <sys/timex.h>
+ #include <sys/types.h>
+ #include <unistd.h>
  
  #include "alloc-util.h"
  #include "fd-util.h"
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <inttypes.h>
+ #include <stdbool.h>
+ #include <stddef.h>
+ #include <stdint.h>
  #include <stdio.h>
  #include <time.h>
  
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   */
  
 +#include "nm-sd-adapt.h"
 +
  #include <errno.h>
- #include <inttypes.h>
  #include <stdbool.h>
  #include <stdlib.h>
  #include <string.h>
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <stdbool.h>
+ #include <stddef.h>
+ #include <stdint.h>
  
  #include "macro.h"
  
@@@ -19,9 -19,7 +19,9 @@@
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
- #include <ctype.h>
 +#include "nm-sd-adapt.h"
 +
+ #include <alloca.h>
  #include <dirent.h>
  #include <errno.h>
  #include <fcntl.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
- #include <sys/file.h>
- #include <sys/ioctl.h>
  #include <sys/mman.h>
- #include <sys/mount.h>
- #include <sys/personality.h>
  #include <sys/prctl.h>
- #include <sys/stat.h>
- #include <sys/statvfs.h>
- #include <sys/time.h>
+ #include <sys/statfs.h>
+ #include <sys/sysmacros.h>
  #include <sys/types.h>
- #include <sys/utsname.h>
- #include <sys/vfs.h>
- #include <sys/wait.h>
- #include <syslog.h>
  #include <unistd.h>
  
- /* When we include libgen.h because we need dirname() we immediately
-  * undefine basename() since libgen.h defines it as a macro to the
-  * POSIX version which is really broken. We prefer GNU basename(). */
- #include <libgen.h>
- #undef basename
- #ifdef HAVE_SYS_AUXV_H
- #include <sys/auxv.h>
- #endif
- /* We include linux/fs.h as last of the system headers, as it
-  * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
- #include <linux/fs.h>
- #if 0 /* NM_IGNORED */
  #include "alloc-util.h"
++#if 0 /* NM_IGNORED */
  #include "build.h"
  #include "def.h"
- #include "device-nodes.h"
  #include "dirent-util.h"
- #include "env-util.h"
- #include "escape.h"
- #include "exit-status.h"
++#endif /* NM_IGNORED */
  #include "fd-util.h"
  #include "fileio.h"
++#if 0 /* NM_IGNORED */
  #include "formats-util.h"
- #include "gunicode.h"
++#endif /* NM_IGNORED */
  #include "hashmap.h"
- #include "hexdecoct.h"
  #include "hostname-util.h"
- #include "ioprio.h"
  #include "log.h"
- #endif /* NM_IGNORED */
  #include "macro.h"
 +#if 0 /* NM_IGNORED */
  #include "missing.h"
- #include "mkdir.h"
- #include "parse-util.h"
 +#endif /* NM_IGNORED */
+ #include "parse-util.h"
  #include "path-util.h"
 +#if 0 /* NM_IGNORED */
  #include "process-util.h"
- #include "random-util.h"
++#endif /* NM_IGNORED */
+ #include "set.h"
++#if 0 /* NM_IGNORED */
  #include "signal-util.h"
- #include "sparse-endian.h"
  #include "stat-util.h"
- #include "string-table.h"
++#endif /* NM_IGNORED */
  #include "string-util.h"
  #include "strv.h"
- #include "terminal-util.h"
+ #include "time-util.h"
++#if 0 /* NM_IGNORED */
  #include "user-util.h"
- #include "utf8.h"
 +#endif /* NM_IGNORED */
  #include "util.h"
- #if 0 /* NM_IGNORED */
- #include "virt.h"
- #endif /* NM_IGNORED */
  
  /* Put this test here for a lack of better place */
  assert_cc(EAGAIN == EWOULDBLOCK);
    along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
  
 +#include "nm-sd-adapt.h"
 +
  #include <alloca.h>
+ #include <errno.h>
  #include <fcntl.h>
  #include <inttypes.h>
  #include <limits.h>
@@@ -686,10 -863,8 +866,9 @@@ int dns_name_address(const char *p, in
  
          return 0;
  }
++#endif /* NM_IGNORED */
  
- int dns_name_root(const char *name) {
-         char label[DNS_LABEL_MAX+1];
-         int r;
+ bool dns_name_is_root(const char *name) {
  
          assert(name);
  
@@@ -749,7 -931,313 +935,315 @@@ int dns_name_to_wire_format(const char 
                  *label_length = r;
                  out += r;
                  len -= r;
          } while (r != 0);
  
+         /* Verify the maximum size of the encoded name. The trailing
+          * dot + NUL byte account are included this time, hence
+          * compare against DNS_HOSTNAME_MAX + 2 (which is 255) this
+          * time. */
+         if (out - buffer > DNS_HOSTNAME_MAX + 2)
+                 return -EINVAL;
          return out - buffer;
  }
++#if 0 /* NM_IGNORED */
+ static bool srv_type_label_is_valid(const char *label, size_t n) {
+         size_t k;
+         assert(label);
+         if (n < 2) /* Label needs to be at least 2 chars long */
+                 return false;
+         if (label[0] != '_') /* First label char needs to be underscore */
+                 return false;
+         /* Second char must be a letter */
+         if (!(label[1] >= 'A' && label[1] <= 'Z') &&
+             !(label[1] >= 'a' && label[1] <= 'z'))
+                 return false;
+         /* Third and further chars must be alphanumeric or a hyphen */
+         for (k = 2; k < n; k++) {
+                 if (!(label[k] >= 'A' && label[k] <= 'Z') &&
+                     !(label[k] >= 'a' && label[k] <= 'z') &&
+                     !(label[k] >= '0' && label[k] <= '9') &&
+                     label[k] != '-')
+                         return false;
+         }
+         return true;
+ }
+ bool dns_srv_type_is_valid(const char *name) {
+         unsigned c = 0;
+         int r;
+         if (!name)
+                 return false;
+         for (;;) {
+                 char label[DNS_LABEL_MAX];
+                 /* This more or less implements RFC 6335, Section 5.1 */
+                 r = dns_label_unescape(&name, label, sizeof(label));
+                 if (r < 0)
+                         return false;
+                 if (r == 0)
+                         break;
+                 if (c >= 2)
+                         return false;
+                 if (!srv_type_label_is_valid(label, r))
+                         return false;
+                 c++;
+         }
+         return c == 2; /* exactly two labels */
+ }
+ bool dns_service_name_is_valid(const char *name) {
+         size_t l;
+         /* This more or less implements RFC 6763, Section 4.1.1 */
+         if (!name)
+                 return false;
+         if (!utf8_is_valid(name))
+                 return false;
+         if (string_has_cc(name, NULL))
+                 return false;
+         l = strlen(name);
+         if (l <= 0)
+                 return false;
+         if (l > 63)
+                 return false;
+         return true;
+ }
+ int dns_service_join(const char *name, const char *type, const char *domain, char **ret) {
+         char escaped[DNS_LABEL_ESCAPED_MAX];
+         _cleanup_free_ char *n = NULL;
+         int r;
+         assert(type);
+         assert(domain);
+         assert(ret);
+         if (!dns_srv_type_is_valid(type))
+                 return -EINVAL;
+         if (!name)
+                 return dns_name_concat(type, domain, ret);
+         if (!dns_service_name_is_valid(name))
+                 return -EINVAL;
+         r = dns_label_escape(name, strlen(name), escaped, sizeof(escaped));
+         if (r < 0)
+                 return r;
+         r = dns_name_concat(type, domain, &n);
+         if (r < 0)
+                 return r;
+         return dns_name_concat(escaped, n, ret);
+ }
+ static bool dns_service_name_label_is_valid(const char *label, size_t n) {
+         char *s;
+         assert(label);
+         if (memchr(label, 0, n))
+                 return false;
+         s = strndupa(label, n);
+         return dns_service_name_is_valid(s);
+ }
+ int dns_service_split(const char *joined, char **_name, char **_type, char **_domain) {
+         _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
+         const char *p = joined, *q = NULL, *d = NULL;
+         char a[DNS_LABEL_MAX], b[DNS_LABEL_MAX], c[DNS_LABEL_MAX];
+         int an, bn, cn, r;
+         unsigned x = 0;
+         assert(joined);
+         /* Get first label from the full name */
+         an = dns_label_unescape(&p, a, sizeof(a));
+         if (an < 0)
+                 return an;
+         if (an > 0) {
+                 x++;
+                 /* If there was a first label, try to get the second one */
+                 bn = dns_label_unescape(&p, b, sizeof(b));
+                 if (bn < 0)
+                         return bn;
+                 if (bn > 0) {
+                         x++;
+                         /* If there was a second label, try to get the third one */
+                         q = p;
+                         cn = dns_label_unescape(&p, c, sizeof(c));
+                         if (cn < 0)
+                                 return cn;
+                         if (cn > 0)
+                                 x++;
+                 } else
+                         cn = 0;
+         } else
+                 an = 0;
+         if (x >= 2 && srv_type_label_is_valid(b, bn)) {
+                 if (x >= 3 && srv_type_label_is_valid(c, cn)) {
+                         if (dns_service_name_label_is_valid(a, an)) {
+                                 /* OK, got <name> . <type> . <type2> . <domain> */
+                                 name = strndup(a, an);
+                                 if (!name)
+                                         return -ENOMEM;
+                                 type = new(char, bn+1+cn+1);
+                                 if (!type)
+                                         return -ENOMEM;
+                                 strcpy(stpcpy(stpcpy(type, b), "."), c);
+                                 d = p;
+                                 goto finish;
+                         }
+                 } else if (srv_type_label_is_valid(a, an)) {
+                         /* OK, got <type> . <type2> . <domain> */
+                         name = NULL;
+                         type = new(char, an+1+bn+1);
+                         if (!type)
+                                 return -ENOMEM;
+                         strcpy(stpcpy(stpcpy(type, a), "."), b);
+                         d = q;
+                         goto finish;
+                 }
+         }
+         name = NULL;
+         type = NULL;
+         d = joined;
+ finish:
+         r = dns_name_normalize(d, &domain);
+         if (r < 0)
+                 return r;
+         if (_domain) {
+                 *_domain = domain;
+                 domain = NULL;
+         }
+         if (_type) {
+                 *_type = type;
+                 type = NULL;
+         }
+         if (_name) {
+                 *_name = name;
+                 name = NULL;
+         }
+         return 0;
+ }
+ int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) {
+         const char* labels[DNS_N_LABELS_MAX+1];
+         unsigned n = 0;
+         const char *p;
+         int r;
+         assert(name);
+         assert(ret);
+         p = name;
+         for (;;) {
+                 if (n > DNS_N_LABELS_MAX)
+                         return -EINVAL;
+                 labels[n] = p;
+                 r = dns_name_parent(&p);
+                 if (r < 0)
+                         return r;
+                 if (r == 0)
+                         break;
+                 n++;
+         }
+         if (n < n_labels)
+                 return -EINVAL;
+         *ret = labels[n - n_labels];
+         return (int) (n - n_labels);
+ }
+ int dns_name_count_labels(const char *name) {
+         unsigned n = 0;
+         const char *p;
+         int r;
+         assert(name);
+         p = name;
+         for (;;) {
+                 r = dns_name_parent(&p);
+                 if (r < 0)
+                         return r;
+                 if (r == 0)
+                         break;
+                 if (n >= DNS_N_LABELS_MAX)
+                         return -EINVAL;
+                 n++;
+         }
+         return (int) n;
+ }
+ int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b) {
+         int r;
+         assert(a);
+         assert(b);
+         while (n_labels > 0) {
+                 r = dns_name_parent(&a);
+                 if (r <= 0)
+                         return r;
+                 n_labels --;
+         }
+         return dns_name_equal(a, b);
+ }
++#endif /* NM_IGNORED */
  
  #pragma once
  
 +#include "nm-sd-adapt.h"
  
- #if 0 /* NM_IGNORED */
+ #include <errno.h>
+ #include <stdbool.h>
+ #include <stddef.h>
+ #include <stdint.h>
  #include "hashmap.h"
  #include "in-addr-util.h"
- #endif /* NM_IGNORED */
  
+ /* Length of a single label, with all escaping removed, excluding any trailing dot or NUL byte */
  #define DNS_LABEL_MAX 63
- #define DNS_NAME_MAX 255
+ /* Worst case length of a single label, with all escaping applied and room for a trailing NUL byte. */
+ #define DNS_LABEL_ESCAPED_MAX (DNS_LABEL_MAX*4+1)
+ /* Maximum length of a full hostname, consisting of a series of unescaped labels, and no trailing dot or NUL byte */
+ #define DNS_HOSTNAME_MAX 253
+ /* Maximum length of a full hostname, on the wire, including the final NUL byte */
+ #define DNS_WIRE_FOMAT_HOSTNAME_MAX 255
+ /* Maximum number of labels per valid hostname */
+ #define DNS_N_LABELS_MAX 127
  
  int dns_label_unescape(const char **name, char *dest, size_t sz);
  int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge