summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Šimerda <psimerda@redhat.com>2013-05-30 16:50:05 +0200
committerPavel Šimerda <psimerda@redhat.com>2013-07-20 16:50:18 +0200
commit21a8a71d4814d21627afe56d8f59818ab07d5c98 (patch)
tree696c6ad33c048de17c0bec80c7eb64d2e0dc6aa4
parent74d8d374b344a3b1810fddccf3df747a856bec6d (diff)
downloadNetworkManager-21a8a71d4814d21627afe56d8f59818ab07d5c98.tar.gz
rdisc: abstract class and fake implementation
Abstract class, fake implementation and a manual testing tool for NetworkManager's internal IPv6 router discovery module. When a real implementation is ready, it will replace nm-ip6-manager and will be used by nm-device.
-rw-r--r--configure.ac2
-rw-r--r--src/rdisc/Makefile.am1
-rw-r--r--src/rdisc/nm-fake-rdisc.c133
-rw-r--r--src/rdisc/nm-fake-rdisc.h49
-rw-r--r--src/rdisc/nm-rdisc.c179
-rw-r--r--src/rdisc/nm-rdisc.h130
-rw-r--r--src/rdisc/tests/.gitignore1
-rw-r--r--src/rdisc/tests/Makefile.am22
-rw-r--r--src/rdisc/tests/rdisc.c26
9 files changed, 543 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 6b70bbdfc7..6de339483b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -689,6 +689,8 @@ src/settings/plugins/example/Makefile
src/settings/tests/Makefile
src/platform/Makefile
src/platform/tests/Makefile
+src/rdisc/Makefile
+src/rdisc/tests/Makefile
src/devices/wimax/Makefile
libnm-util/libnm-util.pc
libnm-util/Makefile
diff --git a/src/rdisc/Makefile.am b/src/rdisc/Makefile.am
new file mode 100644
index 0000000000..3c6155b9c6
--- /dev/null
+++ b/src/rdisc/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = tests
diff --git a/src/rdisc/nm-fake-rdisc.c b/src/rdisc/nm-fake-rdisc.c
new file mode 100644
index 0000000000..f39c5a208c
--- /dev/null
+++ b/src/rdisc/nm-fake-rdisc.c
@@ -0,0 +1,133 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* nm-fake-rdisc.c - Fake implementation of router discovery
+ *
+ * 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, 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) 2013 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "nm-fake-rdisc.h"
+
+#include "nm-logging.h"
+
+#define debug(...) nm_log_dbg (LOGD_IP6, __VA_ARGS__)
+#define warning(...) nm_log_warn (LOGD_IP6, __VA_ARGS__)
+#define error(...) nm_log_err (LOGD_IP6, __VA_ARGS__)
+
+#define NM_FAKE_RDISC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_FAKE_RDISC, NMFakeRDiscPrivate))
+
+G_DEFINE_TYPE (NMFakeRDisc, nm_fake_rdisc, NM_TYPE_RDISC)
+
+/******************************************************************/
+
+NMRDisc *
+nm_fake_rdisc_new (int ifindex, const char *ifname)
+{
+ NMRDisc *rdisc = g_object_new (NM_TYPE_FAKE_RDISC, NULL);
+
+ g_assert (rdisc);
+
+ rdisc->ifindex = ifindex;
+ rdisc->ifname = g_strdup (ifname);
+
+ return rdisc;
+}
+
+static void
+delayed_start (NMRDisc *rdisc)
+{
+ int changed =
+ NM_RDISC_CONFIG_GATEWAYS | NM_RDISC_CONFIG_ADDRESSES | NM_RDISC_CONFIG_ROUTES |
+ NM_RDISC_CONFIG_DNS_SERVERS | NM_RDISC_CONFIG_DNS_DOMAINS;
+ debug ("%d", rdisc->dhcp_level);
+
+ g_signal_emit_by_name (
+ rdisc, NM_RDISC_CONFIG_CHANGED, changed);
+}
+
+static void
+start (NMRDisc *rdisc)
+{
+ g_idle_add ((GSourceFunc) (delayed_start), rdisc);
+}
+
+/******************************************************************/
+
+static void
+nm_fake_rdisc_init (NMFakeRDisc *fake_rdisc)
+{
+ NMRDisc *rdisc = NM_RDISC (fake_rdisc);
+ NMRDiscGateway gateway;
+ NMRDiscAddress address;
+ NMRDiscRoute route;
+ NMRDiscDNSServer dns_server;
+ NMRDiscDNSDomain dns_domain;
+
+ rdisc->dhcp_level = NM_RDISC_DHCP_LEVEL_NONE;
+
+ memset (&gateway, 0, sizeof (gateway));
+ inet_pton (AF_INET6, "fe80::1", &gateway.address);
+ g_array_append_val (rdisc->gateways, gateway);
+ inet_pton (AF_INET6, "fe80::2", &gateway.address);
+ g_array_append_val (rdisc->gateways, gateway);
+ inet_pton (AF_INET6, "fe80::3", &gateway.address);
+ g_array_append_val (rdisc->gateways, gateway);
+
+ memset (&address, 0, sizeof (address));
+ inet_pton (AF_INET6, "2001:db8:a:a::1", &address.address);
+ g_array_append_val (rdisc->addresses, address);
+ inet_pton (AF_INET6, "2001:db8:a:a::2", &address.address);
+ g_array_append_val (rdisc->addresses, address);
+ inet_pton (AF_INET6, "2001:db8:f:f::1", &address.address);
+ g_array_append_val (rdisc->addresses, address);
+
+ memset (&route, 0, sizeof (route));
+ route.plen = 64;
+ inet_pton (AF_INET6, "2001:db8:a:a::", &route.network);
+ g_array_append_val (rdisc->routes, route);
+ inet_pton (AF_INET6, "2001:db8:b:b::", &route.network);
+ g_array_append_val (rdisc->routes, route);
+
+ memset (&dns_server, 0, sizeof (dns_server));
+ inet_pton (AF_INET6, "2001:db8:c:c::1", &dns_server.address);
+ g_array_append_val (rdisc->dns_servers, dns_server);
+ inet_pton (AF_INET6, "2001:db8:c:c::2", &dns_server.address);
+ g_array_append_val (rdisc->dns_servers, dns_server);
+ inet_pton (AF_INET6, "2001:db8:c:c::3", &dns_server.address);
+ g_array_append_val (rdisc->dns_servers, dns_server);
+ inet_pton (AF_INET6, "2001:db8:c:c::4", &dns_server.address);
+ g_array_append_val (rdisc->dns_servers, dns_server);
+ inet_pton (AF_INET6, "2001:db8:c:c::5", &dns_server.address);
+ g_array_append_val (rdisc->dns_servers, dns_server);
+
+ memset (&dns_domain, 0, sizeof (dns_domain));
+ dns_domain.domain = g_strdup ("example.net");
+ g_array_append_val (rdisc->dns_domains, dns_domain);
+ dns_domain.domain = g_strdup ("example.com");
+ g_array_append_val (rdisc->dns_domains, dns_domain);
+ dns_domain.domain = g_strdup ("example.org");
+ g_array_append_val (rdisc->dns_domains, dns_domain);
+}
+
+static void
+nm_fake_rdisc_class_init (NMFakeRDiscClass *klass)
+{
+ NMRDiscClass *rdisc_class = NM_RDISC_CLASS (klass);
+
+ rdisc_class->start = start;
+}
diff --git a/src/rdisc/nm-fake-rdisc.h b/src/rdisc/nm-fake-rdisc.h
new file mode 100644
index 0000000000..248283b22b
--- /dev/null
+++ b/src/rdisc/nm-fake-rdisc.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* nm-fake-rdisc.h - Fake implementation of router discovery
+ *
+ * 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, 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) 2013 Red Hat, Inc.
+ */
+
+#ifndef NM_FAKE_RDISC_H
+#define NM_FAKE_RDISC_H
+
+#include "nm-rdisc.h"
+
+#define NM_TYPE_FAKE_RDISC (nm_fake_rdisc_get_type ())
+#define NM_FAKE_RDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_FAKE_RDISC, NMFakeRDisc))
+#define NM_FAKE_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_FAKE_RDISC, NMFakeRDiscClass))
+#define NM_IS_FAKE_RDISC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_FAKE_RDISC))
+#define NM_IS_FAKE_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_FAKE_RDISC))
+#define NM_FAKE_RDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_FAKE_RDISC, NMFakeRDiscClass))
+
+/******************************************************************/
+
+typedef struct {
+ NMRDisc parent;
+} NMFakeRDisc;
+
+typedef struct {
+ NMRDiscClass parent;
+} NMFakeRDiscClass;
+
+/******************************************************************/
+
+GType nm_fake_rdisc_get_type (void);
+
+NMRDisc *nm_fake_rdisc_new (int ifindex, const char *ifname);
+
+#endif /* NM_FAKE_RDISC_H */
diff --git a/src/rdisc/nm-rdisc.c b/src/rdisc/nm-rdisc.c
new file mode 100644
index 0000000000..7e90e637ed
--- /dev/null
+++ b/src/rdisc/nm-rdisc.c
@@ -0,0 +1,179 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* nm-rdisc.c - Perform IPv6 router discovery
+ *
+ * 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, 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) 2013 Red Hat, Inc.
+ */
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include "nm-rdisc.h"
+
+#include "nm-logging.h"
+
+#define debug(...) nm_log_dbg (LOGD_IP6, __VA_ARGS__)
+
+G_DEFINE_TYPE (NMRDisc, nm_rdisc, G_TYPE_OBJECT)
+
+enum {
+ CONFIG_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/******************************************************************/
+
+void
+nm_rdisc_set_lladdr (NMRDisc *rdisc, const char *addr, size_t addrlen)
+{
+ rdisc->lladdr = g_bytes_new (addr, addrlen);
+}
+
+void
+nm_rdisc_start (NMRDisc *rdisc)
+{
+ NMRDiscClass *klass = NM_RDISC_GET_CLASS (rdisc);
+
+ g_assert (klass->start);
+
+ debug ("(%s): starting router discovery: %d", rdisc->ifname, rdisc->ifindex);
+
+ if (klass->start)
+ klass->start (rdisc);
+}
+
+#define CONFIG_MAP_MAX_STR 7
+
+static void
+config_map_to_string (NMRDiscConfigMap map, char *p)
+{
+ if (map & NM_RDISC_CONFIG_DHCP_LEVEL)
+ *p++ = 'd';
+ if (map & NM_RDISC_CONFIG_GATEWAYS)
+ *p++ = 'G';
+ if (map & NM_RDISC_CONFIG_ADDRESSES)
+ *p++ = 'A';
+ if (map & NM_RDISC_CONFIG_ROUTES)
+ *p++ = 'R';
+ if (map & NM_RDISC_CONFIG_DNS_SERVERS)
+ *p++ = 'S';
+ if (map & NM_RDISC_CONFIG_DNS_DOMAINS)
+ *p++ = 'D';
+ *p = '\0';
+}
+
+static const char *
+dhcp_level_to_string (NMRDiscDHCPLevel dhcp_level)
+{
+ switch (dhcp_level) {
+ case NM_RDISC_DHCP_LEVEL_NONE:
+ return "none";
+ case NM_RDISC_DHCP_LEVEL_OTHERCONF:
+ return "otherconf";
+ case NM_RDISC_DHCP_LEVEL_MANAGED:
+ return "managed";
+ default:
+ return "INVALID";
+ }
+}
+
+#define expiry(item) (item->timestamp + item->lifetime)
+
+static void
+config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed)
+{
+ int i;
+ char changedstr[CONFIG_MAP_MAX_STR];
+ char addrstr[INET6_ADDRSTRLEN];
+
+ config_map_to_string (changed, changedstr);
+ debug ("(%s): router discovery configuration changed [%s]:", rdisc->ifname, changedstr);
+ debug (" dhcp-level %s", dhcp_level_to_string (rdisc->dhcp_level));
+ for (i = 0; i < rdisc->gateways->len; i++) {
+ NMRDiscGateway *gateway = &g_array_index (rdisc->gateways, NMRDiscGateway, i);
+
+ inet_ntop (AF_INET6, &gateway->address, addrstr, sizeof (addrstr));
+ debug (" gateway %s pref %d exp %u", addrstr, gateway->preference, expiry (gateway));
+ }
+ for (i = 0; i < rdisc->addresses->len; i++) {
+ NMRDiscGateway *address = &g_array_index (rdisc->addresses, NMRDiscGateway, i);
+
+ inet_ntop (AF_INET6, &address->address, addrstr, sizeof (addrstr));
+ debug (" address %s exp %u", addrstr, expiry (address));
+ }
+ for (i = 0; i < rdisc->routes->len; i++) {
+ NMRDiscRoute *route = &g_array_index (rdisc->routes, NMRDiscRoute, i);
+
+ inet_ntop (AF_INET6, &route->network, addrstr, sizeof (addrstr));
+ debug (" route %s pref %d exp %u", addrstr, route->preference, expiry (route));
+ }
+ for (i = 0; i < rdisc->dns_servers->len; i++) {
+ NMRDiscDNSServer *dns_server = &g_array_index (rdisc->dns_servers, NMRDiscDNSServer, i);
+
+ inet_ntop (AF_INET6, &dns_server->address, addrstr, sizeof (addrstr));
+ debug (" dns_server %s exp %u", addrstr, expiry (dns_server));
+ }
+ for (i = 0; i < rdisc->dns_domains->len; i++) {
+ NMRDiscDNSDomain *dns_domain = &g_array_index (rdisc->dns_domains, NMRDiscDNSDomain, i);
+
+ debug (" dns_domain %s exp %u", dns_domain->domain, expiry (dns_domain));
+ }
+}
+
+/******************************************************************/
+
+static void
+nm_rdisc_init (NMRDisc *rdisc)
+{
+ rdisc->gateways = g_array_new (FALSE, FALSE, sizeof (NMRDiscGateway));
+ rdisc->addresses = g_array_new (FALSE, FALSE, sizeof (NMRDiscAddress));
+ rdisc->routes = g_array_new (FALSE, FALSE, sizeof (NMRDiscRoute));
+ rdisc->dns_servers = g_array_new (FALSE, FALSE, sizeof (NMRDiscDNSServer));
+ rdisc->dns_domains = g_array_new (FALSE, FALSE, sizeof (NMRDiscDNSDomain));
+}
+
+static void
+nm_rdisc_finalize (GObject *object)
+{
+ NMRDisc *rdisc = NM_RDISC (object);
+
+ g_free (rdisc->ifname);
+ g_array_unref (rdisc->gateways);
+ g_array_unref (rdisc->addresses);
+ g_array_unref (rdisc->routes);
+ g_array_unref (rdisc->dns_servers);
+ g_array_unref (rdisc->dns_domains);
+}
+
+static void
+nm_rdisc_class_init (NMRDiscClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = nm_rdisc_finalize;
+
+ klass->config_changed = config_changed;
+
+ signals[CONFIG_CHANGED] = g_signal_new (
+ NM_RDISC_CONFIG_CHANGED,
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMRDiscClass, config_changed),
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 1, G_TYPE_INT);
+}
diff --git a/src/rdisc/nm-rdisc.h b/src/rdisc/nm-rdisc.h
new file mode 100644
index 0000000000..abdd81cdab
--- /dev/null
+++ b/src/rdisc/nm-rdisc.h
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* nm-rdisc.h - Perform IPv6 router discovery
+ *
+ * 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, 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) 2013 Red Hat, Inc.
+ */
+
+#ifndef NM_RDISC_H
+#define NM_RDISC_H
+
+#include <glib-object.h>
+
+#include <stdlib.h>
+#include <netinet/in.h>
+
+#define NM_TYPE_RDISC (nm_rdisc_get_type ())
+#define NM_RDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_RDISC, NMRDisc))
+#define NM_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_RDISC, NMRDiscClass))
+#define NM_IS_RDISC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_RDISC))
+#define NM_IS_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_RDISC))
+#define NM_RDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_RDISC, NMRDiscClass))
+
+#define NM_RDISC_CONFIG_CHANGED "config-changed"
+
+typedef enum {
+ NM_RDISC_DHCP_LEVEL_UNKNOWN,
+ NM_RDISC_DHCP_LEVEL_NONE,
+ NM_RDISC_DHCP_LEVEL_OTHERCONF,
+ NM_RDISC_DHCP_LEVEL_MANAGED
+} NMRDiscDHCPLevel;
+
+typedef enum {
+ NM_RDISC_PREFERENCE_INVALID,
+ NM_RDISC_PREFERENCE_LOW,
+ NM_RDISC_PREFERENCE_MEDIUM,
+ NM_RDISC_PREFERENCE_HIGH
+} NMRDiscPreference;
+
+typedef struct {
+ struct in6_addr address;
+ guint32 timestamp;
+ guint32 lifetime;
+ NMRDiscPreference preference;
+} NMRDiscGateway;
+
+typedef struct {
+ struct in6_addr address;
+ guint32 timestamp;
+ guint32 lifetime;
+ guint32 preferred_lft;
+} NMRDiscAddress;
+
+typedef struct {
+ struct in6_addr network;
+ int plen;
+ struct in6_addr gateway;
+ guint32 timestamp;
+ guint32 lifetime;
+ NMRDiscPreference preference;
+} NMRDiscRoute;
+
+typedef struct {
+ struct in6_addr address;
+ guint32 timestamp;
+ guint32 lifetime;
+} NMRDiscDNSServer;
+
+typedef struct {
+ char *domain;
+ guint32 timestamp;
+ guint32 lifetime;
+} NMRDiscDNSDomain;
+
+typedef enum {
+ NM_RDISC_CONFIG_DHCP_LEVEL = 1 << 0,
+ NM_RDISC_CONFIG_GATEWAYS = 1 << 1,
+ NM_RDISC_CONFIG_ADDRESSES = 1 << 2,
+ NM_RDISC_CONFIG_ROUTES = 1 << 3,
+ NM_RDISC_CONFIG_DNS_SERVERS = 1 << 4,
+ NM_RDISC_CONFIG_DNS_DOMAINS = 1 << 5
+} NMRDiscConfigMap;
+
+/**
+ * NMRDisc:
+ * @ifindex: Interface index
+ *
+ * Interface-specific structure that handles incoming router advertisements,
+ * caches advertised items and removes them when they are obsolete.
+ */
+typedef struct {
+ GObject parent;
+
+ int ifindex;
+ char *ifname;
+ GBytes *lladdr;
+
+ NMRDiscDHCPLevel dhcp_level;
+ GArray *gateways;
+ GArray *addresses;
+ GArray *routes;
+ GArray *dns_servers;
+ GArray *dns_domains;
+} NMRDisc;
+
+typedef struct {
+ GObjectClass parent;
+
+ void (*start) (NMRDisc *rdisc);
+ void (*config_changed) (NMRDisc *rdisc, NMRDiscConfigMap changed);
+} NMRDiscClass;
+
+GType nm_rdisc_get_type (void);
+
+void nm_rdisc_set_lladdr (NMRDisc *rdisc, const char *addr, size_t addrlen);
+void nm_rdisc_start (NMRDisc *rdisc);
+
+#endif /* NM_RDISC_H */
diff --git a/src/rdisc/tests/.gitignore b/src/rdisc/tests/.gitignore
new file mode 100644
index 0000000000..a773713bb0
--- /dev/null
+++ b/src/rdisc/tests/.gitignore
@@ -0,0 +1 @@
+/rdisc
diff --git a/src/rdisc/tests/Makefile.am b/src/rdisc/tests/Makefile.am
new file mode 100644
index 0000000000..8e3843b7ec
--- /dev/null
+++ b/src/rdisc/tests/Makefile.am
@@ -0,0 +1,22 @@
+AM_CPPFLAGS = \
+ -I${top_srcdir} \
+ -I${top_srcdir}/src \
+ -I${top_srcdir}/src/logging \
+ -I${top_srcdir}/libnm-util \
+ -I${srcdir}/.. \
+ $(GLIB_CFLAGS) \
+ $(LIBNL_CFLAGS)
+
+AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
+AM_LDFLAGS = $(GLIB_LIBS) $(CODE_COVERAGE_LDFLAGS)
+
+@GNOME_CODE_COVERAGE_RULES@
+
+noinst_PROGRAMS = \
+ rdisc
+
+rdisc_SOURCES = \
+ rdisc.c \
+ ../nm-rdisc.c \
+ ../nm-fake-rdisc.c \
+ ../../logging/nm-logging.c
diff --git a/src/rdisc/tests/rdisc.c b/src/rdisc/tests/rdisc.c
new file mode 100644
index 0000000000..4d8a95b025
--- /dev/null
+++ b/src/rdisc/tests/rdisc.c
@@ -0,0 +1,26 @@
+#include <syslog.h>
+
+#include "nm-rdisc.h"
+#include "nm-fake-rdisc.h"
+#include "nm-logging.h"
+
+int
+main (int argc, char **argv)
+{
+ GMainLoop *loop;
+ NMRDisc *rdisc;
+
+ g_type_init ();
+ loop = g_main_loop_new (NULL, FALSE);
+ nm_logging_setup ("debug", NULL, NULL);
+ openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PERROR, LOG_DAEMON);
+
+ rdisc = nm_fake_rdisc_new (1);
+
+ nm_rdisc_start (rdisc);
+ g_main_loop_run (loop);
+
+ g_clear_object (&rdisc);
+
+ return EXIT_SUCCESS;
+}