diff --git a/Modulefile b/Modulefile
index ebe7f37..1a94eab 100644
--- a/Modulefile
+++ b/Modulefile
@@ -1,5 +1,5 @@
 name    'puppet-ff_gw'
-version '0.4.0'
+version '0.1.0'
 license 'BSD 2-clause license'
 author 'Martin Schuette <info@mschuette.name>'
 dependency 'puppetlabs/apt', '>= 1.4.0'
diff --git a/README.md b/README.md
index cb87142..c961525 100644
--- a/README.md
+++ b/README.md
@@ -12,64 +12,19 @@ Also note that this is a really ugly puppet module that ignores all principles
 of modularity and interoperability; instead it follows the "Big ball of mud"
 design pattern.
 
-## Open Problems
-
-* The apt repository at http://bird.network.cz/debian/ does not use PGP
-  signatures, so `bird` and `bird6` will not be installed automatically.
-* Setting the hostname should occur before everything else. So either
-  do that manually or run a small `ff_gw::sysadmin`-only manifest before the
-  main `ff_gw` manifest.
-* User root requires ssh access to the git repository
-  `git@git.hamburg.freifunk.net:fastdkeys` --
-  so create a key and have it authorized beforehand.
-
 ## Usage
 
 Install as a puppet module, then include with node-specific parameters.
 
-### Dependencies
-
-Install Puppet and some required modules with:
-
-```
-apt-get install puppet git
-puppet module install puppetlabs-stdlib
-puppet module install puppetlabs-apt
-puppet module install puppetlabs-vcsrepo
-puppet module install saz-sudo
-puppet module install torrancew-account
-```
-
-Then add this module (which is not in the puppet forge, so it has to be
-downloaded manually):
-
-```
-cd /etc/puppet/modules
-git clone https://github.com/freifunkhamburg/puppet-ff_gw.git ff_gw
-```
-
-### Parameters
-
-Now include the module in your manifest and provide all parameters.
 Basically there are three kinds of parameters: user accounts (optional if you
 do manual user management), network config (has to be in sync with the wiki
 page), and credentials for fastd and openvpn.
 
-
-Example puppet code (save e.g. as `/etc/puppet/gw.pp`):
+Example puppet code:
 
 ```
-
-class { 'ff_gw::sysadmin':
-    # both optional, used for FFHH monitoring:
-    zabbixserver => 'argos.mschuette.name',
-    muninserver  => '78.47.49.236',
-
-    # optional, configure hostname and public IP
-    sethostname => 'gw12.hamburg.freifunk.net',
-    setip       => '5.45.105.34',
-
-    # also optional, let puppet control user accounts:
+class { 'ff_gw':
+    # user accounts:
     accounts => {
         mschuett => {
             comment => 'Martin Schuette',
@@ -77,16 +32,6 @@ class { 'ff_gw::sysadmin':
             groups => ['sudo', 'users'],
         }
     },
-}
-
-class { 'ff_gw':
-    # freifunk config
-    # the network assigned to the ff community
-    ff_net          => '10.112.0.0/16',
-    # the network actually used in the mesh might be smaller than ff_net
-    ff_mesh_net     => '10.112.0.0/18',
-    # as number for icvpn peering
-    ff_as           => '65112',
 
     # network config (example data for gw12)
     mesh_mac        => 'de:ad:be:ef:01:14',
@@ -95,13 +40,6 @@ class { 'ff_gw':
     dhcprange_start => '10.112.30.2',
     dhcprange_end   => '10.112.31.254',
 
-    # only for inter-city VPN hosts
-	gw_do_ic_peering => true,
-	tinc_name        => 'hamburg01',
-	tinc_keyfile     => '/etc/tinc/rsa_key.priv',
-	ic_vpn_ip4       => '10.207.X.Y',
-	ic_vpn_ip6       => 'fec0::a:cf:X:Y',
-
     # secret credentials for fastd and vpn
     secret_key      => '...',
     vpn_ca_crt      => '-----BEGIN CERTIFICATE-----
@@ -110,36 +48,9 @@ MIIE ...
     vpn_usr_crt     => '-----BEGIN CERTIFICATE-----
 MIIE ...
 -----END CERTIFICATE-----',
-    vpn_usr_key     => '-----BEGIN PRIVATE KEY-----
+    vpn_usr_key     => '-----BEGIN CERTIFICATE-----
 MIIE ...
------END PRIVATE KEY-----',
+-----END CERTIFICATE-----',
 }
 ```
 
-### Run Puppet
-
-To apply the puppet manifest (e.g. saved as `gw.pp`) run:
-
-```
-puppet apply --verbose gw.pp
-```
-
-The verbose flag is optional and shows all changes.
-To be even more catious you can also add the `--noop` flag to only show changes
-but not apply them.
-
-## VPN providers
-
-The example above is written for a mullvad VPN using X.509 authentication.
-
-For hide.me with username/password auth use:
-```
-class { 'ff_gw':
-    # ...
-	vpn_provider => 'hideme',
-	vpn_usr_name => 'username',
-	vpn_usr_pass => 'vpn_password',
-    vpn_ca_crt   => '-----BEGIN CERTIFICATE-----
-MIIE ...
------END CERTIFICATE-----',
-```
diff --git a/data/peering.yaml b/data/peering.yaml
index 7ba51e2..b6ebb66 100644
--- a/data/peering.yaml
+++ b/data/peering.yaml
@@ -1,392 +1,321 @@
 peerings_v4:
   srv01:
-    template: locals
+    template: bgp_ibgp
     ip: 10.112.1.1
+    as: 65112
   hamburg01:
-    template: locals
+    template: bgp_ibgp
     ip: 10.112.14.1
+    as: 65112
   hamburg05:
-    template: locals
+    template: bgp_ibgp
     ip: 10.112.18.1
+    as: 65112
   hamburg07:
-    template: locals
+    template: bgp_ibgp
     ip: 10.112.16.1
+    as: 65112
   hamburg08:
-    template: locals
+    template: bgp_ibgp
     ip: 10.112.22.1
+    as: 65112
   hamburg09:
-    template: locals
+    template: bgp_ibgp
     ip: 10.112.24.1
+    as: 65112
+  hamburg11:
+    template: bgp_ibgp
+    ip: 10.112.28.1
+    as: 65112
   hamburg12:
-    template: locals
+    template: bgp_ibgp
     ip: 10.112.30.1
-  hamburg13:
-    template: locals
-    ip: 10.112.32.1
+    as: 65112
 
 # TODO: add this as a second param for intercity gateways
 ic_peerings_v4:
   Augsburg1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.17
     as: 65050
   Augsburg2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.177
     as: 65070
   Aurich1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.15
     as: 65047
   BadZwischenahn1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.26
     as: 65512
   Bayreuth1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.28
     as: 65025
   Berlin1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.5
     as: 44194
   Bielefeld1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.59
     as: 65529
   Bielefeld2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.67
     as: 65529
-  Bremen1:
-    template: peers
-    ip: 10.207.0.196
-    as: 65196
   Chemnitz1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.36
     as: 65053
   diac24_net:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.2.0
     as: 64600
   Dresden1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.19
     as: 65051
   Franken1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.23
     as: 65024
   Franken2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.24
     as: 65024
   Franken3:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.31
     as: 65024
   Frankfurt1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.35
     as: 65026
   Freiburg1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.21
     as: 65026
   Gronau1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.55
     as: 65526
   Gronau2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.60
     as: 65526
   Grossdraxdorf:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.25
     as: 65025
   Halle1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.13
     as: 65046
   Halle2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.14
     as: 65046
   Hannover1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.22
     as: 65511
   Jena1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.33
     as: 65055
   Jena2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.66
     as: 65055
-  Kiel2:
-    template: peers
-    ip: 10.207.0.52
+  Kiel4:
+    template: bgp_icvpn
+    ip: 10.207.0.58
     as: 65525
   Koblenz:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.32
     as: 65032
   Koeln1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.57
     as: 65528
   Leipzig1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.1
     as: 65041
   Leipzig2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.2
     as: 65041
   Ljubljana1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.3.23
     as: 65023
   Ljubljana2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.3.30
     as: 64768
   Luebeck1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.130
     as: 65052
   Luebeck2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.131
     as: 65052
   Mainz1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.37
     as: 65037
   Oldenburg1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.27
     as: 65513
-  Ostholstein1:
-    template: peers
-    ip: 10.207.0.135
-    as: 65152
-  RheinNeckar1:
-    template: peers
-    ip: 10.207.0.142
-    as: 76118
+  Schwarzach1:
+    template: bgp_icvpn
+    ip: 10.207.0.56
+    as: 65527
   Treuenbrietzen:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.18
     as: 65045
   Weimar1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.3
     as: 65042
   Weimar2:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.4
     as: 65042
   Wermelskirchen1:
-    template: peers
+    template: bgp_icvpn
     ip: 10.207.0.7
     as: 65530
-  Wermelskirchen2:
-    template: peers
-    ip: 10.207.0.8
-    as: 65530
-  Dreilaendereck1:
-    template: peers
-    ip: 10.207.0.75
-    as: 65043
-  Flensburg1:
-    template: peers
-    ip: 10.207.0.129
-    as: 65056
-  Guetersloh1:
-    template: peers
-    ip: 10.207.0.132
-    as: 65533
-  Guetersloh4:
-    template: peers
-    ip: 10.207.0.134
-    as: 65533
-  Magdeburg1:
-    template: peers
-    ip: 10.207.39.1
-    as: 65039
-  Magdeburg2:
-    template: peers
-    ip: 10.207.39.2
-    as: 65039
+
 
 peerings_v6:
   srv01:
-    template: locals
+    template: bgp_ibgp
     ip: fd51:2bb2:fd0d::101
     as: 65112
   hamburg01:
-    template: locals
+    template: bgp_ibgp
     ip: fd51:2bb2:fd0d::e01
     as: 65112
   hamburg05:
-    template: locals
+    template: bgp_ibgp
     ip: fd51:2bb2:fd0d::d01
     as: 65112
   hamburg07:
-    template: locals
+    template: bgp_ibgp
     ip: fd51:2bb2:fd0d::a01
     as: 65112
   hamburg08:
-    template: locals
+    template: bgp_ibgp
     ip: fd51:2bb2:fd0d::b01                                                                                             
     as: 65112
   hamburg09:
-    template: locals
+    template: bgp_ibgp
     ip: fd51:2bb2:fd0d::901
     as: 65112
   hamburg11:
-    template: locals
+    template: bgp_ibgp
     ip: fd51:2bb2:fd0d::601
     as: 65112
   hamburg12:
-    template: locals
+    template: bgp_ibgp
     ip: fd51:2bb2:fd0d::501
     as: 65112
-  hamburg13:
-    template: locals
-    ip: fd51:2bb2:fd0d::401
-    as: 65112
 
 ic_peerings_v6:
   Augsburg1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:a
     as: 65050
   Bayreuth:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:19
     as: 65025
   Berlin1:
-    template: upstream
+    template: bgp_icvpn
     ip: fec0::a:cf:0:5
     as: 44194
   Bielefeld1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:59
     as: 65529
   Bielefeld2:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:60
     as: 65529
