about summary refs log tree commit diff
path: root/src/ip6-manager
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2010-11-29 00:47:11 +0100
committerMichael Biebl <biebl@debian.org>2010-11-29 00:47:11 +0100
commit9fae01fa351805b2903e535736e06971bc0b925e (patch)
treec19bccf84c9f894e50fae678ba6ee2b2044e2d30 /src/ip6-manager
Imported Upstream version 0.8.1 upstream/0.8.1
Diffstat (limited to 'src/ip6-manager')
-rw-r--r--src/ip6-manager/Makefile.am26
-rw-r--r--src/ip6-manager/Makefile.in570
-rw-r--r--src/ip6-manager/nm-ip6-manager.c1123
-rw-r--r--src/ip6-manager/nm-ip6-manager.h86
4 files changed, 1805 insertions, 0 deletions
diff --git a/src/ip6-manager/Makefile.am b/src/ip6-manager/Makefile.am
new file mode 100644
index 00000000..c2f55914
--- /dev/null
+++ b/src/ip6-manager/Makefile.am
@@ -0,0 +1,26 @@
+INCLUDES = \
+	-I${top_srcdir} \
+	-I${top_srcdir}/include \
+	-I${top_builddir}/marshallers \
+	-I${top_srcdir}/libnm-util \
+	-I${top_srcdir}/src/logging \
+	-I${top_srcdir}/src \
+	-I${top_srcdir}/src/named-manager
+
+noinst_LTLIBRARIES = libip6-manager.la
+
+libip6_manager_la_SOURCES = \
+	nm-ip6-manager.c \
+	nm-ip6-manager.h
+
+libip6_manager_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	-DG_DISABLE_DEPRECATED
+
+libip6_manager_la_LIBADD = \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS)
+
diff --git a/src/ip6-manager/Makefile.in b/src/ip6-manager/Makefile.in
new file mode 100644
index 00000000..ddb90e0d
--- /dev/null
+++ b/src/ip6-manager/Makefile.in
@@ -0,0 +1,570 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/ip6-manager
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+	$(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libip6_manager_la_DEPENDENCIES =  \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libip6_manager_la_OBJECTS = libip6_manager_la-nm-ip6-manager.lo
+libip6_manager_la_OBJECTS = $(am_libip6_manager_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libip6_manager_la_SOURCES)
+DIST_SOURCES = $(libip6_manager_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+IPTABLES_PATH = @IPTABLES_PATH@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+	-I${top_srcdir} \
+	-I${top_srcdir}/include \
+	-I${top_builddir}/marshallers \
+	-I${top_srcdir}/libnm-util \
+	-I${top_srcdir}/src/logging \
+	-I${top_srcdir}/src \
+	-I${top_srcdir}/src/named-manager
+
+noinst_LTLIBRARIES = libip6-manager.la
+libip6_manager_la_SOURCES = \
+	nm-ip6-manager.c \
+	nm-ip6-manager.h
+
+libip6_manager_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	-DG_DISABLE_DEPRECATED
+
+libip6_manager_la_LIBADD = \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ip6-manager/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/ip6-manager/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libip6-manager.la: $(libip6_manager_la_OBJECTS) $(libip6_manager_la_DEPENDENCIES) 
+	$(LINK)  $(libip6_manager_la_OBJECTS) $(libip6_manager_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libip6_manager_la-nm-ip6-manager.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+libip6_manager_la-nm-ip6-manager.lo: nm-ip6-manager.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libip6_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libip6_manager_la-nm-ip6-manager.lo -MD -MP -MF $(DEPDIR)/libip6_manager_la-nm-ip6-manager.Tpo -c -o libip6_manager_la-nm-ip6-manager.lo `test -f 'nm-ip6-manager.c' || echo '$(srcdir)/'`nm-ip6-manager.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libip6_manager_la-nm-ip6-manager.Tpo $(DEPDIR)/libip6_manager_la-nm-ip6-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-ip6-manager.c' object='libip6_manager_la-nm-ip6-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libip6_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libip6_manager_la-nm-ip6-manager.lo `test -f 'nm-ip6-manager.c' || echo '$(srcdir)/'`nm-ip6-manager.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c
new file mode 100644
index 00000000..f6f6127c
--- /dev/null
+++ b/src/ip6-manager/nm-ip6-manager.c
@@ -0,0 +1,1123 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* nm-ip6-manager.c - Handle IPv6 address configuration for NetworkManager
+ *
+ * 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) 2009 - 2010 Red Hat, Inc.
+ */
+
+#include <errno.h>
+#include <netinet/icmp6.h>
+
+#include <netlink/route/addr.h>
+#include <netlink/route/rtnl.h>
+#include <netlink/route/route.h>
+
+#include "nm-ip6-manager.h"
+#include "nm-netlink-monitor.h"
+#include "NetworkManagerUtils.h"
+#include "nm-marshal.h"
+#include "nm-logging.h"
+#include "nm-system.h"
+
+/* Pre-DHCP addrconf timeout, in seconds */
+#define NM_IP6_TIMEOUT 20
+
+/* FIXME? Stolen from the kernel sources */
+#define IF_RA_OTHERCONF 0x80
+#define IF_RA_MANAGED   0x40
+#define IF_RA_RCVD      0x20
+#define IF_RS_SENT      0x10
+
+typedef struct {
+	NMNetlinkMonitor *monitor;
+	GHashTable *devices;
+
+	struct nl_handle *nlh;
+	struct nl_cache *addr_cache, *route_cache;
+
+	guint netlink_id;
+} NMIP6ManagerPrivate;
+
+#define NM_IP6_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP6_MANAGER, NMIP6ManagerPrivate))
+
+G_DEFINE_TYPE (NMIP6Manager, nm_ip6_manager, G_TYPE_OBJECT)
+
+enum {
+	ADDRCONF_COMPLETE,
+	CONFIG_CHANGED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+typedef enum {
+	NM_IP6_DEVICE_UNCONFIGURED,
+	NM_IP6_DEVICE_GOT_LINK_LOCAL,
+	NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT,
+	NM_IP6_DEVICE_GOT_ADDRESS,
+	NM_IP6_DEVICE_TIMED_OUT
+} NMIP6DeviceState;
+
+typedef struct {
+	struct in6_addr addr;
+	time_t expires;
+} NMIP6RDNSS;
+
+/******************************************************************/
+
+typedef struct {
+	NMIP6Manager *manager;
+	char *iface;
+	int ifindex;
+
+	char *disable_ip6_path;
+	gboolean disable_ip6_save_valid;
+	guint32 disable_ip6_save;
+
+	guint finish_addrconf_id;
+	guint config_changed_id;
+
+	NMIP6DeviceState state;
+	NMIP6DeviceState target_state;
+	gboolean addrconf_complete;
+
+	GArray *rdnss_servers;
+	guint rdnss_timeout_id;
+
+	guint ip6flags_poll_id;
+
+	guint32 ra_flags;
+} NMIP6Device;
+
+static void
+nm_ip6_device_destroy (NMIP6Device *device)
+{
+	g_return_if_fail (device != NULL);
+
+	/* reset the saved IPv6 value */
+	if (device->disable_ip6_save_valid) {
+		nm_utils_do_sysctl (device->disable_ip6_path,
+		                    device->disable_ip6_save ? "1\n" : "0\n");
+	}
+
+	if (device->finish_addrconf_id)
+		g_source_remove (device->finish_addrconf_id);
+	if (device->config_changed_id)
+		g_source_remove (device->config_changed_id);
+	g_free (device->iface);
+	if (device->rdnss_servers)
+		g_array_free (device->rdnss_servers, TRUE);
+	if (device->rdnss_timeout_id)
+		g_source_remove (device->rdnss_timeout_id);
+	if (device->ip6flags_poll_id)
+		g_source_remove (device->ip6flags_poll_id);
+
+	g_slice_free (NMIP6Device, device);
+}
+
+static NMIP6Device *
+nm_ip6_device_new (NMIP6Manager *manager, int ifindex)
+{
+	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+	NMIP6Device *device;
+
+	g_return_val_if_fail (ifindex > 0, NULL);
+
+	device = g_slice_new0 (NMIP6Device);
+	if (!device) {
+		nm_log_err (LOGD_IP6, "(%d): out of memory creating IP6 addrconf object.",
+		            ifindex);
+		return NULL;
+	}
+
+	device->ifindex = ifindex;
+	device->iface = g_strdup (nm_netlink_index_to_iface (ifindex));
+	if (!device->iface) {
+		nm_log_err (LOGD_IP6, "(%d): could not find interface name from index.",
+		            ifindex);
+		goto error;
+	}
+
+	device->manager = manager;
+
+	device->rdnss_servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS));
+
+	g_hash_table_replace (priv->devices, GINT_TO_POINTER (device->ifindex), device);
+
+	/* and the original value of IPv6 enable/disable */
+	device->disable_ip6_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/disable_ipv6",
+	                                            device->iface);
+	g_assert (device->disable_ip6_path);
+	device->disable_ip6_save_valid = nm_utils_get_proc_sys_net_value (device->disable_ip6_path,
+	                                                                  device->iface,
+	                                                                  &device->disable_ip6_save);
+
+	return device;
+
+error:
+	nm_ip6_device_destroy (device);
+	return NULL;
+}
+
+static NMIP6Device *
+nm_ip6_manager_get_device (NMIP6Manager *manager, int ifindex)
+{
+	NMIP6ManagerPrivate *priv;
+
+	g_return_val_if_fail (manager != NULL, NULL);
+	g_return_val_if_fail (NM_IS_IP6_MANAGER (manager), NULL);
+
+	priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+	return g_hash_table_lookup (priv->devices, GINT_TO_POINTER (ifindex));
+}
+
+/******************************************************************/
+
+typedef struct {
+	NMIP6Device *device;
+	guint dhcp_opts;
+	gboolean success;
+} CallbackInfo;
+
+static gboolean
+finish_addrconf (gpointer user_data)
+{
+	CallbackInfo *info = user_data;
+	NMIP6Device *device = info->device;
+	NMIP6Manager *manager = device->manager;
+	int ifindex;
+
+	device->finish_addrconf_id = 0;
+	device->addrconf_complete = TRUE;
+	ifindex = device->ifindex;
+
+	/* We're done, stop polling IPv6 flags */
+	if (device->ip6flags_poll_id) {
+		g_source_remove (device->ip6flags_poll_id);
+		device->ip6flags_poll_id = 0;
+	}
+
+	/* And tell listeners that addrconf is complete */
+	if (info->success) {
+		g_signal_emit (manager, signals[ADDRCONF_COMPLETE], 0,
+		               ifindex, info->dhcp_opts, TRUE);
+	} else {
+		nm_log_info (LOGD_IP6, "(%s): IP6 addrconf timed out or failed.",
+		             device->iface);
+
+		nm_ip6_manager_cancel_addrconf (manager, ifindex);
+		g_signal_emit (manager, signals[ADDRCONF_COMPLETE], 0,
+		               ifindex, info->dhcp_opts, FALSE);
+	}
+
+	return FALSE;
+}
+
+static gboolean
+emit_config_changed (gpointer user_data)
+{
+	CallbackInfo *info = user_data;
+	NMIP6Device *device = info->device;
+	NMIP6Manager *manager = device->manager;
+
+	device->config_changed_id = 0;
+	g_signal_emit (manager, signals[CONFIG_CHANGED], 0,
+	               device->ifindex,
+	               info->dhcp_opts,
+	               info->success);
+	return FALSE;
+}
+
+static void set_rdnss_timeout (NMIP6Device *device);
+
+static gboolean
+rdnss_expired (gpointer user_data)
+{
+	NMIP6Device *device = user_data;
+	CallbackInfo info = { device, IP6_DHCP_OPT_NONE };
+
+	nm_log_dbg (LOGD_IP6, "(%s): IPv6 RDNSS information expired", device->iface);
+
+	set_rdnss_timeout (device);
+	emit_config_changed (&info);
+	return FALSE;
+}
+
+static void
+set_rdnss_timeout (NMIP6Device *device)
+{
+	time_t expires = 0, now = time (NULL);
+	NMIP6RDNSS *rdnss;
+	int i;
+
+	if (device->rdnss_timeout_id) {
+		g_source_remove (device->rdnss_timeout_id);
+		device->rdnss_timeout_id = 0;
+	}
+
+	/* Find the soonest expiration time. */
+	for (i = 0; i < device->rdnss_servers->len; i++) {
+		rdnss = &g_array_index (device->rdnss_servers, NMIP6RDNSS, i);
+		if (rdnss->expires == 0)
+			continue;
+
+		/* If the entry has already expired, remove it; the "+ 1" is
+		 * because g_timeout_add_seconds() might fudge the timing a
+		 * bit.
+		 */
+		if (rdnss->expires <= now + 1) {
+			char buf[INET6_ADDRSTRLEN + 1];
+
+			if (inet_ntop (AF_INET6, &(rdnss->addr), buf, sizeof (buf)) > 0) {
+				nm_log_dbg (LOGD_IP6, "(%s): removing expired RA-provided nameserver %s",
+				            device->iface, buf);
+			}
+			g_array_remove_index_fast (device->rdnss_servers, i--);
+			continue;
+		}
+
+		if (!expires || rdnss->expires < expires)
+			expires = rdnss->expires;
+	}
+
+	if (expires) {
+		device->rdnss_timeout_id = g_timeout_add_seconds (expires - now,
+														  rdnss_expired,
+														  device);
+	}
+}
+
+static CallbackInfo *
+callback_info_new (NMIP6Device *device, guint dhcp_opts, gboolean success)
+{
+	CallbackInfo *info;
+
+	info = g_malloc0 (sizeof (CallbackInfo));
+	info->device = device;
+	info->dhcp_opts = dhcp_opts;
+	info->success = success;
+	return info;
+}
+
+static const char *
+state_to_string (NMIP6DeviceState state)
+{
+	switch (state) {
+	case NM_IP6_DEVICE_UNCONFIGURED:
+		return "unconfigured";
+	case NM_IP6_DEVICE_GOT_LINK_LOCAL:
+		return "got-link-local";
+	case NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT:
+		return "got-ra";
+	case NM_IP6_DEVICE_GOT_ADDRESS:
+		return "got-address";
+	case NM_IP6_DEVICE_TIMED_OUT:
+		return "timed-out";
+	default:
+		return "unknown";
+	}
+}
+
+static void
+nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed)
+{
+	NMIP6Manager *manager = device->manager;
+	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+	struct rtnl_addr *rtnladdr;
+	struct nl_addr *nladdr;
+	struct in6_addr *addr;
+	CallbackInfo *info;
+	guint dhcp_opts = IP6_DHCP_OPT_NONE;
+	gboolean found_linklocal = FALSE, found_other = FALSE;
+
+	nm_log_dbg (LOGD_IP6, "(%s): syncing with netlink (ra_flags 0x%X) (state/target '%s'/'%s')",
+	            device->iface, device->ra_flags,
+	            state_to_string (device->state),
+	            state_to_string (device->target_state));
+
+	/* Look for any IPv6 addresses the kernel may have set for the device */
+	for (rtnladdr = (struct rtnl_addr *) nl_cache_get_first (priv->addr_cache);
+		 rtnladdr;
+		 rtnladdr = (struct rtnl_addr *) nl_cache_get_next ((struct nl_object *) rtnladdr)) {
+		char buf[INET6_ADDRSTRLEN];
+
+		if (rtnl_addr_get_ifindex (rtnladdr) != device->ifindex)
+			continue;
+
+		nladdr = rtnl_addr_get_local (rtnladdr);
+		if (!nladdr || nl_addr_get_family (nladdr) != AF_INET6)
+			continue;
+
+		addr = nl_addr_get_binary_addr (nladdr);
+
+		if (inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN) > 0) {
+			nm_log_dbg (LOGD_IP6, "(%s): netlink address: %s",
+			            device->iface, buf);
+		}
+
+		if (IN6_IS_ADDR_LINKLOCAL (addr)) {
+			if (device->state == NM_IP6_DEVICE_UNCONFIGURED)
+				device->state = NM_IP6_DEVICE_GOT_LINK_LOCAL;
+			found_linklocal = TRUE;
+		} else {
+			if (device->state < NM_IP6_DEVICE_GOT_ADDRESS)
+				device->state = NM_IP6_DEVICE_GOT_ADDRESS;
+			found_other = TRUE;
+		}
+	}
+
+	/* There might be a LL address hanging around on the interface from
+	 * before in the initial run, but if it goes away later, make sure we
+	 * regress from GOT_LINK_LOCAL back to UNCONFIGURED.
+	 */
+	if ((device->state == NM_IP6_DEVICE_GOT_LINK_LOCAL) && !found_linklocal)
+		device->state = NM_IP6_DEVICE_UNCONFIGURED;
+
+	nm_log_dbg (LOGD_IP6, "(%s): addresses synced (state %s)",
+	            device->iface, state_to_string (device->state));
+
+	/* We only care about router advertisements if we want a real IPv6 address */
+	if (   (device->target_state == NM_IP6_DEVICE_GOT_ADDRESS)
+	    && (device->ra_flags & IF_RA_RCVD)) {
+
+		if (device->state < NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT)
+			device->state = NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT;
+
+		if (device->ra_flags & IF_RA_MANAGED) {
+			dhcp_opts = IP6_DHCP_OPT_MANAGED;
+			nm_log_dbg (LOGD_IP6, "router advertisement deferred to DHCPv6");
+		} else if (device->ra_flags & IF_RA_OTHERCONF) {
+			dhcp_opts = IP6_DHCP_OPT_OTHERCONF;
+			nm_log_dbg (LOGD_IP6, "router advertisement requests parallel DHCPv6");
+		}
+	}
+
+	if (!device->addrconf_complete) {
+		/* Managed mode (ie DHCP only) short-circuits automatic addrconf, so
+		 * we don't bother waiting for the device's target state to be reached
+		 * when the RA requests managed mode.
+		 */
+		if (   (device->state >= device->target_state)
+		    || (dhcp_opts == IP6_DHCP_OPT_MANAGED)) {
+			/* device->finish_addrconf_id may currently be a timeout
+			 * rather than an idle, so we remove the existing source.
+			 */
+			if (device->finish_addrconf_id)
+				g_source_remove (device->finish_addrconf_id);
+
+			nm_log_dbg (LOGD_IP6, "(%s): reached target state or Managed-mode requested (state '%s') (dhcp opts 0x%X)",
+			            device->iface, state_to_string (device->state),
+			            dhcp_opts);
+
+			info = callback_info_new (device, dhcp_opts, TRUE);
+			device->finish_addrconf_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+			                                              finish_addrconf,
+			                                              info,
+			                                              (GDestroyNotify) g_free);
+		}
+	} else if (config_changed) {
+		if (!device->config_changed_id) {
+			gboolean success = TRUE;
+
+			/* If for some reason an RA-provided address disappeared, we need
+			 * to make sure we fail the connection as it's no longer valid.
+			 */
+			if (   (device->state == NM_IP6_DEVICE_GOT_ADDRESS)
+			    && (device->target_state == NM_IP6_DEVICE_GOT_ADDRESS)
+			    && !found_other) {
+				nm_log_dbg (LOGD_IP6, "(%s): RA-provided address no longer valid",
+				            device->iface);
+				success = FALSE;
+			}
+
+			info = callback_info_new (device, dhcp_opts, success);
+			device->config_changed_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+			                                             emit_config_changed,
+			                                             info,
+			                                             (GDestroyNotify) g_free);
+		}
+	}
+}
+
+static void
+ref_object (struct nl_object *obj, void *data)
+{
+	struct nl_object **out = data;
+
+	nl_object_get (obj);
+	*out = obj;
+}
+
+static NMIP6Device *
+process_addr (NMIP6Manager *manager, struct nl_msg *msg)
+{
+	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+	NMIP6Device *device;
+	struct rtnl_addr *rtnladdr;
+	int old_size;
+
+	nm_log_dbg (LOGD_IP6, "processing netlink new/del address message");
+
+	rtnladdr = NULL;
+	nl_msg_parse (msg, ref_object, &rtnladdr);
+	if (!rtnladdr) {
+		nm_log_dbg (LOGD_IP6, "error processing netlink new/del address message");
+		return NULL;
+	}
+
+	device = nm_ip6_manager_get_device (manager, rtnl_addr_get_ifindex (rtnladdr));
+	if (!device) {
+		nm_log_dbg (LOGD_IP6, "ignoring message for unknown device");
+		return NULL;
+	}
+
+	old_size = nl_cache_nitems (priv->addr_cache);
+	nl_cache_include (priv->addr_cache, (struct nl_object *)rtnladdr, NULL);
+	rtnl_addr_put (rtnladdr);
+
+	/* The kernel will re-notify us of automatically-added addresses
+	 * every time it gets another router advertisement. We only want
+	 * to notify higher levels if we actually changed something.
+	 */
+	if (nl_cache_nitems (priv->addr_cache) == old_size) {
+		nm_log_dbg (LOGD_IP6, "(%s): address cache unchanged, ignoring message",
+		            device->iface);
+		return NULL;
+	}
+
+	return device;
+}
+
+static NMIP6Device *
+process_route (NMIP6Manager *manager, struct nl_msg *msg)
+{
+	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+	NMIP6Device *device;
+	struct rtnl_route *rtnlroute;
+	int old_size;
+
+	nm_log_dbg (LOGD_IP6, "processing netlink new/del route message");
+
+	rtnlroute = NULL;
+	nl_msg_parse (msg, ref_object, &rtnlroute);
+	if (!rtnlroute) {
+		nm_log_dbg (LOGD_IP6, "error processing netlink new/del route message");
+		return NULL;
+	}
+
+	device = nm_ip6_manager_get_device (manager, rtnl_route_get_oif (rtnlroute));
+	if (!device) {
+		nm_log_dbg (LOGD_IP6, "ignoring message for unknown device");
+		return NULL;
+	}
+
+	old_size = nl_cache_nitems (priv->route_cache);
+	nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL);
+	rtnl_route_put (rtnlroute);
+
+	/* As above in process_addr */
+	if (nl_cache_nitems (priv->route_cache) == old_size) {
+		nm_log_dbg (LOGD_IP6, "(%s): route cache unchanged, ignoring message",
+		            device->iface);
+		return NULL;
+	}
+
+	return device;
+}
+
+static NMIP6Device *
+process_prefix (NMIP6Manager *manager, struct nl_msg *msg)
+{
+	struct prefixmsg *pmsg;
+	NMIP6Device *device;
+
+	/* We don't care about the prefix itself, but if we receive a
+	 * router advertisement telling us to use DHCP, we might not
+	 * get any RTM_NEWADDRs or RTM_NEWROUTEs, so this is our only
+	 * way to notice immediately that an RA was received.
+	 */
+
+	nm_log_dbg (LOGD_IP6, "processing netlink new prefix message");
+
+	pmsg = (struct prefixmsg *) NLMSG_DATA (nlmsg_hdr (msg));
+	device = nm_ip6_manager_get_device (manager, pmsg->prefix_ifindex);
+
+	if (!device || device->addrconf_complete) {
+		nm_log_dbg (LOGD_IP6, "(%s): ignoring unknown or completed device",
+		            device ? device->iface : "(none)");
+		return NULL;
+	}
+
+	return device;
+}
+
+/* RDNSS parsing code based on rdnssd, Copyright 2007 Pierre Ynard,
+ * Rémi Denis-Courmont. GPLv2/3
+ */
+
+#define ND_OPT_RDNSS 25
+struct nd_opt_rdnss {
+	uint8_t nd_opt_rdnss_type;
+	uint8_t nd_opt_rdnss_len;
+	uint16_t nd_opt_rdnss_reserved1;
+	uint32_t nd_opt_rdnss_lifetime;
+	/* followed by one or more IPv6 addresses */
+};
+
+static NMIP6Device *
+process_nduseropt (NMIP6Manager *manager, struct nl_msg *msg)
+{
+	NMIP6Device *device;
+	struct nduseroptmsg *ndmsg;
+	struct nd_opt_hdr *opt;
+	guint opts_len, i;
+	time_t now = time (NULL);
+	struct nd_opt_rdnss *rdnss_opt;
+	struct in6_addr *addr;
+	GArray *servers;
+	NMIP6RDNSS server, *sa, *sb;
+	gboolean changed;
+
+	nm_log_dbg (LOGD_IP6, "processing netlink nduseropt message");
+
+	ndmsg = (struct nduseroptmsg *) NLMSG_DATA (nlmsg_hdr (msg));
+
+	if (ndmsg->nduseropt_family != AF_INET6 ||
+		ndmsg->nduseropt_icmp_type != ND_ROUTER_ADVERT ||
+		ndmsg->nduseropt_icmp_code != 0) {
+		nm_log_dbg (LOGD_IP6, "ignoring non-Router Advertisement message");
+		return NULL;
+	}
+
+	device = nm_ip6_manager_get_device (manager, ndmsg->nduseropt_ifindex);
+	if (!device) {
+		nm_log_dbg (LOGD_IP6, "ignoring message for unknown device");
+		return NULL;
+	}
+
+	servers = g_array_new (FALSE, FALSE, sizeof (NMIP6RDNSS));
+
+	opt = (struct nd_opt_hdr *) (ndmsg + 1);
+	opts_len = ndmsg->nduseropt_opts_len;
+
+	while (opts_len >= sizeof (struct nd_opt_hdr)) {
+		size_t nd_opt_len = opt->nd_opt_len;
+
+		if (nd_opt_len == 0 || opts_len < (nd_opt_len << 3))
+			break;
+
+		if (opt->nd_opt_type != ND_OPT_RDNSS)
+			goto next;
+
+		if (nd_opt_len < 3 || (nd_opt_len & 1) == 0)
+			goto next;
+
+		rdnss_opt = (struct nd_opt_rdnss *) opt;
+
+		/* Pad the DNS server expiry 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).
+		 */
+		server.expires = now + ntohl (rdnss_opt->nd_opt_rdnss_lifetime) + 10;
+
+		for (addr = (struct in6_addr *) (rdnss_opt + 1); nd_opt_len >= 2; addr++, nd_opt_len -= 2) {
+			char buf[INET6_ADDRSTRLEN + 1];
+
+			if (inet_ntop (AF_INET6, addr, buf, sizeof (buf))) {
+				nm_log_dbg (LOGD_IP6, "(%s): found RA-provided nameserver %s (expires in %d seconds)",
+				            device->iface, buf,
+				            ntohl (rdnss_opt->nd_opt_rdnss_lifetime));
+			}
+
+			server.addr = *addr;
+			g_array_append_val (servers, server);
+		}
+
+	next:
+		opts_len -= opt->nd_opt_len << 3;
+		opt = (struct nd_opt_hdr *) ((uint8_t *) opt + (opt->nd_opt_len << 3));
+	}
+
+	/* See if anything (other than expiration time) changed */
+	if (servers->len != device->rdnss_servers->len)
+		changed = TRUE;
+	else {
+		for (i = 0; i < servers->len; i++) {
+			sa = &(g_array_index (servers, NMIP6RDNSS, i));
+			sb = &(g_array_index (device->rdnss_servers, NMIP6RDNSS, i));
+			if (IN6_ARE_ADDR_EQUAL (&sa->addr, &sb->addr) == FALSE) {
+				changed = TRUE;
+				break;
+			}
+		}
+		changed = FALSE;
+	}
+
+	if (changed) {
+		nm_log_dbg (LOGD_IP6, "(%s): RA-provided nameservers changed", device->iface);
+	}
+
+	/* Always copy in new servers (even if unchanged) to get their updated
+	 * expiration times.
+	 */
+	g_array_free (device->rdnss_servers, TRUE);
+	device->rdnss_servers = servers;
+
+	/* Timeouts may have changed even if IPs didn't */
+	set_rdnss_timeout (device);
+
+	if (changed)
+		return device;
+	else
+		return NULL;
+}
+
+static struct nla_policy link_policy[IFLA_MAX + 1] = {
+	[IFLA_PROTINFO] = { .type = NLA_NESTED },
+};
+
+static struct nla_policy link_prot_policy[IFLA_INET6_MAX + 1] = {
+	[IFLA_INET6_FLAGS]	= { .type = NLA_U32 },
+};
+
+static NMIP6Device *
+process_newlink (NMIP6Manager *manager, struct nl_msg *msg)
+{
+	struct nlmsghdr *hdr = nlmsg_hdr (msg);
+	struct ifinfomsg *ifi;
+	NMIP6Device *device;
+	struct nlattr *tb[IFLA_MAX + 1];
+	struct nlattr *pi[IFLA_INET6_MAX + 1];
+	int err;
+
+	ifi = nlmsg_data (hdr);
+	if (ifi->ifi_family != AF_INET6) {
+		nm_log_dbg (LOGD_IP6, "ignoring netlink message family %d", ifi->ifi_family);
+		return NULL;
+	}
+
+	device = nm_ip6_manager_get_device (manager, ifi->ifi_index);
+	if (!device || device->addrconf_complete) {
+		nm_log_dbg (LOGD_IP6, "(%s): ignoring unknown or completed device",
+		            device ? device->iface : "(none)");
+		return NULL;
+	}
+
+	/* FIXME: we have to do this manually for now since libnl doesn't yet
+	 * support the IFLA_PROTINFO attribute of NEWLINK messages.  When it does,
+	 * we can get rid of this function and just grab IFLA_PROTINFO from
+	 * nm_ip6_device_sync_from_netlink(), then get the IFLA_INET6_FLAGS out of
+	 * the PROTINFO.
+	 */
+
+	err = nlmsg_parse (hdr, sizeof (*ifi), tb, IFLA_MAX, link_policy);
+	if (err < 0) {
+		nm_log_dbg (LOGD_IP6, "(%s): error parsing PROTINFO attribute", device->iface);
+		return NULL;
+	}
+	if (!tb[IFLA_PROTINFO]) {
+		nm_log_dbg (LOGD_IP6, "(%s): message had no PROTINFO attribute", device->iface);
+		return NULL;
+	}
+
+	err = nla_parse_nested (pi, IFLA_INET6_MAX, tb[IFLA_PROTINFO], link_prot_policy);
+	if (err < 0) {
+		nm_log_dbg (LOGD_IP6, "(%s): error parsing PROTINFO flags", device->iface);
+		return NULL;
+	}
+	if (!pi[IFLA_INET6_FLAGS]) {
+		nm_log_dbg (LOGD_IP6, "(%s): message had no PROTINFO flags", device->iface);
+		return NULL;
+	}
+
+	device->ra_flags = nla_get_u32 (pi[IFLA_INET6_FLAGS]);
+	nm_log_dbg (LOGD_IP6, "(%s): got IPv6 flags 0x%X", device->iface, device->ra_flags);
+
+	return device;
+}
+
+static void
+netlink_notification (NMNetlinkMonitor *monitor, struct nl_msg *msg, gpointer user_data)
+{
+	NMIP6Manager *manager = (NMIP6Manager *) user_data;
+	NMIP6Device *device;
+	struct nlmsghdr *hdr;
+	gboolean config_changed = FALSE;
+
+	hdr = nlmsg_hdr (msg);
+	nm_log_dbg (LOGD_HW, "netlink notificate type %d", hdr->nlmsg_type);
+	switch (hdr->nlmsg_type) {
+	case RTM_NEWADDR:
+	case RTM_DELADDR:
+		device = process_addr (manager, msg);
+		config_changed = TRUE;
+		break;
+	case RTM_NEWROUTE:
+	case RTM_DELROUTE:
+		device = process_route (manager, msg);
+		config_changed = TRUE;
+		break;
+	case RTM_NEWPREFIX:
+		device = process_prefix (manager, msg);
+		break;
+	case RTM_NEWNDUSEROPT:
+		device = process_nduseropt (manager, msg);
+		config_changed = TRUE;
+		break;
+	case RTM_NEWLINK:
+		device = process_newlink (manager, msg);
+		config_changed = TRUE;
+		break;
+	default:
+		return;
+	}
+
+	if (device) {
+		nm_log_dbg (LOGD_IP6, "(%s): syncing device with netlink changes", device->iface);
+		nm_ip6_device_sync_from_netlink (device, config_changed);
+	}
+}
+
+void
+nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
+                                  int ifindex,
+                                  NMSettingIP6Config *s_ip6,
+                                  const char *accept_ra_path)
+{
+	NMIP6ManagerPrivate *priv;
+	NMIP6Device *device;
+	const char *method = NULL;
+
+	g_return_if_fail (NM_IS_IP6_MANAGER (manager));
+	g_return_if_fail (ifindex > 0);
+
+	priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+
+	device = nm_ip6_device_new (manager, ifindex);
+	g_return_if_fail (device != NULL);
+	g_return_if_fail (   strchr (device->iface, '/') == NULL
+	                  && strcmp (device->iface, "all") != 0
+	                  && strcmp (device->iface, "default") != 0);
+
+	if (s_ip6)
+		method = nm_setting_ip6_config_get_method (s_ip6);
+	if (!method)
+		method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+
+	/* Establish target state and turn router advertisement acceptance on or off */
+	if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
+		device->target_state = NM_IP6_DEVICE_GOT_LINK_LOCAL;
+		nm_utils_do_sysctl (accept_ra_path, "0\n");
+	} else {
+		device->target_state = NM_IP6_DEVICE_GOT_ADDRESS;
+		nm_utils_do_sysctl (accept_ra_path, "1\n");
+	}
+}
+
+static gboolean
+poll_ip6_flags (gpointer user_data)
+{
+	nm_netlink_monitor_request_ip6_info (NM_NETLINK_MONITOR (user_data), NULL);
+	return TRUE;
+}
+
+void
+nm_ip6_manager_begin_addrconf (NMIP6Manager *manager, int ifindex)
+{
+	NMIP6ManagerPrivate *priv;
+	NMIP6Device *device;
+	CallbackInfo *info;
+
+	g_return_if_fail (NM_IS_IP6_MANAGER (manager));
+	g_return_if_fail (ifindex > 0);
+
+	priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+
+	device = (NMIP6Device *) g_hash_table_lookup (priv->devices, GINT_TO_POINTER (ifindex));
+	g_return_if_fail (device != NULL);
+
+	nm_log_info (LOGD_IP6, "Activation (%s) Beginning IP6 addrconf.", device->iface);
+
+	device->addrconf_complete = FALSE;
+	device->ra_flags = 0;
+
+	/* Set up a timeout on the transaction to kill it after the timeout */
+	info = callback_info_new (device, 0, FALSE);
+	device->finish_addrconf_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
+	                                                         NM_IP6_TIMEOUT,
+	                                                         finish_addrconf,
+	                                                         info,
+	                                                         (GDestroyNotify) g_free);
+
+	/* Bounce IPv6 on the interface to ensure the kernel will start looking for
+	 * new RAs; there doesn't seem to be a better way to do this right now.
+	 */
+	if (device->target_state >= NM_IP6_DEVICE_GOT_ADDRESS) {
+		nm_utils_do_sysctl (device->disable_ip6_path, "1\n");
+		g_usleep (200);
+		nm_utils_do_sysctl (device->disable_ip6_path, "0\n");
+	}
+
+	device->ip6flags_poll_id = g_timeout_add_seconds (1, poll_ip6_flags, priv->monitor);
+
+	/* Kick off the initial IPv6 flags request */
+	nm_netlink_monitor_request_ip6_info (priv->monitor, NULL);
+
+	/* Sync flags, etc, from netlink; this will also notice if the
+	 * device is already fully configured and schedule the
+	 * ADDRCONF_COMPLETE signal in that case.
+	 */
+	nm_ip6_device_sync_from_netlink (device, FALSE);
+}
+
+void
+nm_ip6_manager_cancel_addrconf (NMIP6Manager *manager, int ifindex)
+{
+	g_return_if_fail (NM_IS_IP6_MANAGER (manager));
+	g_return_if_fail (ifindex > 0);
+
+	g_hash_table_remove (NM_IP6_MANAGER_GET_PRIVATE (manager)->devices,
+	                     GINT_TO_POINTER (ifindex));
+}
+
+#define FIRST_ROUTE(m) ((struct rtnl_route *) nl_cache_get_first (m))
+#define NEXT_ROUTE(m) ((struct rtnl_route *) nl_cache_get_next ((struct nl_object *) m))
+
+#define FIRST_ADDR(m) ((struct rtnl_addr *) nl_cache_get_first (m))
+#define NEXT_ADDR(m) ((struct rtnl_addr *) nl_cache_get_next ((struct nl_object *) m))
+
+NMIP6Config *
+nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex)
+{
+	NMIP6ManagerPrivate *priv;
+	NMIP6Device *device;
+	NMIP6Config *config;
+	struct rtnl_addr *rtnladdr;
+	struct nl_addr *nladdr;
+	struct in6_addr *addr;
+	NMIP6Address *ip6addr;
+	struct rtnl_route *rtnlroute;
+	struct nl_addr *nldest, *nlgateway;
+	struct in6_addr *dest, *gateway;
+	gboolean defgw_set = FALSE;
+	struct in6_addr defgw;
+	uint32_t metric;
+	NMIP6Route *ip6route;
+	int i;
+
+	g_return_val_if_fail (NM_IS_IP6_MANAGER (manager), NULL);
+	g_return_val_if_fail (ifindex > 0, NULL);
+
+	priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+
+	device = (NMIP6Device *) g_hash_table_lookup (priv->devices,
+	                                              GINT_TO_POINTER (ifindex));
+	if (!device) {
+		nm_log_warn (LOGD_IP6, "(%d): addrconf not started.", ifindex);
+		return NULL;
+	}
+
+	config = nm_ip6_config_new ();
+	if (!config) {
+		nm_log_err (LOGD_IP6, "(%s): out of memory creating IP6 config object.",
+		            device->iface);
+		return NULL;
+	}
+
+	/* Make sure we refill the route and address caches, otherwise we won't get
+	 * up-to-date information here since the netlink route/addr change messages
+	 * may be lagging a bit.
+	 */
+	nl_cache_refill (priv->nlh, priv->route_cache);
+	nl_cache_refill (priv->nlh, priv->addr_cache);
+
+	/* Add routes */
+	for (rtnlroute = FIRST_ROUTE (priv->route_cache); rtnlroute; rtnlroute = NEXT_ROUTE (rtnlroute)) {
+		/* Make sure it's an IPv6 route for this device */
+		if (rtnl_route_get_oif (rtnlroute) != device->ifindex)
+			continue;
+		if (rtnl_route_get_family (rtnlroute) != AF_INET6)
+			continue;
+
+		nldest = rtnl_route_get_dst (rtnlroute);
+		if (!nldest || nl_addr_get_family (nldest) != AF_INET6)
+			continue;
+		dest = nl_addr_get_binary_addr (nldest);
+
+		nlgateway = rtnl_route_get_gateway (rtnlroute);
+		if (!nlgateway || nl_addr_get_family (nlgateway) != AF_INET6)
+			continue;
+		gateway = nl_addr_get_binary_addr (nlgateway);
+
+		if (rtnl_route_get_dst_len (rtnlroute) == 0) {
+			/* Default gateway route; don't add to normal routes but to each address */
+			if (!defgw_set) {
+				memcpy (&defgw, gateway, sizeof (defgw));
+				defgw_set = TRUE;
+			}
+			continue;
+		}
+
+		/* Also ignore link-local routes where the destination and gateway are
+		 * the same, which apparently get added by the kernel but return -EINVAL
+		 * when we try to add them via netlink.
+		 */
+		if (gateway && IN6_ARE_ADDR_EQUAL (dest, gateway))
+			continue;
+
+		ip6route = nm_ip6_route_new ();
+		nm_ip6_route_set_dest (ip6route, dest);
+		nm_ip6_route_set_prefix (ip6route, rtnl_route_get_dst_len (rtnlroute));
+		nm_ip6_route_set_next_hop (ip6route, gateway);
+		metric = rtnl_route_get_metric (rtnlroute, 1);
+		if (metric != UINT_MAX)
+			nm_ip6_route_set_metric (ip6route, metric);
+		nm_ip6_config_take_route (config, ip6route);
+	}
+
+	/* Add addresses */
+	for (rtnladdr = FIRST_ADDR (priv->addr_cache); rtnladdr; rtnladdr = NEXT_ADDR (rtnladdr)) {
+		if (rtnl_addr_get_ifindex (rtnladdr) != device->ifindex)
+			continue;
+
+		nladdr = rtnl_addr_get_local (rtnladdr);
+		if (!nladdr || nl_addr_get_family (nladdr) != AF_INET6)
+			continue;
+
+		addr = nl_addr_get_binary_addr (nladdr);
+		ip6addr = nm_ip6_address_new ();
+		nm_ip6_address_set_prefix (ip6addr, rtnl_addr_get_prefixlen (rtnladdr));
+		nm_ip6_address_set_address (ip6addr, addr);
+		nm_ip6_config_take_address (config, ip6addr);
+		if (defgw_set)
+			nm_ip6_address_set_gateway (ip6addr, &defgw);
+	}
+
+	/* Add DNS servers */
+	if (device->rdnss_servers) {
+		NMIP6RDNSS *rdnss = (NMIP6RDNSS *)(device->rdnss_servers->data);
+
+		for (i = 0; i < device->rdnss_servers->len; i++)
+			nm_ip6_config_add_nameserver (config, &rdnss[i].addr);
+	}
+
+	return config;
+}
+
+/******************************************************************/
+
+static NMIP6Manager *
+nm_ip6_manager_new (void)
+{
+	NMIP6Manager *manager;
+	NMIP6ManagerPrivate *priv;
+
+	manager = g_object_new (NM_TYPE_IP6_MANAGER, NULL);
+	priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+
+	if (!priv->devices) {
+		nm_log_err (LOGD_IP6, "not enough memory to initialize IP6 manager tables");
+		g_object_unref (manager);
+		manager = NULL;
+	}
+
+	return manager;
+}
+
+static NMIP6Manager *singleton = NULL;
+
+NMIP6Manager *
+nm_ip6_manager_get (void)
+{
+	if (!singleton) {
+		singleton = nm_ip6_manager_new ();
+		g_assert (singleton);
+	} else
+		g_object_ref (singleton);
+
+	return singleton;
+}
+
+static void
+nm_ip6_manager_init (NMIP6Manager *manager)
+{
+	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager);
+
+	priv->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+	                                       NULL,
+	                                       (GDestroyNotify) nm_ip6_device_destroy);
+
+	priv->monitor = nm_netlink_monitor_get ();
+	nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_IFADDR, NULL);
+	nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_IPV6_PREFIX, NULL);
+	nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_ND_USEROPT, NULL);
+	nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_LINK, NULL);
+
+	priv->netlink_id = g_signal_connect (priv->monitor, "notification",
+	                                     G_CALLBACK (netlink_notification), manager);
+
+	priv->nlh = nm_netlink_get_default_handle ();
+	priv->addr_cache = rtnl_addr_alloc_cache (priv->nlh);
+	priv->route_cache = rtnl_route_alloc_cache (priv->nlh);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (object);
+
+	g_signal_handler_disconnect (priv->monitor, priv->netlink_id);
+
+	g_hash_table_destroy (priv->devices);
+	g_object_unref (priv->monitor);
+	nl_cache_free (priv->addr_cache);
+	nl_cache_free (priv->route_cache);
+
+	singleton = NULL;
+
+	G_OBJECT_CLASS (nm_ip6_manager_parent_class)->finalize (object);
+}
+
+static void
+nm_ip6_manager_class_init (NMIP6ManagerClass *manager_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
+
+	g_type_class_add_private (manager_class, sizeof (NMIP6ManagerPrivate));
+
+	/* virtual methods */
+	object_class->finalize = finalize;
+
+	/* signals */
+	signals[ADDRCONF_COMPLETE] =
+		g_signal_new ("addrconf-complete",
+					  G_OBJECT_CLASS_TYPE (object_class),
+					  G_SIGNAL_RUN_FIRST,
+					  G_STRUCT_OFFSET (NMIP6ManagerClass, addrconf_complete),
+					  NULL, NULL,
+					  _nm_marshal_VOID__INT_UINT_BOOLEAN,
+					  G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_UINT, G_TYPE_BOOLEAN);
+
+	signals[CONFIG_CHANGED] =
+		g_signal_new ("config-changed",
+					  G_OBJECT_CLASS_TYPE (object_class),
+					  G_SIGNAL_RUN_FIRST,
+					  G_STRUCT_OFFSET (NMIP6ManagerClass, config_changed),
+					  NULL, NULL,
+					  _nm_marshal_VOID__INT_UINT_BOOLEAN,
+					  G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_UINT, G_TYPE_BOOLEAN);
+}
+
diff --git a/src/ip6-manager/nm-ip6-manager.h b/src/ip6-manager/nm-ip6-manager.h
new file mode 100644
index 00000000..77c11068
--- /dev/null
+++ b/src/ip6-manager/nm-ip6-manager.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* nm-ip6-manager.c - Handle IPv6 address configuration for NetworkManager
+ *
+ * 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) 2009 - 2010 Red Hat, Inc.
+ */
+
+#ifndef NM_IP6_MANAGER_H
+#define NM_IP6_MANAGER_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <nm-setting-ip6-config.h>
+
+#include "nm-ip6-config.h"
+
+#define NM_TYPE_IP6_MANAGER            (nm_ip6_manager_get_type ())
+#define NM_IP6_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_MANAGER, NMIP6Manager))
+#define NM_IP6_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_MANAGER, NMIP6ManagerClass))
+#define NM_IS_IP6_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP6_MANAGER))
+#define NM_IS_IP6_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_IP6_MANAGER))
+#define NM_IP6_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP6_MANAGER, NMIP6ManagerClass))
+
+enum {
+	IP6_DHCP_OPT_NONE = 0,
+	IP6_DHCP_OPT_OTHERCONF,
+	IP6_DHCP_OPT_MANAGED
+};
+
+typedef struct {
+	GObject parent;
+} NMIP6Manager;
+
+typedef struct {
+	GObjectClass parent;
+
+	/* Signals */
+
+	/* addrconf_complete is emitted only during initial configuration to indicate
+	 * that the initial configuration is complete.
+	 */
+	void (*addrconf_complete) (NMIP6Manager *manager,
+	                           guint32 ifindex,
+	                           guint dhcp_opts,
+	                           gboolean success);
+
+	/* config_changed gets emitted only *after* initial configuration is
+	 * complete; it's like DHCP renew and indicates that the existing config
+	 * of the interface has changed.
+	 */
+	void (*config_changed)    (NMIP6Manager *manager,
+	                           guint32 ifindex,
+	                           guint dhcp_opts,
+	                           gboolean success);
+} NMIP6ManagerClass;
+
+GType nm_ip6_manager_get_type (void);
+
+NMIP6Manager *nm_ip6_manager_get               (void);
+void          nm_ip6_manager_prepare_interface (NMIP6Manager *manager,
+                                                int ifindex,
+                                                NMSettingIP6Config *s_ip6,
+                                                const char *accept_ra_path);
+void          nm_ip6_manager_begin_addrconf    (NMIP6Manager *manager,
+                                                int ifindex);
+void          nm_ip6_manager_cancel_addrconf   (NMIP6Manager *manager,
+                                                int ifindex);
+
+NMIP6Config * nm_ip6_manager_get_ip6_config    (NMIP6Manager *manager,
+                                                int ifindex);
+
+#endif /* NM_IP6_MANAGER_H */