summary refs log tree commit diff
path: root/src/rdisc/nm-lndp-rdisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rdisc/nm-lndp-rdisc.c')
-rw-r--r--src/rdisc/nm-lndp-rdisc.c434
1 files changed, 0 insertions, 434 deletions
diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c
deleted file mode 100644
index db2965b1..00000000
--- a/src/rdisc/nm-lndp-rdisc.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* nm-lndp-rdisc.c - Router discovery implementation using libndp
- *
- * 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 "nm-default.h"
-
-#include "nm-lndp-rdisc.h"
-
-#include <string.h>
-#include <arpa/inet.h>
-/* stdarg.h included because of a bug in ndp.h */
-#include <stdarg.h>
-#include <ndp.h>
-
-#include "nm-rdisc-private.h"
-#include "NetworkManagerUtils.h"
-#include "nm-platform.h"
-#include "nmp-netns.h"
-
-#define _NMLOG_PREFIX_NAME                "rdisc-lndp"
-
-/*****************************************************************************/
-
-typedef struct {
-	struct ndp *ndp;
-
-	GIOChannel *event_channel;
-	guint event_id;
-	guint ra_timeout_id;  /* first RA timeout */
-} NMLndpRDiscPrivate;
-
-/*****************************************************************************/
-
-struct _NMLndpRDisc {
-	NMRDisc parent;
-	NMLndpRDiscPrivate _priv;
-};
-
-struct _NMLndpRDiscClass {
-	NMRDiscClass parent;
-};
-
-/*****************************************************************************/
-
-G_DEFINE_TYPE (NMLndpRDisc, nm_lndp_rdisc, NM_TYPE_RDISC)
-
-#define NM_LNDP_RDISC_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMLndpRDisc, NM_IS_LNDP_RDISC)
-
-/*****************************************************************************/
-
-static gboolean
-send_rs (NMRDisc *rdisc, GError **error)
-{
-	NMLndpRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
-	struct ndp_msg *msg;
-	int errsv;
-
-	errsv = ndp_msg_new (&msg, NDP_MSG_RS);
-	if (errsv) {
-		errsv = errsv > 0 ? errsv : -errsv;
-		g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		                     "cannot create router solicitation");
-		return FALSE;
-	}
-	ndp_msg_ifindex_set (msg, nm_rdisc_get_ifindex (rdisc));
-
-	errsv = ndp_msg_send (priv->ndp, msg);
-	ndp_msg_destroy (msg);
-	if (errsv) {
-		errsv = errsv > 0 ? errsv : -errsv;
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             "%s (%d)",
-		             g_strerror (errsv), errsv);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-_NM_UTILS_LOOKUP_DEFINE (static, translate_preference, enum ndp_route_preference, NMRDiscPreference,
-	NM_UTILS_LOOKUP_DEFAULT (NM_RDISC_PREFERENCE_INVALID),
-	NM_UTILS_LOOKUP_ITEM (NDP_ROUTE_PREF_LOW,    NM_RDISC_PREFERENCE_LOW),
-	NM_UTILS_LOOKUP_ITEM (NDP_ROUTE_PREF_MEDIUM, NM_RDISC_PREFERENCE_MEDIUM),
-	NM_UTILS_LOOKUP_ITEM (NDP_ROUTE_PREF_HIGH,   NM_RDISC_PREFERENCE_HIGH),
-);
-
-static int
-receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
-{
-	NMRDisc *rdisc = (NMRDisc *) user_data;
-	NMRDiscDataInternal *rdata = rdisc->rdata;
-	NMRDiscConfigMap changed = 0;
-	struct ndp_msgra *msgra = ndp_msgra (msg);
-	struct in6_addr gateway_addr;
-	guint32 now = nm_utils_get_monotonic_timestamp_s ();
-	int offset;
-	int hop_limit;
-
-	/* Router discovery is subject to the following RFC documents:
-	 *
-	 * http://tools.ietf.org/html/rfc4861
-	 * http://tools.ietf.org/html/rfc4862
-	 *
-	 * The biggest difference from good old DHCP is that all configuration
-	 * items have their own lifetimes and they are merged from various
-	 * sources. Router discovery is *not* contract-based, so there is *no*
-	 * single time when the configuration is finished and updates can
-	 * come at any time.
-	 */
-	_LOGD ("received router advertisement at %u", now);
-
-	/* DHCP level:
-	 *
-	 * The problem with DHCP level is what to do if subsequent
-	 * router advertisements carry different flags. Currently we just
-	 * rewrite the flag with every inbound RA.
-	 */
-	{
-		NMRDiscDHCPLevel dhcp_level;
-
-		if (ndp_msgra_flag_managed (msgra))
-			dhcp_level = NM_RDISC_DHCP_LEVEL_MANAGED;
-		else if (ndp_msgra_flag_other (msgra))
-			dhcp_level = NM_RDISC_DHCP_LEVEL_OTHERCONF;
-		else
-			dhcp_level = NM_RDISC_DHCP_LEVEL_NONE;
-
-		/* when receiving multiple RA (possibly from different routers),
-		 * let's keep the "most managed" level. */
-		G_STATIC_ASSERT_EXPR (NM_RDISC_DHCP_LEVEL_MANAGED > NM_RDISC_DHCP_LEVEL_OTHERCONF);
-		G_STATIC_ASSERT_EXPR (NM_RDISC_DHCP_LEVEL_OTHERCONF > NM_RDISC_DHCP_LEVEL_NONE);
-		dhcp_level = MAX (dhcp_level, rdata->public.dhcp_level);
-
-		if (dhcp_level != rdata->public.dhcp_level) {
-			rdata->public.dhcp_level = dhcp_level;
-			changed |= NM_RDISC_CONFIG_DHCP_LEVEL;
-		}
-	}
-
-	/* Default gateway:
-	 *
-	 * Subsequent router advertisements can represent new default gateways
-	 * on the network. We should present all of them in router preference
-	 * order.
-	 */
-	gateway_addr = *ndp_msg_addrto (msg);
-	{
-		NMRDiscGateway gateway = {
-		    .address = gateway_addr,
-		    .timestamp = now,
-		    .lifetime = ndp_msgra_router_lifetime (msgra),
-		    .preference = translate_preference (ndp_msgra_route_preference (msgra)),
-		};
-
-		if (nm_rdisc_add_gateway (rdisc, &gateway))
-			changed |= NM_RDISC_CONFIG_GATEWAYS;
-	}
-
-	/* Addresses & Routes */
-	ndp_msg_opt_for_each_offset (offset, msg, NDP_MSG_OPT_PREFIX) {
-		guint8 r_plen;
-		struct in6_addr r_network;
-
-		/* Device route */
-
-		r_plen = ndp_msg_opt_prefix_len (msg, offset);
-		if (r_plen == 0 || r_plen > 128)
-			continue;
-		nm_utils_ip6_address_clear_host_address (&r_network, ndp_msg_opt_prefix (msg, offset), r_plen);
-
-		if (ndp_msg_opt_prefix_flag_on_link (msg, offset)) {
-			NMRDiscRoute route = {
-			    .network = r_network,
-			    .plen = r_plen,
-			    .timestamp = now,
-			    .lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
-			};
-
-			if (nm_rdisc_add_route (rdisc, &route))
-				changed |= NM_RDISC_CONFIG_ROUTES;
-		}
-
-		/* Address */
-		if (   r_plen == 64
-		    && ndp_msg_opt_prefix_flag_auto_addr_conf (msg, offset)) {
-			NMRDiscAddress address = {
-			    .address = r_network,
-			    .timestamp = now,
-			    .lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
-			    .preferred = ndp_msg_opt_prefix_preferred_time (msg, offset),
-			};
-
-			if (address.preferred > address.lifetime)
-				address.preferred = address.lifetime;
-			if (nm_rdisc_complete_and_add_address (rdisc, &address))
-				changed |= NM_RDISC_CONFIG_ADDRESSES;
-		}
-	}
-	ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_ROUTE) {
-		NMRDiscRoute route = {
-		    .gateway = gateway_addr,
-		    .plen = ndp_msg_opt_route_prefix_len (msg, offset),
-		    .timestamp = now,
-		    .lifetime = ndp_msg_opt_route_lifetime (msg, offset),
-		    .preference = translate_preference (ndp_msg_opt_route_preference (msg, offset)),
-		};
-
-		if (route.plen == 0 || route.plen > 128)
-			continue;
-
-		/* Routers through this particular gateway */
-		nm_utils_ip6_address_clear_host_address (&route.network, ndp_msg_opt_route_prefix (msg, offset), route.plen);
-		if (nm_rdisc_add_route (rdisc, &route))
-			changed |= NM_RDISC_CONFIG_ROUTES;
-	}
-
-	/* DNS information */
-	ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_RDNSS) {
-		static struct in6_addr *addr;
-		int addr_index;
-
-		ndp_msg_opt_rdnss_for_each_addr (addr, addr_index, msg, offset) {
-			NMRDiscDNSServer dns_server = {
-			    .address = *addr,
-			    .timestamp = now,
-			    .lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset),
-			};
-
-			/* Pad the lifetime somewhat to give a bit of slack in cases
-			 * where one RA gets lost or something (which can happen on unreliable
-			 * links like WiFi where certain types of frames are not retransmitted).
-			 * Note that 0 has special meaning and is therefore not adjusted.
-			 */
-			if (dns_server.lifetime && dns_server.lifetime < 7200)
-				dns_server.lifetime = 7200;
-			if (nm_rdisc_add_dns_server (rdisc, &dns_server))
-				changed |= NM_RDISC_CONFIG_DNS_SERVERS;
-		}
-	}
-	ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_DNSSL) {
-		char *domain;
-		int domain_index;
-
-		ndp_msg_opt_dnssl_for_each_domain (domain, domain_index, msg, offset) {
-			NMRDiscDNSDomain dns_domain = {
-			    .domain = domain,
-			    .timestamp = now,
-			    .lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset),
-			};
-
-			/* Pad the lifetime somewhat to give a bit of slack in cases
-			 * where one RA gets lost or something (which can happen on unreliable
-			 * links like WiFi where certain types of frames are not retransmitted).
-			 * Note that 0 has special meaning and is therefore not adjusted.
-			 */
-			if (dns_domain.lifetime && dns_domain.lifetime < 7200)
-				dns_domain.lifetime = 7200;
-			if (nm_rdisc_add_dns_domain (rdisc, &dns_domain))
-				changed |= NM_RDISC_CONFIG_DNS_DOMAINS;
-		}
-	}
-
-	hop_limit = ndp_msgra_curhoplimit (msgra);
-	if (rdata->public.hop_limit != hop_limit) {
-		rdata->public.hop_limit = hop_limit;
-		changed |= NM_RDISC_CONFIG_HOP_LIMIT;
-	}
-
-	/* MTU */
-	ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_MTU) {
-		guint32 mtu = ndp_msg_opt_mtu(msg, offset);
-		if (mtu >= 1280) {
-			if (rdata->public.mtu != mtu) {
-				rdata->public.mtu = mtu;
-				changed |= NM_RDISC_CONFIG_MTU;
-			}
-		} else {
-			/* All sorts of bad things would happen if we accepted this.
-			 * Kernel would set it, but would flush out all IPv6 addresses away
-			 * from the link, even the link-local, and we wouldn't be able to
-			 * listen for further RAs that could fix the MTU. */
-			_LOGW ("MTU too small for IPv6 ignored: %d", mtu);
-		}
-	}
-
-	nm_rdisc_ra_received (rdisc, now, changed);
-	return 0;
-}
-
-static gboolean
-event_ready (GIOChannel *source, GIOCondition condition, NMRDisc *rdisc)
-{
-	nm_auto_pop_netns NMPNetns *netns = NULL;
-	NMLndpRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
-
-	_LOGD ("processing libndp events");
-
-	if (!nm_rdisc_netns_push (rdisc, &netns))
-		return G_SOURCE_CONTINUE;
-
-	ndp_callall_eventfd_handler (priv->ndp);
-	return G_SOURCE_CONTINUE;
-}
-
-static void
-start (NMRDisc *rdisc)
-{
-	NMLndpRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
-	int fd = ndp_get_eventfd (priv->ndp);
-
-	priv->event_channel = g_io_channel_unix_new (fd);
-	priv->event_id = g_io_add_watch (priv->event_channel, G_IO_IN, (GIOFunc) event_ready, rdisc);
-
-	/* Flush any pending messages to avoid using obsolete information */
-	event_ready (priv->event_channel, 0, rdisc);
-
-	ndp_msgrcv_handler_register (priv->ndp, receive_ra, NDP_MSG_RA, nm_rdisc_get_ifindex (rdisc), rdisc);
-}
-
-/*****************************************************************************/
-
-static inline int
-ipv6_sysctl_get (NMPlatform *platform, const char *ifname, const char *property, int min, int max, int defval)
-{
-	return (int) nm_platform_sysctl_get_int_checked (platform,
-	                                                 nm_utils_ip6_property_path (ifname, property),
-	                                                 10,
-	                                                 min,
-	                                                 max,
-	                                                 defval);
-}
-
-static void
-nm_lndp_rdisc_init (NMLndpRDisc *lndp_rdisc)
-{
-}
-
-NMRDisc *
-nm_lndp_rdisc_new (NMPlatform *platform,
-                   int ifindex,
-                   const char *ifname,
-                   NMUtilsStableType stable_type,
-                   const char *network_id,
-                   NMSettingIP6ConfigAddrGenMode addr_gen_mode,
-                   GError **error)
-{
-	nm_auto_pop_netns NMPNetns *netns = NULL;
-	NMRDisc *rdisc;
-	NMLndpRDiscPrivate *priv;
-	int errsv;
-
-	g_return_val_if_fail (NM_IS_PLATFORM (platform), NULL);
-	g_return_val_if_fail (!error || !*error, NULL);
-
-	if (!nm_platform_netns_push (platform, &netns))
-		return NULL;
-
-	rdisc = g_object_new (NM_TYPE_LNDP_RDISC,
-	                      NM_RDISC_PLATFORM, platform,
-	                      NM_RDISC_STABLE_TYPE, (int) stable_type,
-	                      NM_RDISC_IFINDEX, ifindex,
-	                      NM_RDISC_IFNAME, ifname,
-	                      NM_RDISC_NETWORK_ID, network_id,
-	                      NM_RDISC_ADDR_GEN_MODE, (int) addr_gen_mode,
-	                      NM_RDISC_MAX_ADDRESSES, ipv6_sysctl_get (platform, ifname,
-	                                                               "max_addresses",
-	                                                               0, G_MAXINT32, NM_RDISC_MAX_ADDRESSES_DEFAULT),
-	                      NM_RDISC_ROUTER_SOLICITATIONS, ipv6_sysctl_get (platform, ifname,
-	                                                                      "router_solicitations",
-	                                                                      1, G_MAXINT32, NM_RDISC_ROUTER_SOLICITATIONS_DEFAULT),
-	                      NM_RDISC_ROUTER_SOLICITATION_INTERVAL, ipv6_sysctl_get (platform, ifname,
-	                                                                              "router_solicitation_interval",
-	                                                                              1, G_MAXINT32, NM_RDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT),
-	                      NULL);
-
-	priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
-
-	errsv = ndp_open (&priv->ndp);
-
-	if (errsv != 0) {
-		errsv = errsv > 0 ? errsv : -errsv;
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             "failure creating libndp socket: %s (%d)",
-		             g_strerror (errsv), errsv);
-		g_object_unref (rdisc);
-		return NULL;
-	}
-	return rdisc;
-}
-
-static void
-dispose (GObject *object)
-{
-	NMRDisc *rdisc = (NMRDisc *) object;
-	NMLndpRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
-
-	nm_clear_g_source (&priv->event_id);
-	g_clear_pointer (&priv->event_channel, g_io_channel_unref);
-
-	if (priv->ndp) {
-		ndp_msgrcv_handler_unregister (priv->ndp, receive_ra, NDP_MSG_RA, nm_rdisc_get_ifindex (rdisc), rdisc);
-		ndp_close (priv->ndp);
-		priv->ndp = NULL;
-	}
-
-	G_OBJECT_CLASS (nm_lndp_rdisc_parent_class)->dispose (object);
-}
-
-static void
-nm_lndp_rdisc_class_init (NMLndpRDiscClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMRDiscClass *rdisc_class = NM_RDISC_CLASS (klass);
-
-	object_class->dispose = dispose;
-	rdisc_class->start = start;
-	rdisc_class->send_rs = send_rs;
-}