diff -Nur kamikaze_7.09.orig/package/hipl/files/hipd.init kamikaze_7.09/package/hipl/files/hipd.init
--- kamikaze_7.09.orig/package/hipl/files/hipd.init 1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/hipl/files/hipd.init 2008-07-04 16:43:46.000000000 +0200
@@ -0,0 +1,26 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+START=65
+STOP=65
+
+HIPD_OPTS="-bk"
+
+start() {
+ echo -n "Starting hipd"
+ hipd ${HIPD_OPTS}
+ echo "."
+}
+
+restart() {
+ echo -n "Restarting hipd"
+ killall hipd
+ hipd ${HIPD_OPTS}
+ echo "."
+}
+
+stop() {
+ echo -n "Stopping hipd"
+ killall hipd
+ echo "."
+}
--- kamikaze_7.09.orig/package/hipl/files/hipfw.init 2008-08-28 15:58:19.000000000 +0200
+++ kamikaze_7.09/package/hipl/files/hipfw.init 2008-08-20 16:01:20.000000000 +0200
@@ -0,0 +1,21 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006 OpenWrt.org
+
+START=65
+STOP=65
+
+HIPFW_INIT=/etc/hip/test/firewall.init
+HIPFW_START=/etc/hip/test/firewall.start
+
+start() {
+ echo -n "Starting hipfw"
+ ${HIPFW_INIT}
+ ${HIPFW_START}
+ echo "."
+}
+
+stop() {
+ echo -n "Stopping hipfw"
+ killall hipfw
+ echo "."
+}
diff -Nur kamikaze_7.09.orig/package/hipl/files/hipl.modules kamikaze_7.09/package/hipl/files/hipl.modules
--- kamikaze_7.09.orig/package/hipl/files/hipl.modules 1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/hipl/files/hipl.modules 2008-07-04 16:53:37.000000000 +0200
@@ -0,0 +1,17 @@
+hmac
+crypto_null
+sha1
+crypto_hash
+aes
+ipv6
+af_key
+xfrm_user
+ah4
+esp4
+xfrm4_tunnel
+ipcomp
+ah6
+esp6
+tunnel6
+xfrm6_tunnel
+ipcomp6
diff -Nur kamikaze_7.09.orig/package/hipl/files/test/firewall.flush kamikaze_7.09/package/hipl/files/test/firewall.flush
--- kamikaze_7.09.orig/package/hipl/files/test/firewall.flush 1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/hipl/files/test/firewall.flush 2008-08-06 17:08:24.000000000 +0200
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+ip6tables -F INPUT
+ip6tables -F OUTPUT
+ip6tables -F FORWARD
+
diff -Nur kamikaze_7.09.orig/package/hipl/files/test/firewall.init kamikaze_7.09/package/hipl/files/test/firewall.init
--- kamikaze_7.09.orig/package/hipl/files/test/firewall.init 1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/hipl/files/test/firewall.init 2008-08-28 15:53:58.000000000 +0200
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+NET_INTNAT=192.168.6.0/24
+
+iptables -P INPUT ACCEPT
+iptables -P OUTPUT ACCEPT
+iptables -P FORWARD ACCEPT
+
+ip6tables -A FORWARD -p 253 -j QUEUE
+ip6tables -A FORWARD -p 50 -j QUEUE
+ip6tables -A FORWARD -p 22 -j ACCEPT
+ip6tables -A INPUT -p 253 -j QUEUE
+ip6tables -A INPUT -p 50 -j QUEUE
+ip6tables -A INPUT -p 22 -j ACCEPT
+ip6tables -A OUTPUT -p 253 -j QUEUE
+ip6tables -A OUTPUT -p 50 -j QUEUE
+ip6tables -A OUTPUT -p 22 -j ACCEPT
+
+iptables -t nat -F
+
+iptables -t nat -A POSTROUTING -s ${NET_INTNAT} -d ${NET_INTNAT} -j ACCEPT
+iptables -t nat -A POSTROUTING -s ${NET_INTNAT} -j MASQUERADE
diff -Nur kamikaze_7.09.orig/package/hipl/files/test/firewall.rules kamikaze_7.09/package/hipl/files/test/firewall.rules
--- kamikaze_7.09.orig/package/hipl/files/test/firewall.rules 1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/hipl/files/test/firewall.rules 2008-08-06 17:08:24.000000000 +0200
@@ -0,0 +1,13 @@
+# HOOK [match] TARGET
+# HOOK ::=
+# match ::= src_hit [!] --hi
+# -dst_hit [!]
+# -type [!]
+# -i [!]
+# -o [!]
+# -state [!] --verify_responder --accept_mobile
+# TARGET::=
+
+INPUT -src_hit 2001:7c:e802:a62e:cccb:8bd2:79f2:e6d7 -dst_hit 2001:7c:a2ff:6c4:379a:411:bd02:5375 ACCEPT
+OUTPUT -dst_hit 2001:7c:e802:a62e:cccb:8bd2:79f2:e6d7 -src_hit 2001:7c:a2ff:6c4:379a:411:bd02:5375 ACCEPT
+
diff -Nur kamikaze_7.09.orig/package/hipl/files/test/firewall.start kamikaze_7.09/package/hipl/files/test/firewall.start
--- kamikaze_7.09.orig/package/hipl/files/test/firewall.start 1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/hipl/files/test/firewall.start 2008-08-18 15:26:43.000000000 +0200
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# HOOK [match] TARGET
+# HOOK ::=
+# match ::= src_hit [!] --hi
+# -dst_hit [!]
+# -type [!]
+# -i [!]
+# -o [!]
+# -state [!] --verify_responder --accept_mobile
+# TARGET::=
+
+export PATH=.:../../firewall:$PWD/test/performance:$PWD/firewall:$PATH
+
+RULE_FILE=/tmp/fw.tmp
+TIMEOUT=0
+HIPFW_OPTS="-dbkm"
+
+# agony: 2001:1c:fa08:bdca:9401:417e:1589:7c8b
+# envy: 2001:1e:cf29:ce40:e828:c2f2:17e3:5516
+
+ACCEPT_INIT_LIST=2001:1c:fa08:bdca:9401:417e:1589:7c8b
+#ACCEPT_INIT_LIST=
+#DROP_INIT_LIST=2001:1c:fa08:bdca:9401:417e:1589:7c8b
+DROP_INIT_LIST=
+
+RESP=2001:1e:cf29:ce40:e828:c2f2:17e3:5516
+
+rm $RULE_FILE 2>/dev/null
+
+for INIT in $ACCEPT_INIT_LIST
+do
+ echo "FORWARD -src_hit $INIT -dst_hit $RESP ACCEPT" >> $RULE_FILE
+ echo "FORWARD -src_hit $RESP -dst_hit $INIT ACCEPT" >> $RULE_FILE
+done
+
+for INIT in $DROP_INIT_LIST
+do
+ echo "FORWARD -src_hit $INIT -dst_hit $RESP DROP" >> $RULE_FILE
+ echo "FORWARD -src_hit $RESP -dst_hit $INIT DROP" >> $RULE_FILE
+done
+
+hipfw ${HIPFW_OPTS} $RULE_FILE $TIMEOUT
diff -Nur kamikaze_7.09.orig/package/hipl/Makefile kamikaze_7.09/package/hipl/Makefile
--- kamikaze_7.09.orig/package/hipl/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/hipl/Makefile 2008-07-17 14:39:02.636586470 +0200
@@ -0,0 +1,93 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=hipl--openwrt
+PKG_VERSION:=2.6
+
+PKG_SOURCE:=$(PKG_NAME)--$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://localhost/hipl/
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)--$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/hipl
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=+libopenssl +libxml2 +iptables +ipsec-tools +uclibc
+ TITLE:=Host identity protocol
+ URL:=hipl.hiit.fi
+
+endef
+
+CONFIGURE_VARS += \
+ LIBS="-lxml2 -lcrypto -lm -lz" \
+ CPPFLAGS="$$$$CPPFLAGS -I$(STAGING_DIR)/usr/include/libxml2 -I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include" \
+ LDFLAGS="$$$$LDFLAGS -L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
+ OPENWRT="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
+ OPENWRT_LIB_STATIC="$(STAGING_DIR)/lib/libc.a" \
+
+define Build/Configure
+ (cd $(PKG_BUILD_DIR); rm -rf config.{cache,status}; \
+ ./autogen.sh --host=$(GNU_TARGET_NAME) --target=$(GNU_TARGET_NAME) \
+ );
+
+ (cd $(PKG_BUILD_DIR)/libinet6; test -L include || ln -v -s include_glibc23 include; \
+ );
+
+ (cp $(PKG_BUILD_DIR)/libinet6/include/ifaddrs.h $(STAGING_DIR)/include/ \
+ );
+
+ (cd ..; \
+ );
+
+ $(CONFIGURE_VARS);
+
+ $(call Build/Configure/Default, \
+ --enable-shared \
+ --disable-nls \
+ --disable-agent \
+ --enable-midauth \
+ --enable-opendht \
+ --enable-openwrt \
+ --disable-privsep \
+ );
+endef
+
+define Build/Compile
+ ($(CONFIGURE_VARS) \
+ $(MAKE) -C $(PKG_BUILD_DIR));
+
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ INSTALL="install -c" \
+ install
+endef
+
+define Package/hipl/install
+ $(INSTALL_DIR) $(1)/etc/init.d/
+ $(INSTALL_DIR) $(1)/etc/hip/
+ $(INSTALL_DIR) $(1)/etc/hip/test/
+ $(INSTALL_DIR) $(1)/etc/modules.d/
+ $(INSTALL_DIR) $(1)/usr/bin/
+ $(INSTALL_DIR) $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/include/libipsec
+ $(INSTALL_DIR) $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/sbin/
+
+ $(INSTALL_BIN) ./files/hipd.init $(1)/etc/init.d/hipd
+ $(INSTALL_BIN) ./files/hipfw.init $(1)/etc/init.d/hipfw
+ $(INSTALL_DATA) ./files/hipl.modules $(1)/etc/modules.d/35-hipl
+ $(INSTALL_BIN) ./files/test/* $(1)/etc/hip/test/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/conntest* $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hipsetup* $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libinet6test* $(1)/usr/bin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/listifaces* $(1)/usr/bin/
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhip* $(1)/usr/lib/
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libinet6* $(1)/usr/lib/
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libopphip* $(1)/usr/lib/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/* $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,hipl))
diff -Nur kamikaze_7.09.orig/package/libxml2/Makefile kamikaze_7.09/package/libxml2/Makefile
--- kamikaze_7.09.orig/package/libxml2/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/package/libxml2/Makefile 2008-06-18 11:13:46.027201536 +0200
@@ -0,0 +1,101 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 7271 2007-05-18 09:43:14Z florian $
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libxml2
+PKG_VERSION:=2.6.32
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://xmlsoft.org/sources/ \
+ ftp://fr.rpmfind.net/pub/libxml/
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libxml2
+ SECTION:=libs
+ CATEGORY:=Libraries
+ DEPENDS:=+libpthread +zlib
+ TITLE:=Gnome XML library
+ DESCRIPTION:=\
+ A library for manipulating XML and HTML resources.
+ URL:=http://xmlsoft.org/
+endef
+
+define Build/Configure
+ $(call Build/Configure/Default, \
+ --enable-shared \
+ --enable-static \
+ --with-c14n \
+ --with-html \
+ --without-ftp \
+ --without-http \
+ --without-iconv \
+ --without-iso8859x \
+ --with-legacy \
+ --with-output \
+ --with-reader \
+ --with-sax1 \
+ --with-schemas \
+ --with-threads \
+ --with-tree \
+ --with-valid \
+ --with-writer \
+ --with-xinclude \
+ --with-xpath \
+ --with-xptr \
+ --with-zlib \
+ --with-regexp \
+ )
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ DESTDIR="$(PKG_INSTALL_DIR)" \
+ all install
+endef
+
+define Build/InstallDev
+ mkdir -p $(STAGING_DIR)/usr/bin
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/xml2-config $(STAGING_DIR)/usr/bin/
+ mkdir -p $(STAGING_DIR)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/libxml2 $(STAGING_DIR)/usr/include/
+ mkdir -p $(STAGING_DIR)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libxml2.{a,so*} $(STAGING_DIR)/usr/lib/
+ mkdir -p $(STAGING_DIR)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libxml-2.0.pc $(STAGING_DIR)/usr/lib/pkgconfig/
+ $(SED) 's,-I$$$${includedir}/libxml2,,g' $(STAGING_DIR)/usr/bin/xml2-config
+ $(SED) 's,-I$$$${includedir},,g' $(STAGING_DIR)/usr/bin/xml2-config
+ $(SED) 's,-I$(STAGING_DIR)/usr/include,,g' $(STAGING_DIR)/usr/bin/xml2-config
+ $(SED) 's,-L$$$${libdir},,g' $(STAGING_DIR)/usr/bin/xml2-config
+ $(SED) 's,-L$(STAGING_DIR)/usr/lib,,g' $(STAGING_DIR)/usr/bin/xml2-config
+ $(SED) 's,-I$$$${includedir}/libxml2,,g' $(STAGING_DIR)/usr/lib/pkgconfig/libxml-2.0.pc
+ $(SED) 's,-L$$$${libdir},,g' $(STAGING_DIR)/usr/lib/pkgconfig/libxml-2.0.pc
+ $(SED) "s,"prefix\=/usr",prefix=$(STAGING_DIR)/usr," $(STAGING_DIR)/usr/lib/pkgconfig/libxml-2.0.pc
+ $(SED) "s,"exec_prefix\=/usr",exec_prefix=$(STAGING_DIR)/usr," $(STAGING_DIR)/usr/lib/pkgconfig/libxml-2.0.pc
+endef
+
+define Build/UninstallDev
+ rm -rf \
+ $(STAGING_DIR)/usr/bin/xml2-config \
+ $(STAGING_DIR)/usr/include/libxml2 \
+ $(STAGING_DIR)/usr/lib/libxml2.{a,so*} \
+ $(STAGING_DIR)/usr/lib/pkgconfig/libxml-2.0.pc
+endef
+
+define Package/libxml2/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/libxml2.so.* $(1)/usr/lib/
+endef
+
+$(eval $(call BuildPackage,libxml2))
diff -Nur kamikaze_7.09.orig/target/linux/atheros-2.6/config/default kamikaze_7.09/target/linux/atheros-2.6/config/default
--- kamikaze_7.09.orig/target/linux/atheros-2.6/config/default 2007-09-20 10:54:11.000000000 +0200
+++ kamikaze_7.09/target/linux/atheros-2.6/config/default 2008-06-20 00:37:27.000000000 +0200
@@ -44,6 +44,7 @@
# CONFIG_DM9000 is not set
CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_DMA_NONCOHERENT=y
+CONFIG_DUMMY=y
CONFIG_FS_POSIX_ACL=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
# CONFIG_GENERIC_GPIO is not set
@@ -57,10 +58,20 @@
# CONFIG_I2C is not set
# CONFIG_IDE is not set
# CONFIG_IEEE80211 is not set
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_IPSEC_NAT_TRAVERSAL is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
CONFIG_IRQ_CPU=y
CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_MACH_ALCHEMY is not set
+CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_TIMER=m
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
@@ -149,8 +160,9 @@
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_SLRAM is not set
CONFIG_MTD_SPIFLASH=y
+# CONFIG_NETLABEL is not set
CONFIG_NET_SCH_FIFO=y
-# CONFIG_NETDEV_1000 is not set
+CONFIG_PACKET=y
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
@@ -162,6 +174,9 @@
# CONFIG_RTC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_CAPABILITIES=m
+# CONFIG_SECURITY_NETWORK is not set
# CONFIG_SERIAL_8250_EXTENDED is not set
CONFIG_SERIAL_8250_NR_UARTS=1
CONFIG_SERIAL_8250_RUNTIME_UARTS=1
@@ -178,6 +193,7 @@
# CONFIG_SIBYTE_SENTOSA is not set
# CONFIG_SIBYTE_SWARM is not set
# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_SOUND is not set
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
@@ -188,7 +204,9 @@
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_TRAD_SIGNALS=y
+CONFIG_UNIX=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_VIDEO_V4L1_COMPAT is not set
diff -Nur kamikaze_7.09.orig/target/linux/brcm47xx-2.6/config/default kamikaze_7.09/target/linux/brcm47xx-2.6/config/default
--- kamikaze_7.09.orig/target/linux/brcm47xx-2.6/config/default 2007-09-20 10:53:45.000000000 +0200
+++ kamikaze_7.09/target/linux/brcm47xx-2.6/config/default 2008-08-21 10:37:25.000000000 +0200
@@ -193,6 +193,7 @@
# CONFIG_NET_SCH_NETEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NTFS_FS is not set
+CONFIG_PACKET=y
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
@@ -247,6 +248,7 @@
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_TRAD_SIGNALS=y
+CONFIG_UNIX=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_USB_CATC is not set
# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
diff -Nur kamikaze_7.09.orig/target/linux/atheros-2.6/Makefile kamikaze_7.09/target/linux/atheros-2.6/Makefile
--- kamikaze_7.09.orig/target/linux/atheros-2.6/Makefile 2007-09-20 10:54:11.000000000 +0200
+++ kamikaze_7.09/target/linux/atheros-2.6/Makefile 2008-06-20 00:37:27.000000000 +0200
@@ -11,7 +11,7 @@
BOARDNAME:=Atheros
FEATURES:=squashfs jffs2
-LINUX_VERSION:=2.6.21.5
+LINUX_VERSION:=2.6.21.3
define Target/Description
Build firmware images for Atheros SoC boards
diff -Nur kamikaze_7.09.orig/target/linux/atheros-2.6/patches/beet-interfamily-sleep-loopback-2.6.21.3.patch kamikaze_7.09/target/linux/atheros-2.6/patches/beet-interfamily-sleep-loopback-2.6.21.3.patch
--- kamikaze_7.09.orig/target/linux/atheros-2.6/patches/beet-interfamily-sleep-loopback-2.6.21.3.patch 1970-01-01 01:00:00.000000000 +0100
+++ kamikaze_7.09/target/linux/atheros-2.6/patches/beet-interfamily-sleep-loopback-2.6.21.3.patch 2008-06-20 00:37:27.000000000 +0200
@@ -0,0 +1,839 @@
+diff -urN a/include/net/xfrm.h b/include/net/xfrm.h
+--- a/include/net/xfrm.h 2007-05-25 16:36:44.000000000 +0300
++++ b/include/net/xfrm.h 2007-05-25 16:36:44.000000000 +0300
+@@ -237,7 +237,7 @@
+ extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
+ extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
+ extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
+-#define XFRM_ACQ_EXPIRES 30
++#define XFRM_ACQ_EXPIRES 3
+
+ struct xfrm_tmpl;
+ extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
+diff -urN a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
+--- a/net/ipv4/xfrm4_tunnel.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv4/xfrm4_tunnel.c 2007-05-25 16:36:44.000000000 +0300
+@@ -28,7 +28,7 @@
+
+ static int ipip_init_state(struct xfrm_state *x)
+ {
+- if (x->props.mode != XFRM_MODE_TUNNEL)
++ if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != XFRM_MODE_BEET)
+ return -EINVAL;
+
+ if (x->encap)
+diff -urN a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
+--- a/net/ipv4/xfrm4_mode_beet.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv4/xfrm4_mode_beet.c 2007-05-25 16:36:44.000000000 +0300
+@@ -6,6 +6,7 @@
+ * Herbert Xu
+ * Abhinav Pathak
+ * Jeff Ahrenholz
++ * Joakim Koskela
+ */
+
+ #include
+@@ -29,89 +30,163 @@
+ */
+ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+- struct iphdr *iph, *top_iph = NULL;
+- int hdrlen, optlen;
+-
+- iph = skb->nh.iph;
+- skb->h.ipiph = iph;
+-
+- hdrlen = 0;
+- optlen = iph->ihl * 4 - sizeof(*iph);
+- if (unlikely(optlen))
+- hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
+-
+- skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen);
+- top_iph = skb->nh.iph;
+- skb->h.raw += sizeof(*iph) - hdrlen;
+-
+- memmove(top_iph, iph, sizeof(*iph));
+- if (unlikely(optlen)) {
+- struct ip_beet_phdr *ph;
+-
+- BUG_ON(optlen < 0);
+-
+- ph = (struct ip_beet_phdr *)skb->h.raw;
+- ph->padlen = 4 - (optlen & 4);
+- ph->hdrlen = optlen / 8;
+- ph->nexthdr = top_iph->protocol;
+- if (ph->padlen)
+- memset(ph + 1, IPOPT_NOP, ph->padlen);
+-
+- top_iph->protocol = IPPROTO_BEETPH;
+- top_iph->ihl = sizeof(struct iphdr) / 4;
+- }
+-
+- top_iph->saddr = x->props.saddr.a4;
+- top_iph->daddr = x->id.daddr.a4;
+-
+- return 0;
++ struct dst_entry *dst = skb->dst;
++ int hdrlen;
++ struct iphdr *iphv4, *top_iphv4;
++ struct ipv6hdr *iphv6, *top_iphv6;
++
++ if (skb->nh.iph->version == 4) {
++
++ int optlen;
++
++ /* 4-4 */
++
++ iphv4 = skb->nh.iph;
++ skb->h.ipiph = iphv4;
++
++ hdrlen = x->props.header_len;
++
++ optlen = iphv4->ihl * 4 - sizeof(*iphv4);
++
++ if (!optlen) {
++ hdrlen -= IPV4_BEET_PHMAXLEN;
++ } else {
++ skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4));
++ hdrlen -= optlen & 4;
++ }
++
++ skb->nh.raw = skb_push(skb, hdrlen);
++
++ top_iphv4 = skb->nh.iph;
++ hdrlen = iphv4->ihl * 4 - optlen;
++ skb->h.raw += hdrlen;
++ memmove(top_iphv4, iphv4, hdrlen);
++
++ if (unlikely(optlen)) {
++ struct ip_beet_phdr *ph;
++
++ BUG_ON(optlen < 0);
++
++ ph = (struct ip_beet_phdr *)skb->h.raw;
++ ph->padlen = 4 - (optlen & 4);
++ ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
++ ph->nexthdr = iphv4->protocol;
++ top_iphv4->protocol = IPPROTO_BEETPH;
++ top_iphv4->ihl = sizeof(struct iphdr) / 4;
++ }
++
++ top_iphv4->saddr = x->props.saddr.a4;
++ top_iphv4->daddr = x->id.daddr.a4;
++
++ skb->protocol = htons(ETH_P_IP);
++
++ } else if (skb->nh.iph->version == 6) {
++
++ u8 protocol;
++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++
++ /* Inner = 6, Outer = 4 : changing the external IP hdr
++ * to the outer addresses
++ */
++
++ hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN;
++ skb_push(skb, hdrlen);
++ iphv6 = skb->nh.ipv6h;
++
++ skb->nh.raw = skb->data;
++ top_iphv6 = skb->nh.ipv6h;
++
++ protocol = iphv6->nexthdr;
++ skb->nh.raw = skb_pull(skb, delta);
++ top_iphv4 = skb->nh.iph;
++ skb->h.raw = skb->data + hdrlen;
++ top_iphv4->ihl = (sizeof(struct iphdr) >> 2);
++ top_iphv4->version = 4;
++ top_iphv4->id = 0;
++ top_iphv4->frag_off = htons(IP_DF);
++ top_iphv4->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
++ top_iphv4->saddr = x->props.saddr.a4;
++ top_iphv4->daddr = x->id.daddr.a4;
++ skb->h.raw += top_iphv4->ihl*4;
++ top_iphv4->protocol = protocol;
++
++ skb->protocol = htons(ETH_P_IP);
++ } else
++ BUG_ON(1);
++
++ return 0;
+ }
+
+ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
+ {
+ struct iphdr *iph = skb->nh.iph;
++ int hops = skb->nh.iph->ttl;
+ int phlen = 0;
+ int optlen = 0;
++ int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr);
++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
+ __u8 ph_nexthdr = 0, protocol = 0;
+ int err = -EINVAL;
+
+ protocol = iph->protocol;
+
+- if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
+- struct ip_beet_phdr *ph;
+-
+- if (!pskb_may_pull(skb, sizeof(*ph)))
+- goto out;
+- ph = (struct ip_beet_phdr *)(skb->h.ipiph + 1);
+-
+- phlen = sizeof(*ph) + ph->padlen;
+- optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen);
+- if (optlen < 0 || optlen & 3 || optlen > 250)
+- goto out;
+-
+- if (!pskb_may_pull(skb, phlen + optlen))
+- goto out;
+- skb->len -= phlen + optlen;
+-
+- ph_nexthdr = ph->nexthdr;
++ if (x->sel.family == AF_INET6) {
++ /* Here, the inner family is 6, therefore I have to
++ * substitute the IPhdr by enlarging it */
++ if (skb_tailroom(skb) < delta){
++ if (pskb_expand_head(skb, 0, delta, GFP_ATOMIC))
++ goto out;
++ }
++ skb->nh.raw -= delta;
++ } else if (x->sel.family == AF_INET) {
++ if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
++ struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1);
++
++ if (!pskb_may_pull(skb, sizeof(*ph)))
++ goto out;
++
++ phlen = ph->hdrlen * 8;
++ optlen = phlen - ph->padlen - sizeof(*ph);
++ if (optlen < 0 || optlen & 3 || optlen > 250)
++ goto out;
++
++ if (!pskb_may_pull(skb, phlen))
++ goto out;
++
++ ph_nexthdr = ph->nexthdr;
++ }
++ } else
++ BUG_ON(1);
++
++ size += (optlen - phlen);
++ skb_push(skb, size);
++ memmove(skb->data, skb->nh.raw, sizeof(*iph));
++ skb->nh.raw = skb->data;
++
++ if (x->sel.family == AF_INET) {
++ iph = skb->nh.iph;
++ iph->ihl = (sizeof(*iph) + optlen) / 4;
++ iph->tot_len = htons(skb->len);
++ iph->daddr = x->sel.daddr.a4;
++ iph->saddr = x->sel.saddr.a4;
++ if (ph_nexthdr)
++ iph->protocol = ph_nexthdr;
++ else
++ iph->protocol = protocol;
++ iph->check = 0;
++ iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
++ } else if (x->sel.family == AF_INET6) {
++ struct ipv6hdr *ip6h = skb->nh.ipv6h;
++ memset(ip6h->flow_lbl, 0, sizeof(ip6h->flow_lbl));
++ ip6h->version = 6;
++ ip6h->priority = 0;
++ ip6h->nexthdr = protocol;
++ ip6h->hop_limit = hops;
++ ip6h->payload_len = htons(skb->len - size);
++ ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *)&x->sel.daddr.a6);
++ ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *)&x->sel.saddr.a6);
++ skb->protocol = htons(ETH_P_IPV6);
+ }
+-
+- skb->nh.raw = skb->data + (phlen - sizeof(*iph));
+- memmove(skb->nh.raw, iph, sizeof(*iph));
+- skb->h.raw = skb->data + (phlen + optlen);
+- skb->data = skb->h.raw;
+-
+- iph = skb->nh.iph;
+- iph->ihl = (sizeof(*iph) + optlen) / 4;
+- iph->tot_len = htons(skb->len + iph->ihl * 4);
+- iph->daddr = x->sel.daddr.a4;
+- iph->saddr = x->sel.saddr.a4;
+- if (ph_nexthdr)
+- iph->protocol = ph_nexthdr;
+- else
+- iph->protocol = protocol;
+- iph->check = 0;
+- iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
+ err = 0;
+ out:
+ return err;
+diff -urN a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
+--- a/net/ipv4/xfrm4_input.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv4/xfrm4_input.c 2007-05-25 16:36:44.000000000 +0300
+@@ -108,7 +108,7 @@
+ if (x->mode->input(x, skb))
+ goto drop;
+
+- if (x->props.mode == XFRM_MODE_TUNNEL) {
++ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) {
+ decaps = 1;
+ break;
+ }
+diff -urN a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
+--- a/net/ipv4/xfrm4_policy.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv4/xfrm4_policy.c 2007-05-25 16:36:44.000000000 +0300
+@@ -15,6 +15,7 @@
+
+ static struct dst_ops xfrm4_dst_ops;
+ static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
++static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu);
+
+ static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+ {
+@@ -81,10 +82,15 @@
+ }
+ }
+ };
++ union {
++ struct in6_addr *in6;
++ struct in_addr *in;
++ } remote, local;
+ int i;
+ int err;
+ int header_len = 0;
+ int trailer_len = 0;
++ unsigned short encap_family = 0;
+
+ dst = dst_prev = NULL;
+ dst_hold(&rt->u.dst);
+@@ -113,12 +119,21 @@
+
+ dst1->next = dst_prev;
+ dst_prev = dst1;
+-
++ if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
++ encap_family = xfrm[i]->props.family;
++ if(encap_family == AF_INET){
++ remote.in = (struct in_addr*)&xfrm[i]->id.daddr.a4;
++ local.in = (struct in_addr*)&xfrm[i]->props.saddr.a4;
++ } else if (encap_family == AF_INET6){
++ remote.in6 = (struct in6_addr*)xfrm[i]->id.daddr.a6;
++ local.in6 = (struct in6_addr*)xfrm[i]->props.saddr.a6;
++ } else
++ BUG_ON(1);
++ }
+ header_len += xfrm[i]->props.header_len;
+ trailer_len += xfrm[i]->props.trailer_len;
+
+- if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) {
+- unsigned short encap_family = xfrm[i]->props.family;
++ if (encap_family) {
+ switch(encap_family) {
+ case AF_INET:
+ fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4;
+@@ -198,6 +213,12 @@
+ }
+
+ xfrm_init_pmtu(dst);
++ if (encap_family == AF_INET6) {
++ /* The worst case */
++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++ u32 mtu = dst_mtu(dst);
++ xfrm4_update_pmtu(dst, mtu - delta);
++ }
+ return 0;
+
+ error:
+diff -urN a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
+--- a/net/ipv4/xfrm4_mode_tunnel.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv4/xfrm4_mode_tunnel.c 2007-05-25 16:36:44.000000000 +0300
+@@ -83,6 +83,7 @@
+
+ top_iph->saddr = x->props.saddr.a4;
+ top_iph->daddr = x->id.daddr.a4;
++ skb->protocol = htons(ETH_P_IP);
+
+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+ return 0;
+diff -urN a/net/ipv4/esp4.c b/net/ipv4/esp4.c
+--- a/net/ipv4/esp4.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv4/esp4.c 2007-05-25 16:36:44.000000000 +0300
+@@ -402,6 +402,8 @@
+ x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
+ if (x->props.mode == XFRM_MODE_TUNNEL)
+ x->props.header_len += sizeof(struct iphdr);
++ else if (x->props.mode == XFRM_MODE_BEET)
++ x->props.header_len += IPV4_BEET_PHMAXLEN;
+ if (x->encap) {
+ struct xfrm_encap_tmpl *encap = x->encap;
+
+diff -urN a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
+--- a/net/ipv6/xfrm6_state.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv6/xfrm6_state.c 2007-05-25 16:36:44.000000000 +0300
+@@ -98,6 +98,17 @@
+ src[i] = NULL;
+ }
+ }
++ if (j == n)
++ goto end;
++
++ /* Rule 5: select IPsec BEET */
++ for (i = 0; i < n; i++) {
++ if (src[i] &&
++ src[i]->props.mode == XFRM_MODE_BEET) {
++ dst[j++] = src[i];
++ src[i] = NULL;
++ }
++ }
+ if (likely(j == n))
+ goto end;
+
+diff -urN a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
+--- a/net/ipv6/xfrm6_policy.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv6/xfrm6_policy.c 2007-05-25 16:36:44.000000000 +0300
+@@ -24,6 +24,7 @@
+
+ static struct dst_ops xfrm6_dst_ops;
+ static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
++static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu);
+
+ static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl)
+ {
+@@ -89,7 +90,7 @@
+ static inline struct in6_addr*
+ __xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr)
+ {
+- return (x->type->remote_addr) ?
++ return (x->type && x->type->remote_addr) ?
+ (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t *)addr) :
+ (struct in6_addr*)&x->id.daddr;
+ }
+@@ -97,7 +98,7 @@
+ static inline struct in6_addr*
+ __xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr)
+ {
+- return (x->type->local_addr) ?
++ return (x->type && x->type->local_addr) ?
+ (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t *)addr) :
+ (struct in6_addr*)&x->props.saddr;
+ }
+@@ -105,7 +106,7 @@
+ static inline void
+ __xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x)
+ {
+- if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
++ if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT)
+ *nflen += x->props.header_len;
+ else
+ *len += x->props.header_len;
+@@ -114,7 +115,7 @@
+ static inline void
+ __xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x)
+ {
+- if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
++ if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT)
+ *nflen -= x->props.header_len;
+ else
+ *len -= x->props.header_len;
+@@ -131,6 +132,7 @@
+ struct dst_entry *dst, *dst_prev;
+ struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
+ struct rt6_info *rt = rt0;
++ unsigned short encap_family = 0, beet = 0;
+ struct flowi fl_tunnel = {
+ .nl_u = {
+ .ip6_u = {
+@@ -139,6 +141,10 @@
+ }
+ }
+ };
++ union {
++ struct in6_addr *in6;
++ struct in_addr *in;
++ } remote, local;
+ int i;
+ int err = 0;
+ int header_len = 0;
+@@ -175,20 +181,35 @@
+ dst1->next = dst_prev;
+ dst_prev = dst1;
+
++ if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
++ encap_family = xfrm[i]->props.family;
++ beet = (xfrm[i]->props.mode == XFRM_MODE_BEET);
++ if (encap_family == AF_INET6) {
++ remote.in6 = __xfrm6_bundle_addr_remote(xfrm[i], remote.in6);
++ local.in6 = __xfrm6_bundle_addr_local(xfrm[i], local.in6);
++ } else if (encap_family == AF_INET) {
++ remote.in = (struct in_addr*)&xfrm[i]->id.daddr.a4;
++ local.in = (struct in_addr*)&xfrm[i]->props.saddr.a4;
++ } else {
++ BUG_ON(1);
++ }
++ }
++
+ __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
+ trailer_len += xfrm[i]->props.trailer_len;
+
+ if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL ||
++ xfrm[i]->props.mode == XFRM_MODE_BEET ||
+ xfrm[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) {
+- unsigned short encap_family = xfrm[i]->props.family;
+ switch(encap_family) {
+ case AF_INET:
+ fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4;
+ fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;
++ fl_tunnel.fl4_tos = 0;
++ fl_tunnel.fl4_scope = 0;
+ break;
+ case AF_INET6:
+ ipv6_addr_copy(&fl_tunnel.fl6_dst, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_dst));
+-
+ ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_local(xfrm[i], &fl->fl6_src));
+ break;
+ default:
+@@ -259,6 +280,13 @@
+ }
+
+ xfrm_init_pmtu(dst);
++
++ if (beet && encap_family == AF_INET) {
++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++ u32 mtu = dst_mtu(dst);
++ xfrm6_update_pmtu(dst, mtu + delta);
++ }
++
+ return 0;
+
+ error:
+diff -urN a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
+--- a/net/ipv6/xfrm6_tunnel.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv6/xfrm6_tunnel.c 2007-05-25 16:36:44.000000000 +0300
+@@ -307,7 +307,7 @@
+
+ static int xfrm6_tunnel_init_state(struct xfrm_state *x)
+ {
+- if (x->props.mode != XFRM_MODE_TUNNEL)
++ if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != XFRM_MODE_BEET)
+ return -EINVAL;
+
+ if (x->encap)
+diff -urN a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
+--- a/net/ipv6/xfrm6_mode_tunnel.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv6/xfrm6_mode_tunnel.c 2007-05-25 16:36:44.000000000 +0300
+@@ -80,6 +80,7 @@
+ top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
+ ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+ ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
++ skb->protocol = htons(ETH_P_IPV6);
+ return 0;
+ }
+
+diff -urN a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
+--- a/net/ipv6/xfrm6_mode_beet.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv6/xfrm6_mode_beet.c 2007-05-25 16:36:44.000000000 +0300
+@@ -6,6 +6,7 @@
+ * Herbert Xu
+ * Abhinav Pathak
+ * Jeff Ahrenholz
++ * Joakim Koskela
+ */
+
+ #include
+@@ -33,37 +34,154 @@
+ */
+ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+- struct ipv6hdr *iph, *top_iph;
+- u8 *prevhdr;
+- int hdr_len;
+-
+- skb_push(skb, x->props.header_len);
+- iph = skb->nh.ipv6h;
+-
+- hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
+- skb->nh.raw = prevhdr - x->props.header_len;
+- skb->h.raw = skb->data + hdr_len;
+- memmove(skb->data, iph, hdr_len);
+
+- skb->nh.raw = skb->data;
+- top_iph = skb->nh.ipv6h;
+- skb->nh.raw = &top_iph->nexthdr;
+- skb->h.ipv6h = top_iph + 1;
+-
+- ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+- ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
++ struct dst_entry *dst = skb->dst;
++ int hdrlen;
++ struct iphdr *iphv4, *top_iphv4;
++ struct ipv6hdr *iphv6, *top_iphv6;
++
++ if (skb->nh.iph->version == 6) {
++
++ u8 *prevhdr;
++ int hdr_len;
++
++ /* 6-6 */
++
++ hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN;
++ skb_push(skb, hdrlen);
++ iphv6 = skb->nh.ipv6h;
++
++ hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
++ skb->nh.raw = prevhdr - hdrlen;
++ skb->h.raw = skb->data + hdr_len;
++ memmove(skb->data, iphv6, hdr_len);
++
++ skb->nh.raw = skb->data;
++ top_iphv6 = skb->nh.ipv6h;
++ skb->nh.raw = &top_iphv6->nexthdr;
++ skb->h.ipv6h = top_iphv6 + 1;
++ ipv6_addr_copy(&top_iphv6->saddr, (struct in6_addr *)&x->props.saddr);
++ ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr *)&x->id.daddr);
++
++ skb->protocol = htons(ETH_P_IPV6);
++
++ } else if (skb->nh.iph->version == 4) {
++
++ int flags;
++ int optlen;
++ int dsfield;
++ u8 protocol;
++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++
++ /* Inner = 4, Outer = 6*/
++
++ iphv4 = skb->nh.iph;
++ skb->h.ipiph = iphv4;
++
++ hdrlen = x->props.header_len;
++
++ optlen = iphv4->ihl * 4 - sizeof(*iphv4);
++
++ if (!optlen) {
++ hdrlen -= IPV4_BEET_PHMAXLEN;
++ } else {
++ skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4));
++ hdrlen -= optlen & 4;
++ }
++
++ skb->nh.raw = skb_push(skb, hdrlen);
++
++ top_iphv4 = skb->nh.iph;
++ hdrlen = iphv4->ihl * 4 - optlen;
++ skb->h.raw += hdrlen;
++ if (unlikely(optlen)) {
++ struct ip_beet_phdr *ph;
++
++ BUG_ON(optlen < 0);
++
++ ph = (struct ip_beet_phdr *)skb->h.raw;
++ ph->padlen = 4 - (optlen & 4);
++ ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
++ ph->nexthdr = iphv4->protocol;
++ top_iphv4->protocol = IPPROTO_BEETPH;
++ top_iphv4->ihl = sizeof(struct iphdr) / 4;
++ }
++
++ if (unlikely(optlen))
++ protocol = top_iphv4->protocol;
++ else
++ protocol = iphv4->protocol;
++
++ if (skb_headroom(skb) <= 2*delta){
++ if (pskb_expand_head(skb, delta,0, GFP_ATOMIC))
++ return -ENOMEM;
++ }
++
++ skb->nh.raw = skb_push(skb, delta);
++
++ top_iphv6 = skb->nh.ipv6h;
++ skb->h.ipv6h = top_iphv6 + 1;
++ /* DS disclosed */
++ top_iphv6->version = 6;
++ top_iphv6->priority = 0;
++ top_iphv6->flow_lbl[0] = 0;
++ top_iphv6->flow_lbl[1] = 0;
++ top_iphv6->flow_lbl[2] = 0;
++ dsfield = ipv6_get_dsfield(top_iphv6);
++ dsfield = INET_ECN_encapsulate(dsfield, dsfield);
++ flags = x->props.flags;
++ if (flags & XFRM_STATE_NOECN)
++ dsfield &= ~INET_ECN_MASK;
++ ipv6_change_dsfield(top_iphv6, 0, dsfield);
++
++ top_iphv6->nexthdr = protocol;
++ top_iphv6->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
++ top_iphv6->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
++ ipv6_addr_copy(&top_iphv6->saddr,(struct in6_addr *)&x->props.saddr);
++ ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr *)&x->id.daddr);
++ skb->nh.raw = &top_iphv6->nexthdr;
++
++ skb->protocol = htons(ETH_P_IPV6);
++ } else
++ BUG_ON(1);
+
+ return 0;
+ }
+
+ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
+ {
+- struct ipv6hdr *ip6h;
+- int size = sizeof(struct ipv6hdr);
++ struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(skb->h.raw);
++ int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr);
++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++ __u8 proto = skb->nh.ipv6h->nexthdr, hops = skb->nh.ipv6h->hop_limit;
++ __u8 ph_nexthdr = 0;
++ int phlen = 0;
++ int optlen = 0;
++
+ int err = -EINVAL;
+
+- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+- goto out;
++ if (x->sel.family == AF_INET) {
++ /* Inner = IPv4, therefore the IPhdr must be shrunk */
++ /* Inner = 4, Outer = 6 */
++ if (unlikely(proto == IPPROTO_BEETPH)) {
++ if (!pskb_may_pull(skb, sizeof(*ph)))
++ goto out;
++ phlen = ph->hdrlen * 8;
++ optlen = phlen - ph->padlen - sizeof(*ph);
++
++ if (optlen < 0 || optlen & 3 || optlen > 250)
++ goto out;
++ if (!pskb_may_pull(skb, phlen))
++ goto out;
++
++ proto = ph_nexthdr = ph->nexthdr;
++ }
++ skb->nh.raw += delta;
++ }
++
++ if (skb_cloned(skb) &&
++ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
++ goto out;
+
+ skb_push(skb, size);
+ memmove(skb->data, skb->nh.raw, size);
+@@ -71,11 +189,36 @@
+
+ skb->mac.raw = memmove(skb->data - skb->mac_len,
+ skb->mac.raw, skb->mac_len);
+-
+- ip6h = skb->nh.ipv6h;
+- ip6h->payload_len = htons(skb->len - size);
+- ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6);
+- ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6);
++ if (unlikely(phlen)) {
++ skb_pull(skb, phlen - optlen);
++ skb->nh.raw = skb->data;
++ }
++ if (x->sel.family == AF_INET6) {
++ struct ipv6hdr *ip6h = skb->nh.ipv6h;
++ ip6h->payload_len = htons(skb->len - size);
++ ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6);
++ ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6);
++ } else if (x->sel.family == AF_INET) {
++ struct iphdr *iph = skb->nh.iph;
++ iph->ihl = (sizeof(*iph) + optlen) / 4;
++ iph->version = 4;
++ iph->tos = 0;
++ iph->id = 0;
++ iph->frag_off = 0;
++ iph->ttl = hops;
++ iph->protocol = proto;
++ iph->daddr = x->sel.daddr.a4;
++ iph->saddr = x->sel.saddr.a4;
++ iph->tot_len = htons(skb->len);
++ ip_send_check(iph);
++ skb->protocol = htons(ETH_P_IP);
++ if (unlikely(!optlen)) {
++ skb->h.raw = skb->nh.raw;
++ }
++ dst_release(skb->dst);
++ skb->dst = NULL;
++ } else
++ BUG_ON(1);
+ err = 0;
+ out:
+ return err;
+diff -urN a/net/ipv6/esp6.c b/net/ipv6/esp6.c
+--- a/net/ipv6/esp6.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv6/esp6.c 2007-05-25 16:36:44.000000000 +0300
+@@ -242,7 +242,7 @@
+ struct esp_data *esp = x->data;
+ u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
+
+- if (x->props.mode == XFRM_MODE_TUNNEL) {
++ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) {
+ mtu = ALIGN(mtu + 2, blksize);
+ } else {
+ /* The worst case. */
+@@ -365,6 +365,8 @@
+ x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
+ if (x->props.mode == XFRM_MODE_TUNNEL)
+ x->props.header_len += sizeof(struct ipv6hdr);
++ else if (x->props.mode == XFRM_MODE_BEET)
++ x->props.header_len += IPV4_BEET_PHMAXLEN;
+ x->data = esp;
+ return 0;
+
+diff -urN a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
+--- a/net/ipv6/xfrm6_input.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/ipv6/xfrm6_input.c 2007-05-25 16:36:44.000000000 +0300
+@@ -73,7 +73,7 @@
+ if (x->mode->input(x, skb))
+ goto drop;
+
+- if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */
++ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) { /* XXX */
+ decaps = 1;
+ break;
+ }
+diff -urN a/net/dccp/ipv6.c b/net/dccp/ipv6.c
+--- a/net/dccp/ipv6.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/dccp/ipv6.c 2007-05-25 16:36:44.000000000 +0300
+@@ -156,7 +156,7 @@
+ goto out;
+ }
+
+- err = xfrm_lookup(&dst, &fl, sk, 0);
++ err = xfrm_lookup(&dst, &fl, sk, 1);
+ if (err < 0) {
+ sk->sk_err_soft = -err;
+ goto out;
+diff -urN a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+--- a/net/xfrm/xfrm_policy.c 2007-05-25 16:36:44.000000000 +0300
++++ b/net/xfrm/xfrm_policy.c 2007-05-25 16:36:44.000000000 +0300
+@@ -1224,7 +1224,7 @@
+ xfrm_address_t *local = saddr;
+ struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
+
+- if (tmpl->mode == XFRM_MODE_TUNNEL) {
++ if (tmpl->mode == XFRM_MODE_TUNNEL || tmpl->mode == XFRM_MODE_BEET) {
+ remote = &tmpl->id.daddr;
+ local = &tmpl->saddr;
+ family = tmpl->encap_family;
+diff -urN a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+--- a/net/xfrm/xfrm_state.c 2007-05-25 16:36:45.000000000 +0300
++++ b/net/xfrm/xfrm_state.c 2007-05-25 16:36:45.000000000 +0300
+@@ -558,7 +558,7 @@
+ selector.
+ */
+ if (x->km.state == XFRM_STATE_VALID) {
+- if (!xfrm_selector_match(&x->sel, fl, family) ||
++ if (!xfrm_selector_match(&x->sel, fl, x->sel.family) ||
+ !security_xfrm_state_pol_flow_match(x, pol, fl))
+ continue;
+ if (!best ||
+@@ -570,7 +570,7 @@
+ acquire_in_progress = 1;
+ } else if (x->km.state == XFRM_STATE_ERROR ||
+ x->km.state == XFRM_STATE_EXPIRED) {
+- if (xfrm_selector_match(&x->sel, fl, family) &&
++ if (xfrm_selector_match(&x->sel, fl, x->sel.family) &&
+ security_xfrm_state_pol_flow_match(x, pol, fl))
+ error = -ESRCH;
+ }