-  Bremen1:
-    template: peers
-    ip: fec0::a:cf:0:c4
-    as: 65196
   diac24:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:ac:16
     as: 64600
   Franken1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:17
     as: 65024
   Franken2:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:18
     as: 65024
   Freiburg1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:21
     as: 65060
   Gronau1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:50
     as: 65526
   Gronau2:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:51
     as: 65526
-  Kiel0:
-    template: peers
-    ip: fec0::a:cf:0:34
-    as: 65525
   Kiel1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:35
     as: 65525
   Kiel3:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:36
     as: 65525
   Kiel4:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:3a
     as: 65525
   Koeln:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:57
     as: 65528
   Ljubljana1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:3:23
     as: 65023
   Ljubljana2:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:3:30
     as: 64768
   Luebeck1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:82
     as: 65052
   Luebeck2:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:83
     as: 65052
-  Ostholstein1:
-    template: peers
-    ip: fec0::a:cf:0:87
-    as: 65152
+  Schwarzach:
+    template: bgp_icvpn
+    ip: fec0::a:cf:0:56
+    as: 65527
   Weimar1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:3
     as: 65042
-  Weimar2:
-    template: peers
-    ip: fec0::a:cf:0:4
-    as: 65042
   Wermelskirchen1:
-    template: peers
+    template: bgp_icvpn
     ip: fec0::a:cf:0:7
     as: 65530
-  Wermelskirchen2:
-    template: peers
-    ip: fec0::a:cf:0:8
-    as: 65530
-  Dreilaendereck1:
-    template: peers
-    ip: fec0::a:cf:0:be
-    as: 65043
-  Flensburg1:
-    template: peers
-    ip: fec0::a:cf:0:10
-    as: 65056
-  Guetersloh1:
-    template: peers
-    ip: fec0::a:cf:0:84
-    as: 65533
-  Guetersloh4:
-    template: peers
-    ip: fec0::a:cf:0:86
-    as: 65533
-  Magdeburg1:
-    template: peers
-    ip: fec0::a:cf:39:1
-    as: 65039
-  Magdeburg1:
-    template: peers
-    ip: fec0::a:cf:39:2
-    as: 65039
diff --git a/files/etc/iptables/rules.v4 b/files/etc/iptables/rules.v4
index 38537b3..14e4a4c 100644
--- a/files/etc/iptables/rules.v4
+++ b/files/etc/iptables/rules.v4
@@ -1,31 +1,26 @@
-# Generated by iptables-save v1.4.14 on Mon Aug 18 22:31:43 2014
+# Generated by iptables-save v1.4.14 on Sun Mar 24 14:14:50 2013
+*filter
+:INPUT ACCEPT [273:40363]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [194:28568]
+COMMIT
+# Completed on Mon Mar 25 19:41:40 2013
+# Generated by iptables-save v1.4.14 on Mon Mar 25 19:41:40 2013
+*mangle
+:PREROUTING ACCEPT [286:41734]
+:INPUT ACCEPT [273:40363]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [194:28568]
+:POSTROUTING ACCEPT [194:28568]
+-A PREROUTING -i br-ffhh -j MARK --set-xmark 0x1/0xffffffff
+COMMIT
+# Completed on Mon Mar 25 19:41:40 2013
+# Generated by iptables-save v1.4.14 on Mon Mar 25 19:41:40 2013
 *nat
-:PREROUTING ACCEPT [1508898:60980199]
-:INPUT ACCEPT [85622:9125051]
-:OUTPUT ACCEPT [195829:12103496]
-:POSTROUTING ACCEPT [194526:11989631]
+:PREROUTING ACCEPT [15:1459]
+:INPUT ACCEPT [2:88]
+:OUTPUT ACCEPT [1:74]
+:POSTROUTING ACCEPT [1:74]
 -A POSTROUTING -o mullvad -j MASQUERADE
 COMMIT
-# Completed on Mon Aug 18 22:31:43 2014
-# Generated by iptables-save v1.4.14 on Mon Aug 18 22:31:43 2014
-*mangle
-:PREROUTING ACCEPT [100732184:31760093690]
-:INPUT ACCEPT [88878861:23870786312]
-:FORWARD ACCEPT [10499612:7842070628]
-:OUTPUT ACCEPT [158193447:33293545226]
-:POSTROUTING ACCEPT [168692266:41135440990]
--A PREROUTING -i br-ffhh -j MARK --set-xmark 0x1/0xffffffff
--A PREROUTING -i mullvad -j MARK --set-xmark 0x1/0xffffffff
-COMMIT
-# Completed on Mon Aug 18 22:31:43 2014
-# Generated by iptables-save v1.4.14 on Mon Aug 18 22:31:43 2014
-*filter
-:INPUT ACCEPT [88878720:23870769673]
-:FORWARD ACCEPT [10499612:7842070628]
-:OUTPUT ACCEPT [158192660:33293370754]
--A INPUT -i mullvad -m state --state INVALID,NEW,UNTRACKED -j DROP
--A FORWARD -i mullvad -m state --state INVALID,NEW,UNTRACKED -j DROP
--A FORWARD -o eth0 -j DROP
--A FORWARD -i eth0 -j DROP
-COMMIT
-# Completed on Mon Aug 18 22:31:43 2014
+# Completed on Mon Mar 25 19:41:40 2013
diff --git a/files/etc/iptables/rules.v6 b/files/etc/iptables/rules.v6
deleted file mode 100644
index a00c3d0..0000000
--- a/files/etc/iptables/rules.v6
+++ /dev/null
@@ -1,20 +0,0 @@
-# Generated by ip6tables-save v1.4.14 on Mon Aug 18 22:31:43 2014
-*mangle
-:PREROUTING ACCEPT [347182:29416089]
-:INPUT ACCEPT [95377:10719074]
-:FORWARD ACCEPT [50710:3964545]
-:OUTPUT ACCEPT [108706:9522484]
-:POSTROUTING ACCEPT [161591:13748029]
--A PREROUTING -i br-ffhh -j MARK --set-xmark 0x1/0xffffffff
-COMMIT
-# Completed on Mon Aug 18 22:31:43 2014
-# Generated by ip6tables-save v1.4.14 on Mon Aug 18 22:31:43 2014
-*filter
-:INPUT ACCEPT [1244932:115240832]
-:FORWARD ACCEPT [51046:3997994]
-:OUTPUT ACCEPT [1330577:118074893]
--A INPUT -m rt --rt-type 0 -j DROP
--A FORWARD -m rt --rt-type 0 -j DROP
--A OUTPUT -m rt --rt-type 0 -j DROP
-COMMIT
-# Completed on Mon Aug 18 22:31:43 2014
diff --git a/files/etc/openvpn/hideme.conf b/files/etc/openvpn/hideme.conf
deleted file mode 100644
index 79c0455..0000000
--- a/files/etc/openvpn/hideme.conf
+++ /dev/null
@@ -1,42 +0,0 @@
-client
-
-dev mullvad   # this is important because other scripts rely on this device name
-dev-type tun
-
-proto udp
-
-remote nl.hide.me 3478
-
-# Keep trying indefinitely to resolve the
-# host name of the OpenVPN server.  Very useful
-# on machines which are not permanently connected
-# to the internet such as laptops.
-resolv-retry infinite
-
-# Most clients don't need to bind to
-# a specific local port number.
-nobind
-
-# Try to preserve some state across restarts.
-persist-key
-persist-tun
-
-# Set log file verbosity.
-verb 3
-
-# ping 5          # this is pushed by hideme
-# ping-restart 15 # this is pushed by hideme
-
-# Allow calling of built-in executables and user-defined scripts.
-script-security 3 system
-
-# Parses DHCP options from openvpn to update resolv.conf
-route-noexec
-up    /etc/openvpn/hideme/hideme-up
-down  /etc/openvpn/update-dnsmasq-forward
-
-# hideme specifics
-ca /etc/openvpn/hideme/ca.crt
-auth-user-pass /etc/openvpn/hideme/auth.txt
-cipher AES-128-CBC
-reneg-sec 0
diff --git a/files/etc/openvpn/hideme/hideme-up b/files/etc/openvpn/hideme/hideme-up
deleted file mode 100644
index 7574b1c..0000000
--- a/files/etc/openvpn/hideme/hideme-up
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-ip route replace 0.0.0.0/1 via $4 table 42
-ip route replace 128.0.0.0/1 via $4 table 42
-
-ip rule del priority 30000
-ip rule add priority 30000 from $4 table 42
-
-ip route flush cache
-
-/etc/openvpn/update-dnsmasq-forward
-exit 0
diff --git a/files/etc/openvpn/mullvad.conf b/files/etc/openvpn/mullvad.conf
index a7b0003..a438799 100644
--- a/files/etc/openvpn/mullvad.conf
+++ b/files/etc/openvpn/mullvad.conf
@@ -37,7 +37,6 @@ script-security 2
 # Parses DHCP options from openvpn to update resolv.conf
 route-noexec
 up    /etc/openvpn/mullvad/mullvad-up
-down  /etc/openvpn/update-dnsmasq-forward
 
 ping 10
 
diff --git a/files/etc/openvpn/mullvad/mullvad-up b/files/etc/openvpn/mullvad/mullvad-up
deleted file mode 100644
index f59a2bd..0000000
--- a/files/etc/openvpn/mullvad/mullvad-up
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-ip route replace 0.0.0.0/1 via $5 table 42
-ip route replace 128.0.0.0/1 via $5 table 42
-/etc/openvpn/update-dnsmasq-forward
-exit 0
diff --git a/files/etc/openvpn/update-dnsmasq-forward b/files/etc/openvpn/update-dnsmasq-forward
deleted file mode 100755
index eb57a81..0000000
--- a/files/etc/openvpn/update-dnsmasq-forward
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/bash
-# 
-# Parses DHCP options from openvpn to update resolv.conf
-# To use set as 'up' and 'down' script in your openvpn *.conf:
-# up /etc/openvpn/update-resolv-conf
-# down /etc/openvpn/update-resolv-conf
-#
-# Used snippets of resolvconf script by Thomas Hood and Chris Hanson.
-# Licensed under the GNU GPL.  See /usr/share/common-licenses/GPL. 
-# 
-# Example envs set from openvpn:
-#
-#     foreign_option_1='dhcp-option DNS 193.43.27.132'
-#     foreign_option_2='dhcp-option DNS 193.43.27.133'
-#     foreign_option_3='dhcp-option DOMAIN be.bnc.ch'
-#
-
-[ "$script_type" ] || exit 0
-[ "$dev" ] || exit 0
-
-split_into_parts()
-{
-	part1="$1"
-	part2="$2"
-	part3="$3"
-}
-
-case "$script_type" in
-  up)
-	NMSRVRS=""
-	SRCHS=""
-	for optionvarname in ${!foreign_option_*} ; do
-		option="${!optionvarname}"
-		echo "$option"
-		split_into_parts $option
-		if [ "$part1" = "dhcp-option" ] ; then
-			if [ "$part2" = "DNS" ] ; then
-				NMSRVRS="${NMSRVRS:+$NMSRVRS }$part3"
-			elif [ "$part2" = "DOMAIN" ] ; then
-				SRCHS="${SRCHS:+$SRCHS }$part3"
-			fi
-		fi
-	done
-	R=""
-	for NS in $NMSRVRS ; do
-        	R="${R}server=$NS@$dev\n"
-	done
-	echo -en "$R" > /etc/dnsmasq.d/forward
-	/usr/sbin/service dnsmasq restart
-	;;
-  down)
-	echo -n "" > /etc/dnsmasq.d/forward
-	/usr/sbin/service dnsmasq restart
-	;;
-esac
-
diff --git a/files/root/bin/autoupdate_fastd_keys.sh b/files/root/bin/autoupdate_fastd_keys.sh
index 9be4f8f..ae797d5 100644
--- a/files/root/bin/autoupdate_fastd_keys.sh
+++ b/files/root/bin/autoupdate_fastd_keys.sh
@@ -2,10 +2,6 @@
 # Simple script to update fastd peers from git upstream
 # and only send HUP to fastd when changes happend.
 
