Commit e1e428b2 authored by Thomas Haller's avatar Thomas Haller

systemd: merge branch 'th/systemd-lldp-bgo763384' into master

https://bugzilla.gnome.org/show_bug.cgi?id=763384
parents d432edba a8bc65b1
......@@ -86,6 +86,9 @@ AC_SUBST(nmdatadir, '${datadir}'/$PACKAGE, [NetworkManager shared data directory
AC_SUBST(nmstatedir, '${localstatedir}'/lib/$PACKAGE, [NetworkManager persistent state directory])
AC_SUBST(nmrundir, '${runstatedir}'/$PACKAGE, [NetworkManager runtime state directory])
AC_GNU_SOURCE
AC_CHECK_FUNCS([__secure_getenv secure_getenv])
# Alternative configuration plugins
AC_ARG_ENABLE(config-plugin-ibft, AS_HELP_STRING([--enable-config-plugin-ibft], [enable ibft configuration plugin]))
AC_ARG_ENABLE(ifcfg-rh, AS_HELP_STRING([--enable-ifcfg-rh], [enable ifcfg-rh configuration plugin (Fedora/RHEL)]))
......
......@@ -71,6 +71,8 @@ libsystemd_nm_la_SOURCES = \
systemd/src/basic/async.h \
systemd/src/basic/escape.c \
systemd/src/basic/escape.h \
systemd/src/basic/ether-addr-util.c \
systemd/src/basic/ether-addr-util.h \
systemd/src/basic/fd-util.c \
systemd/src/basic/fd-util.h \
systemd/src/basic/fileio.c \
......@@ -106,6 +108,7 @@ libsystemd_nm_la_SOURCES = \
systemd/src/basic/set.h \
systemd/src/basic/siphash24.c \
systemd/src/basic/siphash24.h \
systemd/src/basic/socket-util.c \
systemd/src/basic/socket-util.h \
systemd/src/basic/sparse-endian.h \
systemd/src/basic/stdio-util.h \
......@@ -138,14 +141,11 @@ libsystemd_nm_la_SOURCES = \
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-internal.c \
systemd/src/libsystemd-network/lldp-internal.h \
systemd/src/libsystemd-network/lldp-neighbor.c \
systemd/src/libsystemd-network/lldp-neighbor.h \
systemd/src/libsystemd-network/lldp-network.c \
systemd/src/libsystemd-network/lldp-network.h \
systemd/src/libsystemd-network/lldp-port.c \
systemd/src/libsystemd-network/lldp-port.h \
systemd/src/libsystemd-network/lldp-tlv.c \
systemd/src/libsystemd-network/lldp-tlv.h \
systemd/src/libsystemd-network/lldp.h \
systemd/src/libsystemd-network/network-internal.c \
systemd/src/libsystemd-network/network-internal.h \
......@@ -156,6 +156,7 @@ libsystemd_nm_la_SOURCES = \
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-event/sd-event.c \
systemd/src/libsystemd/sd-id128/sd-id128.c \
systemd/src/shared/dns-domain.c \
systemd/src/shared/dns-domain.h \
......
......@@ -1235,8 +1235,7 @@ update_dynamic_ip_setup (NMDevice *self)
nm_lldp_listener_stop (priv->lldp_listener);
addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length);
if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self),
nm_device_get_iface (self), addr, addr_length, &error)) {
if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error)) {
_LOGD (LOGD_DEVICE, "LLDP listener %p could not be restarted: %s",
priv->lldp_listener, error->message);
g_clear_error (&error);
......@@ -3564,8 +3563,7 @@ activate_stage2_device_config (NMDevice *self)
addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length);
if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self),
nm_device_get_iface (self), addr, addr_length, &error))
if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), &error))
_LOGD (LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener);
else {
_LOGD (LOGD_DEVICE, "LLDP listener %p could not be started: %s",
......
This diff is collapsed.
......@@ -42,8 +42,7 @@ typedef struct {
GType nm_lldp_listener_get_type (void);
NMLldpListener *nm_lldp_listener_new (void);
gboolean nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface,
const guint8 *mac, guint mac_len, GError **error);
gboolean nm_lldp_listener_start (NMLldpListener *self, int ifindex, GError **error);
void nm_lldp_listener_stop (NMLldpListener *self);
gboolean nm_lldp_listener_is_running (NMLldpListener *self);
......
......@@ -27,6 +27,7 @@
#include <sys/types.h>
#include "nm-lldp-listener.h"
#include "nm-sd-adapt.h"
#include "lldp.h"
......@@ -330,9 +331,6 @@ _test_recv_data2_ttl1_check (GMainLoop *loop, NMLldpListener *listener)
_test_recv_data0_check (loop, listener);
g_test_skip ("the test is known to fail");
return;
/* wait for signal. */
notify_id = g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS,
nmtst_main_loop_quit_on_notify, loop);
......@@ -396,14 +394,18 @@ test_recv (TestRecvFixture *fixture, gconstpointer user_data)
TestRecvCallbackInfo info = { };
gsize i_frames;
gulong notify_id;
GError *error = NULL;
guint sd_id;
listener = nm_lldp_listener_new ();
g_assert (listener != NULL);
g_assert (nm_lldp_listener_start (listener, fixture->ifindex, TEST_IFNAME, fixture->mac, ETH_ALEN, NULL));
g_assert (nm_lldp_listener_start (listener, fixture->ifindex, &error));
g_assert_no_error (error);
notify_id = g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS,
(GCallback) lldp_neighbors_changed, &info);
loop = g_main_loop_new (NULL, FALSE);
sd_id = nm_sd_event_attach_default ();
for (i_frames = 0; i_frames < data->frames_len; i_frames++) {
const TestRecvFrame *f = data->frames[i_frames];
......@@ -420,6 +422,7 @@ test_recv (TestRecvFixture *fixture, gconstpointer user_data)
data->check (loop, listener);
nm_clear_g_source (&sd_id);
g_clear_pointer (&loop, g_main_loop_unref);
}
......
......@@ -50,6 +50,7 @@
#include "nm-auth-manager.h"
#include "nm-core-internal.h"
#include "nm-exported-object.h"
#include "nm-sd-adapt.h"
#if !defined(NM_DIST_VERSION)
# define NM_DIST_VERSION VERSION
......@@ -271,6 +272,7 @@ main (int argc, char *argv[])
gboolean wrote_pidfile = FALSE;
char *bad_domains = NULL;
NMConfigCmdLineOptions *config_cli;
guint sd_id = 0;
nm_g_type_init ();
......@@ -474,8 +476,11 @@ main (int argc, char *argv[])
success = TRUE;
if (configure_and_quit == FALSE)
if (configure_and_quit == FALSE) {
sd_id = nm_sd_event_attach_default ();
g_main_loop_run (main_loop);
}
done:
nm_exported_object_class_set_quitting ();
......@@ -486,5 +491,8 @@ done:
unlink (global_opt.pidfile);
nm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error");
nm_clear_g_source (&sd_id);
exit (success ? 0 : 1);
}
......@@ -44,6 +44,7 @@ extern unsigned int if_nametoindex (const char *__ifname);
#include "nm-lndp-rdisc.h"
#include "nm-utils.h"
#include "nm-setting-ip6-config.h"
#include "nm-sd-adapt.h"
#if !defined(NM_DIST_VERSION)
# define NM_DIST_VERSION VERSION
......@@ -345,6 +346,7 @@ main (int argc, char *argv[])
size_t hwaddr_len = 0;
gconstpointer tmp;
gs_free NMUtilsIPv6IfaceId *iid = NULL;
guint sd_id;
nm_g_type_init ();
......@@ -494,6 +496,8 @@ main (int argc, char *argv[])
nm_rdisc_start (rdisc);
}
sd_id = nm_sd_event_attach_default ();
g_main_loop_run (main_loop);
g_clear_pointer (&hwaddr, g_byte_array_unref);
......@@ -502,6 +506,8 @@ main (int argc, char *argv[])
unlink (pidfile);
nm_log_info (LOGD_CORE, "exiting");
nm_clear_g_source (&sd_id);
exit (0);
}
......
......@@ -20,219 +20,126 @@
#include "nm-sd-adapt.h"
#include <unistd.h>
#include <errno.h>
#include "sd-event.h"
#include "fd-util.h"
#include "time-util.h"
struct sd_event_source {
guint refcount;
guint id;
gpointer user_data;
GIOChannel *channel;
union {
struct {
sd_event_io_handler_t cb;
} io;
struct {
sd_event_time_handler_t cb;
uint64_t usec;
} time;
};
};
static struct sd_event_source *
source_new (void)
{
struct sd_event_source *source;
source = g_slice_new0 (struct sd_event_source);
source->refcount = 1;
return source;
}
/*****************************************************************************/
int
sd_event_source_set_priority (sd_event_source *s, int64_t priority)
{
return 0;
asynchronous_close (int fd) {
safe_close (fd);
return -1;
}
sd_event_source*
sd_event_source_unref (sd_event_source *s)
{
/*****************************************************************************
* Integrating sd_event into glib. Taken and adjusted from
* https://www.freedesktop.org/software/systemd/man/sd_event_get_fd.html
*****************************************************************************/
if (!s)
return NULL;
typedef struct SDEventSource {
GSource source;
GPollFD pollfd;
sd_event *event;
guint *default_source_id;
} SDEventSource;
g_return_val_if_fail (s->refcount, NULL);
s->refcount--;
if (s->refcount == 0) {
if (s->id)
g_source_remove (s->id);
if (s->channel) {
/* Don't shut down the channel since systemd will soon close
* the file descriptor itself, which would cause -EBADF.
*/
g_io_channel_unref (s->channel);
}
g_slice_free (struct sd_event_source, s);
}
return NULL;
static gboolean
event_prepare (GSource *source, gint *timeout_)
{
return sd_event_prepare (((SDEventSource *) source)->event) > 0;
}
int
sd_event_source_set_description(sd_event_source *s, const char *description)
static gboolean
event_check (GSource *source)
{
if (!s)
return -EINVAL;
g_source_set_name_by_id (s->id, description);
return 0;
return sd_event_wait (((SDEventSource *) source)->event, 0) > 0;
}
static gboolean
io_ready (GIOChannel *channel, GIOCondition condition, struct sd_event_source *source)
event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
{
int r, revents = 0;
gboolean result;
if (condition & G_IO_IN)
revents |= EPOLLIN;
if (condition & G_IO_OUT)
revents |= EPOLLOUT;
if (condition & G_IO_PRI)
revents |= EPOLLPRI;
if (condition & G_IO_ERR)
revents |= EPOLLERR;
if (condition & G_IO_HUP)
revents |= EPOLLHUP;
source->refcount++;
r = source->io.cb (source, g_io_channel_unix_get_fd (channel), revents, source->user_data);
if (r < 0 || source->refcount <= 1) {
source->id = 0;
result = G_SOURCE_REMOVE;
} else
result = G_SOURCE_CONTINUE;
sd_event_source_unref (source);
return result;
return sd_event_dispatch (((SDEventSource *)source)->event) > 0;
}
int
sd_event_add_io (sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata)
static void
event_finalize (GSource *source)
{
struct sd_event_source *source;
GIOChannel *channel;
GIOCondition condition = 0;
/* systemd supports floating sd_event_source by omitting the @s argument.
* We don't have such users and don't implement floating references. */
g_return_val_if_fail (s, -EINVAL);
channel = g_io_channel_unix_new (fd);
if (!channel)
return -EINVAL;
source = source_new ();
source->io.cb = callback;
source->user_data = userdata;
source->channel = channel;
if (events & EPOLLIN)
condition |= G_IO_IN;
if (events & EPOLLOUT)
condition |= G_IO_OUT;
if (events & EPOLLPRI)
condition |= G_IO_PRI;
if (events & EPOLLERR)
condition |= G_IO_ERR;
if (events & EPOLLHUP)
condition |= G_IO_HUP;
g_io_channel_set_encoding (source->channel, NULL, NULL);
g_io_channel_set_buffered (source->channel, FALSE);
source->id = g_io_add_watch (source->channel, condition, (GIOFunc) io_ready, source);
*s = source;
return 0;
SDEventSource *s;
s = (SDEventSource *) source;
sd_event_unref (s->event);
if (s->default_source_id)
*s->default_source_id = 0;
}
static gboolean
time_ready (struct sd_event_source *source)
static SDEventSource *
event_create_source (sd_event *event, guint *default_source_id)
{
source->refcount++;
static GSourceFuncs event_funcs = {
.prepare = event_prepare,
.check = event_check,
.dispatch = event_dispatch,
.finalize = event_finalize,
};
SDEventSource *source;
g_return_val_if_fail (event, NULL);
source->time.cb (source, source->time.usec, source->user_data);
source->id = 0;
source = (SDEventSource *) g_source_new (&event_funcs, sizeof (SDEventSource));
sd_event_source_unref (source);
source->event = sd_event_ref (event);
source->pollfd.fd = sd_event_get_fd (event);
source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
source->default_source_id = default_source_id;
return G_SOURCE_REMOVE;
g_source_add_poll ((GSource *) source, &source->pollfd);
return source;
}
int
sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata)
static guint
event_attach (sd_event *event, GMainContext *context)
{
struct sd_event_source *source;
uint64_t n = now (clock);
SDEventSource *source;
guint id;
int r;
sd_event *e = event;
guint *p_default_source_id = NULL;
/* systemd supports floating sd_event_source by omitting the @s argument.
* We don't have such users and don't implement floating references. */
g_return_val_if_fail (s, -EINVAL);
if (!e) {
static guint default_source_id = 0;
source = source_new ();
source->time.cb = callback;
source->user_data = userdata;
source->time.usec = usec;
if (default_source_id) {
/* The default event cannot be registered multiple times. */
g_return_val_if_reached (0);
}
if (usec > 1000)
usec = n < usec - 1000 ? usec - n : 1000;
source->id = g_timeout_add (usec / 1000, (GSourceFunc) time_ready, source);
r = sd_event_default (&e);
if (r < 0)
g_return_val_if_reached (0);
*s = source;
return 0;
}
p_default_source_id = &default_source_id;
}
/* sd_event is basically a GMainContext; but since we only
* ever use the default context, nothing to do here.
*/
source = event_create_source (e, p_default_source_id);
id = g_source_attach ((GSource *) source, context);
g_source_unref ((GSource *) source);
int
sd_event_default (sd_event **e)
{
*e = GUINT_TO_POINTER (1);
return 0;
}
sd_event*
sd_event_ref (sd_event *e)
{
return e;
}
if (!event) {
*p_default_source_id = id;
sd_event_unref (e);
}
sd_event*
sd_event_unref (sd_event *e)
{
return NULL;
g_return_val_if_fail (id, 0);
return id;
}
int
sd_event_now (sd_event *e, clockid_t clock, uint64_t *usec)
guint
nm_sd_event_attach_default (void)
{
*usec = now (clock);
return 0;
return event_attach (NULL, NULL);
}
int asynchronous_close(int fd) {
safe_close(fd);
return -1;
}
/*****************************************************************************/
......@@ -26,6 +26,8 @@
#include <sys/resource.h>
#include <time.h>
guint nm_sd_event_attach_default (void);
#define noreturn G_GNUC_NORETURN
#ifndef CLOCK_BOOTTIME
......@@ -102,6 +104,7 @@ G_STMT_START { \
#endif
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <net/if_arp.h>
......@@ -110,6 +113,18 @@ G_STMT_START { \
#define BPF_XOR 0xa0
#endif
#ifndef ETHERTYPE_LLDP
#define ETHERTYPE_LLDP 0x88cc
#endif
#ifndef HAVE_SECURE_GETENV
# ifdef HAVE___SECURE_GETENV
# define secure_getenv __secure_getenv
# else
# error neither secure_getenv nor __secure_getenv is available
# endif
#endif
/*****************************************************************************/
/* work around missing uchar.h */
......@@ -118,6 +133,14 @@ typedef guint32 char32_t;
/*****************************************************************************/
#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
static inline int
sd_notify (int unset_environment, const char *state)
{
return 0;
}
/* Can't include both net/if.h and linux/if.h; so have to define this here */
#ifndef IFNAMSIZ
#define IFNAMSIZ 16
......
......@@ -51,25 +51,29 @@ static inline void freep(void *p) {
#define _cleanup_free_ _cleanup_(freep)
_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
static inline bool size_multiply_overflow(size_t size, size_t need) {
return _unlikely_(need != 0 && size > (SIZE_MAX / need));
}
_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) {
if (size_multiply_overflow(size, need))
return NULL;
return malloc(a * b);
return malloc(size * need);
}
_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) {
if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) {
if (size_multiply_overflow(size, need))
return NULL;
return realloc(p, a * b);
return realloc(p, size * need);
}
_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) {
if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
if (size_multiply_overflow(size, need))
return NULL;
return memdup(p, a * b);
return memdup(p, size * need);
}
void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
......
......@@ -415,6 +415,34 @@ char *xescape(const char *s, const char *bad) {
return r;
}
char *octescape(const char *s, size_t len) {
char *r, *t;
const char *f;
/* Escapes all chars in bad, in addition to \ and " chars,
* in \nnn style escaping. */
r = new(char, len * 4 + 1);
if (!r)
return NULL;
for (f = s, t = r; f < s + len; f++) {
if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
*(t++) = '\\';
*(t++) = '0' + (*f >> 6);
*(t++) = '0' + ((*f >> 3) & 8);
*(t++) = '0' + (*f & 8);
} else
*(t++) = *f;
}
*t = 0;
return r;
}
static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
assert(bad);
......
......@@ -52,6 +52,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
char *xescape(const char *s, const char *bad);
char *octescape(const char *s, size_t len);
char *shell_escape(const char *s, const char *bad);
char *shell_maybe_quote(const char *s);
/***
This file is part of systemd.
Copyright 2014 Tom Gundersen
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "nm-sd-adapt.h"
#include <net/ethernet.h>
#include <stdio.h>
#include <sys/types.h>
#include "ether-addr-util.h"
#include "macro.h"
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
assert(addr);
assert(buffer);
/* Like ether_ntoa() but uses %02x instead of %x to print
* ethernet addresses, which makes them look less funny. Also,
* doesn't use a static buffer. */
sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
addr->ether_addr_octet[0],
addr->ether_addr_octet[1],
addr->ether_addr_octet[2],
addr->ether_addr_octet[3],
addr->ether_addr_octet[4],
addr->ether_addr_octet[5]);
return buffer;
}
bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
assert(a);
assert(b);
return a->ether_addr_octet[0] == b->ether_addr_octet[0] &&
a->ether_addr_octet[1] == b->ether_addr_octet[1] &&