summary refs log tree commit diff
path: root/pkgs/os-specific/linux
diff options
context:
space:
mode:
authorRobin Gloster <mail@glob.in>2016-04-18 13:00:40 +0000
committerRobin Gloster <mail@glob.in>2016-04-18 13:49:22 +0000
commitd020caa5b2eca90ea051403fbb4c52b99ee071b9 (patch)
treeba44ef1e784bca89e0df6b249956fd035b1d86e3 /pkgs/os-specific/linux
parent3e68106afd95df012ddb548575f0133681687a90 (diff)
parent0729f606973870c03d21bb2f21b70d91216943ca (diff)
downloadnixlib-d020caa5b2eca90ea051403fbb4c52b99ee071b9.tar
nixlib-d020caa5b2eca90ea051403fbb4c52b99ee071b9.tar.gz
nixlib-d020caa5b2eca90ea051403fbb4c52b99ee071b9.tar.bz2
nixlib-d020caa5b2eca90ea051403fbb4c52b99ee071b9.tar.lz
nixlib-d020caa5b2eca90ea051403fbb4c52b99ee071b9.tar.xz
nixlib-d020caa5b2eca90ea051403fbb4c52b99ee071b9.tar.zst
nixlib-d020caa5b2eca90ea051403fbb4c52b99ee071b9.zip
Merge remote-tracking branch 'upstream/master' into hardened-stdenv
Diffstat (limited to 'pkgs/os-specific/linux')
-rw-r--r--pkgs/os-specific/linux/alsa-lib/default.nix2
-rw-r--r--pkgs/os-specific/linux/apparmor/default.nix67
-rw-r--r--pkgs/os-specific/linux/ati-drivers/default.nix18
-rw-r--r--pkgs/os-specific/linux/bluez/bluez5.nix2
-rw-r--r--pkgs/os-specific/linux/bluez/bluez5_28.nix2
-rw-r--r--pkgs/os-specific/linux/bluez/default.nix2
-rw-r--r--pkgs/os-specific/linux/cgmanager/default.nix4
-rw-r--r--pkgs/os-specific/linux/checksec/default.nix8
-rw-r--r--pkgs/os-specific/linux/conspy/default.nix8
-rw-r--r--pkgs/os-specific/linux/criu/default.nix13
-rw-r--r--pkgs/os-specific/linux/drbd/default.nix4
-rw-r--r--pkgs/os-specific/linux/fanctl/default.nix46
-rw-r--r--pkgs/os-specific/linux/fanctl/robustness.patch85
-rw-r--r--pkgs/os-specific/linux/firejail/default.nix8
-rw-r--r--pkgs/os-specific/linux/firmware/raspberrypi/default.nix10
-rw-r--r--pkgs/os-specific/linux/fusionio/util.nix2
-rw-r--r--pkgs/os-specific/linux/gradm/default.nix2
-rw-r--r--pkgs/os-specific/linux/iproute/1000-ubuntu-poc-fan-driver.patch65
-rw-r--r--pkgs/os-specific/linux/iproute/1001-ubuntu-poc-fan-driver-v3.patch (renamed from pkgs/os-specific/linux/iproute/ubuntu-fan.patch)87
-rw-r--r--pkgs/os-specific/linux/iproute/1002-ubuntu-poc-fan-driver-vxlan.patch177
-rw-r--r--pkgs/os-specific/linux/iproute/default.nix8
-rw-r--r--pkgs/os-specific/linux/iptables/1.6.nix33
-rw-r--r--pkgs/os-specific/linux/kbd/default.nix2
-rw-r--r--pkgs/os-specific/linux/kernel/linux-4.4.nix4
-rw-r--r--pkgs/os-specific/linux/kernel/linux-4.5.nix5
-rw-r--r--pkgs/os-specific/linux/kernel/linux-testing.nix6
-rw-r--r--pkgs/os-specific/linux/kernel/manual-config.nix2
-rw-r--r--pkgs/os-specific/linux/kernel/patches.nix13
-rw-r--r--pkgs/os-specific/linux/kernel/qat_common_Makefile.patch10
-rw-r--r--pkgs/os-specific/linux/kernel/ubuntu-fan-3.patch616
-rw-r--r--pkgs/os-specific/linux/kernel/ubuntu-fan-4.4.patch1240
-rw-r--r--pkgs/os-specific/linux/kernel/ubuntu-fan-4.patch616
-rw-r--r--pkgs/os-specific/linux/klibc/shrunk.nix6
-rw-r--r--pkgs/os-specific/linux/libcap/default.nix19
-rw-r--r--pkgs/os-specific/linux/libcap/man.nix2
-rw-r--r--pkgs/os-specific/linux/libcap/pam.nix2
-rw-r--r--pkgs/os-specific/linux/libcap/progs.nix5
-rw-r--r--pkgs/os-specific/linux/libnl/default.nix2
-rw-r--r--pkgs/os-specific/linux/lvm2/default.nix6
-rw-r--r--pkgs/os-specific/linux/lxc/default.nix9
-rw-r--r--pkgs/os-specific/linux/lxc/support-db2x.patch4
-rw-r--r--pkgs/os-specific/linux/mcelog/default.nix4
-rw-r--r--pkgs/os-specific/linux/mdadm/default.nix2
-rw-r--r--pkgs/os-specific/linux/module-init-tools/default.nix5
-rw-r--r--pkgs/os-specific/linux/nfs-utils/default.nix2
-rw-r--r--pkgs/os-specific/linux/opengl/xorg-sys/default.nix3
-rw-r--r--pkgs/os-specific/linux/pam/default.nix13
-rw-r--r--pkgs/os-specific/linux/pipework/default.nix2
-rw-r--r--pkgs/os-specific/linux/pm-utils/default.nix4
-rw-r--r--pkgs/os-specific/linux/shadow/default.nix2
-rw-r--r--pkgs/os-specific/linux/sysdig/default.nix6
-rw-r--r--pkgs/os-specific/linux/sysstat/default.nix2
-rw-r--r--pkgs/os-specific/linux/systemd/cryptsetup-generator.nix25
-rw-r--r--pkgs/os-specific/linux/systemd/default.nix67
-rw-r--r--pkgs/os-specific/linux/systemd/hwdb-location.diff19
-rw-r--r--pkgs/os-specific/linux/systemd/libudev.nix19
-rw-r--r--pkgs/os-specific/linux/udev/145.nix53
-rw-r--r--pkgs/os-specific/linux/util-linux/default.nix21
58 files changed, 2003 insertions, 1468 deletions
diff --git a/pkgs/os-specific/linux/alsa-lib/default.nix b/pkgs/os-specific/linux/alsa-lib/default.nix
index c4fd46b3c7da..d2637f99119c 100644
--- a/pkgs/os-specific/linux/alsa-lib/default.nix
+++ b/pkgs/os-specific/linux/alsa-lib/default.nix
@@ -25,6 +25,8 @@ stdenv.mkDerivation rec {
     sed -i -e 's/u_int\([0-9]*\)_t/uint\1_t/g' include/pcm.h
   '';
 
+  outputs = [ "dev" "out" ];
+
   crossAttrs = {
     patchPhase = ''
       sed -i s/extern/static/g include/iatomic.h
diff --git a/pkgs/os-specific/linux/apparmor/default.nix b/pkgs/os-specific/linux/apparmor/default.nix
index 64c6f66575b6..f90601073406 100644
--- a/pkgs/os-specific/linux/apparmor/default.nix
+++ b/pkgs/os-specific/linux/apparmor/default.nix
@@ -1,5 +1,11 @@
-{ stdenv, fetchurl, makeWrapper, autoconf, autoreconfHook, automake, libtool, pkgconfig, perl, which
-, glibc, flex, bison, python27Packages, swig, pam
+{ stdenv, fetchurl, makeWrapper, autoreconfHook
+, pkgconfig, which
+, flex, bison
+, linuxHeaders ? stdenv.cc.libc.linuxHeaders
+, pythonPackages
+, perl
+, swig
+, pam
 }:
 
 let
@@ -8,7 +14,7 @@ let
 
   apparmor-meta = component: with stdenv.lib; {
     homepage = http://apparmor.net/;
-    description = "Linux application security system - ${component}";
+    description = "A mandatory access control system - ${component}";
     license = licenses.gpl2;
     maintainers = with maintainers; [ phreedom thoughtpolice joachifm ];
     platforms = platforms.linux;
@@ -22,7 +28,7 @@ let
   prePatchCommon = ''
     substituteInPlace ./common/Make.rules --replace "/usr/bin/pod2man" "${perl}/bin/pod2man"
     substituteInPlace ./common/Make.rules --replace "/usr/bin/pod2html" "${perl}/bin/pod2html"
-    substituteInPlace ./common/Make.rules --replace "/usr/include/linux/capability.h" "${glibc}/include/linux/capability.h"
+    substituteInPlace ./common/Make.rules --replace "/usr/include/linux/capability.h" "${linuxHeaders}/include/linux/capability.h"
     substituteInPlace ./common/Make.rules --replace "/usr/share/man" "share/man"
   '';
 
@@ -30,28 +36,27 @@ let
     name = "libapparmor-${apparmor-version}";
     src = apparmor-sources;
 
-    buildInputs = [
-      autoconf
-      automake
+    nativeBuildInputs = [
       autoreconfHook
       bison
       flex
-      glibc
-      libtool
-      perl
       pkgconfig
-      python27Packages.python
       swig
       which
     ];
 
+    buildInputs = [
+      perl
+      pythonPackages.python
+    ];
+
     # required to build apparmor-parser
     dontDisableStatic = true;
 
     prePatch = prePatchCommon + ''
-      substituteInPlace ./libraries/libapparmor/src/Makefile.am --replace "/usr/include/netinet/in.h" "${glibc}/include/netinet/in.h"
-      substituteInPlace ./libraries/libapparmor/src/Makefile.in --replace "/usr/include/netinet/in.h" "${glibc}/include/netinet/in.h"
-      '';
+      substituteInPlace ./libraries/libapparmor/src/Makefile.am --replace "/usr/include/netinet/in.h" "${stdenv.cc.libc.dev}/include/netinet/in.h"
+      substituteInPlace ./libraries/libapparmor/src/Makefile.in --replace "/usr/include/netinet/in.h" "${stdenv.cc.libc.dev}/include/netinet/in.h"
+    '';
 
     postPatch = "cd ./libraries/libapparmor";
     configureFlags = "--with-python --with-perl";
@@ -63,13 +68,13 @@ let
     name = "apparmor-utils-${apparmor-version}";
     src = apparmor-sources;
 
+    nativeBuildInputs = [ makeWrapper which ];
+
     buildInputs = [
       perl
-      python27Packages.python
-      python27Packages.readline
+      pythonPackages.python
+      pythonPackages.readline
       libapparmor
-      makeWrapper
-      which
     ];
 
     prePatch = prePatchCommon;
@@ -79,7 +84,7 @@ let
 
     postInstall = ''
       for prog in aa-audit aa-autodep aa-cleanprof aa-complain aa-disable aa-enforce aa-genprof aa-logprof aa-mergeprof aa-status aa-unconfined ; do
-        wrapProgram $out/bin/$prog --prefix PYTHONPATH : "$out/lib/${python27Packages.python.libPrefix}/site-packages:$PYTHONPATH"
+        wrapProgram $out/bin/$prog --prefix PYTHONPATH : "$out/lib/${pythonPackages.python.libPrefix}/site-packages:$PYTHONPATH"
       done
 
       for prog in aa-exec aa-notify ; do
@@ -94,17 +99,14 @@ let
     name = "apparmor-parser-${apparmor-version}";
     src = apparmor-sources;
 
-    buildInputs = [
-      libapparmor
-      bison
-      flex
-      which
-    ];
+    nativeBuildInputs = [ bison flex which ];
+
+    buildInputs = [ libapparmor ];
 
     prePatch = prePatchCommon + ''
       substituteInPlace ./parser/Makefile --replace "/usr/bin/bison" "${bison}/bin/bison"
       substituteInPlace ./parser/Makefile --replace "/usr/bin/flex" "${flex}/bin/flex"
-      substituteInPlace ./parser/Makefile --replace "/usr/include/linux/capability.h" "${glibc}/include/linux/capability.h"
+      substituteInPlace ./parser/Makefile --replace "/usr/include/linux/capability.h" "${linuxHeaders}/include/linux/capability.h"
       ## techdoc.pdf still doesn't build ...
       substituteInPlace ./parser/Makefile --replace "manpages htmlmanpages pdf" "manpages htmlmanpages"
     '';
@@ -119,12 +121,9 @@ let
     name = "apparmor-pam-${apparmor-version}";
     src = apparmor-sources;
 
-    buildInputs = [
-      libapparmor
-      pam
-      pkgconfig
-      which
-    ];
+    nativeBuildInputs = [ pkgconfig which ];
+
+    buildInputs = [ libapparmor pam ];
 
     postPatch = "cd ./changehat/pam_apparmor";
     makeFlags = ''USE_SYSTEM=1'';
@@ -137,7 +136,7 @@ let
     name = "apparmor-profiles-${apparmor-version}";
     src = apparmor-sources;
 
-    buildInputs = [ which ];
+    nativeBuildInputs = [ which ];
 
     postPatch = "cd ./profiles";
     installFlags = ''DESTDIR=$(out) EXTRAS_DEST=$(out)/share/apparmor/extra-profiles'';
@@ -153,7 +152,7 @@ let
 
     installPhase = ''
       mkdir "$out"
-      cp -R ./kernel-patches "$out"
+      cp -R ./kernel-patches/* "$out"
     '';
 
     meta = apparmor-meta "kernel patches";
diff --git a/pkgs/os-specific/linux/ati-drivers/default.nix b/pkgs/os-specific/linux/ati-drivers/default.nix
index 377297feaf75..78903da1f1a1 100644
--- a/pkgs/os-specific/linux/ati-drivers/default.nix
+++ b/pkgs/os-specific/linux/ati-drivers/default.nix
@@ -85,15 +85,17 @@ stdenv.mkDerivation {
 
   inherit glibc /* glibc only used for setting interpreter */;
 
+  # outputs TODO: probably many fixes are needed;
+  # this in particular would be much better by lib.makeLibraryPath
   LD_LIBRARY_PATH = stdenv.lib.concatStringsSep ":"
-    [ "${xorg.libXrandr}/lib/"
-      "${xorg.libXrender}/lib/"
-      "${xorg.libXext}/lib/"
-      "${xorg.libX11}/lib/"
-      "${xorg.libXinerama}/lib/"
-      "${xorg.libSM}/lib/"
-      "${xorg.libICE}/lib/"
-      "${stdenv.cc.cc}/lib/"
+    [ "${xorg.libXrandr.out}/lib/"
+      "${xorg.libXrender.out}/lib/"
+      "${xorg.libXext.out}/lib/"
+      "${xorg.libX11.out}/lib/"
+      "${xorg.libXinerama.out}/lib/"
+      "${xorg.libSM.out}/lib/"
+      "${xorg.libICE.out}/lib/"
+      "${stdenv.cc.cc.out}/lib/"
     ];
 
   # without this some applications like blender don't start, but they start
diff --git a/pkgs/os-specific/linux/bluez/bluez5.nix b/pkgs/os-specific/linux/bluez/bluez5.nix
index 2b73dc798c3f..9750a2a76499 100644
--- a/pkgs/os-specific/linux/bluez/bluez5.nix
+++ b/pkgs/os-specific/linux/bluez/bluez5.nix
@@ -16,7 +16,7 @@ stdenv.mkDerivation rec {
     [ pythonDBus pygobject pygobject3 recursivePthLoader ];
 
   buildInputs =
-    [ pkgconfig dbus.libs glib alsaLib python pythonPackages.wrapPython
+    [ pkgconfig dbus glib alsaLib python pythonPackages.wrapPython
       readline libsndfile udev libical
       # Disables GStreamer; not clear what it gains us other than a
       # zillion extra dependencies.
diff --git a/pkgs/os-specific/linux/bluez/bluez5_28.nix b/pkgs/os-specific/linux/bluez/bluez5_28.nix
index 80adc0fd56b8..68db9345bd0e 100644
--- a/pkgs/os-specific/linux/bluez/bluez5_28.nix
+++ b/pkgs/os-specific/linux/bluez/bluez5_28.nix
@@ -16,7 +16,7 @@ stdenv.mkDerivation rec {
     [ pythonDBus pygobject pygobject3 recursivePthLoader ];
 
   buildInputs =
-    [ pkgconfig dbus.libs glib alsaLib python pythonPackages.wrapPython
+    [ pkgconfig dbus glib alsaLib python pythonPackages.wrapPython
       readline libsndfile udev libical
       # Disables GStreamer; not clear what it gains us other than a
       # zillion extra dependencies.
diff --git a/pkgs/os-specific/linux/bluez/default.nix b/pkgs/os-specific/linux/bluez/default.nix
index 23e5171d1780..4f30bc19caf8 100644
--- a/pkgs/os-specific/linux/bluez/default.nix
+++ b/pkgs/os-specific/linux/bluez/default.nix
@@ -17,7 +17,7 @@ stdenv.mkDerivation rec {
   };
 
   buildInputs =
-    [ pkgconfig dbus.libs glib libusb alsaLib python makeWrapper
+    [ pkgconfig dbus glib libusb alsaLib python makeWrapper
       readline libsndfile
       # Disables GStreamer; not clear what it gains us other than a
       # zillion extra dependencies.
diff --git a/pkgs/os-specific/linux/cgmanager/default.nix b/pkgs/os-specific/linux/cgmanager/default.nix
index 1c79fddeca96..2260ac08b632 100644
--- a/pkgs/os-specific/linux/cgmanager/default.nix
+++ b/pkgs/os-specific/linux/cgmanager/default.nix
@@ -1,11 +1,11 @@
 { stdenv, fetchurl, pkgconfig, libnih, dbus, pam }:
 
 stdenv.mkDerivation rec {
-  name = "cgmanager-0.39";
+  name = "cgmanager-0.41";
 
   src = fetchurl {
     url = "https://linuxcontainers.org/downloads/cgmanager/${name}.tar.gz";
-    sha256 = "0ysv8klnybp727aad2k0aa67s05q027pzfl7rmm0map4nizlhrcy";
+    sha256 = "0n5l4g78ifvyfnj8x9xz06mqn4y8j73sgg4xsbak7hiszfz5bc99";
   };
 
   nativeBuildInputs = [ pkgconfig ];
diff --git a/pkgs/os-specific/linux/checksec/default.nix b/pkgs/os-specific/linux/checksec/default.nix
index 5752bbb72bc4..1a879ba33304 100644
--- a/pkgs/os-specific/linux/checksec/default.nix
+++ b/pkgs/os-specific/linux/checksec/default.nix
@@ -22,13 +22,13 @@ stdenv.mkDerivation rec {
     cp checksec.sh $out/bin/checksec
     chmod +x $out/bin/checksec
     substituteInPlace $out/bin/checksec --replace /bin/bash ${stdenv.shell}
-    substituteInPlace $out/bin/checksec --replace /lib/libc.so.6 ${glibc}/lib/libc.so.6
+    substituteInPlace $out/bin/checksec --replace /lib/libc.so.6 ${glibc.out}/lib/libc.so.6
     substituteInPlace $out/bin/checksec --replace find ${findutils}/bin/find
     substituteInPlace $out/bin/checksec --replace "file $" "${file}/bin/file $"
     substituteInPlace $out/bin/checksec --replace "xargs file" "xargs ${file}/bin/file"
-    substituteInPlace $out/bin/checksec --replace " readelf -" " ${binutils}/bin/readelf -"
-    substituteInPlace $out/bin/checksec --replace "(readelf -" "(${binutils}/bin/readelf -"
-    substituteInPlace $out/bin/checksec --replace "command_exists readelf" "command_exists ${binutils}/bin/readelf"
+    substituteInPlace $out/bin/checksec --replace " readelf -" " ${binutils.out}/bin/readelf -"
+    substituteInPlace $out/bin/checksec --replace "(readelf -" "(${binutils.out}/bin/readelf -"
+    substituteInPlace $out/bin/checksec --replace "command_exists readelf" "command_exists ${binutils.out}/bin/readelf"
     substituteInPlace $out/bin/checksec --replace "/sbin/sysctl -" "${procps}/sbin/sysctl -"
     substituteInPlace $out/bin/checksec --replace "/usr/bin/id -" "${coreutils}/bin/id -"
   '';
diff --git a/pkgs/os-specific/linux/conspy/default.nix b/pkgs/os-specific/linux/conspy/default.nix
index 3c209c6253dd..32905b8ec39f 100644
--- a/pkgs/os-specific/linux/conspy/default.nix
+++ b/pkgs/os-specific/linux/conspy/default.nix
@@ -3,11 +3,11 @@ let
   s = # Generated upstream information
   rec {
     baseName="conspy";
-    version="1.13";
+    version="1.14";
     name="${baseName}-${version}";
-    hash="059sag372n09y1ddb1i0sx013kzkbr8a9pjqk03kyijn8h1z5hl2";
-    url="mirror://sourceforge/project/conspy/conspy-1.13-1/conspy-1.13.tar.gz";
-    sha256="059sag372n09y1ddb1i0sx013kzkbr8a9pjqk03kyijn8h1z5hl2";
+    hash="069k26xpzsvrn3197ix5yd294zvz03zi2xqj4fip6rlsw74habsf";
+    url="mirror://sourceforge/project/conspy/conspy-1.14-1/conspy-1.14.tar.gz";
+    sha256="069k26xpzsvrn3197ix5yd294zvz03zi2xqj4fip6rlsw74habsf";
   };
   buildInputs = [
     autoconf automake ncurses
diff --git a/pkgs/os-specific/linux/criu/default.nix b/pkgs/os-specific/linux/criu/default.nix
index 919799abb699..16116019567d 100644
--- a/pkgs/os-specific/linux/criu/default.nix
+++ b/pkgs/os-specific/linux/criu/default.nix
@@ -1,24 +1,27 @@
 { stdenv, fetchurl, protobuf, protobufc, asciidoc
-, xmlto, utillinux, docbook_xsl, libpaper }:
+, xmlto, utillinux, docbook_xsl, libpaper, libnl, libcap, pkgconfig
+, python }:
 
 stdenv.mkDerivation rec {
   name    = "criu-${version}";
-  version = "1.3-rc2";
+  version = "2.0";
 
   src = fetchurl {
     url    = "http://download.openvz.org/criu/${name}.tar.bz2";
-    sha256 = "1h9ii91aq8cja22j3520vg3qb3y9h6c064s4115s2ldylm8jmi0s";
+    sha256 = "1zqqshslcf503lqip89azp1zz0i8kb7v19b3dyp52izpak62c1z8";
   };
 
   enableParallelBuilding = true;
-  buildInputs = [ protobuf protobufc asciidoc xmlto libpaper ];
+  buildInputs = [ protobuf protobufc asciidoc xmlto libpaper libnl libcap pkgconfig python ];
 
   patchPhase = ''
     chmod +w ./scripts/gen-offsets.sh
     substituteInPlace ./scripts/gen-offsets.sh --replace hexdump ${utillinux}/bin/hexdump
     substituteInPlace ./Documentation/Makefile --replace "2>/dev/null" ""
     substituteInPlace ./Documentation/Makefile --replace "--skip-validation" "--skip-validation -x ${docbook_xsl}/xml/xsl/docbook/manpages/docbook.xsl"
-    substituteInPlace ./Makefile --replace "-Werror" ""
+    substituteInPlace ./criu/Makefile --replace "-I/usr/include/libnl3" "-I${libnl}/include/libnl3"
+    substituteInPlace ./Makefile --replace "tar-name := $(shell git tag -l v$(CRIU_VERSION))" "tar-name = 2.0" # --replace "-Werror" ""
+    ln -sf ${protobuf}/include/google/protobuf/descriptor.proto ./images/google/protobuf/descriptor.proto
   '';
 
   configurePhase = "make config PREFIX=$out";
diff --git a/pkgs/os-specific/linux/drbd/default.nix b/pkgs/os-specific/linux/drbd/default.nix
index d90d6faac396..60615fb1e5be 100644
--- a/pkgs/os-specific/linux/drbd/default.nix
+++ b/pkgs/os-specific/linux/drbd/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchurl, flex, udev, perl }:
+{ stdenv, fetchurl, flex, systemd, perl }:
 
 assert stdenv.isLinux;
 
@@ -18,7 +18,7 @@ stdenv.mkDerivation rec {
 
   preConfigure =
     ''
-      export PATH=${udev}/sbin:$PATH
+      export PATH=${systemd.udev.bin}/sbin:$PATH
       substituteInPlace user/Makefile.in --replace /sbin/ $out/sbin/
       substituteInPlace user/legacy/Makefile.in \
         --replace /sbin/ $out/sbin/ \
diff --git a/pkgs/os-specific/linux/fanctl/default.nix b/pkgs/os-specific/linux/fanctl/default.nix
index 61e100f4c9b7..f60951f5541e 100644
--- a/pkgs/os-specific/linux/fanctl/default.nix
+++ b/pkgs/os-specific/linux/fanctl/default.nix
@@ -1,41 +1,39 @@
-{ stdenv, lib, fetchbzr, makeWrapper, bridge-utils, iproute, dnsmasq, iptables, kmod, utillinux }:
+{ stdenv, lib, fetchurl, gnugrep, glibc, gawk, coreutils, bridge-utils, iproute
+, dnsmasq, iptables, kmod, utillinux, gnused }:
 
-let stateDir = "/var/lib/fan-networking";
-in stdenv.mkDerivation rec {
+stdenv.mkDerivation rec {
   name = "fanctl-${version}";
 
-  version = "0.3.0";
+  version = "0.9.0";
 
-  src = fetchbzr {
-    url = "https://code.launchpad.net/~ubuntu-branches/ubuntu/vivid/ubuntu-fan/vivid-updates";
-    rev = 2;
-    sha256 = "1vcr2rg99g7sx1zynhiggjzc9y9z591i4535hbm21dysy3cisp7i";
+  src = fetchurl {
+    url = "https://launchpad.net/ubuntu/+archive/primary/+files/ubuntu-fan_${version}.tar.xz";
+    sha256 = "03dv5zzb8fkl9kkbhznxm48d6j3fjms74fn0s1zip2gz53l1s14n";
   };
 
-  buildInputs = [ makeWrapper ];
+  # The Ubuntu package creates a number of state/config directories upon
+  # installation, and so the fanctl script expects those directories to exist
+  # before being used. Instead, we patch the fanctl script to gracefully handle
+  # the fact that the directories might not exist yet.
+  # Also, when dnsmasq is given --conf-file="", it will still attempt to read
+  # /etc/dnsmasq.conf; if that file does not exist, dnsmasq subsequently fails,
+  # so we'll use /dev/null, which actually works as intended.
+  patches = [ ./robustness.patch ];
 
-  # When given --conf-file="", dnsmasq still attempts to read /etc/dnsmasq.conf;
-  # if that files does not exist, dnsmasq subsequently fails,
-  # so we'll use /dev/null.
-  #
-  # Also, make sure the state directory before starting dnsmasq.
-  buildPhase = ''
+  postPatch = ''
     substituteInPlace fanctl \
-      --replace '--conf-file= ' \
-                '--conf-file=/dev/null ' \
-      --replace '/var/lib/misc' \
-                '${stateDir}'
-
-    sed -i '/dnsmasq -u/i \
-    mkdir -p ${stateDir}' fanctl
+      --replace '@PATH@' \
+                '${lib.makeBinPath [
+                     gnugrep gawk coreutils bridge-utils iproute dnsmasq
+                     iptables kmod utillinux gnused
+                     glibc # needed for getent
+                   ]}'
   '';
 
   installPhase = ''
     mkdir -p $out/bin $out/man/man8
     cp fanctl.8 $out/man/man8
     cp fanctl $out/bin
-    wrapProgram $out/bin/fanctl --prefix PATH : \
-      ${lib.makeSearchPath "bin" [ bridge-utils iproute dnsmasq iptables kmod utillinux ]};
   '';
 
   meta = with lib; {
diff --git a/pkgs/os-specific/linux/fanctl/robustness.patch b/pkgs/os-specific/linux/fanctl/robustness.patch
new file mode 100644
index 000000000000..7a70a784e3ee
--- /dev/null
+++ b/pkgs/os-specific/linux/fanctl/robustness.patch
@@ -0,0 +1,85 @@
+diff --git a/fanctl b/fanctl
+index 4338b75..84cf987 100755
+--- a/fanctl
++++ b/fanctl
+@@ -5,6 +5,8 @@
+ #   fanctl down 15 10.1.0.1
+ #
+ 
++export PATH="@PATH@"
++
+ usage()
+ {
+ 	echo "Usage: $0 <cmd> [<options>...]" 1>&2
+@@ -23,8 +25,8 @@ run()
+ 	"$@"
+ }
+ 
+-state_dir="/run/ubuntu-fan"
+-lconfig_dir="/var/lib/ubuntu-fan/config"
++state_dir="/run/fan-networking"
++lconfig_dir="/var/lib/fan-networking/config"
+ 
+ __ip_split()
+ {
+@@ -931,12 +933,12 @@ dhcp_reconfigure()
+ 		--strict-order \
+ 		--bind-interfaces \
+ 		--pid-file="$state_dir/dnsmasq-$C_bridge_state.pid" \
+-		--conf-file= \
++		--conf-file=/dev/null \
+ 		$dhcp_flags \
+ 		--dhcp-no-override \
+ 		--except-interface=lo \
+ 		--interface="$C_bridge" \
+-		--dhcp-leasefile=/var/lib/misc/dnsmasq."$C_bridge_state".leases \
++		--dhcp-leasefile=/var/lib/fan-networking/dnsmasq."$C_bridge_state".leases \
+ 		--dhcp-authoritative \
+ 	    || $fail "$C_bridge: failed to start dnsmasq"
+ 
+@@ -1559,21 +1561,23 @@ cmd_config()
+ 
+ 	case "$cmd" in
+ 	list|ls)
+-		ls -1 "$lconfig_dir" | \
+-		while read config
+-		do
+-			case "$config" in
+-			*.conf)		;;
+-			*)		continue ;;
+-			esac
++		if [ -d $lconfig_dir ]; then
++			ls -1 "$lconfig_dir" | \
++			while read config
++			do
++				case "$config" in
++				*.conf)		;;
++				*)		continue ;;
++				esac
+ 
+-			config=$( echo "$config" | sed \
+-				-e 's/.conf$//' \
+-				-e 's/--/ /g' \
+-				-e 's@-@/@g'
+-			)
+-			echo "$config"
+-		done
++				config=$( echo "$config" | sed \
++					-e 's/.conf$//' \
++					-e 's/--/ /g' \
++					-e 's@-@/@g'
++				)
++				echo "$config"
++			done
++		fi
+ 		;;
+ 	show)
+ 		cmd_decode_init
+@@ -1588,6 +1592,7 @@ cmd_config()
+ 		[ -f "$uconfig" ] && cat "$uconfig"
+ 		;;
+ 	set)
++		mkdir -p $lconfig_dir || fail "could not create config directory ($lconfig_dir)"
+ 		cmd_decode_init
+ 		if ! cmd_decode_config "config set" "$@"; then
+ 			fail "invalid config"
diff --git a/pkgs/os-specific/linux/firejail/default.nix b/pkgs/os-specific/linux/firejail/default.nix
index 57820f92cc4f..dac0eb0d0f50 100644
--- a/pkgs/os-specific/linux/firejail/default.nix
+++ b/pkgs/os-specific/linux/firejail/default.nix
@@ -3,11 +3,11 @@ let
   s = # Generated upstream information
   rec {
     baseName="firejail";
-    version="0.9.38";
+    version="0.9.40";
     name="${baseName}-${version}";
-    hash="0j0zvff9rwjwxcxddfhgzimjgmr99kd04nl40dllkrv3apv5ag4i";
-    url="mirror://sourceforge/project/firejail/firejail/firejail-0.9.38-rc1.tar.bz2";
-    sha256="0j0zvff9rwjwxcxddfhgzimjgmr99kd04nl40dllkrv3apv5ag4i";
+    hash="1vr0z694wibjkcpmyg7lz68r53z857c8hsb02cqxi4lfkkcmzgh2";
+    url="mirror://sourceforge/project/firejail/firejail/firejail-0.9.40-rc1.tar.bz2";
+    sha256="1vr0z694wibjkcpmyg7lz68r53z857c8hsb02cqxi4lfkkcmzgh2";
   };
   buildInputs = [
     which
diff --git a/pkgs/os-specific/linux/firmware/raspberrypi/default.nix b/pkgs/os-specific/linux/firmware/raspberrypi/default.nix
index dc0b061af14c..0c61aee9713e 100644
--- a/pkgs/os-specific/linux/firmware/raspberrypi/default.nix
+++ b/pkgs/os-specific/linux/firmware/raspberrypi/default.nix
@@ -2,14 +2,14 @@
 
 let
 
-  rev = "b7bbd3d1683e9f3bb11ef86b952adee71e83862f";
+  rev = "1.20160315";
 
 in stdenv.mkDerivation {
   name = "raspberrypi-firmware-${rev}";
 
   src = fetchurl {
     url = "https://github.com/raspberrypi/firmware/archive/${rev}.tar.gz";
-    sha256 = "16wpwa1y3imd3la477b3rfbfypssvlh0zjdag3hgkm33aysizijp";
+    sha256 = "0a7ycv01s0kk84szsh51hy2mjjil1dzdk0g7k83h50d5nya090fl";
   };
 
   installPhase = ''
@@ -24,9 +24,11 @@ in stdenv.mkDerivation {
     done
   '';
 
-  meta = {
+  meta = with stdenv.lib; {
     description = "Firmware for the Raspberry Pi board";
     homepage = https://github.com/raspberrypi;
-    license = stdenv.lib.licenses.unfree;
+    license = licenses.unfree;
+    platforms = [ "armv6l-linux" "armv7l-linux" ];
+    maintainers = with maintainers; [ viric tavyc ];
   };
 }
diff --git a/pkgs/os-specific/linux/fusionio/util.nix b/pkgs/os-specific/linux/fusionio/util.nix
index e2f8d423a61d..e77d596dc6f8 100644
--- a/pkgs/os-specific/linux/fusionio/util.nix
+++ b/pkgs/os-specific/linux/fusionio/util.nix
@@ -18,7 +18,7 @@ stdenv.mkDerivation {
     cp -r $TMPDIR/{etc,usr/{bin,lib,share}} $out
     for BIN in $(find $out/bin -type f); do
       echo Patching $BIN
-      patchelf --set-interpreter "${glibc}/lib/ld-linux-x86-64.so.2" --set-rpath "${glibc}/lib:${gcc.cc}/lib:${libuuid}/lib:$out/lib" $BIN
+      patchelf --set-interpreter "${glibc.out}/lib/ld-linux-x86-64.so.2" --set-rpath "${glibc.out}/lib:${gcc.cc}/lib:${libuuid}/lib:$out/lib" $BIN
 
       # Test our binary to see if it was correctly patched
       set +e
diff --git a/pkgs/os-specific/linux/gradm/default.nix b/pkgs/os-specific/linux/gradm/default.nix
index 1500cf2f3949..121b6db54002 100644
--- a/pkgs/os-specific/linux/gradm/default.nix
+++ b/pkgs/os-specific/linux/gradm/default.nix
@@ -34,7 +34,7 @@ stdenv.mkDerivation rec {
       "FLEX=${flex}/bin/flex"
       "BISON=${bison}/bin/bison"
       "FIND=${findutils}/bin/find"
-      "STRIP=${binutils}/bin/strip"
+      "STRIP=${binutils.out}/bin/strip"
       "INSTALL=${coreutils}/bin/install"
       "MANDIR=/share/man"
       "MKNOD=true"
diff --git a/pkgs/os-specific/linux/iproute/1000-ubuntu-poc-fan-driver.patch b/pkgs/os-specific/linux/iproute/1000-ubuntu-poc-fan-driver.patch
new file mode 100644
index 000000000000..ca91b8160008
--- /dev/null
+++ b/pkgs/os-specific/linux/iproute/1000-ubuntu-poc-fan-driver.patch
@@ -0,0 +1,65 @@
+Description: POC fan driver support
+ POC Fan driver support
+Author: Jay Vosburgh <jay.vosburgh@canonical.com>
+
+Index: iproute2-4.1.1/include/linux/if_tunnel.h
+===================================================================
+--- iproute2-4.1.1.orig/include/linux/if_tunnel.h
++++ iproute2-4.1.1/include/linux/if_tunnel.h
+@@ -57,6 +57,9 @@ enum {
+ 	IFLA_IPTUN_ENCAP_FLAGS,
+ 	IFLA_IPTUN_ENCAP_SPORT,
+ 	IFLA_IPTUN_ENCAP_DPORT,
++
++	IFLA_IPTUN_FAN_UNDERLAY = 32,
++
+ 	__IFLA_IPTUN_MAX,
+ };
+ #define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
+Index: iproute2-4.1.1/ip/link_iptnl.c
+===================================================================
+--- iproute2-4.1.1.orig/ip/link_iptnl.c
++++ iproute2-4.1.1/ip/link_iptnl.c
+@@ -66,6 +66,7 @@ static int iptunnel_parse_opt(struct lin
+ 	__u32 link = 0;
+ 	__u32 laddr = 0;
+ 	__u32 raddr = 0;
++	__u32 underlay = 0;
+ 	__u8 ttl = 0;
+ 	__u8 tos = 0;
+ 	__u8 pmtudisc = 1;
+@@ -174,6 +175,9 @@ get_failed:
+ 				raddr = get_addr32(*argv);
+ 			else
+ 				raddr = 0;
++		} else if (strcmp(*argv, "underlay") == 0) {
++			NEXT_ARG();
++			underlay = get_addr32(*argv);
+ 		} else if (strcmp(*argv, "local") == 0) {
+ 			NEXT_ARG();
+ 			if (strcmp(*argv, "any"))
+@@ -318,6 +322,9 @@ get_failed:
+ 		}
+ 	}
+ 
++	if (underlay)
++		addattr32(n, 1024, IFLA_IPTUN_FAN_UNDERLAY, underlay);
++
+ 	return 0;
+ }
+ 
+@@ -349,6 +356,14 @@ static void iptunnel_print_opt(struct li
+ 
+ 	fprintf(f, "local %s ", local);
+ 
++	if (tb[IFLA_IPTUN_FAN_UNDERLAY]) {
++		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_FAN_UNDERLAY]);
++
++		if (addr)
++			fprintf(f, "underlay %s ",
++				format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
++	}
++
+ 	if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
+ 		unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
+ 		const char *n = if_indextoname(link, s2);
diff --git a/pkgs/os-specific/linux/iproute/ubuntu-fan.patch b/pkgs/os-specific/linux/iproute/1001-ubuntu-poc-fan-driver-v3.patch
index e55425c2ce6a..a940b341ea0f 100644
--- a/pkgs/os-specific/linux/iproute/ubuntu-fan.patch
+++ b/pkgs/os-specific/linux/iproute/1001-ubuntu-poc-fan-driver-v3.patch
@@ -1,27 +1,19 @@
-This provides support for Ubuntu's Fan Networking [1].
-
-These patches were pulled from:
-https://code.launchpad.net/~ubuntu-branches/ubuntu/vivid/iproute2/vivid-proposed
-
-See revisions 18 and 19.
-
-[1] https://wiki.ubuntu.com/FanNetworking
-
-diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
-index 102ce7a..7b8f0e5 100644
---- a/include/linux/if_tunnel.h
-+++ b/include/linux/if_tunnel.h
-@@ -57,6 +57,9 @@ enum {
- 	IFLA_IPTUN_ENCAP_FLAGS,
- 	IFLA_IPTUN_ENCAP_SPORT,
+Description: Fan driver support v3
+ Fan driver support v3
+Author: Jay Vosburgh <jay.vosburgh@canonical.com>
+Index: iproute2-4.1.1/include/linux/if_tunnel.h
+===================================================================
+--- iproute2-4.1.1.orig/include/linux/if_tunnel.h
++++ iproute2-4.1.1/include/linux/if_tunnel.h
+@@ -59,6 +59,7 @@ enum {
  	IFLA_IPTUN_ENCAP_DPORT,
-+
-+	IFLA_IPTUN_FAN_UNDERLAY = 32,
+ 
+ 	IFLA_IPTUN_FAN_UNDERLAY = 32,
 +	IFLA_IPTUN_FAN_MAP = 33,
+ 
  	__IFLA_IPTUN_MAX,
  };
- #define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
-@@ -131,4 +134,20 @@ enum {
+@@ -134,4 +135,20 @@ enum {
  };
  
  #define IFLA_VTI_MAX	(__IFLA_VTI_MAX - 1)
@@ -42,10 +34,10 @@ index 102ce7a..7b8f0e5 100644
 +};
 +
  #endif /* _IF_TUNNEL_H_ */
-diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
-index 9d6bc98..ec3f05d 100644
---- a/ip/link_iptnl.c
-+++ b/ip/link_iptnl.c
+Index: iproute2-4.1.1/ip/link_iptnl.c
+===================================================================
+--- iproute2-4.1.1.orig/ip/link_iptnl.c
++++ iproute2-4.1.1/ip/link_iptnl.c
 @@ -49,6 +49,42 @@ static void usage(int sit)
  	print_usage(stderr, sit);
  	exit(-1);
@@ -89,21 +81,10 @@ index 9d6bc98..ec3f05d 100644
  
  static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
  			      struct nlmsghdr *n)
-@@ -66,6 +102,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
- 	__u32 link = 0;
- 	__u32 laddr = 0;
- 	__u32 raddr = 0;
-+	__u32 underlay = 0;
- 	__u8 ttl = 0;
- 	__u8 tos = 0;
- 	__u8 pmtudisc = 1;
-@@ -174,6 +211,13 @@ get_failed:
- 				raddr = get_addr32(*argv);
- 			else
- 				raddr = 0;
-+		} else if (strcmp(*argv, "underlay") == 0) {
-+			NEXT_ARG();
-+			underlay = get_addr32(*argv);
+@@ -178,6 +214,10 @@ get_failed:
+ 		} else if (strcmp(*argv, "underlay") == 0) {
+ 			NEXT_ARG();
+ 			underlay = get_addr32(*argv);
 +		} else if (strcmp(*argv, "fan-map") == 0) {
 +			NEXT_ARG();
 +			if (fan_parse_map(&argc, &argv, n))
@@ -111,13 +92,7 @@ index 9d6bc98..ec3f05d 100644
  		} else if (strcmp(*argv, "local") == 0) {
  			NEXT_ARG();
  			if (strcmp(*argv, "any"))
-@@ -318,9 +362,32 @@ get_failed:
- 		}
- 	}
- 
-+	if (underlay)
-+		addattr32(n, 1024, IFLA_IPTUN_FAN_UNDERLAY, underlay);
-+
+@@ -328,6 +368,28 @@ get_failed:
  	return 0;
  }
  
@@ -127,16 +102,18 @@ index 9d6bc98..ec3f05d 100644
 +	struct ip_tunnel_fan_map *m;
 +	struct rtattr *i;
 +	int rem;
++	int p;
 +
 +	fprintf(f, "fan-map ");
 +
 +	rem = RTA_PAYLOAD(attr);
 +	for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
++		p = RTA_PAYLOAD(i);
 +		m = RTA_DATA(i);
 +		fprintf(f, "%s/%d:%s/%d ",
-+			rt_addr_n2a(AF_INET, sizeof(m->overlay), &m->overlay, b1, INET_ADDRSTRLEN),
++			rt_addr_n2a(AF_INET, p, &m->overlay, b1, INET_ADDRSTRLEN),
 +			m->overlay_prefix,
-+			rt_addr_n2a(AF_INET, sizeof(m->overlay), &m->underlay, b2, INET_ADDRSTRLEN),
++			rt_addr_n2a(AF_INET, p, &m->underlay, b2, INET_ADDRSTRLEN),
 +			m->underlay_prefix);
 +	}
 +}
@@ -144,18 +121,10 @@ index 9d6bc98..ec3f05d 100644
  static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
  {
  	char s1[1024];
-@@ -349,6 +416,17 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
- 
- 	fprintf(f, "local %s ", local);
+@@ -364,6 +426,9 @@ static void iptunnel_print_opt(struct li
+ 				format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
+ 	}
  
-+	if (tb[IFLA_IPTUN_FAN_UNDERLAY]) {
-+		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_FAN_UNDERLAY]);
-+
-+		if (addr)
-+			fprintf(f, "underlay %s ",
-+				format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
-+	}
-+
 +	if (tb[IFLA_IPTUN_FAN_MAP])
 +		fan_print_map(f, tb[IFLA_IPTUN_FAN_MAP]);
 +
diff --git a/pkgs/os-specific/linux/iproute/1002-ubuntu-poc-fan-driver-vxlan.patch b/pkgs/os-specific/linux/iproute/1002-ubuntu-poc-fan-driver-vxlan.patch
new file mode 100644
index 000000000000..2ddc2840bdd1
--- /dev/null
+++ b/pkgs/os-specific/linux/iproute/1002-ubuntu-poc-fan-driver-vxlan.patch
@@ -0,0 +1,177 @@
+Description: Fan driver support VXLAN (p4)
+ Fan driver setup support for vxlan interfaces.
+
+Index: iproute2-4.3.0/include/linux/if_link.h
+===================================================================
+--- iproute2-4.3.0.orig/include/linux/if_link.h
++++ iproute2-4.3.0/include/linux/if_link.h
+@@ -392,6 +392,7 @@ enum {
+ 	IFLA_VXLAN_GBP,
+ 	IFLA_VXLAN_REMCSUM_NOPARTIAL,
+ 	IFLA_VXLAN_COLLECT_METADATA,
++	IFLA_VXLAN_FAN_MAP = 33,
+ 	__IFLA_VXLAN_MAX
+ };
+ #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
+Index: iproute2-4.3.0/include/linux/if_tunnel.h
+===================================================================
+--- iproute2-4.3.0.orig/include/linux/if_tunnel.h
++++ iproute2-4.3.0/include/linux/if_tunnel.h
+@@ -145,7 +145,7 @@ enum {
+ 
+ #define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
+ 
+-struct ip_tunnel_fan_map {
++struct ifla_fan_map {
+ 	__be32		underlay;
+ 	__be32		overlay;
+ 	__u16		underlay_prefix;
+Index: iproute2-4.3.0/ip/iplink_vxlan.c
+===================================================================
+--- iproute2-4.3.0.orig/ip/iplink_vxlan.c
++++ iproute2-4.3.0/ip/iplink_vxlan.c
+@@ -15,7 +15,10 @@
+ #include <net/if.h>
+ #include <linux/ip.h>
+ #include <linux/if_link.h>
++#include <linux/types.h>
+ #include <arpa/inet.h>
++#include <linux/in6.h>
++#include <linux/if_tunnel.h>
+ 
+ #include "rt_names.h"
+ #include "utils.h"
+@@ -43,6 +46,45 @@ static void explain(void)
+ 	print_explain(stderr);
+ }
+ 
++static int fan_parse_map(int *argcp, char ***argvp, struct nlmsghdr *n)
++{
++	inet_prefix underlay, overlay;
++	struct ifla_fan_map map;
++	struct rtattr *nest;
++	char **argv = *argvp;
++	int argc = *argcp;
++
++	nest = addattr_nest(n, 1024, IFLA_VXLAN_FAN_MAP);
++	while (argc > 0) {
++		char *colon = strchr(*argv, ':');
++
++		if (!colon) {
++			PREV_ARG();
++			break;
++		}
++		*colon = '\0';
++
++		if (get_prefix(&overlay, *argv, AF_INET))
++			invarg("invalid fan-map overlay", *argv);
++		if (get_prefix(&underlay, colon + 1, AF_INET))
++			invarg("invalid fan-map underlay", colon + 1);
++
++		memcpy(&map.underlay, underlay.data, 4);
++		map.underlay_prefix = underlay.bitlen;
++		memcpy(&map.overlay, overlay.data, 4);
++		map.overlay_prefix = overlay.bitlen;
++
++		argc--, argv++;
++
++		addattr_l(n, 1024, IFLA_FAN_MAPPING, &map, sizeof(map));
++	}
++	addattr_nest_end(n, nest);
++
++	*argcp = argc;
++	*argvp = argv;
++	return 0;
++}
++
+ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
+ 			  struct nlmsghdr *n)
+ {
+@@ -201,6 +243,10 @@ static int vxlan_parse_opt(struct link_u
+ 			udp6zerocsumrx = 0;
+ 		} else if (!matches(*argv, "gbp")) {
+ 			gbp = 1;
++		} else if (!matches(*argv, "fan-map")) {
++			NEXT_ARG();
++			if (fan_parse_map(&argc, &argv, n))
++				invarg("invalid fan-map", *argv);
+ 		} else if (matches(*argv, "help") == 0) {
+ 			explain();
+ 			return -1;
+@@ -279,6 +325,28 @@ static int vxlan_parse_opt(struct link_u
+ 	return 0;
+ }
+ 
++static void fan_print_map(FILE *f, struct rtattr *attr)
++{
++	char b1[INET_ADDRSTRLEN], b2[INET_ADDRSTRLEN];
++	struct ifla_fan_map *m;
++	struct rtattr *i;
++	int rem;
++	int p;
++
++	fprintf(f, "fan-map ");
++
++	rem = RTA_PAYLOAD(attr);
++	for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
++		p = RTA_PAYLOAD(i);
++		m = RTA_DATA(i);
++		fprintf(f, "%s/%d:%s/%d ",
++			rt_addr_n2a(AF_INET, p, &m->overlay, b1, INET_ADDRSTRLEN),
++			m->overlay_prefix,
++			rt_addr_n2a(AF_INET, p, &m->underlay, b2, INET_ADDRSTRLEN),
++			m->underlay_prefix);
++	}
++}
++
+ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
+ {
+ 	__u32 vni;
+@@ -321,6 +389,9 @@ static void vxlan_print_opt(struct link_
+ 		}
+ 	}
+ 
++	if (tb[IFLA_VXLAN_FAN_MAP])
++		fan_print_map(f, tb[IFLA_VXLAN_FAN_MAP]);
++
+ 	if (tb[IFLA_VXLAN_LOCAL]) {
+ 		__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_LOCAL]);
+ 		if (addr)
+Index: iproute2-4.3.0/ip/link_iptnl.c
+===================================================================
+--- iproute2-4.3.0.orig/ip/link_iptnl.c
++++ iproute2-4.3.0/ip/link_iptnl.c
+@@ -49,10 +49,11 @@ static void usage(int sit)
+ 	print_usage(stderr, sit);
+ 	exit(-1);
+ }
++
+ static int fan_parse_map(int *argcp, char ***argvp, struct nlmsghdr *n)
+ {
+ 	inet_prefix underlay, overlay;
+-	struct ip_tunnel_fan_map map;
++	struct ifla_fan_map map;
+ 	struct rtattr *nest;
+ 	char **argv = *argvp;
+ 	int argc = *argcp;
+@@ -61,8 +62,10 @@ static int fan_parse_map(int *argcp, cha
+ 	while (argc > 0) {
+ 		char *colon = strchr(*argv, ':');
+ 
+-		if (!colon)
++		if (!colon) {
++			PREV_ARG();
+ 			break;
++		}
+ 		*colon = '\0';
+ 
+ 		if (get_prefix(&overlay, *argv, AF_INET))
+@@ -371,7 +374,7 @@ get_failed:
+ static void fan_print_map(FILE *f, struct rtattr *attr)
+ {
+ 	char b1[INET_ADDRSTRLEN], b2[INET_ADDRSTRLEN];
+-	struct ip_tunnel_fan_map *m;
++	struct ifla_fan_map *m;
+ 	struct rtattr *i;
+ 	int rem;
+ 	int p;
diff --git a/pkgs/os-specific/linux/iproute/default.nix b/pkgs/os-specific/linux/iproute/default.nix
index 891d39d24dd8..5f328bd90c84 100644
--- a/pkgs/os-specific/linux/iproute/default.nix
+++ b/pkgs/os-specific/linux/iproute/default.nix
@@ -10,7 +10,13 @@ stdenv.mkDerivation rec {
     sha256 = "159988vv3fd78bzhisfl1dl4dd7km3vjzs2d8899a0vcvn412fzh";
   };
 
-  patches = lib.optionals enableFan [ ./ubuntu-fan.patch ];
+  patches = lib.optionals enableFan [
+    # These patches were pulled from:
+    # https://launchpad.net/ubuntu/xenial/+source/iproute2
+    ./1000-ubuntu-poc-fan-driver.patch
+    ./1001-ubuntu-poc-fan-driver-v3.patch
+    ./1002-ubuntu-poc-fan-driver-vxlan.patch
+  ];
 
   preConfigure = ''
     patchShebangs ./configure
diff --git a/pkgs/os-specific/linux/iptables/1.6.nix b/pkgs/os-specific/linux/iptables/1.6.nix
new file mode 100644
index 000000000000..88821a15d73e
--- /dev/null
+++ b/pkgs/os-specific/linux/iptables/1.6.nix
@@ -0,0 +1,33 @@
+{stdenv, fetchurl, bison, flex, libnetfilter_conntrack, libnftnl, libmnl}:
+
+stdenv.mkDerivation rec {
+  name = "iptables-${version}";
+  version = "1.6.0";
+
+  src = fetchurl {
+    url = "http://www.netfilter.org/projects/iptables/files/${name}.tar.bz2";
+    sha256 = "0q0w1x4aijid8wj7dg1ny9fqwll483f1sqw7kvkskd8q1c52mdsb";
+  };
+
+  nativeBuildInputs = [bison flex];
+
+  buildInputs = [libnetfilter_conntrack libnftnl libmnl];
+  
+  preConfigure = ''
+    export NIX_LDFLAGS="$NIX_LDFLAGS -lmnl -lnftnl"
+  '';
+
+  configureFlags = ''
+    --enable-devel
+    --enable-shared
+  '';
+
+  meta = {
+    description = "A program to configure the Linux IP packet filtering ruleset";
+    homepage = http://www.netfilter.org/projects/iptables/index.html;
+    platforms = stdenv.lib.platforms.linux;
+    downloadPage = "http://www.netfilter.org/projects/iptables/files/";
+    updateWalker = true;
+    inherit version;
+  };
+}
diff --git a/pkgs/os-specific/linux/kbd/default.nix b/pkgs/os-specific/linux/kbd/default.nix
index bb2915958f7c..fddaa84a8240 100644
--- a/pkgs/os-specific/linux/kbd/default.nix
+++ b/pkgs/os-specific/linux/kbd/default.nix
@@ -40,7 +40,7 @@ stdenv.mkDerivation rec {
       # Fix the path to gzip/bzip2.
       substituteInPlace src/libkeymap/findfile.c \
         --replace gzip ${gzip}/bin/gzip \
-        --replace bzip2 ${bzip2}/bin/bzip2 \
+        --replace bzip2 ${bzip2.bin}/bin/bzip2 \
 
       # We get a warning in armv5tel-linux and the fuloong2f, so we
       # disable -Werror in it.
diff --git a/pkgs/os-specific/linux/kernel/linux-4.4.nix b/pkgs/os-specific/linux/kernel/linux-4.4.nix
index fecb3b05f97e..c6dfb6935235 100644
--- a/pkgs/os-specific/linux/kernel/linux-4.4.nix
+++ b/pkgs/os-specific/linux/kernel/linux-4.4.nix
@@ -1,12 +1,12 @@
 { stdenv, fetchurl, perl, buildLinux, ... } @ args:
 
 import ./generic.nix (args // rec {
-  version = "4.4.6";
+  version = "4.4.7";
   extraMeta.branch = "4.4";
 
   src = fetchurl {
     url = "mirror://kernel/linux/kernel/v4.x/linux-${version}.tar.xz";
-    sha256 = "0zapxjnawdn0km6b9pc7399zbjiyb0a28rqmsif3afc9qb2cxg53";
+    sha256 = "00nkh0klk9b777fvhgf10wsrc7h8ycchgazwirk2926wmisjhl8q";
   };
 
   kernelPatches = args.kernelPatches;
diff --git a/pkgs/os-specific/linux/kernel/linux-4.5.nix b/pkgs/os-specific/linux/kernel/linux-4.5.nix
index 790175d6e887..14ae13c320d1 100644
--- a/pkgs/os-specific/linux/kernel/linux-4.5.nix
+++ b/pkgs/os-specific/linux/kernel/linux-4.5.nix
@@ -1,13 +1,12 @@
 { stdenv, fetchurl, perl, buildLinux, ... } @ args:
 
 import ./generic.nix (args // rec {
-  version = "4.5";
-  modDirVersion = "4.5.0";
+  version = "4.5.1";
   extraMeta.branch = "4.5";
 
   src = fetchurl {
     url = "mirror://kernel/linux/kernel/v4.x/linux-${version}.tar.xz";
-    sha256 = "172i3arrc34mb7nxw31iqrmbwrdnp8dmrbf8p3b3f6z006sfy3d4";
+    sha256 = "0q6qkp7w5hy1ai13zgvj2982kjk81rfzd8ff7ixp3slq8bmsz07i";
   };
 
   kernelPatches = args.kernelPatches;
diff --git a/pkgs/os-specific/linux/kernel/linux-testing.nix b/pkgs/os-specific/linux/kernel/linux-testing.nix
index e3edaa43b8cd..ea9eb4d551b0 100644
--- a/pkgs/os-specific/linux/kernel/linux-testing.nix
+++ b/pkgs/os-specific/linux/kernel/linux-testing.nix
@@ -1,13 +1,13 @@
 { stdenv, fetchurl, perl, buildLinux, ... } @ args:
 
 import ./generic.nix (args // rec {
-  version = "4.6-rc2";
-  modDirVersion = "4.6.0-rc2";
+  version = "4.6-rc3";
+  modDirVersion = "4.6.0-rc3";
   extraMeta.branch = "4.6";
 
   src = fetchurl {
     url = "mirror://kernel/linux/kernel/v4.x/testing/linux-${version}.tar.xz";
-    sha256 = "0zihk9s1rkgmn0ghiz9xkg0w88w524af5mmad45rbxhm5751nxcr";
+    sha256 = "1vhvhbldk5pvwxhdndyzvyqy5mscpnlz09sfyh2c9rk6wc1hc8xv";
   };
 
   features.iwlwifi = true;
diff --git a/pkgs/os-specific/linux/kernel/manual-config.nix b/pkgs/os-specific/linux/kernel/manual-config.nix
index 1e0c3eeea046..1fb702d57463 100644
--- a/pkgs/os-specific/linux/kernel/manual-config.nix
+++ b/pkgs/os-specific/linux/kernel/manual-config.nix
@@ -74,7 +74,7 @@ let
 
       installsFirmware = (config.isEnabled "FW_LOADER") &&
         (isModular || (config.isDisabled "FIRMWARE_IN_KERNEL"));
-    in (optionalAttrs isModular { outputs = [ "out" "dev" ]; }) // {
+    in (optionalAttrs isModular { outputs = [ "out" "dev" ]; propagatedBuildOutputs = ""; }) // {
       passthru = {
         inherit version modDirVersion config kernelPatches configfile;
       };
diff --git a/pkgs/os-specific/linux/kernel/patches.nix b/pkgs/os-specific/linux/kernel/patches.nix
index a8fb1598af7e..707ebb544bf4 100644
--- a/pkgs/os-specific/linux/kernel/patches.nix
+++ b/pkgs/os-specific/linux/kernel/patches.nix
@@ -71,14 +71,9 @@ rec {
       patch = ./mips-ext3-n32.patch;
     };
 
-  ubuntu_fan =
+  ubuntu_fan_4_4 =
     { name = "ubuntu-fan";
-      patch = ./ubuntu-fan-3.patch;
-    };
-
-  ubuntu_fan_4 =
-    { name = "ubuntu-fan";
-      patch = ./ubuntu-fan-4.patch;
+      patch = ./ubuntu-fan-4.4.patch;
     };
 
   ubuntu_unprivileged_overlayfs =
@@ -159,4 +154,8 @@ rec {
     { name = "mfd_fix_dependency";
       patch = ./chromiumos-patches/mfd-fix-dependency.patch;
     };
+  qat_common_Makefile =
+    { name = "qat_common_Makefile";
+      patch = ./qat_common_Makefile.patch;
+    };
 }
diff --git a/pkgs/os-specific/linux/kernel/qat_common_Makefile.patch b/pkgs/os-specific/linux/kernel/qat_common_Makefile.patch
new file mode 100644
index 000000000000..2d4476a7fe50
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/qat_common_Makefile.patch
@@ -0,0 +1,10 @@
+--- a/drivers/crypto/qat/qat_common/Makefile
++++ b/drivers/crypto/qat/qat_common/Makefile
+@@ -2,6 +2,7 @@
+ 			     $(obj)/qat_rsapubkey-asn1.h
+ $(obj)/qat_rsaprivkey-asn1.o: $(obj)/qat_rsaprivkey-asn1.c \
+ 			      $(obj)/qat_rsaprivkey-asn1.h
++$(obj)/qat_asym_algs.o: $(obj)/qat_rsaprivkey-asn1.h $(obj)/qat_rsapubkey-asn1.h
+ 
+ clean-files += qat_rsapubkey-asn1.c qat_rsapubkey-asn1.h
+ clean-files += qat_rsaprivkey-asn1.c qat_rsapvivkey-asn1.h
diff --git a/pkgs/os-specific/linux/kernel/ubuntu-fan-3.patch b/pkgs/os-specific/linux/kernel/ubuntu-fan-3.patch
deleted file mode 100644
index c80950d06147..000000000000
--- a/pkgs/os-specific/linux/kernel/ubuntu-fan-3.patch
+++ /dev/null
@@ -1,616 +0,0 @@
-From f3c956096902669c3529cb01d40deb0c759ed94f Mon Sep 17 00:00:00 2001
-From: Jay Vosburgh <jay.vosburgh@canonical.com>
-Date: Wed, 1 Apr 2015 16:11:09 -0700
-Subject: [PATCH] UBUNTU: SAUCE: fan: Proof of concept implementation (v2)
-
-Modification to ipip tunnel driver to accept a new netlink option,
-IFLA_IPTUN_FAN_UNDERLAY, which provides a /16 network prefix and enables
-TX side destination address remapping for traffic entering the tunnel
-(to be encapsulated).
-
-For an overlay (inner) address Y.A.B.C, the transformation is F.G.A.B,
-where "F" and "G" are the first two octets of the underlay network (the
-network portion of a /16), "A" and "B" are the low order two octets of the
-underlay network host (the host portion of a /16), and "Y" is a configured
-first octet of the overlay network.
-
-E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
-subnet 99.3.4.0/24.  An overlay network datagram from 99.3.4.5 to 99.6.7.8
-would be directed to underlay host 10.88.6.7, which hosts overlay network
-99.6.7.0/24.
-
-Includes net.fan.version sysctl as a sentinel for availability of the
-fan functionality.
-
-NOTE: this requires an updated iproute2 to facilitate configuration of
-the fan.
-
-BugLink: http://bugs.launchpad.net/bugs/1439706
-Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
-[apw@canonical.com: move IFLA_IPTUN_FAN_UNDERLAY up to avoid clashing
- with future feature additions.]
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
----
- include/net/ip_tunnels.h       |   6 +++
- include/uapi/linux/if_tunnel.h |   4 ++
- net/ipv4/ipip.c                | 112 +++++++++++++++++++++++++++++++++++++++--
- 3 files changed, 117 insertions(+), 5 deletions(-)
-
-diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
-index 25a59eb..d7eada2 100644
---- a/include/net/ip_tunnels.h
-+++ b/include/net/ip_tunnels.h
-@@ -51,6 +51,11 @@ struct ip_tunnel_dst {
- 	__be32				 saddr;
- };
- 
-+/* Underlay address prefix for ipip fan mode */
-+struct ip_tunnel_fan {
-+	u32			underlay;
-+};
-+
- struct ip_tunnel {
- 	struct ip_tunnel __rcu	*next;
- 	struct hlist_node hash_node;
-@@ -82,6 +87,7 @@ struct ip_tunnel {
- #endif
- 	struct ip_tunnel_prl_entry __rcu *prl;	/* potential router list */
- 	unsigned int		prl_count;	/* # of entries in PRL */
-+	struct ip_tunnel_fan	fan;
- 	int			ip_tnl_net_id;
- 	struct gro_cells	gro_cells;
- };
-diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
-index bd3cc11..8f7d269 100644
---- a/include/uapi/linux/if_tunnel.h
-+++ b/include/uapi/linux/if_tunnel.h
-@@ -57,6 +57,10 @@ enum {
- 	IFLA_IPTUN_ENCAP_FLAGS,
- 	IFLA_IPTUN_ENCAP_SPORT,
- 	IFLA_IPTUN_ENCAP_DPORT,
-+
-+	__IFLA_IPTUN_VENDOR_BREAK,		/* Ensure new entries do not hit the below. */
-+	IFLA_IPTUN_FAN_UNDERLAY=32,
-+
- 	__IFLA_IPTUN_MAX,
- };
- #define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
-diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
-index 40403114..e3c27cd 100644
---- a/net/ipv4/ipip.c
-+++ b/net/ipv4/ipip.c
-@@ -209,13 +209,38 @@ drop:
- }
- 
- /*
-+ * Determine fan tunnel endpoint to send packet to, based on the inner IP
-+ * address.  For an overlay (inner) address Y.A.B.C, the transformation is
-+ * F.G.A.B, where "F" and "G" are the first two octets of the underlay
-+ * network (the network portion of a /16), "A" and "B" are the low order
-+ * two octets of the underlay network host (the host portion of a /16),
-+ * and "Y" is a configured first octet of the overlay network.
-+ *
-+ * E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
-+ * subnet 99.3.4.0/24.  An overlay network datagram from 99.3.4.5 to
-+ * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
-+ * overlay network 99.6.7.0/24.
-+ */
-+static void ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
-+{
-+	u32 daddr;
-+
-+	*iph = tunnel->parms.iph;
-+
-+	daddr = ntohl(ip_hdr(skb)->daddr);
-+	iph->daddr = htonl((tunnel->fan.underlay & 0xffff0000) |
-+			   ((daddr >> 8) & 0x0000ffff));
-+}
-+
-+/*
-  *	This function assumes it is being called from dev_queue_xmit()
-  *	and that skb is filled properly by that function.
-  */
- static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
- {
- 	struct ip_tunnel *tunnel = netdev_priv(dev);
--	const struct iphdr  *tiph = &tunnel->parms.iph;
-+	const struct iphdr *tiph;
-+	struct iphdr fiph;
- 
- 	if (unlikely(skb->protocol != htons(ETH_P_IP)))
- 		goto tx_error;
-@@ -224,6 +249,13 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
- 	if (IS_ERR(skb))
- 		goto out;
- 
-+	if (tunnel->fan.underlay) {
-+		ipip_build_fan_iphdr(tunnel, skb, &fiph);
-+		tiph = &fiph;
-+	} else {
-+		tiph = &tunnel->parms.iph;
-+	}
-+
- 	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
- 
- 	ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
-@@ -377,21 +409,44 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
- 	return ret;
- }
- 
-+static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
-+			    struct ip_tunnel_parm *parms)
-+{
-+	u32 net = t->fan.underlay;
-+
-+	if (!data[IFLA_IPTUN_FAN_UNDERLAY])
-+		goto err_check;
-+
-+	net = ntohl(nla_get_be32(data[IFLA_IPTUN_FAN_UNDERLAY])) & 0xffff0000;
-+
-+err_check:
-+	if (parms->iph.daddr && net)
-+		return -EINVAL;
-+
-+	t->fan.underlay = net;
-+
-+	return 0;
-+}
-+
- static int ipip_newlink(struct net *src_net, struct net_device *dev,
- 			struct nlattr *tb[], struct nlattr *data[])
- {
- 	struct ip_tunnel_parm p;
- 	struct ip_tunnel_encap ipencap;
-+	struct ip_tunnel *t = netdev_priv(dev);
-+	int err;
- 
- 	if (ipip_netlink_encap_parms(data, &ipencap)) {
--		struct ip_tunnel *t = netdev_priv(dev);
--		int err = ip_tunnel_encap_setup(t, &ipencap);
-+		err = ip_tunnel_encap_setup(t, &ipencap);
- 
- 		if (err < 0)
- 			return err;
- 	}
- 
- 	ipip_netlink_parms(data, &p);
-+	err = ipip_netlink_fan(data, t, &p);
-+	if (err < 0)
-+		return err;
- 	return ip_tunnel_newlink(dev, tb, &p);
- }
- 
-@@ -400,16 +455,20 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
- {
- 	struct ip_tunnel_parm p;
- 	struct ip_tunnel_encap ipencap;
-+	struct ip_tunnel *t = netdev_priv(dev);
-+	int err;
- 
- 	if (ipip_netlink_encap_parms(data, &ipencap)) {
--		struct ip_tunnel *t = netdev_priv(dev);
--		int err = ip_tunnel_encap_setup(t, &ipencap);
-+		err = ip_tunnel_encap_setup(t, &ipencap);
- 
- 		if (err < 0)
- 			return err;
- 	}
- 
- 	ipip_netlink_parms(data, &p);
-+	err = ipip_netlink_fan(data, t, &p);
-+	if (err < 0)
-+		return err;
- 
- 	if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
- 	    (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
-@@ -441,6 +500,8 @@ static size_t ipip_get_size(const struct net_device *dev)
- 		nla_total_size(2) +
- 		/* IFLA_IPTUN_ENCAP_DPORT */
- 		nla_total_size(2) +
-+		/* IFLA_IPTUN_FAN_UNDERLAY */
-+		nla_total_size(4) +
- 		0;
- }
- 
-@@ -468,6 +529,11 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
- 			tunnel->encap.flags))
- 		goto nla_put_failure;
- 
-+	if (tunnel->fan.underlay)
-+		if (nla_put_be32(skb, IFLA_IPTUN_FAN_UNDERLAY,
-+				 htonl(tunnel->fan.underlay)))
-+			goto nla_put_failure;
-+
- 	return 0;
- 
- nla_put_failure:
-@@ -485,6 +551,9 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
- 	[IFLA_IPTUN_ENCAP_FLAGS]	= { .type = NLA_U16 },
- 	[IFLA_IPTUN_ENCAP_SPORT]	= { .type = NLA_U16 },
- 	[IFLA_IPTUN_ENCAP_DPORT]	= { .type = NLA_U16 },
-+
-+	[__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX]	= { .type = NLA_BINARY },
-+	[IFLA_IPTUN_FAN_UNDERLAY]	= { .type = NLA_U32 },
- };
- 
- static struct rtnl_link_ops ipip_link_ops __read_mostly = {
-@@ -524,6 +593,23 @@ static struct pernet_operations ipip_net_ops = {
- 	.size = sizeof(struct ip_tunnel_net),
- };
- 
-+#ifdef CONFIG_SYSCTL
-+static struct ctl_table_header *ipip_fan_header;
-+static unsigned int ipip_fan_version = 1;
-+
-+static struct ctl_table ipip_fan_sysctls[] = {
-+	{
-+		.procname	= "version",
-+		.data		= &ipip_fan_version,
-+		.maxlen		= sizeof(ipip_fan_version),
-+		.mode		= 0444,
-+		.proc_handler	= proc_dointvec,
-+	},
-+	{},
-+};
-+
-+#endif /* CONFIG_SYSCTL */
-+
- static int __init ipip_init(void)
- {
- 	int err;
-@@ -542,9 +628,22 @@ static int __init ipip_init(void)
- 	if (err < 0)
- 		goto rtnl_link_failed;
- 
-+#ifdef CONFIG_SYSCTL
-+	ipip_fan_header = register_net_sysctl(&init_net, "net/fan",
-+					      ipip_fan_sysctls);
-+	if (!ipip_fan_header) {
-+		err = -ENOMEM;
-+		goto sysctl_failed;
-+	}
-+#endif /* CONFIG_SYSCTL */
-+
- out:
- 	return err;
- 
-+#ifdef CONFIG_SYSCTL
-+sysctl_failed:
-+	rtnl_link_unregister(&ipip_link_ops);
-+#endif /* CONFIG_SYSCTL */
- rtnl_link_failed:
- 	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
- xfrm_tunnel_failed:
-@@ -554,6 +653,9 @@ xfrm_tunnel_failed:
- 
- static void __exit ipip_fini(void)
- {
-+#ifdef CONFIG_SYSCTL
-+	unregister_net_sysctl_table(ipip_fan_header);
-+#endif /* CONFIG_SYSCTL */
- 	rtnl_link_unregister(&ipip_link_ops);
- 	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
- 		pr_info("%s: can't deregister tunnel\n", __func__);
--- 
-2.4.1
-
-From 4ea8011656dfdd76e7a2391bdad47c06f85a9d02 Mon Sep 17 00:00:00 2001
-From: Andy Whitcroft <apw@canonical.com>
-Date: Tue, 21 Jul 2015 16:52:10 +0100
-Subject: [PATCH] UBUNTU: SAUCE: fan: tunnel multiple mapping mode (v3)
-
-Switch to a single tunnel for all mappings, this removes the limitations
-on how many mappings each tunnel can handle, and therefore how many Fan
-slices each local address may hold.
-
-NOTE: This introduces a new kernel netlink interface which needs updated
-iproute2 support.
-
-BugLink: http://bugs.launchpad.net/bugs/1470091
-Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
-Acked-by: Tim Gardner <tim.gardner@canonical.com>
-Acked-by: Brad Figg <brad.figg@canonical.com>
-Signed-off-by: Brad Figg <brad.figg@canonical.com>
----
- include/net/ip_tunnels.h       |  14 ++++-
- include/uapi/linux/if_tunnel.h |  20 ++++++-
- net/ipv4/ip_tunnel.c           |   7 ++-
- net/ipv4/ipip.c                | 120 +++++++++++++++++++++++++++++++++--------
- 4 files changed, 133 insertions(+), 28 deletions(-)
-
-diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
-index d7eada2..2f7bc8c 100644
---- a/include/net/ip_tunnels.h
-+++ b/include/net/ip_tunnels.h
-@@ -51,9 +51,18 @@ struct ip_tunnel_dst {
- 	__be32				 saddr;
- };
- 
--/* Underlay address prefix for ipip fan mode */
-+/* A fan overlay /8 (250.0.0.0/8, for example) maps to exactly one /16
-+ * underlay (10.88.0.0/16, for example).  Multiple local addresses within
-+ * the /16 may be used, but a particular overlay may not span
-+ * multiple underlay subnets.
-+ *
-+ * We store one underlay, indexed by the overlay's high order octet.
-+ */
-+#define FAN_OVERLAY_CNT		256
-+
- struct ip_tunnel_fan {
--	u32			underlay;
-+/*	u32 __rcu	*map;*/
-+	u32		map[FAN_OVERLAY_CNT];
- };
- 
- struct ip_tunnel {
-@@ -104,6 +113,7 @@ struct ip_tunnel {
- #define TUNNEL_OAM		__cpu_to_be16(0x0200)
- #define TUNNEL_CRIT_OPT		__cpu_to_be16(0x0400)
- #define TUNNEL_OPTIONS_PRESENT	__cpu_to_be16(0x0800)
-+#define TUNNEL_FAN		__cpu_to_be16(0x4000)
- 
- struct tnl_ptk_info {
- 	__be16 flags;
-diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
-index 8f7d269..9625934 100644
---- a/include/uapi/linux/if_tunnel.h
-+++ b/include/uapi/linux/if_tunnel.h
-@@ -58,8 +58,8 @@ enum {
- 	IFLA_IPTUN_ENCAP_SPORT,
- 	IFLA_IPTUN_ENCAP_DPORT,
- 
--	__IFLA_IPTUN_VENDOR_BREAK,		/* Ensure new entries do not hit the below. */
--	IFLA_IPTUN_FAN_UNDERLAY=32,
-+	__IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
-+	IFLA_IPTUN_FAN_MAP = 33,
- 
- 	__IFLA_IPTUN_MAX,
- };
-@@ -135,4 +135,20 @@ enum {
- };
- 
- #define IFLA_VTI_MAX	(__IFLA_VTI_MAX - 1)
-+
-+enum {
-+	IFLA_FAN_UNSPEC,
-+	IFLA_FAN_MAPPING,
-+	__IFLA_FAN_MAX,
-+};
-+
-+#define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
-+
-+struct ip_tunnel_fan_map {
-+	__be32		underlay;
-+	__be32		overlay;
-+	__u16		underlay_prefix;
-+	__u16		overlay_prefix;
-+};
-+
- #endif /* _UAPI_IF_TUNNEL_H_ */
-diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
-index d3e4479..60bd10f 100644
---- a/net/ipv4/ip_tunnel.c
-+++ b/net/ipv4/ip_tunnel.c
-@@ -1078,6 +1078,11 @@ out:
- }
- EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
- 
-+static int ip_tunnel_is_fan(struct ip_tunnel *tunnel)
-+{
-+	return tunnel->parms.i_flags & TUNNEL_FAN;
-+}
-+
- int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
- 			 struct ip_tunnel_parm *p)
- {
-@@ -1087,7 +1092,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
- 	struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
- 
- 	if (dev == itn->fb_tunnel_dev)
--		return -EINVAL;
-+		return ip_tunnel_is_fan(tunnel) ? 0 : -EINVAL;
- 
- 	t = ip_tunnel_find(itn, p, dev->type);
- 
-diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
-index e3c27cd..d6ebc66 100644
---- a/net/ipv4/ipip.c
-+++ b/net/ipv4/ipip.c
-@@ -107,6 +107,7 @@
- #include <linux/init.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/if_ether.h>
-+#include <linux/inetdevice.h>
- 
- #include <net/sock.h>
- #include <net/ip.h>
-@@ -208,6 +209,11 @@ drop:
- 	return 0;
- }
- 
-+static int ipip_tunnel_is_fan(struct ip_tunnel *tunnel)
-+{
-+	return tunnel->parms.i_flags & TUNNEL_FAN;
-+}
-+
- /*
-  * Determine fan tunnel endpoint to send packet to, based on the inner IP
-  * address.  For an overlay (inner) address Y.A.B.C, the transformation is
-@@ -221,15 +227,20 @@ drop:
-  * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
-  * overlay network 99.6.7.0/24.
-  */
--static void ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
-+static int ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
- {
--	u32 daddr;
--
--	*iph = tunnel->parms.iph;
-+	unsigned int overlay;
-+	u32 daddr, underlay;
- 
- 	daddr = ntohl(ip_hdr(skb)->daddr);
--	iph->daddr = htonl((tunnel->fan.underlay & 0xffff0000) |
--			   ((daddr >> 8) & 0x0000ffff));
-+	overlay = daddr >> 24;
-+	underlay = tunnel->fan.map[overlay];
-+	if (!underlay)
-+		return -EINVAL;
-+
-+	*iph = tunnel->parms.iph;
-+	iph->daddr = htonl(underlay | ((daddr >> 8) & 0x0000ffff));
-+	return 0;
- }
- 
- /*
-@@ -249,8 +260,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
- 	if (IS_ERR(skb))
- 		goto out;
- 
--	if (tunnel->fan.underlay) {
--		ipip_build_fan_iphdr(tunnel, skb, &fiph);
-+	if (ipip_tunnel_is_fan(tunnel)) {
-+		if (ipip_build_fan_iphdr(tunnel, skb, &fiph))
-+			goto tx_error;
- 		tiph = &fiph;
- 	} else {
- 		tiph = &tunnel->parms.iph;
-@@ -409,21 +421,65 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
- 	return ret;
- }
- 
-+static void ipip_fan_free_map(struct ip_tunnel *t)
-+{
-+	memset(&t->fan.map, 0, sizeof(t->fan.map));
-+}
-+
-+static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
-+{
-+	u32 overlay, overlay_mask, underlay, underlay_mask;
-+
-+	if ((map->underlay_prefix && map->underlay_prefix != 16) ||
-+	    (map->overlay_prefix && map->overlay_prefix != 8))
-+		return -EINVAL;
-+
-+	overlay = ntohl(map->overlay);
-+	overlay_mask = ntohl(inet_make_mask(map->overlay_prefix));
-+
-+	underlay = ntohl(map->underlay);
-+	underlay_mask = ntohl(inet_make_mask(map->underlay_prefix));
-+
-+	if ((overlay & ~overlay_mask) || (underlay & ~underlay_mask))
-+		return -EINVAL;
-+
-+	if (!(overlay & overlay_mask) && (underlay & underlay_mask))
-+		return -EINVAL;
-+
-+	t->parms.i_flags |= TUNNEL_FAN;
-+
-+	/* Special case: overlay 0 and underlay 0 clears all mappings */
-+	if (!overlay && !underlay) {
-+		ipip_fan_free_map(t);
-+		return 0;
-+	}
-+
-+	overlay >>= (32 - map->overlay_prefix);
-+	t->fan.map[overlay] = underlay;
-+
-+	return 0;
-+}
-+	
-+
- static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
- 			    struct ip_tunnel_parm *parms)
- {
--	u32 net = t->fan.underlay;
--
--	if (!data[IFLA_IPTUN_FAN_UNDERLAY])
--		goto err_check;
-+	struct ip_tunnel_fan_map *map;
-+	struct nlattr *attr;
-+	int rem, rv;
- 
--	net = ntohl(nla_get_be32(data[IFLA_IPTUN_FAN_UNDERLAY])) & 0xffff0000;
-+	if (!data[IFLA_IPTUN_FAN_MAP])
-+		return 0;
- 
--err_check:
--	if (parms->iph.daddr && net)
-+	if (parms->iph.daddr)
- 		return -EINVAL;
- 
--	t->fan.underlay = net;
-+	nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
-+		map = nla_data(attr);
-+		rv = ipip_fan_set_map(t, map);
-+		if (rv)
-+			return rv;
-+	}
- 
- 	return 0;
- }
-@@ -500,8 +556,8 @@ static size_t ipip_get_size(const struct net_device *dev)
- 		nla_total_size(2) +
- 		/* IFLA_IPTUN_ENCAP_DPORT */
- 		nla_total_size(2) +
--		/* IFLA_IPTUN_FAN_UNDERLAY */
--		nla_total_size(4) +
-+		/* IFLA_IPTUN_FAN_MAP */
-+		nla_total_size(sizeof(struct ip_tunnel_fan_map)) * 256 +
- 		0;
- }
- 
-@@ -529,10 +585,28 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
- 			tunnel->encap.flags))
- 		goto nla_put_failure;
- 
--	if (tunnel->fan.underlay)
--		if (nla_put_be32(skb, IFLA_IPTUN_FAN_UNDERLAY,
--				 htonl(tunnel->fan.underlay)))
-+	if (tunnel->parms.i_flags & TUNNEL_FAN) {
-+		struct nlattr *fan_nest;
-+		int i;
-+
-+		fan_nest = nla_nest_start(skb, IFLA_IPTUN_FAN_MAP);
-+		if (!fan_nest)
- 			goto nla_put_failure;
-+		for (i = 0; i < 256; i++) {
-+			if (tunnel->fan.map[i]) {
-+				struct ip_tunnel_fan_map map;
-+
-+				map.underlay = htonl(tunnel->fan.map[i]);
-+				map.underlay_prefix = 16;
-+				map.overlay = htonl(i << 24);
-+				map.overlay_prefix = 8;
-+				if (nla_put(skb, IFLA_FAN_MAPPING,
-+					    sizeof(map), &map))
-+					goto nla_put_failure;
-+			}
-+		}
-+		nla_nest_end(skb, fan_nest);
-+	}
- 
- 	return 0;
- 
-@@ -553,7 +627,7 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
- 	[IFLA_IPTUN_ENCAP_DPORT]	= { .type = NLA_U16 },
- 
- 	[__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX]	= { .type = NLA_BINARY },
--	[IFLA_IPTUN_FAN_UNDERLAY]	= { .type = NLA_U32 },
-+	[IFLA_IPTUN_FAN_MAP]		= { .type = NLA_NESTED },
- };
- 
- static struct rtnl_link_ops ipip_link_ops __read_mostly = {
-@@ -595,7 +669,7 @@ static struct pernet_operations ipip_net_ops = {
- 
- #ifdef CONFIG_SYSCTL
- static struct ctl_table_header *ipip_fan_header;
--static unsigned int ipip_fan_version = 1;
-+static unsigned int ipip_fan_version = 3;
- 
- static struct ctl_table ipip_fan_sysctls[] = {
- 	{
--- 
-2.4.1
-
diff --git a/pkgs/os-specific/linux/kernel/ubuntu-fan-4.4.patch b/pkgs/os-specific/linux/kernel/ubuntu-fan-4.4.patch
new file mode 100644
index 000000000000..39150ad790d3
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/ubuntu-fan-4.4.patch
@@ -0,0 +1,1240 @@
+From e64058be3b97c5bd3e034fc4ece21e306ef6f90b Mon Sep 17 00:00:00 2001
+From: Jay Vosburgh <jay.vosburgh@canonical.com>
+Date: Wed, 1 Apr 2015 16:11:09 -0700
+Subject: [PATCH] UBUNTU: SAUCE: fan: tunnel multiple mapping mode (v3)
+
+Switch to a single tunnel for all mappings, this removes the limitations
+on how many mappings each tunnel can handle, and therefore how many Fan
+slices each local address may hold.
+
+NOTE: This introduces a new kernel netlink interface which needs updated
+iproute2 support.
+
+BugLink: http://bugs.launchpad.net/bugs/1470091
+Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
+Signed-off-by: Andy Whitcroft <apw@canonical.com>
+Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
+
+Conflicts:
+	include/net/ip_tunnels.h
+---
+ include/net/ip_tunnels.h       |  15 ++++
+ include/uapi/linux/if_tunnel.h |  20 +++++
+ net/ipv4/ip_tunnel.c           |   7 +-
+ net/ipv4/ipip.c                | 186 +++++++++++++++++++++++++++++++++++++++--
+ 4 files changed, 222 insertions(+), 6 deletions(-)
+
+diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
+index 62a750a..47fec59 100644
+--- a/include/net/ip_tunnels.h
++++ b/include/net/ip_tunnels.h
+@@ -91,6 +91,19 @@ struct ip_tunnel_dst {
+ };
+ 
+ struct metadata_dst;
++/* A fan overlay /8 (250.0.0.0/8, for example) maps to exactly one /16
++ * underlay (10.88.0.0/16, for example).  Multiple local addresses within
++ * the /16 may be used, but a particular overlay may not span
++ * multiple underlay subnets.
++ *
++ * We store one underlay, indexed by the overlay's high order octet.
++ */
++#define FAN_OVERLAY_CNT		256
++
++struct ip_tunnel_fan {
++/*	u32 __rcu	*map;*/
++	u32		map[FAN_OVERLAY_CNT];
++};
+ 
+ struct ip_tunnel {
+ 	struct ip_tunnel __rcu	*next;
+@@ -123,6 +136,7 @@ struct ip_tunnel {
+ #endif
+ 	struct ip_tunnel_prl_entry __rcu *prl;	/* potential router list */
+ 	unsigned int		prl_count;	/* # of entries in PRL */
++	struct ip_tunnel_fan	fan;
+ 	int			ip_tnl_net_id;
+ 	struct gro_cells	gro_cells;
+ 	bool			collect_md;
+@@ -143,6 +157,7 @@ struct ip_tunnel {
+ #define TUNNEL_VXLAN_OPT	__cpu_to_be16(0x1000)
+ 
+ #define TUNNEL_OPTIONS_PRESENT	(TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT)
++#define TUNNEL_FAN		__cpu_to_be16(0x4000)
+ 
+ struct tnl_ptk_info {
+ 	__be16 flags;
+diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
+index af4de90..85a3e4b 100644
+--- a/include/uapi/linux/if_tunnel.h
++++ b/include/uapi/linux/if_tunnel.h
+@@ -57,6 +57,10 @@ enum {
+ 	IFLA_IPTUN_ENCAP_FLAGS,
+ 	IFLA_IPTUN_ENCAP_SPORT,
+ 	IFLA_IPTUN_ENCAP_DPORT,
++
++	__IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
++	IFLA_IPTUN_FAN_MAP = 33,
++
+ 	__IFLA_IPTUN_MAX,
+ };
+ #define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
+@@ -132,4 +136,20 @@ enum {
+ };
+ 
+ #define IFLA_VTI_MAX	(__IFLA_VTI_MAX - 1)
++
++enum {
++	IFLA_FAN_UNSPEC,
++	IFLA_FAN_MAPPING,
++	__IFLA_FAN_MAX,
++};
++
++#define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
++
++struct ip_tunnel_fan_map {
++	__be32		underlay;
++	__be32		overlay;
++	__u16		underlay_prefix;
++	__u16		overlay_prefix;
++};
++
+ #endif /* _UAPI_IF_TUNNEL_H_ */
+diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
+index cbb51f3..7a6174b 100644
+--- a/net/ipv4/ip_tunnel.c
++++ b/net/ipv4/ip_tunnel.c
+@@ -1110,6 +1110,11 @@ out:
+ }
+ EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
+ 
++static int ip_tunnel_is_fan(struct ip_tunnel *tunnel)
++{
++	return tunnel->parms.i_flags & TUNNEL_FAN;
++}
++
+ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
+ 			 struct ip_tunnel_parm *p)
+ {
+@@ -1119,7 +1124,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
+ 	struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
+ 
+ 	if (dev == itn->fb_tunnel_dev)
+-		return -EINVAL;
++		return ip_tunnel_is_fan(tunnel) ? 0 : -EINVAL;
+ 
+ 	t = ip_tunnel_find(itn, p, dev->type);
+ 
+diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
+index a09fb0d..56e8984 100644
+--- a/net/ipv4/ipip.c
++++ b/net/ipv4/ipip.c
+@@ -107,6 +107,7 @@
+ #include <linux/init.h>
+ #include <linux/netfilter_ipv4.h>
+ #include <linux/if_ether.h>
++#include <linux/inetdevice.h>
+ 
+ #include <net/sock.h>
+ #include <net/ip.h>
+@@ -208,6 +209,40 @@ drop:
+ 	return 0;
+ }
+ 
++static int ipip_tunnel_is_fan(struct ip_tunnel *tunnel)
++{
++	return tunnel->parms.i_flags & TUNNEL_FAN;
++}
++
++/*
++ * Determine fan tunnel endpoint to send packet to, based on the inner IP
++ * address.  For an overlay (inner) address Y.A.B.C, the transformation is
++ * F.G.A.B, where "F" and "G" are the first two octets of the underlay
++ * network (the network portion of a /16), "A" and "B" are the low order
++ * two octets of the underlay network host (the host portion of a /16),
++ * and "Y" is a configured first octet of the overlay network.
++ *
++ * E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
++ * subnet 99.3.4.0/24.  An overlay network datagram from 99.3.4.5 to
++ * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
++ * overlay network 99.6.7.0/24.
++ */
++static int ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
++{
++	unsigned int overlay;
++	u32 daddr, underlay;
++
++	daddr = ntohl(ip_hdr(skb)->daddr);
++	overlay = daddr >> 24;
++	underlay = tunnel->fan.map[overlay];
++	if (!underlay)
++		return -EINVAL;
++
++	*iph = tunnel->parms.iph;
++	iph->daddr = htonl(underlay | ((daddr >> 8) & 0x0000ffff));
++	return 0;
++}
++
+ /*
+  *	This function assumes it is being called from dev_queue_xmit()
+  *	and that skb is filled properly by that function.
+@@ -215,7 +250,8 @@ drop:
+ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+ 	struct ip_tunnel *tunnel = netdev_priv(dev);
+-	const struct iphdr  *tiph = &tunnel->parms.iph;
++	const struct iphdr *tiph;
++	struct iphdr fiph;
+ 
+ 	if (unlikely(skb->protocol != htons(ETH_P_IP)))
+ 		goto tx_error;
+@@ -224,6 +260,14 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	if (IS_ERR(skb))
+ 		goto out;
+ 
++	if (ipip_tunnel_is_fan(tunnel)) {
++		if (ipip_build_fan_iphdr(tunnel, skb, &fiph))
++			goto tx_error;
++		tiph = &fiph;
++	} else {
++		tiph = &tunnel->parms.iph;
++	}
++
+ 	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
+ 
+ 	ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
+@@ -375,21 +419,88 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
+ 	return ret;
+ }
+ 
++static void ipip_fan_free_map(struct ip_tunnel *t)
++{
++	memset(&t->fan.map, 0, sizeof(t->fan.map));
++}
++
++static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
++{
++	u32 overlay, overlay_mask, underlay, underlay_mask;
++
++	if ((map->underlay_prefix && map->underlay_prefix != 16) ||
++	    (map->overlay_prefix && map->overlay_prefix != 8))
++		return -EINVAL;
++
++	overlay = ntohl(map->overlay);
++	overlay_mask = ntohl(inet_make_mask(map->overlay_prefix));
++
++	underlay = ntohl(map->underlay);
++	underlay_mask = ntohl(inet_make_mask(map->underlay_prefix));
++
++	if ((overlay & ~overlay_mask) || (underlay & ~underlay_mask))
++		return -EINVAL;
++
++	if (!(overlay & overlay_mask) && (underlay & underlay_mask))
++		return -EINVAL;
++
++	t->parms.i_flags |= TUNNEL_FAN;
++
++	/* Special case: overlay 0 and underlay 0 clears all mappings */
++	if (!overlay && !underlay) {
++		ipip_fan_free_map(t);
++		return 0;
++	}
++
++	overlay >>= (32 - map->overlay_prefix);
++	t->fan.map[overlay] = underlay;
++
++	return 0;
++}
++	
++
++static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
++			    struct ip_tunnel_parm *parms)
++{
++	struct ip_tunnel_fan_map *map;
++	struct nlattr *attr;
++	int rem, rv;
++
++	if (!data[IFLA_IPTUN_FAN_MAP])
++		return 0;
++
++	if (parms->iph.daddr)
++		return -EINVAL;
++
++	nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
++		map = nla_data(attr);
++		rv = ipip_fan_set_map(t, map);
++		if (rv)
++			return rv;
++	}
++
++	return 0;
++}
++
+ static int ipip_newlink(struct net *src_net, struct net_device *dev,
+ 			struct nlattr *tb[], struct nlattr *data[])
+ {
+ 	struct ip_tunnel_parm p;
+ 	struct ip_tunnel_encap ipencap;
++	struct ip_tunnel *t = netdev_priv(dev);
++	int err;
+ 
+ 	if (ipip_netlink_encap_parms(data, &ipencap)) {
+-		struct ip_tunnel *t = netdev_priv(dev);
+-		int err = ip_tunnel_encap_setup(t, &ipencap);
++		err = ip_tunnel_encap_setup(t, &ipencap);
+ 
+ 		if (err < 0)
+ 			return err;
+ 	}
+ 
+ 	ipip_netlink_parms(data, &p);
++	err = ipip_netlink_fan(data, t, &p);
++	if (err < 0)
++		return err;
+ 	return ip_tunnel_newlink(dev, tb, &p);
+ }
+ 
+@@ -398,16 +509,20 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
+ {
+ 	struct ip_tunnel_parm p;
+ 	struct ip_tunnel_encap ipencap;
++	struct ip_tunnel *t = netdev_priv(dev);
++	int err;
+ 
+ 	if (ipip_netlink_encap_parms(data, &ipencap)) {
+-		struct ip_tunnel *t = netdev_priv(dev);
+-		int err = ip_tunnel_encap_setup(t, &ipencap);
++		err = ip_tunnel_encap_setup(t, &ipencap);
+ 
+ 		if (err < 0)
+ 			return err;
+ 	}
+ 
+ 	ipip_netlink_parms(data, &p);
++	err = ipip_netlink_fan(data, t, &p);
++	if (err < 0)
++		return err;
+ 
+ 	if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
+ 	    (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
+@@ -439,6 +554,8 @@ static size_t ipip_get_size(const struct net_device *dev)
+ 		nla_total_size(2) +
+ 		/* IFLA_IPTUN_ENCAP_DPORT */
+ 		nla_total_size(2) +
++		/* IFLA_IPTUN_FAN_MAP */
++		nla_total_size(sizeof(struct ip_tunnel_fan_map)) * 256 +
+ 		0;
+ }
+ 
+@@ -466,6 +583,29 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
+ 			tunnel->encap.flags))
+ 		goto nla_put_failure;
+ 
++	if (tunnel->parms.i_flags & TUNNEL_FAN) {
++		struct nlattr *fan_nest;
++		int i;
++
++		fan_nest = nla_nest_start(skb, IFLA_IPTUN_FAN_MAP);
++		if (!fan_nest)
++			goto nla_put_failure;
++		for (i = 0; i < 256; i++) {
++			if (tunnel->fan.map[i]) {
++				struct ip_tunnel_fan_map map;
++
++				map.underlay = htonl(tunnel->fan.map[i]);
++				map.underlay_prefix = 16;
++				map.overlay = htonl(i << 24);
++				map.overlay_prefix = 8;
++				if (nla_put(skb, IFLA_FAN_MAPPING,
++					    sizeof(map), &map))
++					goto nla_put_failure;
++			}
++		}
++		nla_nest_end(skb, fan_nest);
++	}
++
+ 	return 0;
+ 
+ nla_put_failure:
+@@ -483,6 +623,9 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
+ 	[IFLA_IPTUN_ENCAP_FLAGS]	= { .type = NLA_U16 },
+ 	[IFLA_IPTUN_ENCAP_SPORT]	= { .type = NLA_U16 },
+ 	[IFLA_IPTUN_ENCAP_DPORT]	= { .type = NLA_U16 },
++
++	[__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX]	= { .type = NLA_BINARY },
++	[IFLA_IPTUN_FAN_MAP]		= { .type = NLA_NESTED },
+ };
+ 
+ static struct rtnl_link_ops ipip_link_ops __read_mostly = {
+@@ -523,6 +666,23 @@ static struct pernet_operations ipip_net_ops = {
+ 	.size = sizeof(struct ip_tunnel_net),
+ };
+ 
++#ifdef CONFIG_SYSCTL
++static struct ctl_table_header *ipip_fan_header;
++static unsigned int ipip_fan_version = 3;
++
++static struct ctl_table ipip_fan_sysctls[] = {
++	{
++		.procname	= "version",
++		.data		= &ipip_fan_version,
++		.maxlen		= sizeof(ipip_fan_version),
++		.mode		= 0444,
++		.proc_handler	= proc_dointvec,
++	},
++	{},
++};
++
++#endif /* CONFIG_SYSCTL */
++
+ static int __init ipip_init(void)
+ {
+ 	int err;
+@@ -541,9 +701,22 @@ static int __init ipip_init(void)
+ 	if (err < 0)
+ 		goto rtnl_link_failed;
+ 
++#ifdef CONFIG_SYSCTL
++	ipip_fan_header = register_net_sysctl(&init_net, "net/fan",
++					      ipip_fan_sysctls);
++	if (!ipip_fan_header) {
++		err = -ENOMEM;
++		goto sysctl_failed;
++	}
++#endif /* CONFIG_SYSCTL */
++
+ out:
+ 	return err;
+ 
++#ifdef CONFIG_SYSCTL
++sysctl_failed:
++	rtnl_link_unregister(&ipip_link_ops);
++#endif /* CONFIG_SYSCTL */
+ rtnl_link_failed:
+ 	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+ xfrm_tunnel_failed:
+@@ -553,6 +726,9 @@ xfrm_tunnel_failed:
+ 
+ static void __exit ipip_fini(void)
+ {
++#ifdef CONFIG_SYSCTL
++	unregister_net_sysctl_table(ipip_fan_header);
++#endif /* CONFIG_SYSCTL */
+ 	rtnl_link_unregister(&ipip_link_ops);
+ 	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
+ 		pr_info("%s: can't deregister tunnel\n", __func__);
+-- 
+2.7.4
+
+From 14aba409d044e3a314c09c650e1c42de699700b8 Mon Sep 17 00:00:00 2001
+From: Jay Vosburgh <jay.vosburgh@canonical.com>
+Date: Wed, 11 Nov 2015 13:04:50 +0000
+Subject: [PATCH] UBUNTU: SAUCE: fan: add VXLAN implementation
+
+Generify the fan mapping support and utilise that to implement fan
+mappings over vxlan transport.
+
+Expose the existance of this functionality (when the module is loaded)
+via an additional sysctl marker.
+
+Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
+[apw@canonical.com: added feature marker for fan over vxlan.]
+Signed-off-by: Andy Whitcroft <apw@canonical.com>
+---
+ drivers/net/vxlan.c            | 245 +++++++++++++++++++++++++++++++++++++++++
+ include/net/ip_tunnels.h       |  19 +++-
+ include/net/vxlan.h            |   2 +
+ include/uapi/linux/if_link.h   |   1 +
+ include/uapi/linux/if_tunnel.h |   2 +-
+ net/ipv4/ip_tunnel.c           |   7 +-
+ net/ipv4/ipip.c                | 242 +++++++++++++++++++++++++++++++---------
+ 7 files changed, 453 insertions(+), 65 deletions(-)
+
+diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
+index 405a7b6..a17cfd0 100644
+--- a/drivers/net/vxlan.c
++++ b/drivers/net/vxlan.c
+@@ -23,6 +23,7 @@
+ #include <linux/udp.h>
+ #include <linux/igmp.h>
+ #include <linux/etherdevice.h>
++#include <linux/inetdevice.h>
+ #include <linux/if_ether.h>
+ #include <linux/if_vlan.h>
+ #include <linux/hash.h>
+@@ -106,6 +107,167 @@ static inline bool vxlan_collect_metadata(struct vxlan_sock *vs)
+ 	       ip_tunnel_collect_metadata();
+ }
+ 
++static struct ip_fan_map *vxlan_fan_find_map(struct vxlan_dev *vxlan, __be32 daddr)
++{
++	struct ip_fan_map *fan_map;
++
++	rcu_read_lock();
++	list_for_each_entry_rcu(fan_map, &vxlan->fan.fan_maps, list) {
++		if (fan_map->overlay ==
++		    (daddr & inet_make_mask(fan_map->overlay_prefix))) {
++			rcu_read_unlock();
++			return fan_map;
++		}
++	}
++	rcu_read_unlock();
++
++	return NULL;
++}
++
++static void vxlan_fan_flush_map(struct vxlan_dev *vxlan)
++{
++	struct ip_fan_map *fan_map;
++
++	list_for_each_entry_rcu(fan_map, &vxlan->fan.fan_maps, list) {
++		list_del_rcu(&fan_map->list);
++		kfree_rcu(fan_map, rcu);
++	}
++}
++
++static int vxlan_fan_del_map(struct vxlan_dev *vxlan, __be32 overlay)
++{
++	struct ip_fan_map *fan_map;
++
++	fan_map = vxlan_fan_find_map(vxlan, overlay);
++	if (!fan_map)
++		return -ENOENT;
++
++	list_del_rcu(&fan_map->list);
++	kfree_rcu(fan_map, rcu);
++
++	return 0;
++}
++
++static int vxlan_fan_add_map(struct vxlan_dev *vxlan, struct ifla_fan_map *map)
++{
++	__be32 overlay_mask, underlay_mask;
++	struct ip_fan_map *fan_map;
++
++	overlay_mask = inet_make_mask(map->overlay_prefix);
++	underlay_mask = inet_make_mask(map->underlay_prefix);
++
++	netdev_dbg(vxlan->dev, "vfam: map: o %x/%d u %x/%d om %x um %x\n",
++		   map->overlay, map->overlay_prefix,
++		   map->underlay, map->underlay_prefix,
++		   overlay_mask, underlay_mask);
++
++	if ((map->overlay & ~overlay_mask) || (map->underlay & ~underlay_mask))
++		return -EINVAL;
++
++	if (!(map->overlay & overlay_mask) && (map->underlay & underlay_mask))
++		return -EINVAL;
++
++	/* Special case: overlay 0 and underlay 0: flush all mappings */
++	if (!map->overlay && !map->underlay) {
++		vxlan_fan_flush_map(vxlan);
++		return 0;
++	}
++	
++	/* Special case: overlay set and underlay 0: clear map for overlay */
++	if (!map->underlay)
++		return vxlan_fan_del_map(vxlan, map->overlay);
++
++	if (vxlan_fan_find_map(vxlan, map->overlay))
++		return -EEXIST;
++
++	fan_map = kmalloc(sizeof(*fan_map), GFP_KERNEL);
++	fan_map->underlay = map->underlay;
++	fan_map->overlay = map->overlay;
++	fan_map->underlay_prefix = map->underlay_prefix;
++	fan_map->overlay_mask = ntohl(overlay_mask);
++	fan_map->overlay_prefix = map->overlay_prefix;
++
++	list_add_tail_rcu(&fan_map->list, &vxlan->fan.fan_maps);
++
++	return 0;
++}
++	
++static int vxlan_parse_fan_map(struct nlattr *data[], struct vxlan_dev *vxlan)
++{
++	struct ifla_fan_map *map;
++	struct nlattr *attr;
++	int rem, rv;
++
++	nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
++		map = nla_data(attr);
++		rv = vxlan_fan_add_map(vxlan, map);
++		if (rv)
++			return rv;
++	}
++
++	return 0;
++}
++
++static int vxlan_fan_build_rdst(struct vxlan_dev *vxlan, struct sk_buff *skb,
++				      struct vxlan_rdst *fan_rdst)
++{
++	struct ip_fan_map *f_map;
++	union vxlan_addr *va;
++	u32 daddr, underlay;
++	struct arphdr *arp;
++	void *arp_ptr;
++	struct ethhdr *eth;
++	struct iphdr *iph;
++
++	eth = eth_hdr(skb);
++	switch (eth->h_proto) {
++	case htons(ETH_P_IP):
++		iph = ip_hdr(skb);
++		if (!iph)
++			return -EINVAL;
++		daddr = iph->daddr;
++		break;
++	case htons(ETH_P_ARP):
++		arp = arp_hdr(skb);
++		if (!arp)
++			return -EINVAL;
++		arp_ptr = arp + 1;
++		netdev_dbg(vxlan->dev,
++			   "vfbr: arp sha %pM sip %pI4 tha %pM tip %pI4\n",
++			   arp_ptr, arp_ptr + skb->dev->addr_len,
++			   arp_ptr + skb->dev->addr_len + 4,
++			   arp_ptr + (skb->dev->addr_len * 2) + 4);
++		arp_ptr += (skb->dev->addr_len * 2) + 4;
++		memcpy(&daddr, arp_ptr, 4);
++		break;
++	default:
++		netdev_dbg(vxlan->dev, "vfbr: unknown eth p %x\n", eth->h_proto);
++		return -EINVAL;
++	}
++
++	f_map = vxlan_fan_find_map(vxlan, daddr);
++	if (!f_map)
++		return -EINVAL;
++
++	daddr = ntohl(daddr);
++	underlay = ntohl(f_map->underlay);
++	if (!underlay)
++		return -EINVAL;
++
++	memset(fan_rdst, 0, sizeof(*fan_rdst));
++	va = &fan_rdst->remote_ip;
++	va->sa.sa_family = AF_INET;
++	fan_rdst->remote_vni = vxlan->default_dst.remote_vni;
++	va->sin.sin_addr.s_addr = htonl(underlay |
++					((daddr & ~f_map->overlay_mask) >>
++					 (32 - f_map->overlay_prefix -
++					  (32 - f_map->underlay_prefix))));
++	netdev_dbg(vxlan->dev, "vfbr: daddr %x ul %x dst %x\n",
++		   daddr, underlay, va->sin.sin_addr.s_addr);
++
++	return 0;
++}
++
+ #if IS_ENABLED(CONFIG_IPV6)
+ static inline
+ bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b)
+@@ -2029,6 +2191,13 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ 			goto rt_tx_error;
+ 		}
+ 
++		if (fan_has_map(&vxlan->fan) && rt->rt_flags & RTCF_LOCAL) {
++			netdev_dbg(dev, "discard fan to localhost %pI4\n",
++				   &dst->sin.sin_addr.s_addr);
++			ip_rt_put(rt);
++			goto tx_free;
++		}
++
+ 		/* Bypass encapsulation if the destination is local */
+ 		if (rt->rt_flags & RTCF_LOCAL &&
+ 		    !(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
+@@ -2169,6 +2338,20 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		return NETDEV_TX_OK;
+ 	}
+ 
++	if (fan_has_map(&vxlan->fan)) {
++		struct vxlan_rdst fan_rdst;
++
++		netdev_dbg(vxlan->dev, "vxlan_xmit p %x d %pM\n",
++			   eth->h_proto, eth->h_dest);
++		if (vxlan_fan_build_rdst(vxlan, skb, &fan_rdst)) {
++			dev->stats.tx_dropped++;
++			kfree_skb(skb);
++			return NETDEV_TX_OK;
++		}
++		vxlan_xmit_one(skb, dev, &fan_rdst, 0);
++		return NETDEV_TX_OK;
++	}
++
+ 	f = vxlan_find_mac(vxlan, eth->h_dest);
+ 	did_rsc = false;
+ 
+@@ -2532,6 +2715,8 @@ static void vxlan_setup(struct net_device *dev)
+ 
+ 	for (h = 0; h < FDB_HASH_SIZE; ++h)
+ 		INIT_HLIST_HEAD(&vxlan->fdb_head[h]);
++
++	INIT_LIST_HEAD(&vxlan->fan.fan_maps);
+ }
+ 
+ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
+@@ -2881,6 +3066,7 @@ EXPORT_SYMBOL_GPL(vxlan_dev_create);
+ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
+ 			 struct nlattr *tb[], struct nlattr *data[])
+ {
++	struct vxlan_dev *vxlan = netdev_priv(dev);
+ 	struct vxlan_config conf;
+ 	int err;
+ 
+@@ -2899,6 +3085,12 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
+ 		conf.remote_ip.sa.sa_family = AF_INET6;
+ 	}
+ 
++	if (data[IFLA_VXLAN_FAN_MAP]) {
++		err = vxlan_parse_fan_map(data, vxlan);
++		if (err)
++			return err;
++	}
++
+ 	if (data[IFLA_VXLAN_LOCAL]) {
+ 		conf.saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]);
+ 		conf.saddr.sa.sa_family = AF_INET;
+@@ -3037,6 +3229,7 @@ static size_t vxlan_get_size(const struct net_device *dev)
+ 		nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */
+ 		nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_TX */
+ 		nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */
++		nla_total_size(sizeof(struct ip_fan_map) * 256) +
+ 		0;
+ }
+ 
+@@ -3083,6 +3276,26 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
+ 		}
+ 	}
+ 
++	if (fan_has_map(&vxlan->fan)) {
++		struct nlattr *fan_nest;
++		struct ip_fan_map *fan_map;
++
++		fan_nest = nla_nest_start(skb, IFLA_VXLAN_FAN_MAP);
++		if (!fan_nest)
++			goto nla_put_failure;
++		list_for_each_entry_rcu(fan_map, &vxlan->fan.fan_maps, list) {
++			struct ifla_fan_map map;
++
++			map.underlay = fan_map->underlay;
++			map.underlay_prefix = fan_map->underlay_prefix;
++			map.overlay = fan_map->overlay;
++			map.overlay_prefix = fan_map->overlay_prefix;
++			if (nla_put(skb, IFLA_FAN_MAPPING, sizeof(map), &map))
++				goto nla_put_failure;
++		}
++		nla_nest_end(skb, fan_nest);
++	}
++
+ 	if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->cfg.ttl) ||
+ 	    nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->cfg.tos) ||
+ 	    nla_put_u8(skb, IFLA_VXLAN_LEARNING,
+@@ -3201,6 +3414,22 @@ static __net_init int vxlan_init_net(struct net *net)
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_SYSCTL
++static struct ctl_table_header *vxlan_fan_header;
++static unsigned int vxlan_fan_version = 4;
++
++static struct ctl_table vxlan_fan_sysctls[] = {
++	{
++		.procname	= "vxlan",
++		.data		= &vxlan_fan_version,
++		.maxlen		= sizeof(vxlan_fan_version),
++		.mode		= 0444,
++		.proc_handler	= proc_dointvec,
++	},
++	{},
++};
++#endif /* CONFIG_SYSCTL */
++
+ static void __net_exit vxlan_exit_net(struct net *net)
+ {
+ 	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+@@ -3256,7 +3485,20 @@ static int __init vxlan_init_module(void)
+ 	if (rc)
+ 		goto out3;
+ 
++#ifdef CONFIG_SYSCTL
++	vxlan_fan_header = register_net_sysctl(&init_net, "net/fan",
++					      vxlan_fan_sysctls);
++	if (!vxlan_fan_header) {
++		rc = -ENOMEM;
++		goto sysctl_failed;
++	}
++#endif /* CONFIG_SYSCTL */
++
+ 	return 0;
++#ifdef CONFIG_SYSCTL
++sysctl_failed:
++	rtnl_link_unregister(&vxlan_link_ops);
++#endif /* CONFIG_SYSCTL */
+ out3:
+ 	unregister_netdevice_notifier(&vxlan_notifier_block);
+ out2:
+@@ -3269,6 +3511,9 @@ late_initcall(vxlan_init_module);
+ 
+ static void __exit vxlan_cleanup_module(void)
+ {
++#ifdef CONFIG_SYSCTL
++	unregister_net_sysctl_table(vxlan_fan_header);
++#endif /* CONFIG_SYSCTL */
+ 	rtnl_link_unregister(&vxlan_link_ops);
+ 	unregister_netdevice_notifier(&vxlan_notifier_block);
+ 	destroy_workqueue(vxlan_wq);
+diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
+index 47fec59..28a38e5 100644
+--- a/include/net/ip_tunnels.h
++++ b/include/net/ip_tunnels.h
+@@ -100,9 +100,18 @@ struct metadata_dst;
+  */
+ #define FAN_OVERLAY_CNT		256
+ 
++struct ip_fan_map {
++	__be32			underlay;
++	__be32			overlay;
++	u16			underlay_prefix;
++	u16			overlay_prefix;
++	u32			overlay_mask;
++	struct list_head	list;
++	struct rcu_head		rcu;
++};
++
+ struct ip_tunnel_fan {
+-/*	u32 __rcu	*map;*/
+-	u32		map[FAN_OVERLAY_CNT];
++	struct list_head	fan_maps;
+ };
+ 
+ struct ip_tunnel {
+@@ -157,7 +166,11 @@ struct ip_tunnel {
+ #define TUNNEL_VXLAN_OPT	__cpu_to_be16(0x1000)
+ 
+ #define TUNNEL_OPTIONS_PRESENT	(TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT)
+-#define TUNNEL_FAN		__cpu_to_be16(0x4000)
++
++static inline int fan_has_map(const struct ip_tunnel_fan *fan)
++{
++	return !list_empty(&fan->fan_maps);
++}
+ 
+ struct tnl_ptk_info {
+ 	__be16 flags;
+diff --git a/include/net/vxlan.h b/include/net/vxlan.h
+index e289ada..542f421 100644
+--- a/include/net/vxlan.h
++++ b/include/net/vxlan.h
+@@ -161,6 +161,8 @@ struct vxlan_dev {
+ 	struct vxlan_rdst default_dst;	/* default destination */
+ 	u32		  flags;	/* VXLAN_F_* in vxlan.h */
+ 
++	struct ip_tunnel_fan fan;
++
+ 	struct timer_list age_timer;
+ 	spinlock_t	  hash_lock;
+ 	unsigned int	  addrcnt;
+diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
+index 5ad5737..6cde3bf 100644
+--- a/include/uapi/linux/if_link.h
++++ b/include/uapi/linux/if_link.h
+@@ -443,6 +443,7 @@ enum {
+ 	IFLA_VXLAN_GBP,
+ 	IFLA_VXLAN_REMCSUM_NOPARTIAL,
+ 	IFLA_VXLAN_COLLECT_METADATA,
++	IFLA_VXLAN_FAN_MAP = 33,
+ 	__IFLA_VXLAN_MAX
+ };
+ #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
+diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
+index 85a3e4b..d36b150 100644
+--- a/include/uapi/linux/if_tunnel.h
++++ b/include/uapi/linux/if_tunnel.h
+@@ -145,7 +145,7 @@ enum {
+ 
+ #define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
+ 
+-struct ip_tunnel_fan_map {
++struct ifla_fan_map {
+ 	__be32		underlay;
+ 	__be32		overlay;
+ 	__u16		underlay_prefix;
+diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
+index 7a6174b..c821bf1 100644
+--- a/net/ipv4/ip_tunnel.c
++++ b/net/ipv4/ip_tunnel.c
+@@ -1110,11 +1110,6 @@ out:
+ }
+ EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
+ 
+-static int ip_tunnel_is_fan(struct ip_tunnel *tunnel)
+-{
+-	return tunnel->parms.i_flags & TUNNEL_FAN;
+-}
+-
+ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
+ 			 struct ip_tunnel_parm *p)
+ {
+@@ -1124,7 +1119,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
+ 	struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
+ 
+ 	if (dev == itn->fb_tunnel_dev)
+-		return ip_tunnel_is_fan(tunnel) ? 0 : -EINVAL;
++		return fan_has_map(&tunnel->fan) ? 0 : -EINVAL;
+ 
+ 	t = ip_tunnel_find(itn, p, dev->type);
+ 
+diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
+index 56e8984..3877b0e 100644
+--- a/net/ipv4/ipip.c
++++ b/net/ipv4/ipip.c
+@@ -108,6 +108,7 @@
+ #include <linux/netfilter_ipv4.h>
+ #include <linux/if_ether.h>
+ #include <linux/inetdevice.h>
++#include <linux/rculist.h>
+ 
+ #include <net/sock.h>
+ #include <net/ip.h>
+@@ -209,37 +210,144 @@ drop:
+ 	return 0;
+ }
+ 
+-static int ipip_tunnel_is_fan(struct ip_tunnel *tunnel)
++static struct ip_fan_map *ipip_fan_find_map(struct ip_tunnel *t, __be32 daddr)
+ {
+-	return tunnel->parms.i_flags & TUNNEL_FAN;
++	struct ip_fan_map *fan_map;
++
++	rcu_read_lock();
++	list_for_each_entry_rcu(fan_map, &t->fan.fan_maps, list) {
++		if (fan_map->overlay ==
++		    (daddr & inet_make_mask(fan_map->overlay_prefix))) {
++			rcu_read_unlock();
++			return fan_map;
++		}
++	}
++	rcu_read_unlock();
++
++	return NULL;
+ }
+ 
+-/*
+- * Determine fan tunnel endpoint to send packet to, based on the inner IP
+- * address.  For an overlay (inner) address Y.A.B.C, the transformation is
+- * F.G.A.B, where "F" and "G" are the first two octets of the underlay
+- * network (the network portion of a /16), "A" and "B" are the low order
+- * two octets of the underlay network host (the host portion of a /16),
+- * and "Y" is a configured first octet of the overlay network.
++/* Determine fan tunnel endpoint to send packet to, based on the inner IP
++ * address.  
++ *
++ * Given a /8 overlay and /16 underlay, for an overlay (inner) address
++ * Y.A.B.C, the transformation is F.G.A.B, where "F" and "G" are the first
++ * two octets of the underlay network (the network portion of a /16), "A"
++ * and "B" are the low order two octets of the underlay network host (the
++ * host portion of a /16), and "Y" is a configured first octet of the
++ * overlay network.
++ *
++ * E.g., underlay host 10.88.3.4/16 with an overlay of 99.0.0.0/8 would
++ * host overlay subnet 99.3.4.0/24.  An overlay network datagram from
++ * 99.3.4.5 to 99.6.7.8, would be directed to underlay host 10.88.6.7,
++ * which hosts overlay network subnet 99.6.7.0/24.  This transformation is
++ * described in detail further below.
++ *
++ * Using netmasks for the overlay and underlay other than /8 and /16, as
++ * shown above, can yield larger (or smaller) overlay subnets, with the
++ * trade-off of allowing fewer (or more) underlay hosts to participate.
++ *
++ * The size of each overlay network subnet is defined by the total of the
++ * network mask of the overlay plus the size of host portion of the
++ * underlay network. In the above example, /8 + /16 = /24.
++ *
++ * E.g., consider underlay host 10.99.238.5/20 and overlay 99.0.0.0/8. In
++ * this case, the network portion of the underlay is 10.99.224.0/20, and
++ * the host portion is 0.0.14.5 (12 bits).  To determine the overlay
++ * network subnet, the 12 bits of host portion are left shifted 12 bits
++ * (/20 - /8) and ORed with the overlay subnet prefix.  This yields an
++ * overlay subnet of 99.224.80/20, composed of 8 bits overlay, followed by
++ * 12 bits underlay.  This yields 12 bits in the overlay network portion,
++ * allowing for 4094 addresses in each overlay network subnet.  The
++ * trade-off is that fewer hosts may participate in the underlay network,
++ * as its host address size has shrunk from 16 bits (65534 addresses) in
++ * the first example to 12 bits (4094 addresses) here.
++ *
++ * For fewer hosts per overlay subnet (permitting a larger number of
++ * underlay hosts to participate), the underlay netmask may be made
++ * smaller.
++ *
++ * E.g., underlay host 10.111.1.2/12 (network 10.96.0.0/12, host portion
++ * is 0.15.1.2, 20 bits) with an overlay of 33.0.0.0/8 would left shift
++ * the 20 bits of host by 4 (so that it's highest order bit is adjacent to
++ * the lowest order bit of the /8 overlay).  This yields an overlay subnet
++ * of 33.240.16.32/28 (8 bits overlay, 20 bits from the host portion of
++ * the underlay).  This provides more addresses for the underlay network
++ * (approximately 2^20), but each host's segment of the overlay provides
++ * only 4 bits of addresses (14 usable).
++ *
++ * It is also possible to adjust the overlay subnet.
++ *
++ * For an overlay of 240.0.0.0/5 and underlay of 10.88.0.0/20, consider
++ * underlay host 10.88.129.2; the 12 bits of host, 0.0.1.2, are left
++ * shifted 15 bits (/20 - /5), yielding an overlay network of
++ * 240.129.0.0/17.  An underlay host of 10.88.244.215 would yield an
++ * overlay network of 242.107.128.0/17.
++ *
++ * For an overlay of 100.64.0.0/10 and underlay of 10.224.220.0/24, for
++ * underlay host 10.224.220.10, the underlay host portion (.10) is left
++ * shifted 14 bits, yielding an overlay network subnet of 100.66.128.0/18.
++ * This would permit 254 addresses on the underlay, with each overlay
++ * segment providing approximately 2^14 - 2 addresses (16382).
++ *
++ * For packets being encapsulated, the overlay network destination IP
++ * address is deconstructed into its overlay and underlay-derived
++ * portions.  The underlay portion (determined by the overlay mask and
++ * overlay subnet mask) is right shifted according to the size of the
++ * underlay network mask.  This value is then ORed with the network
++ * portion of the underlay network to produce the underlay network
++ * destination for the encapsulated datagram.
++ *
++ * For example, using the initial example of underlay 10.88.3.4/16 and
++ * overlay 99.0.0.0/8, with underlay host 10.88.3.4/16 providing overlay
++ * subnet 99.3.4.0/24 with specfic host 99.3.4.5.  A datagram from
++ * 99.3.4.5 to 99.6.7.8 would first have the underlay host derived portion
++ * of the address extracted.  This is a number of bits equal to underlay
++ * network host portion.  In the destination address, the highest order of
++ * these bits is one bit lower than the lowest order bit from the overlay
++ * network mask.
++ *
++ * Using the sample value, 99.6.7.8, the overlay mask is /8, and the
++ * underlay mask is /16 (leaving 16 bits for the host portion).  The bits
++ * to be shifted are the middle two octets, 0.6.7.0, as this is 99.6.7.8
++ * ANDed with the mask 0x00ffff00 (which is 16 bits, the highest order of
++ * which is 1 bit lower than the lowest order overlay address bit).
+  *
+- * E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
+- * subnet 99.3.4.0/24.  An overlay network datagram from 99.3.4.5 to
+- * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
+- * overlay network 99.6.7.0/24.
++ * These octets, 0.6.7.0, are then right shifted 8 bits, yielding 0.0.6.7.
++ * This value is then ORed with the underlay network portion,
++ * 10.88.0.0/16, providing 10.88.6.7 as the final underlay destination for
++ * the encapuslated datagram.
++ *
++ * Another transform using the final example: overlay 100.64.0.0/10 and
++ * underlay 10.224.220.0/24.  Consider overlay address 100.66.128.1
++ * sending a datagram to 100.66.200.5.  In this case, 8 bits (the host
++ * portion size of 10.224.220.0/24) beginning after the 100.64/10 overlay
++ * prefix are masked off, yielding 0.2.192.0.  This is right shifted 14
++ * (32 - 10 - (32 - 24), i.e., the number of bits between the overlay
++ * network portion and the underlay host portion) bits, yielding 0.0.0.11.
++ * This is ORed with the underlay network portion, 10.224.220.0/24, giving
++ * the underlay destination of 10.224.220.11 for overlay destination
++ * 100.66.200.5.
+  */
+ static int ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
+ {
+-	unsigned int overlay;
++	struct ip_fan_map *f_map;
+ 	u32 daddr, underlay;
+ 
++	f_map = ipip_fan_find_map(tunnel, ip_hdr(skb)->daddr);
++	if (!f_map)
++		return -ENOENT;
++
+ 	daddr = ntohl(ip_hdr(skb)->daddr);
+-	overlay = daddr >> 24;
+-	underlay = tunnel->fan.map[overlay];
++	underlay = ntohl(f_map->underlay);
+ 	if (!underlay)
+ 		return -EINVAL;
+ 
+ 	*iph = tunnel->parms.iph;
+-	iph->daddr = htonl(underlay | ((daddr >> 8) & 0x0000ffff));
++	iph->daddr = htonl(underlay |
++			   ((daddr & ~f_map->overlay_mask) >>
++			    (32 - f_map->overlay_prefix -
++			     (32 - f_map->underlay_prefix))));
+ 	return 0;
+ }
+ 
+@@ -260,7 +368,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	if (IS_ERR(skb))
+ 		goto out;
+ 
+-	if (ipip_tunnel_is_fan(tunnel)) {
++	if (fan_has_map(&tunnel->fan)) {
+ 		if (ipip_build_fan_iphdr(tunnel, skb, &fiph))
+ 			goto tx_error;
+ 		tiph = &fiph;
+@@ -325,6 +433,8 @@ static const struct net_device_ops ipip_netdev_ops = {
+ 
+ static void ipip_tunnel_setup(struct net_device *dev)
+ {
++	struct ip_tunnel *t = netdev_priv(dev);
++
+ 	dev->netdev_ops		= &ipip_netdev_ops;
+ 
+ 	dev->type		= ARPHRD_TUNNEL;
+@@ -336,6 +446,7 @@ static void ipip_tunnel_setup(struct net_device *dev)
+ 	dev->features		|= IPIP_FEATURES;
+ 	dev->hw_features	|= IPIP_FEATURES;
+ 	ip_tunnel_setup(dev, ipip_net_id);
++	INIT_LIST_HEAD(&t->fan.fan_maps);
+ }
+ 
+ static int ipip_tunnel_init(struct net_device *dev)
+@@ -419,41 +530,65 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
+ 	return ret;
+ }
+ 
+-static void ipip_fan_free_map(struct ip_tunnel *t)
++static void ipip_fan_flush_map(struct ip_tunnel *t)
+ {
+-	memset(&t->fan.map, 0, sizeof(t->fan.map));
++	struct ip_fan_map *fan_map;
++
++	list_for_each_entry_rcu(fan_map, &t->fan.fan_maps, list) {
++		list_del_rcu(&fan_map->list);
++		kfree_rcu(fan_map, rcu);
++	}
+ }
+ 
+-static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
++static int ipip_fan_del_map(struct ip_tunnel *t, __be32 overlay)
+ {
+-	u32 overlay, overlay_mask, underlay, underlay_mask;
++	struct ip_fan_map *fan_map;
+ 
+-	if ((map->underlay_prefix && map->underlay_prefix != 16) ||
+-	    (map->overlay_prefix && map->overlay_prefix != 8))
+-		return -EINVAL;
++	fan_map = ipip_fan_find_map(t, overlay);
++	if (!fan_map)
++		return -ENOENT;
++
++	list_del_rcu(&fan_map->list);
++	kfree_rcu(fan_map, rcu);
+ 
+-	overlay = ntohl(map->overlay);
+-	overlay_mask = ntohl(inet_make_mask(map->overlay_prefix));
++	return 0;
++}
+ 
+-	underlay = ntohl(map->underlay);
+-	underlay_mask = ntohl(inet_make_mask(map->underlay_prefix));
++static int ipip_fan_add_map(struct ip_tunnel *t, struct ifla_fan_map *map)
++{
++	__be32 overlay_mask, underlay_mask;
++	struct ip_fan_map *fan_map;
+ 
+-	if ((overlay & ~overlay_mask) || (underlay & ~underlay_mask))
+-		return -EINVAL;
++	overlay_mask = inet_make_mask(map->overlay_prefix);
++	underlay_mask = inet_make_mask(map->underlay_prefix);
+ 
+-	if (!(overlay & overlay_mask) && (underlay & underlay_mask))
++	if ((map->overlay & ~overlay_mask) || (map->underlay & ~underlay_mask))
+ 		return -EINVAL;
+ 
+-	t->parms.i_flags |= TUNNEL_FAN;
++	if (!(map->overlay & overlay_mask) && (map->underlay & underlay_mask))
++		return -EINVAL;
+ 
+-	/* Special case: overlay 0 and underlay 0 clears all mappings */
+-	if (!overlay && !underlay) {
+-		ipip_fan_free_map(t);
++	/* Special case: overlay 0 and underlay 0: flush all mappings */
++	if (!map->overlay && !map->underlay) {
++		ipip_fan_flush_map(t);
+ 		return 0;
+ 	}
++	
++	/* Special case: overlay set and underlay 0: clear map for overlay */
++	if (!map->underlay)
++		return ipip_fan_del_map(t, map->overlay);
++
++	if (ipip_fan_find_map(t, map->overlay))
++		return -EEXIST;
++
++	fan_map = kmalloc(sizeof(*fan_map), GFP_KERNEL);
++	fan_map->underlay = map->underlay;
++	fan_map->overlay = map->overlay;
++	fan_map->underlay_prefix = map->underlay_prefix;
++	fan_map->overlay_mask = ntohl(overlay_mask);
++	fan_map->overlay_prefix = map->overlay_prefix;
+ 
+-	overlay >>= (32 - map->overlay_prefix);
+-	t->fan.map[overlay] = underlay;
++	list_add_tail_rcu(&fan_map->list, &t->fan.fan_maps);
+ 
+ 	return 0;
+ }
+@@ -462,7 +597,7 @@ static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
+ static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
+ 			    struct ip_tunnel_parm *parms)
+ {
+-	struct ip_tunnel_fan_map *map;
++	struct ifla_fan_map *map;
+ 	struct nlattr *attr;
+ 	int rem, rv;
+ 
+@@ -474,7 +609,7 @@ static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
+ 
+ 	nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
+ 		map = nla_data(attr);
+-		rv = ipip_fan_set_map(t, map);
++		rv = ipip_fan_add_map(t, map);
+ 		if (rv)
+ 			return rv;
+ 	}
+@@ -555,7 +690,7 @@ static size_t ipip_get_size(const struct net_device *dev)
+ 		/* IFLA_IPTUN_ENCAP_DPORT */
+ 		nla_total_size(2) +
+ 		/* IFLA_IPTUN_FAN_MAP */
+-		nla_total_size(sizeof(struct ip_tunnel_fan_map)) * 256 +
++		nla_total_size(sizeof(struct ifla_fan_map)) * 256 +
+ 		0;
+ }
+ 
+@@ -583,25 +718,22 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
+ 			tunnel->encap.flags))
+ 		goto nla_put_failure;
+ 
+-	if (tunnel->parms.i_flags & TUNNEL_FAN) {
++	if (fan_has_map(&tunnel->fan)) {
+ 		struct nlattr *fan_nest;
+-		int i;
++		struct ip_fan_map *fan_map;
+ 
+ 		fan_nest = nla_nest_start(skb, IFLA_IPTUN_FAN_MAP);
+ 		if (!fan_nest)
+ 			goto nla_put_failure;
+-		for (i = 0; i < 256; i++) {
+-			if (tunnel->fan.map[i]) {
+-				struct ip_tunnel_fan_map map;
+-
+-				map.underlay = htonl(tunnel->fan.map[i]);
+-				map.underlay_prefix = 16;
+-				map.overlay = htonl(i << 24);
+-				map.overlay_prefix = 8;
+-				if (nla_put(skb, IFLA_FAN_MAPPING,
+-					    sizeof(map), &map))
+-					goto nla_put_failure;
+-			}
++		list_for_each_entry_rcu(fan_map, &tunnel->fan.fan_maps, list) {
++			struct ifla_fan_map map;
++
++			map.underlay = fan_map->underlay;
++			map.underlay_prefix = fan_map->underlay_prefix;
++			map.overlay = fan_map->overlay;
++			map.overlay_prefix = fan_map->overlay_prefix;
++			if (nla_put(skb, IFLA_FAN_MAPPING, sizeof(map), &map))
++				goto nla_put_failure;
+ 		}
+ 		nla_nest_end(skb, fan_nest);
+ 	}
+-- 
+2.7.4
+
diff --git a/pkgs/os-specific/linux/kernel/ubuntu-fan-4.patch b/pkgs/os-specific/linux/kernel/ubuntu-fan-4.patch
deleted file mode 100644
index 0050af6c2527..000000000000
--- a/pkgs/os-specific/linux/kernel/ubuntu-fan-4.patch
+++ /dev/null
@@ -1,616 +0,0 @@
-From f3c956096902669c3529cb01d40deb0c759ed94f Mon Sep 17 00:00:00 2001
-From: Jay Vosburgh <jay.vosburgh@canonical.com>
-Date: Wed, 1 Apr 2015 16:11:09 -0700
-Subject: [PATCH] UBUNTU: SAUCE: fan: Proof of concept implementation (v2)
-
-Modification to ipip tunnel driver to accept a new netlink option,
-IFLA_IPTUN_FAN_UNDERLAY, which provides a /16 network prefix and enables
-TX side destination address remapping for traffic entering the tunnel
-(to be encapsulated).
-
-For an overlay (inner) address Y.A.B.C, the transformation is F.G.A.B,
-where "F" and "G" are the first two octets of the underlay network (the
-network portion of a /16), "A" and "B" are the low order two octets of the
-underlay network host (the host portion of a /16), and "Y" is a configured
-first octet of the overlay network.
-
-E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
-subnet 99.3.4.0/24.  An overlay network datagram from 99.3.4.5 to 99.6.7.8
-would be directed to underlay host 10.88.6.7, which hosts overlay network
-99.6.7.0/24.
-
-Includes net.fan.version sysctl as a sentinel for availability of the
-fan functionality.
-
-NOTE: this requires an updated iproute2 to facilitate configuration of
-the fan.
-
-BugLink: http://bugs.launchpad.net/bugs/1439706
-Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
-[apw@canonical.com: move IFLA_IPTUN_FAN_UNDERLAY up to avoid clashing
- with future feature additions.]
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
----
- include/net/ip_tunnels.h       |   6 +++
- include/uapi/linux/if_tunnel.h |   4 ++
- net/ipv4/ipip.c                | 112 +++++++++++++++++++++++++++++++++++++++--
- 3 files changed, 117 insertions(+), 5 deletions(-)
-
-diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
-index 25a59eb..d7eada2 100644
---- a/include/net/ip_tunnels.h
-+++ b/include/net/ip_tunnels.h
-@@ -51,6 +51,11 @@ struct ip_tunnel_dst {
- 	__be32				 saddr;
- };
- 
-+/* Underlay address prefix for ipip fan mode */
-+struct ip_tunnel_fan {
-+	u32			underlay;
-+};
-+
- struct ip_tunnel {
- 	struct ip_tunnel __rcu	*next;
- 	struct hlist_node hash_node;
-@@ -82,6 +87,7 @@ struct ip_tunnel {
- #endif
- 	struct ip_tunnel_prl_entry __rcu *prl;	/* potential router list */
- 	unsigned int		prl_count;	/* # of entries in PRL */
-+	struct ip_tunnel_fan	fan;
- 	int			ip_tnl_net_id;
- 	struct gro_cells	gro_cells;
- };
-diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
-index bd3cc11..8f7d269 100644
---- a/include/uapi/linux/if_tunnel.h
-+++ b/include/uapi/linux/if_tunnel.h
-@@ -57,6 +57,10 @@ enum {
- 	IFLA_IPTUN_ENCAP_FLAGS,
- 	IFLA_IPTUN_ENCAP_SPORT,
- 	IFLA_IPTUN_ENCAP_DPORT,
-+
-+	__IFLA_IPTUN_VENDOR_BREAK,		/* Ensure new entries do not hit the below. */
-+	IFLA_IPTUN_FAN_UNDERLAY=32,
-+
- 	__IFLA_IPTUN_MAX,
- };
- #define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
-diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
-index 40403114..e3c27cd 100644
---- a/net/ipv4/ipip.c
-+++ b/net/ipv4/ipip.c
-@@ -209,13 +209,38 @@ drop:
- }
- 
- /*
-+ * Determine fan tunnel endpoint to send packet to, based on the inner IP
-+ * address.  For an overlay (inner) address Y.A.B.C, the transformation is
-+ * F.G.A.B, where "F" and "G" are the first two octets of the underlay
-+ * network (the network portion of a /16), "A" and "B" are the low order
-+ * two octets of the underlay network host (the host portion of a /16),
-+ * and "Y" is a configured first octet of the overlay network.
-+ *
-+ * E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
-+ * subnet 99.3.4.0/24.  An overlay network datagram from 99.3.4.5 to
-+ * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
-+ * overlay network 99.6.7.0/24.
-+ */
-+static void ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
-+{
-+	u32 daddr;
-+
-+	*iph = tunnel->parms.iph;
-+
-+	daddr = ntohl(ip_hdr(skb)->daddr);
-+	iph->daddr = htonl((tunnel->fan.underlay & 0xffff0000) |
-+			   ((daddr >> 8) & 0x0000ffff));
-+}
-+
-+/*
-  *	This function assumes it is being called from dev_queue_xmit()
-  *	and that skb is filled properly by that function.
-  */
- static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
- {
- 	struct ip_tunnel *tunnel = netdev_priv(dev);
--	const struct iphdr  *tiph = &tunnel->parms.iph;
-+	const struct iphdr *tiph;
-+	struct iphdr fiph;
- 
- 	if (unlikely(skb->protocol != htons(ETH_P_IP)))
- 		goto tx_error;
-@@ -224,6 +249,13 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
- 	if (IS_ERR(skb))
- 		goto out;
- 
-+	if (tunnel->fan.underlay) {
-+		ipip_build_fan_iphdr(tunnel, skb, &fiph);
-+		tiph = &fiph;
-+	} else {
-+		tiph = &tunnel->parms.iph;
-+	}
-+
- 	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
- 
- 	ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
-@@ -377,21 +409,44 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
- 	return ret;
- }
- 
-+static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
-+			    struct ip_tunnel_parm *parms)
-+{
-+	u32 net = t->fan.underlay;
-+
-+	if (!data[IFLA_IPTUN_FAN_UNDERLAY])
-+		goto err_check;
-+
-+	net = ntohl(nla_get_be32(data[IFLA_IPTUN_FAN_UNDERLAY])) & 0xffff0000;
-+
-+err_check:
-+	if (parms->iph.daddr && net)
-+		return -EINVAL;
-+
-+	t->fan.underlay = net;
-+
-+	return 0;
-+}
-+
- static int ipip_newlink(struct net *src_net, struct net_device *dev,
- 			struct nlattr *tb[], struct nlattr *data[])
- {
- 	struct ip_tunnel_parm p;
- 	struct ip_tunnel_encap ipencap;
-+	struct ip_tunnel *t = netdev_priv(dev);
-+	int err;
- 
- 	if (ipip_netlink_encap_parms(data, &ipencap)) {
--		struct ip_tunnel *t = netdev_priv(dev);
--		int err = ip_tunnel_encap_setup(t, &ipencap);
-+		err = ip_tunnel_encap_setup(t, &ipencap);
- 
- 		if (err < 0)
- 			return err;
- 	}
- 
- 	ipip_netlink_parms(data, &p);
-+	err = ipip_netlink_fan(data, t, &p);
-+	if (err < 0)
-+		return err;
- 	return ip_tunnel_newlink(dev, tb, &p);
- }
- 
-@@ -400,16 +455,20 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
- {
- 	struct ip_tunnel_parm p;
- 	struct ip_tunnel_encap ipencap;
-+	struct ip_tunnel *t = netdev_priv(dev);
-+	int err;
- 
- 	if (ipip_netlink_encap_parms(data, &ipencap)) {
--		struct ip_tunnel *t = netdev_priv(dev);
--		int err = ip_tunnel_encap_setup(t, &ipencap);
-+		err = ip_tunnel_encap_setup(t, &ipencap);
- 
- 		if (err < 0)
- 			return err;
- 	}
- 
- 	ipip_netlink_parms(data, &p);
-+	err = ipip_netlink_fan(data, t, &p);
-+	if (err < 0)
-+		return err;
- 
- 	if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
- 	    (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
-@@ -441,6 +500,8 @@ static size_t ipip_get_size(const struct net_device *dev)
- 		nla_total_size(2) +
- 		/* IFLA_IPTUN_ENCAP_DPORT */
- 		nla_total_size(2) +
-+		/* IFLA_IPTUN_FAN_UNDERLAY */
-+		nla_total_size(4) +
- 		0;
- }
- 
-@@ -468,6 +529,11 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
- 			tunnel->encap.flags))
- 		goto nla_put_failure;
- 
-+	if (tunnel->fan.underlay)
-+		if (nla_put_be32(skb, IFLA_IPTUN_FAN_UNDERLAY,
-+				 htonl(tunnel->fan.underlay)))
-+			goto nla_put_failure;
-+
- 	return 0;
- 
- nla_put_failure:
-@@ -485,6 +551,9 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
- 	[IFLA_IPTUN_ENCAP_FLAGS]	= { .type = NLA_U16 },
- 	[IFLA_IPTUN_ENCAP_SPORT]	= { .type = NLA_U16 },
- 	[IFLA_IPTUN_ENCAP_DPORT]	= { .type = NLA_U16 },
-+
-+	[__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX]	= { .type = NLA_BINARY },
-+	[IFLA_IPTUN_FAN_UNDERLAY]	= { .type = NLA_U32 },
- };
- 
- static struct rtnl_link_ops ipip_link_ops __read_mostly = {
-@@ -524,6 +593,23 @@ static struct pernet_operations ipip_net_ops = {
- 	.size = sizeof(struct ip_tunnel_net),
- };
- 
-+#ifdef CONFIG_SYSCTL
-+static struct ctl_table_header *ipip_fan_header;
-+static unsigned int ipip_fan_version = 1;
-+
-+static struct ctl_table ipip_fan_sysctls[] = {
-+	{
-+		.procname	= "version",
-+		.data		= &ipip_fan_version,
-+		.maxlen		= sizeof(ipip_fan_version),
-+		.mode		= 0444,
-+		.proc_handler	= proc_dointvec,
-+	},
-+	{},
-+};
-+
-+#endif /* CONFIG_SYSCTL */
-+
- static int __init ipip_init(void)
- {
- 	int err;
-@@ -542,9 +628,22 @@ static int __init ipip_init(void)
- 	if (err < 0)
- 		goto rtnl_link_failed;
- 
-+#ifdef CONFIG_SYSCTL
-+	ipip_fan_header = register_net_sysctl(&init_net, "net/fan",
-+					      ipip_fan_sysctls);
-+	if (!ipip_fan_header) {
-+		err = -ENOMEM;
-+		goto sysctl_failed;
-+	}
-+#endif /* CONFIG_SYSCTL */
-+
- out:
- 	return err;
- 
-+#ifdef CONFIG_SYSCTL
-+sysctl_failed:
-+	rtnl_link_unregister(&ipip_link_ops);
-+#endif /* CONFIG_SYSCTL */
- rtnl_link_failed:
- 	xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
- xfrm_tunnel_failed:
-@@ -554,6 +653,9 @@ xfrm_tunnel_failed:
- 
- static void __exit ipip_fini(void)
- {
-+#ifdef CONFIG_SYSCTL
-+	unregister_net_sysctl_table(ipip_fan_header);
-+#endif /* CONFIG_SYSCTL */
- 	rtnl_link_unregister(&ipip_link_ops);
- 	if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
- 		pr_info("%s: can't deregister tunnel\n", __func__);
--- 
-2.4.1
-
-From 4ea8011656dfdd76e7a2391bdad47c06f85a9d02 Mon Sep 17 00:00:00 2001
-From: Andy Whitcroft <apw@canonical.com>
-Date: Tue, 21 Jul 2015 16:52:10 +0100
-Subject: [PATCH] UBUNTU: SAUCE: fan: tunnel multiple mapping mode (v3)
-
-Switch to a single tunnel for all mappings, this removes the limitations
-on how many mappings each tunnel can handle, and therefore how many Fan
-slices each local address may hold.
-
-NOTE: This introduces a new kernel netlink interface which needs updated
-iproute2 support.
-
-BugLink: http://bugs.launchpad.net/bugs/1470091
-Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
-Signed-off-by: Andy Whitcroft <apw@canonical.com>
-Acked-by: Tim Gardner <tim.gardner@canonical.com>
-Acked-by: Brad Figg <brad.figg@canonical.com>
-Signed-off-by: Brad Figg <brad.figg@canonical.com>
----
- include/net/ip_tunnels.h       |  14 ++++-
- include/uapi/linux/if_tunnel.h |  20 ++++++-
- net/ipv4/ip_tunnel.c           |   7 ++-
- net/ipv4/ipip.c                | 120 +++++++++++++++++++++++++++++++++--------
- 4 files changed, 133 insertions(+), 28 deletions(-)
-
-diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
-index d7eada2..2f7bc8c 100644
---- a/include/net/ip_tunnels.h
-+++ b/include/net/ip_tunnels.h
-@@ -51,9 +51,18 @@ struct ip_tunnel_dst {
- 	__be32				 saddr;
- };
- 
--/* Underlay address prefix for ipip fan mode */
-+/* A fan overlay /8 (250.0.0.0/8, for example) maps to exactly one /16
-+ * underlay (10.88.0.0/16, for example).  Multiple local addresses within
-+ * the /16 may be used, but a particular overlay may not span
-+ * multiple underlay subnets.
-+ *
-+ * We store one underlay, indexed by the overlay's high order octet.
-+ */
-+#define FAN_OVERLAY_CNT		256
-+
- struct ip_tunnel_fan {
--	u32			underlay;
-+/*	u32 __rcu	*map;*/
-+	u32		map[FAN_OVERLAY_CNT];
- };
- 
- struct ip_tunnel {
-@@ -104,6 +113,7 @@ struct ip_tunnel {
- #define TUNNEL_OAM		__cpu_to_be16(0x0200)
- #define TUNNEL_CRIT_OPT		__cpu_to_be16(0x0400)
- #define TUNNEL_GENEVE_OPT	__cpu_to_be16(0x0800)
- #define TUNNEL_VXLAN_OPT	__cpu_to_be16(0x1000)
-+#define TUNNEL_FAN		__cpu_to_be16(0x4000)
- 
- #define TUNNEL_OPTIONS_PRESENT	(TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT)
-diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
-index 8f7d269..9625934 100644
---- a/include/uapi/linux/if_tunnel.h
-+++ b/include/uapi/linux/if_tunnel.h
-@@ -58,8 +58,8 @@ enum {
- 	IFLA_IPTUN_ENCAP_SPORT,
- 	IFLA_IPTUN_ENCAP_DPORT,
- 
--	__IFLA_IPTUN_VENDOR_BREAK,		/* Ensure new entries do not hit the below. */
--	IFLA_IPTUN_FAN_UNDERLAY=32,
-+	__IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
-+	IFLA_IPTUN_FAN_MAP = 33,
- 
- 	__IFLA_IPTUN_MAX,
- };
-@@ -135,4 +135,20 @@ enum {
- };
- 
- #define IFLA_VTI_MAX	(__IFLA_VTI_MAX - 1)
-+
-+enum {
-+	IFLA_FAN_UNSPEC,
-+	IFLA_FAN_MAPPING,
-+	__IFLA_FAN_MAX,
-+};
-+
-+#define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
-+
-+struct ip_tunnel_fan_map {
-+	__be32		underlay;
-+	__be32		overlay;
-+	__u16		underlay_prefix;
-+	__u16		overlay_prefix;
-+};
-+
- #endif /* _UAPI_IF_TUNNEL_H_ */
-diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
-index d3e4479..60bd10f 100644
---- a/net/ipv4/ip_tunnel.c
-+++ b/net/ipv4/ip_tunnel.c
-@@ -1078,6 +1078,11 @@ out:
- }
- EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
- 
-+static int ip_tunnel_is_fan(struct ip_tunnel *tunnel)
-+{
-+	return tunnel->parms.i_flags & TUNNEL_FAN;
-+}
-+
- int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
- 			 struct ip_tunnel_parm *p)
- {
-@@ -1087,7 +1092,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
- 	struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
- 
- 	if (dev == itn->fb_tunnel_dev)
--		return -EINVAL;
-+		return ip_tunnel_is_fan(tunnel) ? 0 : -EINVAL;
- 
- 	t = ip_tunnel_find(itn, p, dev->type);
- 
-diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
-index e3c27cd..d6ebc66 100644
---- a/net/ipv4/ipip.c
-+++ b/net/ipv4/ipip.c
-@@ -107,6 +107,7 @@
- #include <linux/init.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/if_ether.h>
-+#include <linux/inetdevice.h>
- 
- #include <net/sock.h>
- #include <net/ip.h>
-@@ -208,6 +209,11 @@ drop:
- 	return 0;
- }
- 
-+static int ipip_tunnel_is_fan(struct ip_tunnel *tunnel)
-+{
-+	return tunnel->parms.i_flags & TUNNEL_FAN;
-+}
-+
- /*
-  * Determine fan tunnel endpoint to send packet to, based on the inner IP
-  * address.  For an overlay (inner) address Y.A.B.C, the transformation is
-@@ -221,15 +227,20 @@ drop:
-  * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
-  * overlay network 99.6.7.0/24.
-  */
--static void ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
-+static int ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
- {
--	u32 daddr;
--
--	*iph = tunnel->parms.iph;
-+	unsigned int overlay;
-+	u32 daddr, underlay;
- 
- 	daddr = ntohl(ip_hdr(skb)->daddr);
--	iph->daddr = htonl((tunnel->fan.underlay & 0xffff0000) |
--			   ((daddr >> 8) & 0x0000ffff));
-+	overlay = daddr >> 24;
-+	underlay = tunnel->fan.map[overlay];
-+	if (!underlay)
-+		return -EINVAL;
-+
-+	*iph = tunnel->parms.iph;
-+	iph->daddr = htonl(underlay | ((daddr >> 8) & 0x0000ffff));
-+	return 0;
- }
- 
- /*
-@@ -249,8 +260,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
- 	if (IS_ERR(skb))
- 		goto out;
- 
--	if (tunnel->fan.underlay) {
--		ipip_build_fan_iphdr(tunnel, skb, &fiph);
-+	if (ipip_tunnel_is_fan(tunnel)) {
-+		if (ipip_build_fan_iphdr(tunnel, skb, &fiph))
-+			goto tx_error;
- 		tiph = &fiph;
- 	} else {
- 		tiph = &tunnel->parms.iph;
-@@ -409,21 +421,65 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
- 	return ret;
- }
- 
-+static void ipip_fan_free_map(struct ip_tunnel *t)
-+{
-+	memset(&t->fan.map, 0, sizeof(t->fan.map));
-+}
-+
-+static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
-+{
-+	u32 overlay, overlay_mask, underlay, underlay_mask;
-+
-+	if ((map->underlay_prefix && map->underlay_prefix != 16) ||
-+	    (map->overlay_prefix && map->overlay_prefix != 8))
-+		return -EINVAL;
-+
-+	overlay = ntohl(map->overlay);
-+	overlay_mask = ntohl(inet_make_mask(map->overlay_prefix));
-+
-+	underlay = ntohl(map->underlay);
-+	underlay_mask = ntohl(inet_make_mask(map->underlay_prefix));
-+
-+	if ((overlay & ~overlay_mask) || (underlay & ~underlay_mask))
-+		return -EINVAL;
-+
-+	if (!(overlay & overlay_mask) && (underlay & underlay_mask))
-+		return -EINVAL;
-+
-+	t->parms.i_flags |= TUNNEL_FAN;
-+
-+	/* Special case: overlay 0 and underlay 0 clears all mappings */
-+	if (!overlay && !underlay) {
-+		ipip_fan_free_map(t);
-+		return 0;
-+	}
-+
-+	overlay >>= (32 - map->overlay_prefix);
-+	t->fan.map[overlay] = underlay;
-+
-+	return 0;
-+}
-+	
-+
- static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
- 			    struct ip_tunnel_parm *parms)
- {
--	u32 net = t->fan.underlay;
--
--	if (!data[IFLA_IPTUN_FAN_UNDERLAY])
--		goto err_check;
-+	struct ip_tunnel_fan_map *map;
-+	struct nlattr *attr;
-+	int rem, rv;
- 
--	net = ntohl(nla_get_be32(data[IFLA_IPTUN_FAN_UNDERLAY])) & 0xffff0000;
-+	if (!data[IFLA_IPTUN_FAN_MAP])
-+		return 0;
- 
--err_check:
--	if (parms->iph.daddr && net)
-+	if (parms->iph.daddr)
- 		return -EINVAL;
- 
--	t->fan.underlay = net;
-+	nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
-+		map = nla_data(attr);
-+		rv = ipip_fan_set_map(t, map);
-+		if (rv)
-+			return rv;
-+	}
- 
- 	return 0;
- }
-@@ -500,8 +556,8 @@ static size_t ipip_get_size(const struct net_device *dev)
- 		nla_total_size(2) +
- 		/* IFLA_IPTUN_ENCAP_DPORT */
- 		nla_total_size(2) +
--		/* IFLA_IPTUN_FAN_UNDERLAY */
--		nla_total_size(4) +
-+		/* IFLA_IPTUN_FAN_MAP */
-+		nla_total_size(sizeof(struct ip_tunnel_fan_map)) * 256 +
- 		0;
- }
- 
-@@ -529,10 +585,28 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
- 			tunnel->encap.flags))
- 		goto nla_put_failure;
- 
--	if (tunnel->fan.underlay)
--		if (nla_put_be32(skb, IFLA_IPTUN_FAN_UNDERLAY,
--				 htonl(tunnel->fan.underlay)))
-+	if (tunnel->parms.i_flags & TUNNEL_FAN) {
-+		struct nlattr *fan_nest;
-+		int i;
-+
-+		fan_nest = nla_nest_start(skb, IFLA_IPTUN_FAN_MAP);
-+		if (!fan_nest)
- 			goto nla_put_failure;
-+		for (i = 0; i < 256; i++) {
-+			if (tunnel->fan.map[i]) {
-+				struct ip_tunnel_fan_map map;
-+
-+				map.underlay = htonl(tunnel->fan.map[i]);
-+				map.underlay_prefix = 16;
-+				map.overlay = htonl(i << 24);
-+				map.overlay_prefix = 8;
-+				if (nla_put(skb, IFLA_FAN_MAPPING,
-+					    sizeof(map), &map))
-+					goto nla_put_failure;
-+			}
-+		}
-+		nla_nest_end(skb, fan_nest);
-+	}
- 
- 	return 0;
- 
-@@ -553,7 +627,7 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
- 	[IFLA_IPTUN_ENCAP_DPORT]	= { .type = NLA_U16 },
- 
- 	[__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX]	= { .type = NLA_BINARY },
--	[IFLA_IPTUN_FAN_UNDERLAY]	= { .type = NLA_U32 },
-+	[IFLA_IPTUN_FAN_MAP]		= { .type = NLA_NESTED },
- };
- 
- static struct rtnl_link_ops ipip_link_ops __read_mostly = {
-@@ -595,7 +669,7 @@ static struct pernet_operations ipip_net_ops = {
- 
- #ifdef CONFIG_SYSCTL
- static struct ctl_table_header *ipip_fan_header;
--static unsigned int ipip_fan_version = 1;
-+static unsigned int ipip_fan_version = 3;
- 
- static struct ctl_table ipip_fan_sysctls[] = {
- 	{
--- 
-2.4.1
-
diff --git a/pkgs/os-specific/linux/klibc/shrunk.nix b/pkgs/os-specific/linux/klibc/shrunk.nix
index 066b4fcb4e06..2ce833d104fd 100644
--- a/pkgs/os-specific/linux/klibc/shrunk.nix
+++ b/pkgs/os-specific/linux/klibc/shrunk.nix
@@ -8,10 +8,10 @@ stdenv.mkDerivation {
   name = "${klibc.name}";
   buildCommand = ''
     mkdir -p $out/lib
-    cp -prd ${klibc}/lib/klibc/bin $out/
-    cp -p ${klibc}/lib/*.so $out/lib/
+    cp -prd ${klibc.out}/lib/klibc/bin $out/
+    cp -p ${klibc.out}/lib/*.so $out/lib/
     chmod +w $out/*
-    old=$(echo ${klibc}/lib/klibc-*.so)
+    old=$(echo ${klibc.out}/lib/klibc-*.so)
     new=$(echo $out/lib/klibc-*.so)
     for i in $out/bin/*; do
       echo $i
diff --git a/pkgs/os-specific/linux/libcap/default.nix b/pkgs/os-specific/linux/libcap/default.nix
index 8157270d67d7..c8484babcdf8 100644
--- a/pkgs/os-specific/linux/libcap/default.nix
+++ b/pkgs/os-specific/linux/libcap/default.nix
@@ -3,12 +3,14 @@
 stdenv.mkDerivation rec {
   name = "libcap-${version}";
   version = "2.24";
-  
+
   src = fetchurl {
     url = "mirror://kernel/linux/libs/security/linux-privs/libcap2/${name}.tar.xz";
     sha256 = "0rbc9qbqs5bp9am9s9g83wxj5k4ixps2agy9dxr1v1fwg27mdr6f";
   };
-  
+
+  outputs = [ "dev" "out" ];
+
   nativeBuildInputs = [ perl ];
   propagatedBuildInputs = [ attr ];
 
@@ -16,14 +18,11 @@ stdenv.mkDerivation rec {
 
   makeFlags = "lib=lib prefix=$(out)";
 
-  passthru = {
-    postinst = n : ''
-      mkdir -p $out/share/doc/${n}
-      cp ../License $out/share/doc/${n}/License
-    '';
-  };
-
-  postInstall = passthru.postinst name;
+  postInstall = ''
+    rm "$out"/lib/*.a
+    mkdir -p "$dev/share/doc/${name}"
+    cp ../License "$dev/share/doc/${name}/License"
+  '';
 
   meta = {
     description = "Library for working with POSIX capabilities";
diff --git a/pkgs/os-specific/linux/libcap/man.nix b/pkgs/os-specific/linux/libcap/man.nix
index 9aac3c4e1f5a..eeb780f095bd 100644
--- a/pkgs/os-specific/linux/libcap/man.nix
+++ b/pkgs/os-specific/linux/libcap/man.nix
@@ -10,6 +10,4 @@ stdenv.mkDerivation rec {
   makeFlags = "MANDIR=$(out)/share/man";
 
   preConfigure = "cd doc";
-
-  postInstall = libcap.postinst name;
 }
diff --git a/pkgs/os-specific/linux/libcap/pam.nix b/pkgs/os-specific/linux/libcap/pam.nix
index b78f32dccbb4..3dd7cd947af2 100644
--- a/pkgs/os-specific/linux/libcap/pam.nix
+++ b/pkgs/os-specific/linux/libcap/pam.nix
@@ -12,6 +12,4 @@ stdenv.mkDerivation rec {
   preConfigure = "cd pam_cap";
 
   makeFlags = "${libcap.makeFlags} PAM_CAP=yes";
-
-  postInstall = libcap.postinst name;
 }
diff --git a/pkgs/os-specific/linux/libcap/progs.nix b/pkgs/os-specific/linux/libcap/progs.nix
index ae4446c82e6c..e3871f15f885 100644
--- a/pkgs/os-specific/linux/libcap/progs.nix
+++ b/pkgs/os-specific/linux/libcap/progs.nix
@@ -21,5 +21,8 @@ stdenv.mkDerivation rec {
 
   installFlags = "RAISE_SETFCAP=no";
 
-  postInstall = libcap.postinst name;
+  postInstall = ''
+    mkdir -p "$out/share/doc/${name}"
+    cp ../License "$out/share/doc/${name}/"
+  '';
 }
diff --git a/pkgs/os-specific/linux/libnl/default.nix b/pkgs/os-specific/linux/libnl/default.nix
index afd9695420e3..1e1ed0a6112c 100644
--- a/pkgs/os-specific/linux/libnl/default.nix
+++ b/pkgs/os-specific/linux/libnl/default.nix
@@ -11,6 +11,8 @@ stdenv.mkDerivation {
     owner = "thom311";
   };
 
+  outputs = [ "dev" "bin" "out" "man" ];
+
   nativeBuildInputs = [ autoreconfHook bison flex pkgconfig ];
 
   meta = {
diff --git a/pkgs/os-specific/linux/lvm2/default.nix b/pkgs/os-specific/linux/lvm2/default.nix
index 351c2f609814..9147cb813714 100644
--- a/pkgs/os-specific/linux/lvm2/default.nix
+++ b/pkgs/os-specific/linux/lvm2/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchurl, pkgconfig, udev, utillinux, coreutils, enable_dmeventd ? false }:
+{ stdenv, fetchurl, pkgconfig, systemd, libudev, utillinux, coreutils, enable_dmeventd ? false }:
 
 let
   version = "2.02.140";
@@ -22,7 +22,7 @@ stdenv.mkDerivation {
   ] ++ stdenv.lib.optional enable_dmeventd " --enable-dmeventd";
 
   nativeBuildInputs = [ pkgconfig ];
-  buildInputs = [ udev ];
+  buildInputs = [ libudev ];
 
   preConfigure =
     ''
@@ -30,7 +30,7 @@ stdenv.mkDerivation {
         --replace /usr/bin/tr ${coreutils}/bin/tr
       substituteInPlace scripts/lvm2_activation_generator_systemd_red_hat.c \
         --replace /usr/sbin/lvm $out/sbin/lvm \
-        --replace /usr/bin/udevadm ${udev}/bin/udevadm
+        --replace /usr/bin/udevadm ${systemd.udev.bin}/bin/udevadm
 
       sed -i /DEFAULT_SYS_DIR/d Makefile.in
       sed -i /DEFAULT_PROFILE_DIR/d conf/Makefile.in
diff --git a/pkgs/os-specific/linux/lxc/default.nix b/pkgs/os-specific/linux/lxc/default.nix
index fcfe4975fd72..4ac5d0c7951c 100644
--- a/pkgs/os-specific/linux/lxc/default.nix
+++ b/pkgs/os-specific/linux/lxc/default.nix
@@ -12,11 +12,11 @@ in
 with stdenv.lib;
 stdenv.mkDerivation rec {
   name = "lxc-${version}";
-  version = "1.1.5";
+  version = "2.0.0";
 
   src = fetchurl {
     url = "https://linuxcontainers.org/downloads/lxc/lxc-${version}.tar.gz";
-    sha256 = "1gnhgs4i2zamfdydj895inr9i072658wd47nf1ryw5710hdsv24m";
+    sha256 = "1r0hgk91n3frrmla1681l74ag5sngbbkdagvjfqzxwcf9l8pwwsv";
   };
 
   nativeBuildInputs = [
@@ -29,10 +29,6 @@ stdenv.mkDerivation rec {
 
   patches = [
     ./support-db2x.patch
-    (fetchpatch {
-      url = "https://github.com/lxc/lxc/commit/3db8dd39a797f87f8b348f1b6b44953a25f3f170.patch";
-      sha256 = "0scbzm9dqqhqsl0ri8da8a34r4qj9ph0cg68l9s7gw01vpvqbs8l";
-    })
   ];
 
   XML_CATALOG_FILES = "${docbook_xml_dtd_45}/xml/dtd/docbook/catalog.xml";
@@ -40,7 +36,6 @@ stdenv.mkDerivation rec {
   configureFlags = [
     "--localstatedir=/var"
     "--sysconfdir=/etc"
-    "--enable-doc"
     "--disable-api-docs"
     "--with-init-script=none"
     "--with-distro=nixos" # just to be sure it is "unknown"
diff --git a/pkgs/os-specific/linux/lxc/support-db2x.patch b/pkgs/os-specific/linux/lxc/support-db2x.patch
index 4662ca2e5048..16715992d35f 100644
--- a/pkgs/os-specific/linux/lxc/support-db2x.patch
+++ b/pkgs/os-specific/linux/lxc/support-db2x.patch
@@ -1,8 +1,8 @@
 diff --git a/configure.ac b/configure.ac
-index 92a4690..4dd341b 100644
+index 84f8699..dce9033 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -91,9 +91,9 @@ if test "x$enable_doc" = "xyes" -o "x$enable_doc" = "xauto"; then
+@@ -192,9 +192,9 @@ if test "x$enable_doc" = "xyes" -o "x$enable_doc" = "xauto"; then
  	AC_SUBST(db2xman)
  fi
  AM_CONDITIONAL([ENABLE_DOCBOOK], [test "x$db2xman" != "x"])
diff --git a/pkgs/os-specific/linux/mcelog/default.nix b/pkgs/os-specific/linux/mcelog/default.nix
index cd2cd511435f..254a5ce4e287 100644
--- a/pkgs/os-specific/linux/mcelog/default.nix
+++ b/pkgs/os-specific/linux/mcelog/default.nix
@@ -2,10 +2,10 @@
 
 stdenv.mkDerivation rec {
   name = "mcelog-${version}";
-  version = "135";
+  version = "136";
 
   src = fetchFromGitHub {
-    sha256 = "1bkbcb2zz7x7q893f1r8bm783jb3v7ww1yqys1hmqzn40hdwfr8p";
+    sha256 = "0bk46vi39cifahqwrkzivqf4fr34aqfip960x7awks9hiil8skwr";
     rev = "v${version}";
     repo = "mcelog";
     owner = "andikleen";
diff --git a/pkgs/os-specific/linux/mdadm/default.nix b/pkgs/os-specific/linux/mdadm/default.nix
index 465dc58199ed..3fe9d462412c 100644
--- a/pkgs/os-specific/linux/mdadm/default.nix
+++ b/pkgs/os-specific/linux/mdadm/default.nix
@@ -12,7 +12,7 @@ stdenv.mkDerivation rec {
 
   # This is to avoid self-references, which causes the initrd to explode
   # in size and in turn prevents mdraid systems from booting.
-  allowedReferences = [ stdenv.glibc ];
+  allowedReferences = [ stdenv.glibc.out ];
 
   patches = [ ./no-self-references.patch ];
 
diff --git a/pkgs/os-specific/linux/module-init-tools/default.nix b/pkgs/os-specific/linux/module-init-tools/default.nix
index 1302d7b1fef0..ded6e77e43b4 100644
--- a/pkgs/os-specific/linux/module-init-tools/default.nix
+++ b/pkgs/os-specific/linux/module-init-tools/default.nix
@@ -1,5 +1,7 @@
 { stdenv, fetchurl, docbook2x, docbook_sgml_dtd_41 }:
 
+assert (stdenv.lib.elem stdenv.system stdenv.lib.platforms.linux);
+
 stdenv.mkDerivation {
   name = "module-init-tools-3.16";
 
@@ -20,6 +22,8 @@ stdenv.mkDerivation {
     })
   ];
 
+  buildInputs = [ stdenv.glibc.dev stdenv.glibc.static ];
+
   SGML_CATALOG_FILES = "${docbook_sgml_dtd_41}/sgml/dtd/docbook-4.1/docbook.cat";
 
   patches = [ ./module-dir.patch ./docbook2man.patch ];
@@ -29,5 +33,6 @@ stdenv.mkDerivation {
   meta = {
     homepage = http://www.kernel.org/pub/linux/utils/kernel/module-init-tools/;
     description = "Tools for loading and managing Linux kernel modules";
+    platforms = stdenv.lib.platforms.linux;
   };
 }
diff --git a/pkgs/os-specific/linux/nfs-utils/default.nix b/pkgs/os-specific/linux/nfs-utils/default.nix
index 0dde3bca4e47..504d3790d868 100644
--- a/pkgs/os-specific/linux/nfs-utils/default.nix
+++ b/pkgs/os-specific/linux/nfs-utils/default.nix
@@ -21,7 +21,7 @@ stdenv.mkDerivation rec {
       "--with-statedir=/var/lib/nfs"
       "--with-tirpcinclude=${libtirpc}/include/tirpc"
     ]
-    ++ stdenv.lib.optional (stdenv ? glibc) "--with-rpcgen=${stdenv.glibc}/bin/rpcgen";
+    ++ stdenv.lib.optional (stdenv ? glibc) "--with-rpcgen=${stdenv.glibc.bin}/bin/rpcgen";
 
   patchPhase =
     ''
diff --git a/pkgs/os-specific/linux/opengl/xorg-sys/default.nix b/pkgs/os-specific/linux/opengl/xorg-sys/default.nix
index 5bb757a73a06..7da890ae7e33 100644
--- a/pkgs/os-specific/linux/opengl/xorg-sys/default.nix
+++ b/pkgs/os-specific/linux/opengl/xorg-sys/default.nix
@@ -11,6 +11,7 @@
 stdenv.mkDerivation {
   name = "xorg-sys-opengl-3";
   builder = ./builder.sh;
-  neededLibs = [xorg.libXxf86vm xorg.libXext expat libdrm stdenv.cc.cc];
+  neededLibs = map (p: p.out)
+    [xorg.libXxf86vm xorg.libXext expat libdrm stdenv.cc.cc];
 }
 
diff --git a/pkgs/os-specific/linux/pam/default.nix b/pkgs/os-specific/linux/pam/default.nix
index f7cadd469d70..d84c6224eebe 100644
--- a/pkgs/os-specific/linux/pam/default.nix
+++ b/pkgs/os-specific/linux/pam/default.nix
@@ -9,10 +9,14 @@ stdenv.mkDerivation rec {
     sha256 = "1n9lnf9gjs72kbj1g354v1xhi2j27aqaah15vykh7cnkq08i4arl";
   };
 
+  outputs = [ "out" "doc" "man" /* "modules" */ ];
+
   nativeBuildInputs = [ flex ];
 
   buildInputs = [ cracklib ];
 
+  enableParallelBuilding = true;
+
   crossAttrs = {
     propagatedBuildInputs = [ flex.crossDrv cracklib.crossDrv ];
     preConfigure = preConfigure + ''
@@ -31,7 +35,14 @@ stdenv.mkDerivation rec {
   postInstall = ''
     mv -v $out/sbin/unix_chkpwd{,.orig}
     ln -sv /var/setuid-wrappers/unix_chkpwd $out/sbin/unix_chkpwd
-  '';
+  ''; /*
+    rm -rf $out/etc
+    mkdir -p $modules/lib
+    mv $out/lib/security $modules/lib/
+  '';*/
+  # don't move modules, because libpam needs to (be able to) find them,
+  # which is done by dlopening $out/lib/security/pam_foo.so
+  # $out/etc was also missed: pam_env(login:session): Unable to open config file
 
   preConfigure = ''
     configureFlags="$configureFlags --includedir=$out/include/security"
diff --git a/pkgs/os-specific/linux/pipework/default.nix b/pkgs/os-specific/linux/pipework/default.nix
index 225515cb70a2..a686bd5496d7 100644
--- a/pkgs/os-specific/linux/pipework/default.nix
+++ b/pkgs/os-specific/linux/pipework/default.nix
@@ -16,7 +16,7 @@ stdenv.mkDerivation rec {
     mkdir -p $out/bin
     cp pipework $out/bin
     wrapProgram $out/bin/pipework --prefix PATH : \
-      ${lib.makeSearchPath "bin" [ bridge-utils iproute lxc openvswitch docker busybox dhcpcd dhcp ]};
+      ${lib.makeBinPath [ bridge-utils iproute lxc openvswitch docker busybox dhcpcd dhcp ]};
   '';
   meta = with lib; {
     description = "Software-Defined Networking tools for LXC";
diff --git a/pkgs/os-specific/linux/pm-utils/default.nix b/pkgs/os-specific/linux/pm-utils/default.nix
index 4fb7fc8cb0b8..19315ec2d0ba 100644
--- a/pkgs/os-specific/linux/pm-utils/default.nix
+++ b/pkgs/os-specific/linux/pm-utils/default.nix
@@ -3,10 +3,10 @@
 
 let
 
-  binPath = stdenv.lib.makeSearchPath "bin"
+  binPath = stdenv.lib.makeBinPath
     [ coreutils gnugrep utillinux module_init_tools procps kbd dbus_tools ];
 
-  sbinPath = stdenv.lib.makeSearchPath "sbin"
+  sbinPath = stdenv.lib.makeSearchPathOutputs "sbin" ["bin"]
     [ procps ];
 
 in
diff --git a/pkgs/os-specific/linux/shadow/default.nix b/pkgs/os-specific/linux/shadow/default.nix
index f928dc8e657c..321e94e3aaf4 100644
--- a/pkgs/os-specific/linux/shadow/default.nix
+++ b/pkgs/os-specific/linux/shadow/default.nix
@@ -37,7 +37,7 @@ stdenv.mkDerivation rec {
 
   preBuild = assert glibc != null;
     ''
-      substituteInPlace lib/nscd.c --replace /usr/sbin/nscd ${glibc}/sbin/nscd
+      substituteInPlace lib/nscd.c --replace /usr/sbin/nscd ${glibc.bin}/bin/nscd
     '';
 
   postInstall =
diff --git a/pkgs/os-specific/linux/sysdig/default.nix b/pkgs/os-specific/linux/sysdig/default.nix
index 358f7d38efa4..99b869abcb0e 100644
--- a/pkgs/os-specific/linux/sysdig/default.nix
+++ b/pkgs/os-specific/linux/sysdig/default.nix
@@ -2,14 +2,14 @@
 let
   inherit (stdenv.lib) optional optionalString;
   baseName = "sysdig";
-  version = "0.8.0";
+  version = "0.9.0";
 in
 stdenv.mkDerivation {
-  name="${baseName}-${version}";
+  name = "${baseName}-${version}";
 
   src = fetchurl {
     url = "https://github.com/draios/sysdig/archive/${version}.tar.gz";
-    sha256 = "1939k3clwxg09m1bn0szqiy2nxg66srl72n7476jc58hgaraq3dr";
+    sha256 = "198x1zmlydvi4i1sfvs8xjh9z5pb47l6xs4phrnkwwak46rhka3j";
   };
 
   buildInputs = [
diff --git a/pkgs/os-specific/linux/sysstat/default.nix b/pkgs/os-specific/linux/sysstat/default.nix
index 6544210b2067..16431c465c16 100644
--- a/pkgs/os-specific/linux/sysstat/default.nix
+++ b/pkgs/os-specific/linux/sysstat/default.nix
@@ -13,7 +13,7 @@ stdenv.mkDerivation rec {
   preConfigure = ''
     export PATH_CP=$(type -tp cp)
     export PATH_CHKCONFIG=/no-such-program
-    export BZIP=${bzip2}/bin/bzip2
+    export BZIP=${bzip2.bin}/bin/bzip2
     export SYSTEMCTL=systemctl
   '';
 
diff --git a/pkgs/os-specific/linux/systemd/cryptsetup-generator.nix b/pkgs/os-specific/linux/systemd/cryptsetup-generator.nix
new file mode 100644
index 000000000000..2935990755c6
--- /dev/null
+++ b/pkgs/os-specific/linux/systemd/cryptsetup-generator.nix
@@ -0,0 +1,25 @@
+{ stdenv, systemd, cryptsetup }:
+
+assert stdenv.isLinux;
+
+stdenv.lib.overrideDerivation systemd (p: {
+  version = p.version;
+  name = "systemd-cryptsetup-generator";
+
+  nativeBuildInputs = p.nativeBuildInputs ++ [ cryptsetup ];
+  outputs = [ "out" ];
+
+  buildPhase = ''
+    make $makeFlags built-sources
+    make $makeFlags systemd-cryptsetup
+    make $makeFlags systemd-cryptsetup-generator
+  '';
+
+  installPhase = ''
+    mkdir -p $out/lib/systemd/
+    cp systemd-cryptsetup $out/lib/systemd/systemd-cryptsetup
+
+    mkdir -p $out/lib/systemd/system-generators/
+    cp systemd-cryptsetup-generator $out/lib/systemd/system-generators/systemd-cryptsetup-generator
+  '';
+})
diff --git a/pkgs/os-specific/linux/systemd/default.nix b/pkgs/os-specific/linux/systemd/default.nix
index cb1521a4005e..0f066e380c1b 100644
--- a/pkgs/os-specific/linux/systemd/default.nix
+++ b/pkgs/os-specific/linux/systemd/default.nix
@@ -1,5 +1,5 @@
-{ stdenv, fetchFromGitHub, pkgconfig, intltool, gperf, libcap, dbus, kmod
-, xz, pam, acl, cryptsetup, libuuid, m4, utillinuxMinimal
+{ stdenv, fetchFromGitHub, pkgconfig, intltool, gperf, libcap, kmod
+, zlib, xz, pam, acl, cryptsetup, libuuid, m4, utillinux, libffi
 , glib, kbd, libxslt, coreutils, libgcrypt, libgpgerror, libapparmor, audit, lz4
 , kexectools, libmicrohttpd, linuxHeaders, libseccomp
 , autoreconfHook, gettext, docbook_xsl, docbook_xml_dtd_42, docbook_xml_dtd_45
@@ -19,18 +19,27 @@ stdenv.mkDerivation rec {
     sha256 = "1q0pyrljmq73qcan9rfqsiw66l1g159m5in5qgb8zwlwhl928670";
   };
 
-  outputs = [ "out" "man" "doc" ];
+  patches = [ ./hwdb-location.diff ];
+
+  /* gave up for now!
+  outputs = [ "out" "libudev" "doc" ]; # maybe: "dev"
+  # note: there are many references to ${systemd}/...
+  outputDev = "out";
+  propagatedBuildOutputs = "libudev";
+  */
+  outputs = [ "out" "man" ];
 
   buildInputs =
     [ linuxHeaders pkgconfig intltool gperf libcap kmod xz pam acl
       /* cryptsetup */ libuuid m4 glib libxslt libgcrypt libgpgerror
-      libmicrohttpd kexectools libseccomp audit lz4 libapparmor
+      libmicrohttpd kexectools libseccomp libffi audit lz4 libapparmor
       /* FIXME: we may be able to prevent the following dependencies
          by generating an autoconf'd tarball, but that's probably not
          worth it. */
       autoreconfHook gettext docbook_xsl docbook_xml_dtd_42 docbook_xml_dtd_45
     ];
 
+
   configureFlags =
     [ "--localstatedir=/var"
       "--sysconfdir=/etc"
@@ -74,14 +83,15 @@ stdenv.mkDerivation rec {
       for i in src/remount-fs/remount-fs.c src/core/mount.c src/core/swap.c src/fsck/fsck.c units/emergency.service.in units/rescue.service.in src/journal/cat.c src/core/shutdown.c src/nspawn/nspawn.c src/shared/generator.c; do
         test -e $i
         substituteInPlace $i \
-          --replace /usr/bin/getent ${stdenv.glibc}/bin/getent \
-          --replace /bin/mount ${utillinuxMinimal}/bin/mount \
-          --replace /bin/umount ${utillinuxMinimal}/bin/umount \
-          --replace /sbin/swapon ${utillinuxMinimal}/sbin/swapon \
-          --replace /sbin/swapoff ${utillinuxMinimal}/sbin/swapoff \
+          --replace /usr/bin/getent ${stdenv.glibc.bin}/bin/getent \
+          --replace /bin/mount ${utillinux.bin}/bin/mount \
+          --replace /bin/umount ${utillinux.bin}/bin/umount \
+          --replace /sbin/swapon ${utillinux.bin}/sbin/swapon \
+          --replace /sbin/swapoff ${utillinux.bin}/sbin/swapoff \
+          --replace /sbin/fsck ${utillinux.bin}/sbin/fsck \
           --replace /bin/echo ${coreutils}/bin/echo \
           --replace /bin/cat ${coreutils}/bin/cat \
-          --replace /sbin/sulogin ${utillinuxMinimal}/sbin/sulogin \
+          --replace /sbin/sulogin ${utillinux.bin}/sbin/sulogin \
           --replace /usr/lib/systemd/systemd-fsck $out/lib/systemd/systemd-fsck
       done
 
@@ -89,12 +99,24 @@ stdenv.mkDerivation rec {
         --replace /usr/lib/systemd/catalog/ $out/lib/systemd/catalog/
 
       configureFlagsArray+=("--with-ntp-servers=0.nixos.pool.ntp.org 1.nixos.pool.ntp.org 2.nixos.pool.ntp.org 3.nixos.pool.ntp.org")
+
+      #export NIX_CFLAGS_LINK+=" -Wl,-rpath,$libudev/lib"
     '';
 
+  /*
+  makeFlags = [
+    "udevlibexecdir=$(libudev)/lib/udev"
+    # udev rules refer to $out, and anything but libs should probably go to $out
+    "udevrulesdir=$(out)/lib/udev/rules.d"
+    "udevhwdbdir=$(out)/lib/udev/hwdb.d"
+  ];
+  */
+
+
   PYTHON_BINARY = "${coreutils}/bin/env python"; # don't want a build time dependency on Python
 
   NIX_CFLAGS_COMPILE =
-    [ # Can't say ${polkit}/bin/pkttyagent here because that would
+    [ # Can't say ${polkit.bin}/bin/pkttyagent here because that would
       # lead to a cyclic dependency.
       "-UPOLKIT_AGENT_BINARY_PATH" "-DPOLKIT_AGENT_BINARY_PATH=\"/run/current-system/sw/bin/pkttyagent\""
       "-fno-stack-protector"
@@ -147,8 +169,30 @@ stdenv.mkDerivation rec {
       # "kernel-install" shouldn't be used on NixOS.
       find $out -name "*kernel-install*" -exec rm {} \;
     ''; # */
+  /*
+      # Move lib(g)udev to a separate output. TODO: maybe split them up
+      #   to avoid libudev pulling glib
+      mkdir -p "$libudev/lib"
+      mv "$out"/lib/lib{,g}udev* "$libudev/lib/"
+
+      for i in "$libudev"/lib/*.la; do
+        substituteInPlace $i --replace "$out" "$libudev"
+      done
+      for i in "$out"/lib/pkgconfig/{libudev,gudev-1.0}.pc; do
+        substituteInPlace $i --replace "libdir=$out" "libdir=$libudev"
+      done
+  */
 
   enableParallelBuilding = true;
+  /*
+  # some libs fail to link to liblzma and/or libffi
+  postFixup = let extraLibs = stdenv.lib.makeLibraryPath [ xz.out libffi.out zlib.out ];
+    in ''
+      for f in "$out"/lib/*.so.0.*; do
+        patchelf --set-rpath `patchelf --print-rpath "$f"`':${extraLibs}' "$f"
+      done
+    '';
+  */
 
   # The interface version prevents NixOS from switching to an
   # incompatible systemd at runtime.  (Switching across reboots is
@@ -165,3 +209,4 @@ stdenv.mkDerivation rec {
     maintainers = [ stdenv.lib.maintainers.eelco stdenv.lib.maintainers.simons ];
   };
 }
+
diff --git a/pkgs/os-specific/linux/systemd/hwdb-location.diff b/pkgs/os-specific/linux/systemd/hwdb-location.diff
new file mode 100644
index 000000000000..31e7a027f50d
--- /dev/null
+++ b/pkgs/os-specific/linux/systemd/hwdb-location.diff
@@ -0,0 +1,19 @@
+diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c
+index 06c9831..e74825c 100644
+--- a/src/libsystemd/sd-hwdb/sd-hwdb.c
++++ b/src/libsystemd/sd-hwdb/sd-hwdb.c
+@@ -268,13 +268,8 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) {
+ }
+ 
+ static const char hwdb_bin_paths[] =
+-        "/etc/systemd/hwdb/hwdb.bin\0"
+         "/etc/udev/hwdb.bin\0"
+-        "/usr/lib/systemd/hwdb/hwdb.bin\0"
+-#ifdef HAVE_SPLIT_USR
+-        "/lib/systemd/hwdb/hwdb.bin\0"
+-#endif
+-        UDEVLIBEXECDIR "/hwdb.bin\0";
++        ;
+ 
+ _public_ int sd_hwdb_new(sd_hwdb **ret) {
+         _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
diff --git a/pkgs/os-specific/linux/systemd/libudev.nix b/pkgs/os-specific/linux/systemd/libudev.nix
new file mode 100644
index 000000000000..0fe45aee9164
--- /dev/null
+++ b/pkgs/os-specific/linux/systemd/libudev.nix
@@ -0,0 +1,19 @@
+{ stdenv, systemd }:
+
+stdenv.mkDerivation {
+  name = "libudev-${systemd.version}";
+
+  unpackPhase = ":";
+  outputs = [ "dev" "out" ];
+  installPhase = ''
+    mkdir -p "$out/lib" "$dev/lib/pkgconfig" "$dev/include"
+    cp -P "${systemd}"/lib/libudev.* "$out/lib/"
+    cp -P "${systemd}"/lib/pkgconfig/libudev.pc "$dev/lib/pkgconfig/"
+    cp -P "${systemd}"/include/libudev.h "$dev/include/"
+
+    substituteInPlace "$dev"/lib/pkgconfig/*.pc \
+      --replace "${systemd}" "$out"
+    sed "/^includedir=/cincludedir=$dev/include" -i "$dev"/lib/pkgconfig/*.pc
+  '';
+}
+
diff --git a/pkgs/os-specific/linux/udev/145.nix b/pkgs/os-specific/linux/udev/145.nix
new file mode 100644
index 000000000000..6dd551e1ce13
--- /dev/null
+++ b/pkgs/os-specific/linux/udev/145.nix
@@ -0,0 +1,53 @@
+{ stdenv, fetchurl, gperf, pkgconfig, glib, acl, libusb, usbutils, pciutils }:
+
+assert stdenv ? glibc;
+
+stdenv.mkDerivation rec {
+  name = "udev-145";
+
+  src = fetchurl {
+    url = "mirror://kernel/linux/utils/kernel/hotplug/${name}.tar.bz2";
+    sha256 = "1zmibp6n7d582fqx8vmg9vb2a1435hghfpz36056bc25ccwf7yiv";
+  };
+
+  buildInputs = [gperf pkgconfig glib acl libusb usbutils];
+
+  configureFlags = "--with-pci-ids-path=${pciutils}/share/pci.ids";
+
+  preConfigure =
+    ''
+      substituteInPlace extras/keymap/Makefile.in \
+        --replace /usr/include ${stdenv.glibc.dev}/include
+    '';
+
+  postInstall =
+    ''
+      # Install some rules that really should be installed by default.
+      for i in 40-alsa.rules 40-infiniband.rules 40-isdn.rules 40-pilot-links.rules 64-device-mapper.rules 64-md-raid.rules; do
+        cp rules/packages/$i $out/libexec/rules.d/
+      done
+
+      # The path to rule_generator.functions in write_cd_rules and
+      # write_net_rules is broken.  Also, don't store the mutable
+      # persistant rules in /etc/udev/rules.d but in
+      # /var/lib/udev/rules.d.
+      for i in $out/libexec/write_cd_rules $out/libexec/write_net_rules; do
+        substituteInPlace $i \
+          --replace /lib/udev $out/libexec \
+          --replace /etc/udev/rules.d /var/lib/udev/rules.d
+      done
+
+      # Don't set PATH to /bin:/sbin; won't work in NixOS.
+      substituteInPlace $out/libexec/rule_generator.functions \
+        --replace 'PATH=' '#PATH='
+
+      # Don't hardcore the FIRMWARE_DIRS variable; obtain it from the
+      # environment of the caller.
+      sed '3,4d' -i $out/libexec/firmware.sh
+    '';
+
+  meta = {
+    homepage = http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html;
+    description = "Udev manages the /dev filesystem";
+  };
+}
diff --git a/pkgs/os-specific/linux/util-linux/default.nix b/pkgs/os-specific/linux/util-linux/default.nix
index a84740b1a30b..263fa4490dc8 100644
--- a/pkgs/os-specific/linux/util-linux/default.nix
+++ b/pkgs/os-specific/linux/util-linux/default.nix
@@ -1,6 +1,4 @@
-{ stdenv, fetchurl, zlib, ncurses ? null, perl ? null, pam, systemd ? null
-, pkgconfig
-}:
+{ stdenv, fetchurl, pkgconfig, zlib, ncurses ? null, perl ? null, pam, systemd }:
 
 stdenv.mkDerivation rec {
   name = "util-linux-2.27.1";
@@ -10,12 +8,15 @@ stdenv.mkDerivation rec {
     sha256 = "1452hz5zx56a3mad8yrg5wb0vy5zi19mpjp6zx1yr6p9xp6qz08a";
   };
 
-  outputs = [ "out" "man" ];
-
   patches = [
     ./rtcwake-search-PATH-for-shutdown.patch
   ];
 
+  outputs = [ "bin" "out" "man" ]; # TODO: $bin is kept the first for now
+  # due to lots of ${utillinux}/bin occurences and headers being rather small
+  outputDev = "bin";
+
+
   #FIXME: make it also work on non-nixos?
   postPatch = ''
     # Substituting store paths would create a circular dependency on systemd
@@ -46,6 +47,9 @@ stdenv.mkDerivation rec {
     ''}
   '';
 
+  makeFlags = "usrbin_execdir=$(bin)/bin usrsbin_execdir=$(bin)/sbin";
+
+  nativeBuildInputs = [ pkgconfig ];
   buildInputs =
     [ zlib pam ]
     ++ stdenv.lib.optional (ncurses != null) ncurses
@@ -53,15 +57,16 @@ stdenv.mkDerivation rec {
     ++ stdenv.lib.optional (perl != null) perl;
 
   postInstall = ''
-    rm $out/bin/su # su should be supplied by the su package (shadow)
+    rm "$bin/bin/su" # su should be supplied by the su package (shadow)
   '';
 
   enableParallelBuilding = true;
 
-  meta = {
+  meta = with stdenv.lib; {
     homepage = http://www.kernel.org/pub/linux/utils/util-linux/;
     description = "A set of system utilities for Linux";
-    platforms = stdenv.lib.platforms.linux;
+    license = licenses.gpl2; # also contains parts under more permissive licenses
+    platforms = platforms.linux;
     priority = 6; # lower priority than coreutils ("kill") and shadow ("login" etc.) packages
   };
 }