-if [[ "$1" == "-v" ]]; then
-  VERBOSE=1
-fi
-
 # CONFIGURE THIS TO YOUR PEER DIRECTORY
 FASTD_PEERS=/etc/fastd/ffhh-mesh-vpn/peers
 
@@ -21,11 +17,11 @@ GIT_REVISION=$(getCurrentVersion)
 
 # Automagically commit local changes
 # This preserves local changes
-git commit --quiet -m "CRON: auto commit" > /dev/null
+git commit -m "CRON: auto commit"
 
 # Pull latest changes from upstream
-git fetch --quiet
-git merge origin/master --quiet -m "Auto Merge"
+git fetch
+git merge origin/master -m "Auto Merge"
 
 # Get new version hash
 GIT_NEW_REVISION=$(getCurrentVersion)
@@ -33,7 +29,7 @@ GIT_NEW_REVISION=$(getCurrentVersion)
 if [ $GIT_REVISION != $GIT_NEW_REVISION ]
 then
   # Version has changed we need to update
-  test -n "$VERBOSE" && echo "Reload fastd peers"
+  echo "Reload fastd peers"
   kill -HUP $(pidof fastd)
 fi
 
diff --git a/files/usr/local/bin/check_gateway b/files/usr/local/bin/check_gateway
index 1e65f07..91059e0 100644
--- a/files/usr/local/bin/check_gateway
+++ b/files/usr/local/bin/check_gateway
@@ -1,8 +1,7 @@
 #!/bin/bash
-INTERFACE=mullvad        # Set to name of VPN interface
+INTERFACE=mullvad
 shopt -s nullglob
 
-# Test whether gateway is connected to the outer world via VPN
 ping -q -I $INTERFACE 8.8.8.8 -c 4 -i 1 -W 5 >/dev/null 2>&1
 
 if test $? -eq 0; then
@@ -11,41 +10,13 @@ else
     NEW_STATE=off
 fi
 
