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; + }