-# Iterate through network interfaces in sys file system
 for MESH in /sys/class/net/*/mesh; do
-# Check whether gateway modus needs to be changed
 OLD_STATE="$(cat $MESH/gw_mode)"
 [ "$OLD_STATE" == "$NEW_STATE" ] && continue
-    echo $NEW_STATE > $MESH/gw_mode
-    echo 54MBit/54MBit > $MESH/gw_bandwidth
-    logger "batman gateway mode changed to $NEW_STATE"
-
-    # Check whether gateway modus has been deactivated
-    if [ "$NEW_STATE" == "off" ]; then
-        # Shutdown DHCP server to prevent renewal of leases
-        /usr/sbin/service isc-dhcp-server stop
-    fi
-
-    # Check whether gateway modus has been activated
-    if [ "$NEW_STATE" == "server" ]; then
-        # Restart DHCP server
-        /usr/sbin/service isc-dhcp-server start
-    fi
-    exit 0
+         echo $NEW_STATE > $MESH/gw_mode
+         echo 54MBit/54MBit > $MESH/gw_bandwidth
+         logger "batman gateway mode changed to $NEW_STATE"
 done
 
-if [ "$NEW_STATE" == "server" ]; then
-    /usr/sbin/service isc-dhcp-server status 2>&1> /dev/null
-    if [[ $? -ne 0 ]]
-    then
-        /usr/sbin/service isc-dhcp-server restart
-    fi
-fi
-if [ "$NEW_STATE" == "off" ]; then
-    /usr/sbin/service isc-dhcp-server status 2>&1> /dev/null
-    if [[ $? -eq 0 ]]
-    then
-        /usr/sbin/service isc-dhcp-server stop
-    fi
-fi
+# vim: noai:ts=4:sw=4:ff=unix:ft=text:fdm=marker
 
diff --git a/files/usr/share/munin/plugins/dhcp-pool b/files/usr/share/munin/plugins/dhcp-pool
deleted file mode 100644
index 2cb715d..0000000
--- a/files/usr/share/munin/plugins/dhcp-pool
+++ /dev/null
@@ -1,192 +0,0 @@
-#!/usr/bin/perl -w
-#
-# Copyright (C) 2008 Rien Broekstra <rien@rename-it.nl>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 2 dated June,
-# 1991.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-#
-#
-# Munin plugin to measure saturation of DHCP pools.
-#
-# Configuration variables:
-#
-#       conffile     - path to dhcpd's configuration file (default "/etc/dhcpd.conf")
-#       leasefile    - path to dhcpd's leases file (default "/var/lib/dhcp/dhcpd.leases")
-#
-# Parameters:
-#
-#       config    (required)
-#
-# Version 1.0, 2-12-2008
-
-use POSIX;
-use Time::Local;
-use strict;
-
-my $CONFFILE = exists $ENV{'conffile'} ? $ENV{'conffile'} : "/etc/dhcpd.conf";
-my $LEASEFILE = exists $ENV{'leasefile'} ? $ENV{'leasefile'} : "/var/lib/dhcp/dhcpd.leases";
-
-if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ) {
-
-}
-elsif ( defined $ARGV[0] and $ARGV[0] eq "config" ) {
-    my (%pools, $start, $label);
-
-    # Print general information
-    print "graph_title DHCP pool usage (in %)\n";
-    print "graph_args --upper-limit 100 -l 0\n";
-    print "graph_vlabel %\n";
-    print "graph_category network\n";
-
-    # Determine the available IP pools
-    %pools = determine_pools();
-    
-    # Print a label for each pool
-    foreach $start (keys %pools) {
-	$label = ip2string($start);
-	$label =~ s/\./\_/g;
-	print "$label.label Pool ".ip2string($start)."\n";
-	print "$label.warning 75\n";
-	print "$label.critical 100\n";
-    }
-}
-else {
-    my (@activeleases, %pools, $start, $end, $size, $free, $label, $lease);
-    
-    # Determine all leased IP addresses 
-    @activeleases = determine_active_leases();
-    
-    # Determine the available IP pools
-    %pools = determine_pools();
-
-    # For each pool, count how many leases from that pool are currently active
-    foreach $start (keys %pools) {
-	$size = $pools{$start};
-	$end = $start+$size;
-	$free = $size;
-
-	foreach $lease (@activeleases) {
-	    if ($lease >= $start && $lease <= $end) {
-		$free--;
-	    }
-	}
-	$label = ip2string($start);
-	$label =~ s/\./\_/g;
-	print "$label.value ".sprintf("%.1f", 100*($size-$free)/$size)."\n";
-    }
-}
-
-# Parse dhcpd.conf for range statements.
-#
-# Returns a hash with start IP -> size
-sub determine_pools {
-    my (%pools, @conffile, $line, $start, $end, $size);
-
-    open(CONFFILE, "<${CONFFILE}") || exit -1;
-    @conffile = <CONFFILE>;
-    close (CONFFILE);
-
-    foreach $line (@conffile) {
-	if ($line =~ /range[\s]+([\d]+\.[\d]+\.[\d]+\.[\d]+)[\s]+([\d]+\.[\d]+\.[\d]+\.[\d]+)/) {
-	    $start = string2ip($1);
-	    $end = string2ip($2);
-	    $size = $end - $start;
-	    defined($start) || next;
-	    defined($end) || next;
-	    
-	    $pools{$start} = $size;
-	}
-    }
-    return %pools;
-}
-
-# Very simple parser for dhcpd.leases. This will break very easily if dhcpd decides to 
-# format the file differently. Ideally a simple recursive-descent parser should be used.
-#
-# Returns an array with currently leased IP's
-sub determine_active_leases {
-    my (@leasefile, $startdate, $enddate, $lease, @activeleases, $mytz, $line, %saw);
-
-    open(LEASEFILE, "<${LEASEFILE}") || exit -1;
-    @leasefile = <LEASEFILE>;
-    close (LEASEFILE);
-
-    @activeleases = ();
-
-    # Portable way of converting a GMT date/time string to timestamp is setting TZ to UTC, and then calling mktime()
-    $mytz = $ENV{'TZ'};
-    $ENV{'TZ'} = 'UTC 0';
-    tzset();
-
-    foreach $line (@leasefile) {
-	if ($line =~ /lease ([\d]+\.[\d]+\.[\d]+\.[\d]+)/) {
-	    $lease = string2ip($1);
-	    defined($lease) || next;
-
-	    undef $startdate;
-	    undef $enddate;
-	}
-	elsif ($line =~ /starts \d ([\d]{4})\/([\d]{2})\/([\d]{2}) ([\d]{2}):([\d]{2}):([\d]{2})/) {
-	    $startdate = mktime($6, $5, $4, $3, $2-1, $1-1900, 0, 0);
-	}
-	elsif ($line =~ /ends \d ([\d]{4})\/([\d]{2})\/([\d]{2}) ([\d]{2}):([\d]{2}):([\d]{2})/) {
-	    $enddate = mktime($6, $5, $4, $3, $2-1, $1-1900, 0, 0);
-	    if (defined($enddate) && defined($startdate) && defined($lease)) {
-		if ($startdate < time() && $enddate > time()) {
-		    push (@activeleases, $lease);
-		}
-	    }
-	}
-
-    }
-    
-    # Set TZ back to its original setting
-    if (defined($mytz)) {
-	$ENV{'TZ'} = $mytz;
-    }
-    else {
-	delete $ENV{'TZ'};
-    }
-    tzset();
-
-    # Sort the array, strip doubles, and return
-    return grep(!$saw{$_}++, @activeleases);
-}
-
-#
-# Helper routine to convert an IP address a.b.c.d into an integer
-#
-# Returns an integer representation of an IP address
-sub string2ip {
-    my $string = shift;
-    defined($string) || return undef;
-    if ($string =~ /([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)/) {
-	if ($1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255) {
-	    return undef;
-	}
-	else {
-	    return $1 << 24 | $2 << 16 | $3 << 8 | $4;
-	}
-    }
-    return undef;
-}
-	    
-#
-# Returns a dotted quad notation of an 
-#
-sub ip2string {
-    my $ip = shift;
-    defined ($ip) || return undef;
-    return sprintf ("%d.%d.%d.%d", ($ip >> 24) & 0xff, ($ip >> 16) & 0xff, ($ip >> 8) & 0xff, $ip & 0xff);
-}
diff --git a/manifests/init.pp b/manifests/init.pp
index cc5f9f1..13813ec 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -1,35 +1,13 @@
-class ff_gw(
-  $ff_net,
-  $ff_mesh_net,
-  $ff_as,
-  $mesh_mac,
-  $gw_ipv4, $gw_ipv4_netmask   = '255.255.192.0',
-  $gw_ipv6, $gw_ipv6_prefixlen = '64',
-  $gw_pub_ipv6, $gw_pub_ipv6_prefixlen = '64',
-  $secret_key,                                      # for fastd
-  $vpn_provider = 'mullvad',                        # supported: mullvad or hideme
-  $vpn_ca_crt   = false,                            # openvpn CA cert to verify server
-  $vpn_usr_crt  = false, $vpn_usr_key = false,      # openvpn x.509 credentials
-  $vpn_usr_name = false,                            # openvpn user for auth-user-pass
-  $vpn_usr_pass = false,                            # openvpn password for auth-user-pass
-  $dhcprange_start, $dhcprange_end,
-  $gw_do_ic_peering = false,                        # configure inter city VPN
-  $tinc_name = false,
-  $tinc_keyfile = '/etc/tinc/rsa_key.priv',
-  $ic_vpn_ip4 = false,
-  $ic_vpn_ip6 = false
-) {
+class ff_gw($mesh_mac, $gw_ipv4, $gw_ipv6, $secret_key, $dhcprange_start, $dhcprange_end, $gw_do_ic_peering = false) {
+  class { 'ff_gw::apt': }
+  ->
   class { 'ff_gw::software': }
   ->
   class { 'ff_gw::fastd':
-    mesh_mac          => $mesh_mac,
-    gw_ipv4           => $gw_ipv4,
-    gw_ipv4_netmask   => $gw_ipv4_netmask,
-    gw_ipv6           => $gw_ipv6,
-    gw_ipv6_prefixlen => $gw_ipv6_prefixlen,
-    gw_pub_ipv6           => $gw_pub_ipv6,
-    gw_pub_ipv6_prefixlen => $gw_pub_ipv6_prefixlen,
-    secret_key        => $secret_key,
+    mesh_mac   => $mesh_mac,
+    gw_ipv4    => $gw_ipv4,
+    gw_ipv6    => $gw_ipv6,
+    secret_key => $secret_key,
   }
   ->
   class { 'ff_gw::dhcpd':
@@ -42,40 +20,30 @@ class ff_gw(
     own_ipv6 => $gw_ipv6,
   }
   ->
-  class { 'ff_gw::vpn':
-    provider => $vpn_provider,
-    usr_crt  => $vpn_usr_crt,
-    usr_key  => $vpn_usr_key,
-    ca_crt   => $vpn_ca_crt,
-    usr_name => $vpn_usr_name,
-    usr_pass => $vpn_usr_pass,
-  }
+  class { 'ff_gw::vpn': }
   ->
   class { 'ff_gw::iptables': }
   ->
   class { 'ff_gw::dnsmasq': }
   ->
-  class { 'ff_gw::dns_resolvconf':
-    gw_ipv4 => $gw_ipv4,
-  }
-  ->
   class { 'ff_gw::bird':
-    ff_net           => $ff_net,
-    ff_mesh_net      => $ff_mesh_net,
-    ff_as            => $ff_as,
     own_ipv4         => $gw_ipv4,
     own_ipv6         => $gw_ipv6,
     gw_do_ic_peering => $gw_do_ic_peering,
-    ic_vpn_ip6       => $ic_vpn_ip6,
   }
+}
 
-  if $gw_do_ic_peering {
-    class { 'ff_gw::tinc':
-      tinc_name    => $tinc_name,
-      tinc_keyfile => $tinc_keyfile,
-      ic_vpn_ip4   => $ic_vpn_ip4,
-      ic_vpn_ip6   => $ic_vpn_ip6
-    }
+class ff_gw::apt() {
+  class { '::apt':
+    always_apt_update => true
+  }
+  # batman repo
+  apt::source { 'universe-factory':
+    location   => 'http://repo.universe-factory.net/debian/',
+    release    => 'sid',
+    repos      => 'main',
+    key        => 'AB7A88C5B89033D8',
+    key_server => 'pgpkeys.mit.edu',
   }
 }
 
@@ -98,12 +66,8 @@ class ff_gw::software {
   }
 }
 
-class ff_gw::fastd($mesh_mac, $gw_ipv4, $gw_ipv4_netmask, $gw_ipv6, $gw_ipv6_prefixlen, $gw_pub_ipv6, $gw_pub_ipv6_prefixlen, $secret_key) {
+class ff_gw::fastd($mesh_mac, $gw_ipv4, $gw_ipv6, $secret_key) {
   validate_re($mesh_mac, '^de:ad:be:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}$')
-  # TODO: parameterize interface names
-  $br_if   = 'br-ffhh'
-  $bat_if  = 'bat0'
-  $mesh_if = 'ffhh-mesh-vpn'
 
   file {
     '/etc/fastd/ffhh-mesh-vpn':
@@ -114,7 +78,6 @@ class ff_gw::fastd($mesh_mac, $gw_ipv4, $gw_ipv4_netmask, $gw_ipv6, $gw_ipv6_pre
       content => template('ff_gw/etc/fastd/ffhh-mesh-vpn/fastd.conf.erb');
     '/etc/fastd/ffhh-mesh-vpn/secret.conf':
       ensure  => file,
-      mode    => '0600',
       content => inline_template('secret "<%= @secret_key %>";');
     '/root/bin':
       ensure => directory;
@@ -126,60 +89,45 @@ class ff_gw::fastd($mesh_mac, $gw_ipv4, $gw_ipv4_netmask, $gw_ipv6, $gw_ipv6_pre
       ensure => file,
       mode   => '0755',
       source => 'puppet:///modules/ff_gw/usr/local/bin/check_gateway';
-  }
-  ->
-  # should use an abstraction layer like https://forge.puppetlabs.com/ajjahn/network,
-  # but I found none that is flexible enough to handle all our config lines
-  augeas {
-    "${br_if}-inet6":
-      context => '/files/etc/network/interfaces',
-      changes => [
-        "set auto[child::1 = '${br_if}']/1 ${br_if}",
-        "set iface[. = '${br_if}'][1] ${br_if}",
-        "set iface[. = '${br_if}'][1]/family inet6",
-        "set iface[. = '${br_if}'][1]/method static",
-        "set iface[. = '${br_if}'][1]/bridge-ports none",
-        "set iface[. = '${br_if}'][1]/address ${gw_ipv6}",
-        "set iface[. = '${br_if}'][1]/netmask ${gw_ipv6_prefixlen}",
-        "set iface[. = '${br_if}'][1]/post-up '/sbin/ip -6 addr add ${gw_pub_ipv6}/${gw_pub_ipv6_prefixlen} dev \$IFACE'",
-      ],
-  }
-  ->
-  augeas {
-    "${br_if}-inet":
-      context => '/files/etc/network/interfaces',
-      changes => [
-        "set iface[. = '${br_if}'][2] ${br_if}",
-        "set iface[. = '${br_if}'][2]/family inet",
-        "set iface[. = '${br_if}'][2]/method static",
-        "set iface[. = '${br_if}'][2]/address ${gw_ipv4}",
-        "set iface[. = '${br_if}'][2]/netmask ${gw_ipv4_netmask}",
-      ],
-  }
-  ->
-  # TODO: parameterize ffhh-mesh-vpn
-  augeas {
-    $bat_if:
-      context => '/files/etc/network/interfaces',
-      changes => [
-        "set allow-hotplug[child::1 = '${bat_if}']/1 ${bat_if}",
-        "set iface[. = '${bat_if}'] ${bat_if}",
-        "set iface[. = '${bat_if}']/family inet6",
-        "set iface[. = '${bat_if}']/method manual",
-        "set iface[. = '${bat_if}']/pre-up[1] 'modprobe batman-adv'",
-        "set iface[. = '${bat_if}']/pre-up[2] 'batctl if add ${mesh_if}'",
-        "set iface[. = '${bat_if}']/up 'ip link set \$IFACE up'",
-        "set iface[. = '${bat_if}']/post-up[1] 'brctl addif ${br_if} \$IFACE'",
-        "set iface[. = '${bat_if}']/post-up[2] 'batctl it 10000'",
-        "set iface[. = '${bat_if}']/pre-down 'brctl delif ${br_if} \$IFACE || true'",
-        "set iface[. = '${bat_if}']/down 'ip link set \$IFACE down'",
-      ];
+    '/etc/network/interfaces':
+      ensure  => file,
+      #
+      content => inline_template('# managed by puppet
+
+# The loopback network interface
+auto lo
+iface lo inet loopback
+
+# The primary network interface
+allow-hotplug eth0
+iface eth0 inet dhcp
+
+auto br-ffhh
+iface br-ffhh inet6 static
+  bridge-ports none
+  address <%= @gw_ipv6 %>
+  netmask 64
+iface br-ffhh inet static
+  address <%= @gw_ipv4 %>
+  netmask 255.255.192.0
+
+allow-hotplug bat0
+iface bat0 inet6 manual
+  pre-up modprobe batman-adv
+  pre-up batctl if add ffhh-mesh-vpn
+  up ip link set $IFACE up
+  post-up brctl addif br-ffhh $IFACE
+  post-up batctl it 10000
+  post-up /sbin/ip rule add from all fwmark 0x1 table 42
+  pre-down brctl delif br-ffhh $IFACE || true
+  down ip link set $IFACE down
+');
   }
   ->
   vcsrepo { '/etc/fastd/ffhh-mesh-vpn/peers':
     ensure   => present,
     provider => git,
-    source   => 'git@git.hamburg.freifunk.net:fastdkeys',
+    source   => 'git@freifunk-gw01.hamburg.ccc.de:fastdkeys',
   }
 
   cron {
@@ -272,11 +220,7 @@ class ff_gw::dhcpd($gw_ipv4, $dhcprange_start, $dhcprange_end) {
     '/etc/rsyslog.d/dhcpd.conf':
       ensure  => file,
       notify  => Service['rsyslog'],
-      content => '# managed by puppet
-# log DHCP warnings
-local7.warn /var/log/dhcpd.log
-# but do not log DHCP leases etc.
-local7.* ~';
+      content => 'local7.warn /var/log/dhcpd.log';
     '/etc/default/isc-dhcpd':
       ensure  => file,
       content => '# managed by puppet
@@ -361,19 +305,6 @@ class ff_gw::dnsmasq() {
   }
 }
 
-class ff_gw::dns_resolvconf($gw_ipv4) {
-  # add our own IP as first entry to /etc/resolv.conf
-  # try to preserve everything else as the default nameserver should be the fastest
-  augeas { 'edit_resolv_conf':
-      context => '/files/etc/resolv.conf',
-      changes => [
-          'ins nameserver before nameserver[1]',
-          "set nameserver[1] \"${gw_ipv4}\"",
-      ],
-      onlyif  => "get nameserver[1] != \"${gw_ipv4}\"",
-  }
-}
-
 class ff_gw::radvd($own_ipv6) {
   package {
     'radvd':
@@ -396,9 +327,7 @@ class ff_gw::radvd($own_ipv6) {
     context => '/files/etc/sysctl.conf',
     changes => [
       'set net.ipv4.ip_forward 1',
-      'set net.ipv6.conf.all.forwarding 1',
-      'set net.ipv4.icmp_errors_use_inbound_ifaddr 1',
-      'set net.ipv4.netfilter.ip_conntrack_max 65536'
+      'set net.ipv6.conf.all.forwarding 1'
     ],
   }
   ~>
@@ -410,32 +339,10 @@ class ff_gw::radvd($own_ipv6) {
   }
 }
 
-class ff_gw::vpn($provider, $ca_crt, $usr_crt, $usr_key, $usr_name, $usr_pass, $openvpn_version = '2.3.2-7~bpo70+1', $ensure = 'running') {
-  # TODO: note that even the hideme.conf uses the interface name 'mullvad',
-  #       because that interface is referenced elsewhere
-
-  # TODO: maybe we should check that provider and auth methods match
-  #       atm we trust the caller to give the right combination
-  if $usr_name {
-    # hideme config with user/pass file
-    file {
-      "/etc/openvpn/${provider}/auth.txt":
-        ensure  => file,
-        mode    => '0600',
-        content => "$usr_name\n$usr_pass\n";
-    }
-  } elsif $usr_crt {
-    # mullvad config with x.509
-    file {
-      "/etc/openvpn/${provider}/client.crt":
-        ensure  => file,
-        content => $usr_crt;
-      "/etc/openvpn/${provider}/client.key":
-        ensure  => file,
-        mode    => '0600',
-        content => $usr_key;
-    }
-  }
+class ff_gw::vpn($ca_crt, $usr_crt, $usr_key, $openvpn_version = '2.3.2-7~bpo70+1', $ensure = 'running') {
+  # TODO: this name is used in several places including dnsmasq
+  # and is even used for other providers, thus hard to change
+  $vpnname = 'mullvad'
 
   package {
     'openvpn':
@@ -443,22 +350,28 @@ class ff_gw::vpn($provider, $ca_crt, $usr_crt, $usr_key, $usr_name, $usr_pass, $
   }
   ->
   file {
-    "/etc/openvpn/${provider}":
+    "/etc/openvpn/${vpnname}":
       ensure => directory;
-    "/etc/openvpn/${provider}/ca.crt":
+    "/etc/openvpn/${vpnname}/ca.crt":
       ensure  => file,
       content => $ca_crt;
-    "/etc/openvpn/${provider}/${provider}-up":
+    "/etc/openvpn/${vpnname}/client.crt":
+      ensure  => file,
+      content => $usr_crt;
+    "/etc/openvpn/${vpnname}/client.key":
+      ensure  => file,
+      mode    => '0600',
+      content => $usr_key;
+    "/etc/openvpn/${vpnname}/mullvad-up":
+      ensure  => file,
+      mode    => '0755',
+      content => '#!/bin/sh
+ip route replace 0.0.0.0/1 via $5 table 42
+ip route replace 128.0.0.0/1 via $5 table 42
+exit 0';
+    "/etc/openvpn/${vpnname}.conf":
       ensure => file,
-      mode   => '0755',
-      source => "puppet:///modules/ff_gw/etc/openvpn/${provider}/${provider}-up";
-    "/etc/openvpn/${provider}.conf":
-      ensure => file,
-      source => "puppet:///modules/ff_gw/etc/openvpn/${provider}.conf";
-    '/etc/openvpn/update-dnsmasq-forward':
-      ensure => file,
-      mode   => '0755',
-      source => 'puppet:///modules/ff_gw/etc/openvpn/update-dnsmasq-forward';
+      source => "puppet:///modules/ff_gw/etc/openvpn/${vpnname}.conf";
   }
   ~>
   service { 'openvpn':
@@ -483,12 +396,9 @@ class ff_gw::iptables {
     '/etc/iptables/rules.v4':
       ensure => file,
       source => 'puppet:///modules/ff_gw/etc/iptables/rules.v4';
-    '/etc/iptables/rules.v6':
-      ensure => file,
-      source => 'puppet:///modules/ff_gw/etc/iptables/rules.v6';
     '/etc/rc.local':
       ensure  => file,
-      content => '#!/bin/sh
+      content => '#!/bin/sh -e
 # managed by puppet
 #
 # rc.local
@@ -504,9 +414,6 @@ class ff_gw::iptables {
 
 /sbin/ip route add unreachable default table 42
 /sbin/ip rule add from all fwmark 0x1 table 42
-/sbin/ip -6 rule add from all fwmark 0x1 table 42
-/bin/echo 8192 > /sys/module/nf_conntrack/parameters/hashsize
-/sbin/ip -6 rule add priority 30000 from all fwmark 0x1 table 43
 exit 0';
   }
   ~>
@@ -517,7 +424,7 @@ exit 0';
   }
 }
 
-class ff_gw::bird($ff_net, $ff_mesh_net, $ff_as, $own_ipv4, $own_ipv6, $gw_do_ic_peering, $ic_vpn_ip6, $version = '1.4.4-1~bpo70+1') {
+class ff_gw::bird($own_ipv4, $own_ipv6, $gw_do_ic_peering, $version = 'present') {
   # read peering data from data file
   $module_path = get_module_path($module_name)
   $peeringdata = loadyaml("${module_path}/data/peering.yaml")
@@ -526,47 +433,15 @@ class ff_gw::bird($ff_net, $ff_mesh_net, $ff_as, $own_ipv4, $own_ipv6, $gw_do_ic
   $ic_peerings_v4 = $peeringdata[ic_peerings_v4]
   $ic_peerings_v6 = $peeringdata[ic_peerings_v6]
 
-  # for compatibility with old & new bird versions
-  file { '/etc/bird':
-    ensure => directory;
-  }
-
   package {
-    'bird':
+    'bird6':
       ensure => $version,
   }
   ->
   file {
-    '/etc/bird/bird.conf':
-      ensure  => file,
-      require => File['/etc/bird'],
-      content => template('ff_gw/etc/bird/bird.conf.erb');
-    '/etc/bird.conf':
-      ensure => link,
-      target => '/etc/bird/bird.conf';
-  }
-  ~>
-  service {
-    'bird':
-      ensure  => running,
-      enable  => true,
-      require => Service['openvpn'],
-  }
-
-  package {
-    'bird6':
-      ensure  => $version,
-      require => Package['bird'],
-  }
-  ->
-  file {
-    '/etc/bird/bird6.conf':
-      ensure  => file,
-      require => File['/etc/bird'],
-      content => template('ff_gw/etc/bird/bird6.conf.erb');
     '/etc/bird6.conf':
-      ensure  => link,
-      target  => '/etc/bird/bird6.conf';
+      ensure  => file,
+      content => template('ff_gw/etc/bird6.conf.erb');
   }
   ~>
   service {
@@ -576,57 +451,20 @@ class ff_gw::bird($ff_net, $ff_mesh_net, $ff_as, $own_ipv4, $own_ipv6, $gw_do_ic
       require => Service['openvpn'],
   }
 
-}
-
-class ff_gw::tinc($tinc_name, $tinc_keyfile, $ic_vpn_ip4, $ic_vpn_ip6, $version = 'present') {
-  # note: class ff_gw needs default values and sets these to false.
-  # in case the tinc class is applied then these are the real checks,
-  # making sure the user set usable parameters:
-  validate_string($tinc_name)
-  validate_string($tinc_keyfile)
-  validate_string($ic_vpn_ip4)
-  validate_string($ic_vpn_ip6)
 
   package {
-    'tinc':
+    'bird':
       ensure => $version,
   }
   ->
-  vcsrepo { '/etc/tinc/icvpn':
-    ensure   => present,
-    provider => git,
-    source   => 'https://github.com/freifunk/icvpn',
-  }
-  ->
   file {
-    '/etc/tinc/nets.boot':
+    '/etc/bird.conf':
       ensure  => file,
-      content => '# all tinc networks -- managed by puppet
-icvpn
-';
-    '/etc/tinc/icvpn/tinc.conf':
-      ensure  => file,
-      content => template('ff_gw/etc/tinc/icvpn/tinc.conf.erb');
-    '/etc/tinc/icvpn/tinc-up':
-      ensure  => file,
-      mode    => '0755',
-      content => inline_template('#!/bin/sh
-/sbin/ip link set dev $INTERFACE up
-/sbin/ip addr add dev $INTERFACE <%= @ic_vpn_ip4 %>/16 broadcast 10.207.255.255
-/sbin/ip -6 addr add dev $INTERFACE <%= @ic_vpn_ip6 %>/96 preferred_lft 0
-');
-    '/etc/tinc/icvpn/tinc-down':
-      ensure  => file,
-      mode    => '0755',
-      content => inline_template('#!/bin/sh
-/sbin/ip addr del dev $INTERFACE <%= @ic_vpn_ip4 %>/16 broadcast 10.207.255.255
-/sbin/ip -6 addr del dev $INTERFACE <%= @ic_vpn_ip6 %>/96
-/sbin/ip link set dev $INTERFACE down
-');
+      content => template('ff_gw/etc/bird.conf.erb');
   }
   ~>
   service {
-    'tinc':
+    'bird':
       ensure  => running,
       enable  => true,
       require => Service['openvpn'],
diff --git a/manifests/sysadmin.pp b/manifests/sysadmin.pp
index b5f3d9f..88caf39 100644
--- a/manifests/sysadmin.pp
+++ b/manifests/sysadmin.pp
@@ -1,36 +1,29 @@
 # kitchen sink class for various small settings
-class ff_gw::sysadmin($zabbixserver = '127.0.0.1', $muninserver = '127.0.0.1', $sethostname = false, $setip = false, $accounts = {}) {
-  # first of all: fix my hostname
-  if $sethostname and $setip {
-    # set system hostname
-    class { 'ff_gw::sysadmin::hostname':
-      newname => $sethostname,
-      newip   => $setip,
-    }
+class ff_gw::sysadmin {
+
+  # use Hiera as a Puppet data source
+  file {
+    '/etc/puppet/hiera.yaml':
+      # content from git repo, not from puppet
+      ensure => file;
+    '/etc/hiera.yaml':
+      ensure => link,
+      target => '/etc/puppet/hiera.yaml';
   }
 
-  # next important thing: set up apt repositories
-  class { 'ff_gw::sysadmin::software': }
-
-  # remove cronjob
-  cron {
-    'ntpdate-debian':
-      ensure  => absent,
-      command => '/usr/sbin/ntpdate-debian',
-      user    => root,
-      minute  => '0';
+  # use backports repo
+  apt::source { 'wheezy-backports':
+    location   => 'http://ftp.de.debian.org/debian/',
+    release    => 'wheezy-backports',
+    repos      => 'main',
   }
-  # replace with a real NTP daemon
-  package { 'ntp':
-    ensure => present,
-  }
-  ~>
-  service { 'ntp':
-    ensure => true,
+  # some more packages
+  package {
+    ['vim-nox', 'git', 'etckeeper', 'pv', 'curl', 'atop',
+    'screen', 'tcpdump', 'rsync', 'file']:
+      ensure => installed,
   }
 
-  # user accounts
-  create_resources('account', $accounts)
   # Sudo
   include sudo
   sudo::conf { 'admins':
@@ -53,101 +46,91 @@ class ff_gw::sysadmin($zabbixserver = '127.0.0.1', $muninserver = '127.0.0.1', $
     enable => true,
   }
 
-  class { 'ff_gw::sysadmin::zabbix':
-    zabbixserver => $zabbixserver,
-  }
-  class { 'ff_gw::sysadmin::munin':
-    muninserver => $muninserver,
-  }
-}
-
-class ff_gw::sysadmin::hostname($newname, $newip) {
-  # short name
-  $alias = regsubst($newname, '^([^.]*).*$', '\1')
-
-  # clean old names
-  if $::hostname != $alias {
-    host { $::hostname: ensure => absent }
-  }
-  if $::fqdn != $newname {
-    host { $::fqdn:     ensure => absent }
-  }
-
-  # rewrite config files:
-  host { $newname:
-    ensure => present,
-    ip     => $newip,
-    alias  => $alias ? {
-      $::hostname => undef,
-      default     => $alias
-    },
-    before => Exec['hostname.sh'],
-  }
-
-  file { '/etc/mailname':
-    ensure  => present,
-    owner   => 'root',
-    group   => 'root',
-    mode    => '0644',
-    content => "${newname}\n",
-  }
-
-  file { '/etc/hostname':
-    ensure  => present,
-    owner   => 'root',
-    group   => 'root',
-    mode    => '0644',
-    content => "${newname}\n",
-    notify  => Exec['hostname.sh'],
-  }
-
-  exec { 'hostname.sh':
-    command     => '/etc/init.d/hostname.sh start',
-    refreshonly => true,
-  }
-}
-
-# everything related to apt-repos and default tools
-class ff_gw::sysadmin::software() {
-  class { '::apt':
-    always_apt_update => true
-  }
-  # use backports repo
-  apt::source { 'wheezy-backports':
-    location => 'http://ftp.de.debian.org/debian/',
-    release  => 'wheezy-backports',
-    repos    => 'main',
-  }
-  # batman repo
-  apt::source { 'universe-factory':
-    location   => 'http://repo.universe-factory.net/debian/',
-    release    => 'sid',
-    repos      => 'main',
-    key        => '16EF3F64CB201D9C',
-    key_server => 'pool.sks-keyservers.net',
-  }
-  # bird repo // TODO: no PGP key
-  apt::source { 'bird-network':
-    location   => 'http://bird.network.cz/debian/',
+  # zabbix
+  apt::source { 'zabbix':
+    location   => 'http://repo.zabbix.com/zabbix/2.2/debian',
     release    => 'wheezy',
     repos      => 'main',
+    key        => '79EA5ED4',
+    key_server => 'pgpkeys.mit.edu',
+  }
+  ->
+  package { 'zabbix-agent':
+    ensure => latest;
+  }
+  ->
+  file { '/etc/zabbix/zabbix_agentd.d/argos_monitoring.conf':
+    ensure  => file,
+    content => "# managed by puppet
+Server=argos.mschuette.name
+HostnameItem=${::hostname}
+";
+  }
+  ~>
+  service { 'zabbix-agent':
+    ensure => running,
+    enable => true,
   }
 
-  # then install some basic packages
+  # munin
   package {
-    ['vim-nox', 'git', 'etckeeper', 'pv', 'curl', 'atop',
-    'screen', 'tcpdump', 'rsync', 'file', 'psmisc', 'ntpdate']:
+    [ 'munin-node', 'vnstat' ]:
       ensure => installed,
   }
   ->
-  # remove atop cronjob
-  file { '/etc/cron.d/atop':
-    ensure => absent,
+  file {
+    '/etc/munin/munin-node.conf':
+      ensure  => file,
+      # mostly Debin pkg default
+      content => inline_template('# managed by puppet
+log_level 4
+log_file /var/log/munin/munin-node.log
+pid_file /var/run/munin/munin-node.pid
+
+background 1
+setsid 1
+
+user root
+group root
+
+# Regexps for files to ignore
+ignore_file [\#~]$
+ignore_file DEADJOE$
+ignore_file \.bak$
+ignore_file %$
+ignore_file \.dpkg-(tmp|new|old|dist)$
+ignore_file \.rpm(save|new)$
+ignore_file \.pod$
+
+port 4949
+
+host_name <%= @fqdn %>
+cidr_allow 78.47.49.236/32
+host <%= @ipaddress_eth0 %>
+');
+    '/usr/share/munin/plugins/vnstat_':
+      ensure => file,
+      mode   => '0755',
+      source => 'puppet:///modules/ff_gw/usr/share/munin/plugins/vnstat_';
+    '/etc/munin/plugins/vnstat_eth0_monthly_rxtx':
+      ensure => link,
+      target => '/usr/share/munin/plugins/vnstat_';
+    '/usr/share/munin/plugins/udp-statistics':
+      ensure => file,
+      mode   => '0755',
+      source => 'puppet:///modules/ff_gw/usr/share/munin/plugins/udp-statistics';
+    '/etc/munin/plugins/udp-statistics':
+      ensure => link,
+      target => '/usr/share/munin/plugins/udp-statistics';
+    # TODO: delete not needed plugins
+    '/etc/munin/plugin-conf.d/vnstat':
+      ensure  => file,
+      content => '[vnstat_eth0_monthly_rxtx]
+env.estimate 1';
   }
-  ->
-  # stop atop daemon (cf. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=506191)
-  service { 'atop':
-    ensure  => stopped,
-    enable  => false,
+  ~>
+  service { 'munin-node':
+    ensure => running,
+    enable => true;
   }
 }
diff --git a/manifests/sysadmin/munin.pp b/manifests/sysadmin/munin.pp
deleted file mode 100644
index 2a4acd8..0000000
--- a/manifests/sysadmin/munin.pp
+++ /dev/null
@@ -1,99 +0,0 @@
-# munin config
-class ff_gw::sysadmin::munin($muninserver) {
-  package {
-    [ 'munin-node', 'vnstat', 'bc' ]:
-      ensure => installed,
-  }
-  ->
-  file {
-    '/etc/munin/munin-node.conf':
-      ensure  => file,
-      # mostly Debin pkg default
-      content => inline_template('# managed by puppet
-log_level 4
-log_file /var/log/munin/munin-node.log
-pid_file /var/run/munin/munin-node.pid
-
-background 1
-setsid 1
-
-user root
-group root
-
-# Regexps for files to ignore
-ignore_file [\#~]$
-ignore_file DEADJOE$
-ignore_file \.bak$
-ignore_file %$
-ignore_file \.dpkg-(tmp|new|old|dist)$
-ignore_file \.rpm(save|new)$
-ignore_file \.pod$
-
-port 4949
-
-host_name <%= @fqdn %>
-cidr_allow <%= @muninserver %>/32
-host <%= @ipaddress_eth0 %>
-');
-    '/usr/share/munin/plugins/vnstat_':
-      ensure => file,
-      mode   => '0755',
-      source => 'puppet:///modules/ff_gw/usr/share/munin/plugins/vnstat_';
-    '/etc/munin/plugins/vnstat_eth0_monthly_rxtx':
-      ensure => link,
-      target => '/usr/share/munin/plugins/vnstat_';
-    '/usr/share/munin/plugins/udp-statistics':
-      ensure => file,
-      mode   => '0755',
-      source => 'puppet:///modules/ff_gw/usr/share/munin/plugins/udp-statistics';
-    '/etc/munin/plugins/udp-statistics':
-      ensure => link,
-      target => '/usr/share/munin/plugins/udp-statistics';
-    '/usr/share/munin/plugins/dhcp-pool':
-      ensure => file,
-      mode   => '0755',
-      source => 'puppet:///modules/ff_gw/usr/share/munin/plugins/dhcp-pool';
-    '/etc/munin/plugins/dhcp-pool':
-      ensure => link,
-      target => '/usr/share/munin/plugins/dhcp-pool';
-    '/etc/munin/plugin-conf.d/dhcp-pool':
-      ensure  => file,
-      content => '[dhcp-pool]
-env.leasefile /var/lib/dhcp/dhcpd.leases
-env.conffile /etc/dhcp/dhcpd.conf';
-    '/etc/munin/plugins/if_mullvad':
-      ensure => link,
-      target => '/usr/share/munin/plugins/if_';
-    '/etc/munin/plugins/if_err_mullvad':
-      ensure => link,
-      target => '/usr/share/munin/plugins/if_err_';
-    '/etc/munin/plugins/if_bat0':
-      ensure => link,
-      target => '/usr/share/munin/plugins/if_';
-    '/etc/munin/plugins/if_err_bat0':
-      ensure => link,
-      target => '/usr/share/munin/plugins/if_err_';
-    '/etc/munin/plugins/if_br-ffhh':
-      ensure => link,
-      target => '/usr/share/munin/plugins/if_';
-    '/etc/munin/plugins/if_err_br-ffhh':
-      ensure => link,
-      target => '/usr/share/munin/plugins/if_err_';
-    '/etc/munin/plugins/if_ffhh-mesh-vpn':
-      ensure => link,
-      target => '/usr/share/munin/plugins/if_';
-    '/etc/munin/plugins/if_err_ffhh-mesh-vpn':
-      ensure => link,
-      target => '/usr/share/munin/plugins/if_err_';
-    # TODO: delete not needed plugins
-    '/etc/munin/plugin-conf.d/vnstat':
-      ensure  => file,
-      content => '[vnstat_eth0_monthly_rxtx]
-env.estimate 1';
-  }
-  ~>
-  service { 'munin-node':
-    ensure => running,
-    enable => true;
-  }
-}
diff --git a/manifests/sysadmin/zabbix.pp b/manifests/sysadmin/zabbix.pp
deleted file mode 100644
index d3db871..0000000
--- a/manifests/sysadmin/zabbix.pp
+++ /dev/null
@@ -1,28 +0,0 @@
-# zabbix agent config
-class ff_gw::sysadmin::zabbix($zabbixserver) {
-  apt::source { 'zabbix':
-    location   => 'http://repo.zabbix.com/zabbix/2.2/debian',
-    release    => 'wheezy',
-    repos      => 'main',
-    key        => '79EA5ED4',
-    key_server => 'pgpkeys.mit.edu',
-  }
-  ->
-  package { 'zabbix-agent':
-    ensure => latest;
-  }
-  ->
-  file { '/etc/zabbix/zabbix_agentd.d/argos_monitoring.conf':
-    ensure  => file,
-    content => "# managed by puppet
-Server=${zabbixserver}
-ServerActive=${zabbixserver}
-HostnameItem=${::hostname}
-";
-  }
-  ~>
-  service { 'zabbix-agent':
-    ensure => running,
-    enable => true,
-  }
-}
diff --git a/templates/etc/bird.conf.erb b/templates/etc/bird.conf.erb
new file mode 100644
index 0000000..ac6cd2e
--- /dev/null
+++ b/templates/etc/bird.conf.erb
@@ -0,0 +1,151 @@
+router id <%= @own_ipv4 %>;
+
+table ffhh; # BGP Peerings
+table ibgp;
+table icvpn; # BGP Peerings (ICVPN)
+table freifunk; # Kernel table 42 (Routing from Freifunk networks)
+
+function is_freifunk_dn42() {
+    return (net ~ [
+        10.0.0.0/8{12,32},
+        10.100.0.0/14,
+        172.22.0.0/15+,
+        172.31.0.0/16
+        ]);
+}
+
+function is_freifunk() {
+    return (net ~ [10.0.0.0/8+]);
+}
+
+function is_chaosvpn() {
+    return (net ~ [172.31.0.0/16+]);
+}
+
+function is_self_net() {
+    return (net ~ [10.112.0.0/16+]);
+}
+
+function is_self() {
+    return (proto = "static_ffhh");
+}
+
+function is_dn42_aggregate() {
+    return (net ~ [172.22.0.0/15{16,32}]);
+}
+
+filter ffhh_internal_export {
+    if (proto = "dn42_aggregate_ffhh" || proto = "local_ffhh") then accept;
+    if (source != RTS_BGP && proto != "pipe_icvpn") then reject; 
+    if (proto ~ "bgp_ibgp_*") then reject;
+    if (is_dn42_aggregate()) then reject;
+    accept;
+}
+
+
+protocol pipe pipe_ffhh {
+    peer table ffhh;
+    import all;
+    export none;
+};
+
+protocol pipe pipe_icvpn {
+    table ffhh;
+    peer table icvpn;
+    export where is_self();
+    import all;
+    mode opaque;
+};
+
+protocol pipe pipe_freifunk {
+    peer table freifunk;
+    import none;
+    export all;
+};
+
+protocol pipe pipe_ibgp {
+    peer table ibgp;
+    import all;
+    export where !is_self_net();
+    mode opaque;
+};
+
+protocol kernel kernel_master {
+    scan time 20;
+    import none;
+    export filter {
+        krt_prefsrc = <%= @own_ipv4 %>;
+        accept;
+    };
+};
+
+protocol kernel kernel_freifunk {
+    scan time 20;
+    import none;
+    export filter {
+        krt_prefsrc = <%= @own_ipv4 %>;
+        accept;
+    };
+    table freifunk;
+    device routes;
+    kernel table 42;
+};
+
+# This pseudo-protocol watches all interface up/down events.
+protocol device {
+    scan time 10;       # Scan interfaces every 10 seconds
+};
+
+protocol static unreachable_default {
+    table freifunk;
+    route 0.0.0.0/0 reject;
+};
+
+protocol static static_ffhh {
+    table ffhh;
+    route 10.112.0.0/16 reject;
+};
+
+protocol static local_ffhh {
+    table ffhh;
+    route 10.112.0.0/18 via "freifunk";
+};
+
+protocol static dn42_aggregate_ffhh {
+    table ffhh;
+    route 172.22.0.0/15 reject;
+};
+
+
+template bgp bgp_ibgp {
+    local as 65112;
+    table ibgp;
+    import filter {
+        preference = 99;
+        accept;
+    };
+    export all;
+    gateway direct;
+    next hop self;
+};
+
+template bgp bgp_icvpn {
+    local as 65112;
+    table icvpn;
+    import where (is_freifunk_dn42() && !is_self_net());
+    export all;
+};
+
+<% @peerings_v4.each_pair do |key, hash| -%><% if hash["ip"] != @own_ipv4 -%>
+protocol bgp <%= key %> from <%= hash["template"] %> {
+  neighbor <%= hash["ip"] %> as <%= hash["as"] %>;
+};
+<% end -%><% end -%>
+
+<% if @gw_do_ic_peering -%>
+<% @ic_peerings_v4.each_pair do |key, hash| -%><% if hash["ip"] != @own_ipv4 -%>
+protocol bgp <%= key %> from <%= hash["template"] %> {
+  neighbor <%= hash["ip"] %> as <%= hash["as"] %>;
+};
+<% end -%><% end -%>
+<% end -%>
diff --git a/templates/etc/bird/bird.conf.erb b/templates/etc/bird/bird.conf.erb
deleted file mode 100644
index 2697190..0000000
--- a/templates/etc/bird/bird.conf.erb
+++ /dev/null
@@ -1,190 +0,0 @@
-table ibgp; # internal BGP peerings
-table ebgp; # external (icvpn) BGP peerings
-table freifunk; # kernel table 42 for routing from ff network
-
-define ownas = <%= @ff_as %>;
-
-router id <%= @own_ipv4 %>;
-
-### functions ###
-
-# own network
-function is_self_net() {
-    return (net ~ [<%= @ff_net %>+]);
-}
-
-# freifunk ip ranges in general
-function is_freifunk() {
-  return net ~ [ 10.0.0.0/8+,
-    104.0.0.0/8+
-  ];
-}
-
-# dn42 ip ranges
-function is_dn42() {
-  return net ~ [ 172.22.0.0/15+,
-    195.160.168.0/23+,
-    91.204.4.0/22+,
-    193.43.220.0/23+,
-    87.106.29.254/32,
-    85.25.246.16/28+,
-    46.4.248.192/27+,
-    94.45.224.0/19+,
-    195.191.196.0/23+,
-    80.244.241.224/27+,
-    46.19.90.48/28+,
-    46.19.90.96/28+,
-    178.63.170.40/32,
-    188.40.34.241/32,
-    195.16.84.40/29+,
-    37.1.89.160/29+,
-    178.33.32.123/32+,
-    37.1.89.160/29+,
-    185.28.77.16/29+,
-    185.28.77.192/27+,
-    192.175.48.0/24+
-  ];
-}
-
-# chaosvpn ranges
-function is_chaos() {
-  return net ~ [ 10.4.0.0/16+,
-    10.32.0.0/16+,
-    10.42.16.0/20+, # legacy
-    10.100.0.0/14+,
-    10.104.0.0/14+,
-    172.31.0.0/16+,
-    83.133.178.0/23+,
-    172.26.0.0/15+,
-    176.9.52.58/32+,
-    193.103.159.0/24+,
-    193.103.160.0/23+,
-    212.12.50.208/29+,
-    213.238.61.128/26+
-  ];
-}
-
-### kernel ###
-
-# synchronize from bird to main kernel routing table
-# nothing in the other direction
-protocol kernel k_mast {
-    scan time 10;
-    import none;
-    export filter {
-        krt_prefsrc = <%= @own_ipv4 %>;
-        accept;
-    };
-};
-
-# synchronize from birds freifunk table to kernel routing table 42
-# nothing in the other direction
-protocol kernel k_frei {
-    scan time 10;
-    table freifunk;
-    kernel table 42;
-    import none;
-    export filter {
-        krt_prefsrc = <%= @own_ipv4 %>;
-        accept;
-    };
-};
-
-# this pseudo-protocol watches all interface up/down events
-protocol device {
-    scan time 10;
-};
-
-### pipes ###
-
-# sync nothing from main routing table to ebgp
-# sync routes (not own network) from ebgp to main routing table
-protocol pipe p_maintbl {
-    peer table ebgp;
-    import where !is_self_net();
-    export none;
-};
-
-# sync routes (not own network) from ebgp to ibgp
-# sync routes (all) from ibgp to ebgp
-protocol pipe p_ibgptbl {
-  table ebgp;
-  peer table ibgp;
-  import all;
-  export where !is_self_net();
-};
-
-# sync routes (freifunk, dn42 and chaosvpn) from ibgp to freifunk
-# sync nothing from freifunk to ibgp
-protocol pipe p_freitbl {
-  table ibgp;
-  peer table freifunk;
-  import none;
-  export where (is_freifunk() || is_dn42() || is_chaos());
-};
-
-### static routes ###
-
-# if no openvpn is running, reject everything we do not have a route for
-protocol static unreachable_default {
-  route 0.0.0.0/0 reject;
-  table freifunk;
-};
-
-protocol static static_ffhh {  
-  route <%= @ff_net %> reject;
-  table ebgp;
-};
-
-# in hamburg we use a /18 from our /16 in the mesh
-# create a route for that in freifunk table
-protocol static local_ffhh {
-  route <%= @ff_mesh_net %> via "br-ffhh";
-  table freifunk;
-};
-
-### templates ###
-
-# template for same city freifunk gateways
-template bgp locals {
-  table ibgp;
-  local as ownas;
-  import filter {
-    preference = 99;
-    accept;
-  };
-  export where source = RTS_BGP;
-  direct;
-  next hop self;
-};
-
-### local gateways ###
-
-<% @peerings_v4.each_pair do |key, hash| -%><% if hash["ip"] != @own_ipv4 -%>
-protocol bgp <%= key %> from <%= hash["template"] %> {
-  neighbor <%= hash["ip"] %> as ownas;
-};
-<% end -%><% end -%>
-
-<% if @gw_do_ic_peering -%>
-### icvpn peerings ###
-
-# template for icvpn gateways of other cities
-template bgp peers {
-  table ebgp;
-  local as ownas;
-  # ignore routes for our own network
-  import where ((is_freifunk() || is_dn42()) && !is_chaos() && !is_self_net());
-  export where ((is_freifunk() || is_dn42()) && !is_chaos());
-  route limit 10000;
-};
-
-<% @ic_peerings_v4.each_pair do |key, hash| -%><% if hash["ip"] != @own_ipv4 -%>
-protocol bgp <%= key %> from <%= hash["template"] %> {
-  neighbor <%= hash["ip"] %> as <%= hash["as"] %>;
-};
-<% end -%><% end -%>
-<% end -%>
-
-# this is for local peerings not managed by puppet
-include "*.peering";
diff --git a/templates/etc/bird/bird6.conf.erb b/templates/etc/bird/bird6.conf.erb
deleted file mode 100644
index 8bd036e..0000000
--- a/templates/etc/bird/bird6.conf.erb
+++ /dev/null
@@ -1,199 +0,0 @@
-table ibgp;	# internal BGP peerings
-table ebgp;	# external (icvpn) BGP peerings
-table freifunk; # synced to kernel table 42 for routing from ff network
-table unreach;	# synced to kernel table 43 to intercept in cases there 
-		# is no default route via icvpn
-
-# quite self explanatory :)
-define ownas = <%= @ff_as %>;
-
-# the router id in bird is 32 bit wide and bird allows the IPv4 notation
-# to set it. quite confusing, but setting it to the gateway's IPv4 address
-# is a good approach here.
-router id <%= @own_ipv4 %>;
-
-### functions ###
-
-# own networks as of http://wiki.freifunk.net/IPv6:Prefixe and
-# http://wiki.freifunk.net/IC-VPN
-# the '+' defines to not only match the prefix length given but
-# also any smaller prefixes (like 48 and 64)
-function is_self_net() {
-  return net ~ [ fd51:2bb2:fd0d::/48+,
-    2001:bf7:180::/44+,
-    2001:bf7:190::/44+,
-    2001:bf7:200::/44+,
-    2001:bf7:210::/44+,
-    2001:bf7:220::/44+,
-    2001:bf7:230::/44+];
-}
-
-# freifunk ip ranges in general
-# this is the public address space assigned to the
-# Foerderverein freie Netzwerke e.V.
-function is_freifunk() {
-  return net ~ [ 2001:bf7::/32+ ];
-}
-
-# unique local addresses
-# this is the non-public address range used within freifunk
-# communities and the IC-VPN
-function is_ula() {
-  return net ~ [ fc00::/7{48,64} ];
-}
-
-# default route
-# be careful with importing default routes from arbitrary peers
-function is_default() {
-  return net ~ [ ::0/0 ];
-}
-
-### kernel ###
-
-# synchronize from bird to main kernel routing table
-# nothing in the other direction
-# do not sync a default route we received to the main routing table
-# as this might collide with the normal default route of the host
-protocol kernel k_mast {
-  scan time 20;
-  import none;
-  export where !is_default();
-};
-
-# synchronize from birds freifunk table to kernel routing table 42
-# nothing in the other direction
-protocol kernel k_frei {
-  scan time 20;
-  table freifunk;
-  kernel table 42;
-  import none;
-  export all;
-};
-
-# syncronize from birds unreach table to kernel routing table 43
-# nothing in the other direction
-protocol kernel k_unreach {
-  scan time 20;
-  table unreach;
-  kernel table 43;
-  import none;
-  export all;
-};
-
-# this pseudo-protocol watches all interface up/down events
-protocol device {
-    scan time 20;
-};
-
-### pipes ###
-
-# sync nothing from main routing table to ebgp
-# sync routes (not own network) from ebgp to main routing table
-protocol pipe p_maintbl {
-  peer table ebgp;
-  import where !is_self_net();
-  export none;
-};
-
-# sync routes (not own network) from ebgp to ibgp
-# sync routes (all) from ibgp to ebgp
-protocol pipe p_ibgptbl {
-  table ebgp;
-  peer table ibgp;
-  import all;
-  export where !is_self_net();
-};
-
-# sync routes (freifunk, ula and default routes we got) from ibgp to freifunk
-# sync nothing from freifunk to ibgp
-protocol pipe p_freitbl {
-  table ibgp;
-  peer table freifunk;
-  import none;
-  export where is_freifunk() || is_default() || is_ula();
-};
-
-### static routes ###
-
-# here you should define unreachable (=reject) routes for your own
-# prefixes from http://wiki.freifunk.net/IC-VPN and
-# http://wiki.freifunk.net/IPv6:Prefixe
-protocol static static_ffhh {  
-  route fd51:2bb2:fd0d::/48 reject;
-  route 2001:bf7:180::/44 reject;
-  route 2001:bf7:190::/44 reject;
-  route 2001:bf7:200::/44 reject;
-  route 2001:bf7:210::/44 reject;
-  route 2001:bf7:220::/44 reject;
-  route 2001:bf7:230::/44 reject;
-  table ebgp;
-};
-
-# these are the address ranges used in your network
-# note that these should be /64 networks in most cases from within
-# the above bigger ranges
-protocol static local_ffhh {
-  route fd51:2bb2:fd0d::/64 via "br-ffhh"; # replace br-ffhh with the name
-  route 2001:bf7:180::/64 via "br-ffhh";   # of your freifunk interface
-  table freifunk;
-};
-
-# this defines an unreachable default route so that pakets are not forwarded
-# via the main routing table if no default route exists within table 42
-# note that this requires an additional rule within your policy routing
-protocol static unreachable_default {
-  route ::/0 reject;
-  table unreach;
-};
-
-### templates ###
-
-# template for same city freifunk gateways
-# even the ones which do not have a direct IC-VPN connection
-template bgp locals {
-  table ibgp;
-  local as ownas;
-  source address <%= @own_ipv6 %>;
-  import filter {
-    preference = 99;
-    accept;
-  };
-  export where source = RTS_BGP;
-  direct;
-  next hop self;
-};
-
-<% @peerings_v6.each_pair do |key, hash| -%><% if hash["ip"] != @own_ipv6 -%>
-protocol bgp <%= key %> from <%= hash["template"] %> {
-  neighbor <%= hash["ip"] %> as <%= hash["as"] %>;
-};
-<% end -%><% end -%>
-
-<% if @gw_do_ic_peering -%>
-# template for icvpn gateways of other cities
-template bgp peers {
-  table ebgp;
-  local as ownas;
-  source address <%= @ic_vpn_ip6 %>;
-  # ignore routes for our own network
-  import where (is_freifunk() || is_ula()) && !is_self_net();
-  export where (is_ula() || is_freifunk() || (source = RTS_BGP)) && !is_default();
-  route limit 10000;
-};
-
-# template for upstream gateways
-# that are allowed to announce a default route to us
-template bgp upstream from peers {
-  # accept freifunk networks and default route
-  import where (is_freifunk() || is_ula() || is_default()) && !is_self_net();
-};
-
-<% @ic_peerings_v6.each_pair do |key, hash| -%><% if hash["ip"] != @own_ipv6 -%>
-protocol bgp <%= key %> from <%= hash["template"] %> {
-  neighbor <%= hash["ip"] %> as <%= hash["as"] %>;
-};
-<% end -%><% end -%>
-<% end -%>
-
-# this is for local peerings not managed by puppet
-include "*.peering6";
diff --git a/templates/etc/bird6.conf.erb b/templates/etc/bird6.conf.erb
new file mode 100644
index 0000000..1f73075
--- /dev/null
+++ b/templates/etc/bird6.conf.erb
@@ -0,0 +1,87 @@
+# managed by puppet
+#
+# the ff ip of the gateway
+router id <%= @own_ipv4 %>;
+
+# routing tables
+table ffhh;
+
+# filter to check ulas
+function is_ula() {
+  return (net ~ [ fc00::/7{48,64} ]);
+}
+
+function is_self() {
+  return (proto = "static_ffhh");
+}
+
+filter ffhh_internal_export {
+  if (proto = "local_ffhh") then accept;
+  if (source != RTS_BGP) then reject;
+  if (is_ula() && proto != "static_ffhh") then accept;
+  else reject;
+}
+
+# don't use kernel's routes for bird, but export bird's routes to kernel
+protocol kernel {
+  scan time 20;  # Scan kernel routing table every 20 seconds
+  import none;  # Default is import all
+  export all;
+}
+
+# This pseudo-protocol watches all interface up/down events.
+protocol device {
+  scan time 10;  # Scan interfaces every 10 seconds
+}
+
+# define our routes
+protocol static static_ffhh {
+  table ffhh;
+  # reject route if announced from external
+  route fd51:2bb2:fd0d::/48 reject;
+};
+
+protocol static local_ffhh {
+  table ffhh;
+  route fd51:2bb2:fd0d::/64 via "br-ffhh";
+};
+
+protocol pipe pipe_ffhh {
+  peer table ffhh;
+  import all;
+  export none;
+};
+
+# template for internal routing
+template bgp bgp_ibgp {
+  table ffhh;
+  local as 65112;
+  source address <%= @own_ipv6 %>;
+  import all;
+  export where source = RTS_BGP;
+  gateway direct;
+  next hop self;
+};
+
+# icvpn template for hamburg03
+template bgp bgp_icvpn {
+  local as 65112;
+  source address <%= @own_ipv6 %>;
+  table ffhh;
+  import where is_ula();
+  export where is_self() || (source = RTS_BGP);
+};
+
+<% @peerings_v6.each_pair do |key, hash| -%><% if hash["ip"] != @own_ipv6 -%>
+protocol bgp <%= key %> from <%= hash["template"] %> {
+  neighbor <%= hash["ip"] %> as <%= hash["as"] %>;
+};
+<% end -%><% end -%>
+
+<% if @gw_do_ic_peering -%>
+<% @ic_peerings_v6.each_pair do |key, hash| -%><% if hash["ip"] != @own_ipv6 -%>
+protocol bgp <%= key %> from <%= hash["template"] %> {
+  neighbor <%= hash["ip"] %> as <%= hash["as"] %>;
+};
+<% end -%><% end -%>
+<% end -%>
diff --git a/templates/etc/dhcp/dhcpd.conf.erb b/templates/etc/dhcp/dhcpd.conf.erb
index 56a2ca4..733d413 100644
--- a/templates/etc/dhcp/dhcpd.conf.erb
+++ b/templates/etc/dhcp/dhcpd.conf.erb
@@ -16,10 +16,9 @@ subnet 10.112.0.0 netmask 255.255.192.0 {
     authoritative;
     range <%= @dhcprange_start %> <%= @dhcprange_end %>;
 
-    # DNS: this gateway (<%= @gw_ipv4 %>) & srv01 (10.112.1.1)
-    option domain-name-servers <%= @gw_ipv4 %>, 10.112.1.1;
+    # DNS: srv01 (10.112.1.1) & gw01 (10.112.14.1)
+    option domain-name-servers 10.112.1.1, 10.112.14.1;
     option routers <%= @gw_ipv4 %>;
-    option ntp-servers 10.112.16.1, 10.112.22.1;
 }
 
 include "/etc/dhcp/static.conf";
diff --git a/templates/etc/fastd/ffhh-mesh-vpn/fastd.conf.erb b/templates/etc/fastd/ffhh-mesh-vpn/fastd.conf.erb
index b4962e9..0ea508d 100644
--- a/templates/etc/fastd/ffhh-mesh-vpn/fastd.conf.erb
+++ b/templates/etc/fastd/ffhh-mesh-vpn/fastd.conf.erb
@@ -4,7 +4,6 @@ log to syslog level info;
 interface "ffhh-mesh-vpn";
 method "salsa2012+gmac"; # new method, between gateways for the moment (faster)
 method "xsalsa20-poly1305"; # old method
-secure handshakes no; # be compatible to old peers
 bind 0.0.0.0:10000;
 hide ip addresses yes;
 hide mac addresses yes;
diff --git a/templates/etc/radvd.conf.erb b/templates/etc/radvd.conf.erb
index 0932dac..50cffde 100644
--- a/templates/etc/radvd.conf.erb
+++ b/templates/etc/radvd.conf.erb
@@ -7,9 +7,6 @@ interface br-ffhh
 
  prefix fd51:2bb2:fd0d::/64 {
  };
- prefix 2001:bf7:180::/64 {
- };
-
 
  RDNSS <%= @own_ipv6 %> {
  };
diff --git a/templates/etc/tinc/icvpn/tinc.conf.erb b/templates/etc/tinc/icvpn/tinc.conf.erb
deleted file mode 100644
index 5ea534b..0000000
--- a/templates/etc/tinc/icvpn/tinc.conf.erb
+++ /dev/null
@@ -1,56 +0,0 @@
-Name = <%= @tinc_name %>
-PrivateKeyFile = <%= @tinc_keyfile %>
-Mode = Switch
-PingTimeout = 30
-Port = 656
-Hostnames = yes
-
-ConnectTo = augsburg1
-ConnectTo = augsburg2
-ConnectTo = bayreuth1
-ConnectTo = berlin1
-ConnectTo = bielefeld1
-ConnectTo = bielefeld2
-ConnectTo = bremen2
-ConnectTo = chemnitz1
-ConnectTo = diac24_sbc
-ConnectTo = diac24_sbz
-ConnectTo = dreilaendereck1
-ConnectTo = dresden1
-ConnectTo = ffhallevpn1
-ConnectTo = flensburg1
-ConnectTo = franken1
-ConnectTo = franken2
-ConnectTo = franken3
-ConnectTo = franken_ro1
-ConnectTo = freiburg1
-ConnectTo = gronau1
-ConnectTo = gronau2
-ConnectTo = guetersloh1
-ConnectTo = guetersloh4
-ConnectTo = halle1
-ConnectTo = jena1
-ConnectTo = jena2
-ConnectTo = kiel0
-ConnectTo = kiel1
-ConnectTo = kiel2
-ConnectTo = kiel3
-ConnectTo = kiel4
-ConnectTo = koeln1
-ConnectTo = leipzig1
-ConnectTo = leipzig2
-ConnectTo = ljubljana1
-ConnectTo = luebeck1
-ConnectTo = luebeck2
-ConnectTo = magdeburg1
-ConnectTo = magdeburg2
-ConnectTo = mainz1
-ConnectTo = nrw2
-ConnectTo = oldenburg1
-ConnectTo = ostholstein1
-ConnectTo = rheinneckar1
-ConnectTo = ruhrgebiet1
-ConnectTo = weimar1
-ConnectTo = weimar2
-ConnectTo = wiesbaden1
-