mirror of
https://github.com/qosmio/nss-packages.git
synced 2025-12-24 20:21:38 +00:00
Merge branch 'NSS-11.2-K5.15' of https://github.com/qosmio/nss-packages into NSS-11.2-K5.15
This commit is contained in:
commit
9ffb83d311
41
nat46/Makefile
Normal file
41
nat46/Makefile
Normal file
@ -0,0 +1,41 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=nat46
|
||||
|
||||
PKG_MIRROR_HASH:=0627c7122ff7432aadb443e92e11a9ad7710add0ff512eebe17d7e3c041e0d2a
|
||||
PKG_SOURCE_URL:=https://github.com/ayourtch/nat46.git
|
||||
PKG_SOURCE_DATE:=2020-06-26
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_VERSION:=1182f30785e4274913f01a8c3d7e1b5437ae3819
|
||||
|
||||
PKG_MAINTAINER:=Hans Dedecker <dedeckeh@gmail.com>
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define KernelPackage/nat46
|
||||
DEPENDS:=@IPV6 +kmod-nf-conntrack6
|
||||
TITLE:=Stateless NAT46 translation kernel module
|
||||
SECTION:=kernel
|
||||
SUBMENU:=Network Support
|
||||
FILES:=$(PKG_BUILD_DIR)/nat46/modules/nat46.ko
|
||||
AUTOLOAD:=$(call AutoLoad,33,nat46)
|
||||
endef
|
||||
|
||||
include $(INCLUDE_DIR)/kernel-defaults.mk
|
||||
|
||||
define Build/Compile
|
||||
$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)/nat46/modules" \
|
||||
MODFLAGS="-DMODULE -mlong-calls" \
|
||||
EXTRA_CFLAGS="-DNAT46_VERSION=\\\"$(PKG_SOURCE_VERSION)\\\"" \
|
||||
modules
|
||||
cp $(PKG_BUILD_DIR)/nat46/modules/Module.symvers $(PKG_BUILD_DIR)/Module.symvers
|
||||
endef
|
||||
|
||||
define Build/InstallDev
|
||||
mkdir -p -m 0777 $(STAGING_DIR)/usr/include/nat46
|
||||
$(CP) $(PKG_BUILD_DIR)/nat46/modules/*.h $(STAGING_DIR)/usr/include/nat46/
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,nat46))
|
||||
34
nat46/patches/100-kernel-5.4-compat.patch
Normal file
34
nat46/patches/100-kernel-5.4-compat.patch
Normal file
@ -0,0 +1,34 @@
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <net/route.h>
|
||||
+#include <linux/version.h>
|
||||
|
||||
#include "nat46-glue.h"
|
||||
#include "nat46-core.h"
|
||||
@@ -1601,7 +1602,11 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
/* Remove any debris in the socket control block */
|
||||
memset(IPCB(new_skb), 0, sizeof(struct inet_skb_parm));
|
||||
/* Remove netfilter references to IPv6 packet, new netfilter references will be created based on IPv4 packet */
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
|
||||
nf_reset(new_skb);
|
||||
+#else
|
||||
+ nf_reset_ct(new_skb);
|
||||
+#endif
|
||||
|
||||
/* modify packet: actual IPv6->IPv4 transformation */
|
||||
truncSize = v6packet_l3size - sizeof(struct iphdr); /* chop first 20 bytes */
|
||||
@@ -1806,7 +1811,11 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
/* Remove any debris in the socket control block */
|
||||
memset(IPCB(new_skb), 0, sizeof(struct inet_skb_parm));
|
||||
/* Remove netfilter references to IPv4 packet, new netfilter references will be created based on IPv6 packet */
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
|
||||
nf_reset(new_skb);
|
||||
+#else
|
||||
+ nf_reset_ct(new_skb);
|
||||
+#endif
|
||||
|
||||
/* expand header (add 20 extra bytes at the beginning of sk_buff) */
|
||||
pskb_expand_head(new_skb, IPV6V4HDRDELTA + (add_frag_header?8:0), 0, GFP_ATOMIC);
|
||||
30
nat46/patches/101-skb-reset.patch
Normal file
30
nat46/patches/101-skb-reset.patch
Normal file
@ -0,0 +1,30 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Sun Sep 20 13:33:42 2020 +0530
|
||||
|
||||
nat46: Add skb_ext_reset to reset skb extensions
|
||||
|
||||
This patch adds support to reset the skb extensions before
|
||||
resetting the netfilter. Without the change, conntrack
|
||||
is in invalid state and traffic gets dropped.
|
||||
|
||||
Change-Id: I24ee6fe8a9a9dec09d61d8e716fff587f65e4e4f
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -1605,6 +1605,7 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
|
||||
nf_reset(new_skb);
|
||||
#else
|
||||
+ skb_ext_reset(new_skb);
|
||||
nf_reset_ct(new_skb);
|
||||
#endif
|
||||
|
||||
@@ -1814,6 +1815,7 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
|
||||
nf_reset(new_skb);
|
||||
#else
|
||||
+ skb_ext_reset(new_skb);
|
||||
nf_reset_ct(new_skb);
|
||||
#endif
|
||||
|
||||
199
nat46/patches/102-mapt.patch
Normal file
199
nat46/patches/102-mapt.patch
Normal file
@ -0,0 +1,199 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Sat Aug 1 13:27:20 2020 +0530
|
||||
|
||||
nat46: Export APIs for acceleration engine support in nat46 for kernel 5.4
|
||||
|
||||
This patch is propagated from kernel 4.4 commit
|
||||
861e64a607fd22d5af089cf56539f42a2e31d581
|
||||
|
||||
The patch defines and exports APIs in nat46 to be used for accelaration.
|
||||
|
||||
Change-Id: I7934b15544953f870d3595b8b359433b4fff7c30
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -1491,6 +1491,10 @@ int pairs_xlate_v6_to_v4_outer(nat46_ins
|
||||
return ( (xlate_src >= 0) && (xlate_dst >= 0) );
|
||||
}
|
||||
|
||||
+int xlate_6_to_4(struct net_device *dev, struct ipv6hdr *ip6h, uint16_t proto, __u32 *pv4saddr, __u32 *pv4daddr) {
|
||||
+ return pairs_xlate_v6_to_v4_outer(netdev_nat46_instance(dev), ip6h, proto, pv4saddr, pv4daddr);
|
||||
+}
|
||||
+EXPORT_SYMBOL(xlate_6_to_4);
|
||||
|
||||
void nat46_ipv6_input(struct sk_buff *old_skb) {
|
||||
struct ipv6hdr *ip6h = ipv6_hdr(old_skb);
|
||||
@@ -1628,6 +1632,10 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
|
||||
nat46debug(5, "about to send v4 packet, flags: %02x", IPCB(new_skb)->flags);
|
||||
nat46_netdev_count_xmit(new_skb, old_skb->dev);
|
||||
+
|
||||
+ /* set skb->iif */
|
||||
+ new_skb->skb_iif = old_skb->skb_iif;
|
||||
+
|
||||
netif_rx(new_skb);
|
||||
|
||||
/* TBD: should copy be released here? */
|
||||
@@ -1732,6 +1740,10 @@ int pairs_xlate_v4_to_v6_outer(nat46_ins
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int xlate_4_to_6(struct net_device *dev, struct iphdr *hdr4, uint16_t sport, uint16_t dport, void *v6saddr, void *v6daddr) {
|
||||
+ return pairs_xlate_v4_to_v6_outer(netdev_nat46_instance(dev), hdr4, &sport, &dport, v6saddr, v6daddr);
|
||||
+}
|
||||
+EXPORT_SYMBOL(xlate_4_to_6);
|
||||
|
||||
void nat46_ipv4_input(struct sk_buff *old_skb) {
|
||||
nat46_instance_t *nat46 = get_nat46_instance(old_skb);
|
||||
@@ -1859,10 +1871,32 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
|
||||
nat46debug(5, "about to send v6 packet, flags: %02x", IPCB(new_skb)->flags);
|
||||
nat46_netdev_count_xmit(new_skb, old_skb->dev);
|
||||
+
|
||||
+ /* set skb->iif */
|
||||
+ new_skb->skb_iif = old_skb->skb_iif;
|
||||
+
|
||||
netif_rx(new_skb);
|
||||
|
||||
done:
|
||||
release_nat46_instance(nat46);
|
||||
}
|
||||
|
||||
+int nat46_get_npairs(struct net_device *dev) {
|
||||
+ nat46_instance_t *nat46 = netdev_nat46_instance(dev);
|
||||
+ return nat46->npairs;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nat46_get_npairs);
|
||||
|
||||
+bool nat46_get_rule_config(struct net_device *dev, nat46_xlate_rulepair_t **nat46_rule_pair, int *count) {
|
||||
+ nat46_instance_t *nat46 = netdev_nat46_instance(dev);
|
||||
+ if (nat46->npairs < 1) {
|
||||
+ /*
|
||||
+ * no rules ?
|
||||
+ */
|
||||
+ return false;
|
||||
+ }
|
||||
+ *count = nat46->npairs;
|
||||
+ *nat46_rule_pair = nat46->pairs;
|
||||
+ return true;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nat46_get_rule_config);
|
||||
--- a/nat46/modules/nat46-core.h
|
||||
+++ b/nat46/modules/nat46-core.h
|
||||
@@ -42,18 +42,18 @@ typedef enum {
|
||||
#define NAT46_SIGNATURE 0x544e3634
|
||||
#define FREED_NAT46_SIGNATURE 0xdead544e
|
||||
|
||||
-typedef struct {
|
||||
+typedef struct nat46_xlate_rule {
|
||||
nat46_xlate_style_t style;
|
||||
struct in6_addr v6_pref;
|
||||
- int v6_pref_len;
|
||||
- u32 v4_pref;
|
||||
- int v4_pref_len;
|
||||
- int ea_len;
|
||||
- int psid_offset;
|
||||
- int fmr_flag;
|
||||
+ int v6_pref_len;
|
||||
+ u32 v4_pref;
|
||||
+ int v4_pref_len;
|
||||
+ int ea_len;
|
||||
+ int psid_offset;
|
||||
+ int fmr_flag;
|
||||
} nat46_xlate_rule_t;
|
||||
|
||||
-typedef struct {
|
||||
+typedef struct nat46_xlate_rulepair {
|
||||
nat46_xlate_rule_t local;
|
||||
nat46_xlate_rule_t remote;
|
||||
} nat46_xlate_rulepair_t;
|
||||
@@ -82,4 +82,9 @@ nat46_instance_t *get_nat46_instance(str
|
||||
nat46_instance_t *alloc_nat46_instance(int npairs, nat46_instance_t *old, int from_ipair, int to_ipair);
|
||||
void release_nat46_instance(nat46_instance_t *nat46);
|
||||
|
||||
+int xlate_6_to_4(struct net_device *dev, struct ipv6hdr *ip6h, uint16_t proto, __u32 *pv4saddr, __u32 *pv4daddr);
|
||||
+int xlate_4_to_6(struct net_device *dev, struct iphdr *hdr4, uint16_t sport, uint16_t dport, void *v6saddr, void *v6daddr);
|
||||
+bool nat46_get_rule_config(struct net_device *dev, nat46_xlate_rulepair_t **nat46_rule_pair, int *count);
|
||||
+int nat46_get_npairs(struct net_device *dev);
|
||||
+
|
||||
#endif
|
||||
--- a/nat46/modules/nat46-netdev.c
|
||||
+++ b/nat46/modules/nat46-netdev.c
|
||||
@@ -24,10 +24,12 @@
|
||||
#include <net/ip6_route.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <linux/version.h>
|
||||
+#include <linux/radix-tree.h>
|
||||
#include "nat46-core.h"
|
||||
#include "nat46-module.h"
|
||||
|
||||
#define NETDEV_DEFAULT_NAME "nat46."
|
||||
+static RADIX_TREE(netdev_tree, GFP_ATOMIC);
|
||||
|
||||
typedef struct {
|
||||
u32 sig;
|
||||
@@ -79,6 +81,18 @@ void nat46_netdev_count_xmit(struct sk_b
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
}
|
||||
|
||||
+void nat46_update_stats(struct net_device *dev, uint32_t rx_packets, uint32_t rx_bytes,
|
||||
+ uint32_t tx_packets, uint32_t tx_bytes, uint32_t rx_dropped, uint32_t tx_dropped)
|
||||
+{
|
||||
+ dev->stats.rx_packets += rx_packets;
|
||||
+ dev->stats.rx_bytes += rx_bytes;
|
||||
+ dev->stats.tx_packets += tx_packets;
|
||||
+ dev->stats.tx_bytes += tx_bytes;
|
||||
+ dev->stats.rx_dropped += rx_dropped;
|
||||
+ dev->stats.tx_dropped += tx_dropped;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nat46_update_stats);
|
||||
+
|
||||
void *netdev_nat46_instance(struct net_device *dev) {
|
||||
nat46_netdev_priv_t *priv = netdev_priv(dev);
|
||||
return priv->nat46;
|
||||
@@ -155,6 +169,11 @@ int nat46_netdev_create(char *basename,
|
||||
printk("nat46: netdevice nat46 '%s' created successfully.\n", devname);
|
||||
kfree(devname);
|
||||
|
||||
+ /*
|
||||
+ * add this netdevice to list
|
||||
+ */
|
||||
+ radix_tree_insert(&netdev_tree, (*dev)->ifindex, (void *)*dev);
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_register_dev:
|
||||
@@ -169,9 +188,23 @@ void nat46_netdev_destroy(struct net_dev
|
||||
{
|
||||
netdev_nat46_set_instance(dev, NULL);
|
||||
unregister_netdev(dev);
|
||||
+ radix_tree_delete(&netdev_tree, dev->ifindex);
|
||||
printk("nat46: Destroying nat46 device.\n");
|
||||
}
|
||||
|
||||
+bool is_map_t_dev(struct net_device *dev)
|
||||
+{
|
||||
+ if(!dev) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if(radix_tree_lookup(&netdev_tree, dev->ifindex)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+EXPORT_SYMBOL(is_map_t_dev);
|
||||
+
|
||||
static int is_nat46(struct net_device *dev) {
|
||||
nat46_netdev_priv_t *priv = netdev_priv(dev);
|
||||
return (priv && (NAT46_DEVICE_SIGNATURE == priv->sig));
|
||||
--- a/nat46/modules/nat46-netdev.h
|
||||
+++ b/nat46/modules/nat46-netdev.h
|
||||
@@ -24,3 +24,6 @@ void nat64_show_all_configs(struct seq_f
|
||||
void nat46_netdev_count_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
void *netdev_nat46_instance(struct net_device *dev);
|
||||
|
||||
+void nat46_update_stats(struct net_device *dev, uint32_t rx_packets, uint32_t rx_bytes, uint32_t tx_packets, uint32_t tx_bytes,
|
||||
+ uint32_t rx_dropped, uint32_t tx_dropped);
|
||||
+bool is_map_t_dev(struct net_device *dev);
|
||||
56
nat46/patches/103-tos.patch
Normal file
56
nat46/patches/103-tos.patch
Normal file
@ -0,0 +1,56 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Sat Aug 1 13:55:33 2020 +0530
|
||||
|
||||
nat46: Set IPv6 traffic class from IPv4 ToS value
|
||||
|
||||
Set IPv6 traffic class from IPv4 ToS value during
|
||||
IPv4 to IPv6 translation and vice-versa.
|
||||
|
||||
This patch is propagated from kernel 4.4 commit
|
||||
1cd3b55b059d4513649bb73bc69da931ed3beb7b
|
||||
|
||||
Change-Id: Ia14e53447e829c8648c01656237ac902ad8674ec
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -807,11 +807,12 @@ void *get_next_header_ptr6(void *pv6, in
|
||||
}
|
||||
|
||||
void fill_v4hdr_from_v6hdr(struct iphdr * iph, struct ipv6hdr *ip6h, __u32 v4saddr, __u32 v4daddr, __u16 id, __u16 frag_off, __u16 proto, int l3_payload_len) {
|
||||
+ uint32_t ver_class_flow = ntohl(*(__be32 *)ip6h);
|
||||
iph->ttl = ip6h->hop_limit;
|
||||
iph->saddr = v4saddr;
|
||||
iph->daddr = v4daddr;
|
||||
iph->protocol = proto;
|
||||
- *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (0x00/*tos*/ & 0xff));
|
||||
+ *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | ((ver_class_flow >> 20) & 0xff));
|
||||
iph->frag_off = frag_off;
|
||||
iph->id = id;
|
||||
iph->tot_len = htons( l3_payload_len + IPV4HDRSIZE );
|
||||
@@ -1750,7 +1751,7 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
struct sk_buff *new_skb;
|
||||
uint16_t sport = 0, dport = 0;
|
||||
|
||||
- int tclass = 0;
|
||||
+ uint8_t tclass;
|
||||
int flowlabel = 0;
|
||||
int check_for_l4 = 0;
|
||||
int having_l4 = 0;
|
||||
@@ -1761,6 +1762,8 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
|
||||
char v6saddr[16], v6daddr[16];
|
||||
|
||||
+ tclass = hdr4->tos;
|
||||
+
|
||||
memset(v6saddr, 1, 16);
|
||||
memset(v6daddr, 2, 16);
|
||||
|
||||
@@ -1843,7 +1846,6 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
memset(hdr6, 0, sizeof(*hdr6) + (add_frag_header?8:0));
|
||||
|
||||
/* build IPv6 header */
|
||||
- tclass = 0; /* traffic class */
|
||||
*(__be32 *)hdr6 = htonl(0x60000000 | (tclass << 20)) | flowlabel; /* version, priority, flowlabel */
|
||||
|
||||
/* IPv6 length is a payload length, IPv4 is hdr+payload */
|
||||
440
nat46/patches/104-icmp.patch
Normal file
440
nat46/patches/104-icmp.patch
Normal file
@ -0,0 +1,440 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Mon Aug 3 17:03:37 2020 +0530
|
||||
|
||||
nat46: Fix for icmp translation issues.
|
||||
|
||||
This patch is propagated from kernel 4.4 commit
|
||||
45fce10ba0105515289930b3e3f9df57bf3c22b6.
|
||||
|
||||
Fixed icmpv4 to icmpv6 and vice-versa translation issues, in accordance with RFC6145.
|
||||
|
||||
The change covers:
|
||||
1. Translation of ICMP errors from IPv4 to IPv6 and vice-versa.
|
||||
2. Translation of inner L3 packet header {Eth:IPv4:ICMP:IPv4:ICMP} in ICMP error messages.
|
||||
3. Address translation for packets not having port numbers, hence CE/BR needs to fetch this
|
||||
information from inner header (atleast 28 bytes (IP hdr + 8 bytes) of orignal packet received
|
||||
that is transmitted back will be there in response).
|
||||
|
||||
Change-Id: I677474728aeaee656376fdb1edcb9476783d5b40
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -22,6 +22,9 @@
|
||||
#include "nat46-glue.h"
|
||||
#include "nat46-core.h"
|
||||
|
||||
+static uint16_t xlate_pkt_in_err_v4_to_v6(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
+ struct sk_buff *old_skb, uint16_t *sport, uint16_t *dport);
|
||||
+
|
||||
void
|
||||
nat46debug_dump(nat46_instance_t *nat46, int level, void *addr, int len)
|
||||
{
|
||||
@@ -806,6 +809,14 @@ void *get_next_header_ptr6(void *pv6, in
|
||||
return ret;
|
||||
}
|
||||
|
||||
+void fill_v6hdr_from_v4hdr(struct iphdr *iph, struct ipv6hdr *ip6h) {
|
||||
+ *((__be16 *)ip6h) = htons((6 << 12) | (iph->tos << 4)); /* Version, Traffic Class */
|
||||
+ memset(&(ip6h->flow_lbl), 0, sizeof(ip6h->flow_lbl)); /* Flowlabel */
|
||||
+ ip6h->payload_len = htons(ntohs(iph->tot_len) - IPV4HDRSIZE);
|
||||
+ ip6h->nexthdr = iph->protocol;
|
||||
+ ip6h->hop_limit = iph->ttl;
|
||||
+}
|
||||
+
|
||||
void fill_v4hdr_from_v6hdr(struct iphdr * iph, struct ipv6hdr *ip6h, __u32 v4saddr, __u32 v4daddr, __u16 id, __u16 frag_off, __u16 proto, int l3_payload_len) {
|
||||
uint32_t ver_class_flow = ntohl(*(__be32 *)ip6h);
|
||||
iph->ttl = ip6h->hop_limit;
|
||||
@@ -1128,34 +1139,34 @@ static void nat46_fixup_icmp6_paramprob(
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, -1 };
|
||||
u32 *pptr6 = icmp6_parameter_ptr(icmp6h);
|
||||
u8 *pptr4 = icmp_parameter_ptr((struct icmphdr *)icmp6h);
|
||||
- int new_pptr = -1;
|
||||
+ int8_t new_pptr = -1;
|
||||
int len = ntohs(ip6h->payload_len)-sizeof(*icmp6h);
|
||||
|
||||
switch(icmp6h->icmp6_code) {
|
||||
+ case 1:
|
||||
+ update_icmp6_type_code(nat46, icmp6h, 3, 2);
|
||||
+ break;
|
||||
case 0:
|
||||
if(*pptr6 < sizeof(ptr6_4)/sizeof(ptr6_4[0])) {
|
||||
new_pptr = ptr6_4[*pptr6];
|
||||
if (new_pptr >= 0) {
|
||||
icmp6h->icmp6_cksum = csum16_upd(icmp6h->icmp6_cksum, (*pptr6 & 0xffff), (new_pptr << 8));
|
||||
*pptr4 = 0xff & new_pptr;
|
||||
- } else {
|
||||
- ip6h->nexthdr = NEXTHDR_NONE;
|
||||
+ update_icmp6_type_code(nat46, icmp6h, 12, 0);
|
||||
+ break;
|
||||
}
|
||||
- } else {
|
||||
- ip6h->nexthdr = NEXTHDR_NONE;
|
||||
}
|
||||
- break;
|
||||
- case 1:
|
||||
- *pptr6 = 0;
|
||||
- update_icmp6_type_code(nat46, icmp6h, 3, 2);
|
||||
- len = xlate_payload6_to4(nat46, (icmp6h + 1), get_next_header_ptr6((icmp6h + 1), len), len, &icmp6h->icmp6_cksum, ptailTruncSize);
|
||||
- break;
|
||||
+#if __has_attribute(__fallthrough__)
|
||||
+ __attribute__((__fallthrough__));
|
||||
+#endif
|
||||
case 2: /* fallthrough to default */
|
||||
default:
|
||||
ip6h->nexthdr = NEXTHDR_NONE;
|
||||
+ return;
|
||||
}
|
||||
-}
|
||||
|
||||
+ len = xlate_payload6_to4(nat46, (icmp6h + 1), get_next_header_ptr6((icmp6h + 1), len), len, &icmp6h->icmp6_cksum, ptailTruncSize);
|
||||
+}
|
||||
|
||||
/* Fixup ICMP6->ICMP before IP header translation, according to http://tools.ietf.org/html/rfc6145 */
|
||||
|
||||
@@ -1211,17 +1222,19 @@ int ip6_input_not_interested(nat46_insta
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static uint16_t nat46_fixup_icmp_time_exceeded(nat46_instance_t *nat46, struct iphdr *iph, struct icmphdr *icmph, struct sk_buff *old_skb) {
|
||||
+static uint16_t nat46_fixup_icmp_time_exceeded(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
+ struct icmphdr *icmph, struct sk_buff *old_skb, uint16_t *sport, uint16_t *dport) {
|
||||
/*
|
||||
* Set the Type to 3, and adjust the
|
||||
* ICMP checksum both to take the type change into account and
|
||||
* to include the ICMPv6 pseudo-header. The Code is unchanged.
|
||||
*/
|
||||
icmph->type = 3;
|
||||
- return 0;
|
||||
+ return xlate_pkt_in_err_v4_to_v6(nat46, iph, old_skb, sport, dport);
|
||||
}
|
||||
|
||||
-static uint16_t nat46_fixup_icmp_parameterprob(nat46_instance_t *nat46, struct iphdr *iph, struct icmphdr *icmph, struct sk_buff *old_skb) {
|
||||
+static uint16_t nat46_fixup_icmp_parameterprob(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
+ struct icmphdr *icmph, struct sk_buff *old_skb, uint16_t *sport, uint16_t *dport) {
|
||||
/*
|
||||
* Set the Type to 4, and adjust the
|
||||
* ICMP checksum both to take the type/code change into account
|
||||
@@ -1264,27 +1277,33 @@ static uint16_t nat46_fixup_icmp_paramet
|
||||
*/
|
||||
static int ptr4_6[] = { 0, 1, 4, 4, -1, -1, -1, -1, 7, 6, -1, -1, 8, 8, 8, 8, 24, 24, 24, 24, -1 };
|
||||
u8 *icmp_pptr = icmp_parameter_ptr(icmph);
|
||||
- int new_pptr = -1;
|
||||
+ u32 *icmp6_pptr = icmp6_parameter_ptr((struct icmp6hdr *)icmph);
|
||||
+ int8_t new_pptr = -1;
|
||||
+
|
||||
+ icmph->type = 4;
|
||||
+
|
||||
switch (icmph->code) {
|
||||
case 0:
|
||||
case 2:
|
||||
if (*icmp_pptr < (sizeof(ptr4_6)/sizeof(ptr4_6[0]))) {
|
||||
icmph->code = 0;
|
||||
new_pptr = ptr4_6[*icmp_pptr];
|
||||
- if(new_pptr >= 0) {
|
||||
- /* FIXME: update the parameter pointer in ICMPv6 with new_pptr value */
|
||||
+ if (new_pptr >= 0) {
|
||||
+ *icmp6_pptr = new_pptr;
|
||||
+ return xlate_pkt_in_err_v4_to_v6(nat46, iph, old_skb, sport, dport);
|
||||
}
|
||||
- } else {
|
||||
- iph->protocol = NEXTHDR_NONE;
|
||||
}
|
||||
- break;
|
||||
+#if __has_attribute(__fallthrough__)
|
||||
+ __attribute__((__fallthrough__));
|
||||
+#endif
|
||||
default:
|
||||
iph->protocol = NEXTHDR_NONE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static uint16_t nat46_fixup_icmp_dest_unreach(nat46_instance_t *nat46, struct iphdr *iph, struct icmphdr *icmph, struct sk_buff *old_skb) {
|
||||
+static uint16_t nat46_fixup_icmp_dest_unreach(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
+ struct icmphdr *icmph, struct sk_buff *old_skb, uint16_t *sport, uint16_t *dport) {
|
||||
/*
|
||||
* Translate the Code as
|
||||
* described below, set the Type to 1, and adjust the ICMP
|
||||
@@ -1347,16 +1366,21 @@ static uint16_t nat46_fixup_icmp_dest_un
|
||||
|
||||
u16 *pmtu = ((u16 *)icmph) + 3; /* IPv4-compatible MTU value is 16 bit */
|
||||
|
||||
+ icmph->type = 1;
|
||||
+
|
||||
switch (icmph->code) {
|
||||
case 0:
|
||||
case 1:
|
||||
icmph->code = 0;
|
||||
break;
|
||||
- case 2:
|
||||
- /* FIXME: set ICMPv6 parameter pointer to 6 */
|
||||
+ case 2: {
|
||||
+ u32 *icmp6_pptr = icmp6_parameter_ptr((struct icmp6hdr *)icmph);
|
||||
+ *icmp6_pptr = 6; /* Offset to Next Proto field in IPv6 header. */
|
||||
icmph->type = 4;
|
||||
icmph->code = 1;
|
||||
+ nat46debug(3, "ICMP Proto Unreachable translated into IPv6 Param Prob.\n");
|
||||
break;
|
||||
+ }
|
||||
case 3:
|
||||
icmph->code = 4;
|
||||
break;
|
||||
@@ -1406,14 +1430,15 @@ static uint16_t nat46_fixup_icmp_dest_un
|
||||
break;
|
||||
default:
|
||||
iph->protocol = NEXTHDR_NONE;
|
||||
+ return 0;
|
||||
}
|
||||
- return 0;
|
||||
+ return xlate_pkt_in_err_v4_to_v6(nat46, iph, old_skb, sport, dport);
|
||||
}
|
||||
|
||||
-
|
||||
/* Fixup ICMP->ICMP6 before IP header translation, according to http://tools.ietf.org/html/rfc6145 */
|
||||
|
||||
-static uint16_t nat46_fixup_icmp(nat46_instance_t *nat46, struct iphdr *iph, struct sk_buff *old_skb) {
|
||||
+static uint16_t nat46_fixup_icmp(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
+ struct sk_buff *old_skb, uint16_t *sport, uint16_t *dport) {
|
||||
struct icmphdr *icmph = (struct icmphdr *)(iph+1);
|
||||
uint16_t ret = 0;
|
||||
|
||||
@@ -1422,22 +1447,22 @@ static uint16_t nat46_fixup_icmp(nat46_i
|
||||
switch(icmph->type) {
|
||||
case ICMP_ECHO:
|
||||
icmph->type = ICMPV6_ECHO_REQUEST;
|
||||
- ret = icmph->un.echo.id;
|
||||
+ *sport = *dport = icmph->un.echo.id;
|
||||
nat46debug(3, "ICMP echo request translated into IPv6, id: %d", ntohs(ret));
|
||||
break;
|
||||
case ICMP_ECHOREPLY:
|
||||
icmph->type = ICMPV6_ECHO_REPLY;
|
||||
- ret = icmph->un.echo.id;
|
||||
+ *sport = *dport = icmph->un.echo.id;
|
||||
nat46debug(3, "ICMP echo reply translated into IPv6, id: %d", ntohs(ret));
|
||||
break;
|
||||
case ICMP_TIME_EXCEEDED:
|
||||
- ret = nat46_fixup_icmp_time_exceeded(nat46, iph, icmph, old_skb);
|
||||
+ ret = nat46_fixup_icmp_time_exceeded(nat46, iph, icmph, old_skb, sport, dport);
|
||||
break;
|
||||
case ICMP_PARAMETERPROB:
|
||||
- ret = nat46_fixup_icmp_parameterprob(nat46, iph, icmph, old_skb);
|
||||
+ ret = nat46_fixup_icmp_parameterprob(nat46, iph, icmph, old_skb, sport, dport);
|
||||
break;
|
||||
case ICMP_DEST_UNREACH:
|
||||
- ret = nat46_fixup_icmp_dest_unreach(nat46, iph, icmph, old_skb);
|
||||
+ ret = nat46_fixup_icmp_dest_unreach(nat46, iph, icmph, old_skb, sport, dport);
|
||||
break;
|
||||
default:
|
||||
/* Silently drop. */
|
||||
@@ -1457,11 +1482,13 @@ int pairs_xlate_v6_to_v4_outer(nat46_ins
|
||||
|
||||
if(-1 == xlate_dst) {
|
||||
if (xlate_v6_to_v4(nat46, &apair->local, &ip6h->daddr, pv4daddr)) {
|
||||
+ nat46debug(5, "Dst addr %pI6 to %pI4 \n", &ip6h->daddr, pv4daddr);
|
||||
xlate_dst = ipair;
|
||||
}
|
||||
}
|
||||
if(-1 == xlate_src) {
|
||||
if (xlate_v6_to_v4(nat46, &apair->remote, &ip6h->saddr, pv4saddr)) {
|
||||
+ nat46debug(5, "Src addr %pI6 to %pI4 \n", &ip6h->saddr, pv4saddr);
|
||||
xlate_src = ipair;
|
||||
}
|
||||
}
|
||||
@@ -1560,6 +1587,7 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
}
|
||||
|
||||
if(!pairs_xlate_v6_to_v4_outer(nat46, ip6h, proto, &v4saddr, &v4daddr)) {
|
||||
+ nat46debug(0, "[nat46] Could not translate v6->v4");
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -1713,11 +1741,13 @@ int pairs_xlate_v4_to_v6_outer(nat46_ins
|
||||
|
||||
if(-1 == xlate_src) {
|
||||
if(xlate_v4_to_v6(nat46, &apair->local, &hdr4->saddr, v6saddr, sport)) {
|
||||
+ nat46debug(5, "Src addr %pI4 to %pI6 \n", &hdr4->saddr, v6saddr);
|
||||
xlate_src = ipair;
|
||||
}
|
||||
}
|
||||
if(-1 == xlate_dst) {
|
||||
if(xlate_v4_to_v6(nat46, &apair->remote, &hdr4->daddr, v6daddr, dport)) {
|
||||
+ nat46debug(5, "Dst addr %pI4 to %pI6 \n", &hdr4->daddr, v6daddr);
|
||||
xlate_dst = ipair;
|
||||
}
|
||||
}
|
||||
@@ -1746,10 +1776,145 @@ int xlate_4_to_6(struct net_device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL(xlate_4_to_6);
|
||||
|
||||
+/* FIXME: This is a workaround, till the LPM is not added. The sport & dport in inner header will be dport & sport of the outer
|
||||
+ * header, respectively. Hence, dest. and source ips of inner header will be found in local & remote rules, respectively.
|
||||
+ * Will work only for a pair of local & remote rules. Once LPM is brought in, this method can be removed and
|
||||
+ * pairs_xlate_v4_to_v6_outer be used instead.
|
||||
+ */
|
||||
+int pairs_xlate_v4_to_v6_inner(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
+ uint16_t sport, uint16_t dport, void *v6saddr, void *v6daddr) {
|
||||
+ int ipair = 0;
|
||||
+ nat46_xlate_rulepair_t *apair = NULL;
|
||||
+ int xlate_src = -1;
|
||||
+ int xlate_dst = -1;
|
||||
+
|
||||
+ for (ipair = 0; ipair < nat46->npairs; ipair++) {
|
||||
+ apair = &nat46->pairs[ipair];
|
||||
+
|
||||
+ if (-1 == xlate_dst) {
|
||||
+ if (xlate_v4_to_v6(nat46, &apair->local, &iph->daddr, v6daddr, &dport)) {
|
||||
+ nat46debug(3, "Dst addr %pI4 to %pI6 \n", &iph->daddr, v6daddr);
|
||||
+ xlate_dst = ipair;
|
||||
+ }
|
||||
+ }
|
||||
+ if (-1 == xlate_src) {
|
||||
+ if(xlate_v4_to_v6(nat46, &apair->remote, &iph->saddr, v6saddr, &sport)) {
|
||||
+ nat46debug(3, "Src addr %pI4 to %pI6 \n", &iph->saddr, v6saddr);
|
||||
+ xlate_src = ipair;
|
||||
+ }
|
||||
+ }
|
||||
+ if ((xlate_src >= 0) && (xlate_dst >= 0)) {
|
||||
+ /* we did manage to translate it */
|
||||
+ nat46debug(5, "[nat46] Inner header xlate results: src %d dst %d", xlate_src, xlate_dst);
|
||||
+ return 1;
|
||||
+ } else {
|
||||
+ /* We did not match fully and there are more rules */
|
||||
+ if((ipair+1 < nat46->npairs) && is_last_pair_in_group(apair)) {
|
||||
+ xlate_src = -1;
|
||||
+ xlate_dst = -1;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+ nat46debug(1, "[nat46] Could not find a translation pair v4->v6");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static uint16_t xlate_pkt_in_err_v4_to_v6(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
+ struct sk_buff *old_skb, uint16_t *sport, uint16_t *dport) {
|
||||
+ struct ipv6hdr ip6h;
|
||||
+ char v6saddr[16], v6daddr[16];
|
||||
+ uint16_t temp_port = 0;
|
||||
+ int ret = 0;
|
||||
+ struct icmphdr *icmph = (struct icmphdr *)(iph + 1);
|
||||
+ struct iphdr *iiph = (struct iphdr *)(icmph + 1);
|
||||
+
|
||||
+ switch (iiph->protocol) {
|
||||
+ case IPPROTO_TCP: {
|
||||
+ struct tcphdr *th = (struct tcphdr *)(iiph + 1);
|
||||
+ *sport = th->source;
|
||||
+ *dport = th->dest;
|
||||
+ iiph->protocol = NEXTHDR_TCP;
|
||||
+ break;
|
||||
+ }
|
||||
+ case IPPROTO_UDP: {
|
||||
+ struct udphdr *udp = (struct udphdr *)(iiph + 1);
|
||||
+ *sport = udp->source;
|
||||
+ *dport = udp->dest;
|
||||
+ iiph->protocol = NEXTHDR_UDP;
|
||||
+ break;
|
||||
+ }
|
||||
+ case IPPROTO_ICMP: {
|
||||
+ struct icmphdr *icmph = (struct icmphdr *)(iiph + 1);
|
||||
+ iiph->protocol = NEXTHDR_ICMP;
|
||||
+ switch (icmph->type) {
|
||||
+ case ICMP_ECHO:
|
||||
+ icmph->type = ICMPV6_ECHO_REQUEST;
|
||||
+ *sport = *dport = icmph->un.echo.id;
|
||||
+ break;
|
||||
+ case ICMP_ECHOREPLY:
|
||||
+ icmph->type = ICMPV6_ECHO_REPLY;
|
||||
+ *sport = *dport = icmph->un.echo.id;
|
||||
+ break;
|
||||
+ default:
|
||||
+ nat46debug(3, "ICMP Error message can't be inside another ICMP Error messgae.");
|
||||
+ *sport = *dport = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ nat46debug(3, "[ICMPv4] Next header: %u. Only TCP, UDP, and ICMP are supported.", iiph->protocol);
|
||||
+ *sport = *dport = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ nat46debug(3, "Retrieved from pkt in error: dest port %d, and src port %d.", ntohs(*dport), ntohs(*sport));
|
||||
+
|
||||
+ if (!pairs_xlate_v4_to_v6_inner(nat46, iiph, *sport, *dport, v6saddr, v6daddr)) {
|
||||
+ nat46debug(0, "[nat46] Could not translate inner header v4->v6");
|
||||
+ *sport = *dport = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ fill_v6hdr_from_v4hdr (iiph, &ip6h);
|
||||
+ memcpy(&ip6h.saddr, v6saddr, sizeof(ip6h.saddr));
|
||||
+ memcpy(&ip6h.daddr, v6daddr, sizeof(ip6h.daddr));
|
||||
+
|
||||
+ if (skb_tailroom(old_skb) >= IPV6V4HDRDELTA){
|
||||
+ skb_put(old_skb, IPV6V4HDRDELTA);
|
||||
+ memmove(((char *)iiph + IPV6HDRSIZE), (iiph + 1), ntohs(iiph->tot_len) - IPV4HDRSIZE);
|
||||
+ memcpy(iiph, &ip6h, IPV6HDRSIZE);
|
||||
+ }
|
||||
+ else {
|
||||
+ ret = pskb_expand_head(old_skb, 0, IPV6V4HDRDELTA, GFP_ATOMIC);
|
||||
+ if (unlikely(ret)) {
|
||||
+ nat46debug(0, "[nat46] Could not copy v4 skb");
|
||||
+ *sport = *dport = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ skb_put(old_skb, IPV6V4HDRDELTA);
|
||||
+ iiph = (struct iphdr *)(icmp_hdr(old_skb) + 1);
|
||||
+ memmove(((char *)iiph + IPV6HDRSIZE), (iiph + 1), ntohs(iiph->tot_len) - IPV4HDRSIZE);
|
||||
+ memcpy(iiph, &ip6h, IPV6HDRSIZE);
|
||||
+ nat46 = get_nat46_instance(old_skb);
|
||||
+ iph = ip_hdr(old_skb);
|
||||
+ }
|
||||
+
|
||||
+ /* Swapping Ports for outer header */
|
||||
+ /* Another work-around till LPM is not present. */
|
||||
+ temp_port = *sport;
|
||||
+ *sport = *dport;
|
||||
+ *dport = temp_port;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
void nat46_ipv4_input(struct sk_buff *old_skb) {
|
||||
nat46_instance_t *nat46 = get_nat46_instance(old_skb);
|
||||
struct sk_buff *new_skb;
|
||||
- uint16_t sport = 0, dport = 0;
|
||||
+ uint16_t sport = 0, dport = 0, ret = 0;
|
||||
|
||||
uint8_t tclass;
|
||||
int flowlabel = 0;
|
||||
@@ -1772,11 +1937,11 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
}
|
||||
nat46debug(1, "nat46_ipv4_input packet");
|
||||
nat46debug(5, "nat46_ipv4_input protocol: %d, len: %d, flags: %02x", hdr4->protocol, old_skb->len, IPCB(old_skb)->flags);
|
||||
- if(0 == (ntohs(hdr4->frag_off) & 0x3FFF) ) {
|
||||
+ if(0 == (ntohs(hdr4->frag_off) & 0x3FFF) ) { /* Checking for MF */
|
||||
check_for_l4 = 1;
|
||||
} else {
|
||||
add_frag_header = 1;
|
||||
- if (0 == (ntohs(hdr4->frag_off) & 0x1FFF)) {
|
||||
+ if (0 == (ntohs(hdr4->frag_off) & 0x1FFF)) { /* Checking for Frag Offset */
|
||||
check_for_l4 = 1;
|
||||
}
|
||||
}
|
||||
@@ -1798,9 +1963,10 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
break;
|
||||
}
|
||||
case IPPROTO_ICMP:
|
||||
- sport = dport = nat46_fixup_icmp(nat46, hdr4, old_skb);
|
||||
- having_l4 = 1;
|
||||
- break;
|
||||
+ ret = nat46_fixup_icmp(nat46, hdr4, old_skb, &sport, &dport);
|
||||
+ nat46debug(3, "ICMP translated to dest port %d, and src port %d.", ntohs(dport), ntohs(sport));
|
||||
+ having_l4 = 1;
|
||||
+ break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
639
nat46/patches/105-longest-prefix-match.patch
Normal file
639
nat46/patches/105-longest-prefix-match.patch
Normal file
@ -0,0 +1,639 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Tue Aug 4 10:33:59 2020 +0530
|
||||
|
||||
nat46: Adding support for multiple MAP-T rules.
|
||||
|
||||
This patch is propagated from kernel 4.4 commit
|
||||
05a122b0cb0d3a99f040c94b3f626e7350f1445b
|
||||
|
||||
This change covers:
|
||||
1. Support for adding maximum of 32 MAP-T rules (DMR + FMRs).
|
||||
2. Support for rule lookup based on Longest Prefix Match method.
|
||||
3. Support for validation of new rules being inserted.
|
||||
|
||||
Change-Id: Id87448a8f544273b40c20aaab6e5c63b0dbd72e
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -121,6 +121,13 @@ int try_parse_ipv6_prefix(struct in6_add
|
||||
*arg_plen++ = 0;
|
||||
if (pref_len) {
|
||||
*pref_len = simple_strtol(arg_plen, NULL, 10);
|
||||
+
|
||||
+ /*
|
||||
+ * ipv6 prefix should be <= 128
|
||||
+ */
|
||||
+ if (*pref_len > IPV6_BITS_MAX) {
|
||||
+ return -1;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
err = (1 != in6_pton(arg, -1, (u8 *)pref, '\0', NULL));
|
||||
@@ -134,6 +141,13 @@ int try_parse_ipv4_prefix(u32 *v4addr, i
|
||||
*arg_plen++ = 0;
|
||||
if (pref_len) {
|
||||
*pref_len = simple_strtol(arg_plen, NULL, 10);
|
||||
+
|
||||
+ /*
|
||||
+ * ipv4 prefix len should be <= 32
|
||||
+ */
|
||||
+ if (*pref_len > IPV4_BITS_MAX) {
|
||||
+ return -1;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
err = (1 != in4_pton(arg, -1, (u8 *)v4addr, '/', NULL));
|
||||
@@ -176,11 +190,127 @@ int try_parse_rule_arg(nat46_xlate_rule_
|
||||
return err;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Parse the config commands in the buffer,
|
||||
- * destructive (puts zero between the args)
|
||||
+static inline void nat46_swap(nat46_xlate_rulepair_t *var1, nat46_xlate_rulepair_t *var2) {
|
||||
+ nat46_xlate_rulepair_t temp;
|
||||
+ temp = *var1;
|
||||
+ *var1 = *var2;
|
||||
+ *var2 = temp;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Sort rule pairs based on prefix length.
|
||||
*/
|
||||
+void nat46_sort_rule_array(nat46_instance_t *nat46) {
|
||||
+ int i, j;
|
||||
+ int nelem = nat46->npairs;
|
||||
+ nat46_xlate_rulepair_t *array = NULL;
|
||||
+
|
||||
+ memcpy(nat46->sorted_ipv4_local_pairs, nat46->pairs, nelem * sizeof(nat46_xlate_rulepair_t));
|
||||
+ memcpy(nat46->sorted_ipv4_remote_pairs, nat46->pairs, nelem * sizeof(nat46_xlate_rulepair_t));
|
||||
+ memcpy(nat46->sorted_ipv6_local_pairs, nat46->pairs, nelem * sizeof(nat46_xlate_rulepair_t));
|
||||
+ memcpy(nat46->sorted_ipv6_remote_pairs, nat46->pairs, nelem * sizeof(nat46_xlate_rulepair_t));
|
||||
+
|
||||
+ array = &nat46->sorted_ipv4_local_pairs[0];
|
||||
+ for (i = 0; i < nelem - 1; i++) {
|
||||
+ for (j = 0; j < nelem - i - 1; j++) {
|
||||
+ if (array[j].local.v4_pref_len < array[j+1].local.v4_pref_len) {
|
||||
+ nat46_swap (&array[j], &array[j+1]);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ array = &nat46->sorted_ipv4_remote_pairs[0];
|
||||
+ for (i = 0; i < nelem - 1; i++) {
|
||||
+ for (j = 0; j < nelem - i - 1; j++) {
|
||||
+ if (array[j].remote.v4_pref_len < array[j+1].remote.v4_pref_len) {
|
||||
+ nat46_swap (&array[j], &array[j+1]);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
+ array = &nat46->sorted_ipv6_local_pairs[0];
|
||||
+ for (i = 0; i < nelem - 1; i++) {
|
||||
+ for (j = 0; j < nelem - i - 1; j++) {
|
||||
+ if (array[j].local.v6_pref_len < array[j+1].local.v6_pref_len) {
|
||||
+ nat46_swap (&array[j], &array[j+1]);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ array = &nat46->sorted_ipv6_remote_pairs[0];
|
||||
+ for (i = 0; i < nelem - 1; i++) {
|
||||
+ for (j = 0; j < nelem - i - 1; j++) {
|
||||
+ if (array[j].remote.v6_pref_len < array[j+1].remote.v6_pref_len) {
|
||||
+ nat46_swap (&array[j], &array[j+1]);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+bool nat46_validate_RFC6052_style(nat46_instance_t *nat46, nat46_xlate_rule_t rule)
|
||||
+{
|
||||
+ if (rule.style == NAT46_XLATE_RFC6052) {
|
||||
+ if (!((rule.v6_pref_len == 32) || (rule.v6_pref_len == 40) ||
|
||||
+ (rule.v6_pref_len == 48) || (rule.v6_pref_len == 56) ||
|
||||
+ (rule.v6_pref_len == 64) || (rule.v6_pref_len == 96))) {
|
||||
+ nat46debug(3, "IPv6 prefix len is invalid");
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool nat46_validate_MAP_style(nat46_instance_t *nat46, nat46_xlate_rule_t rule)
|
||||
+{
|
||||
+ int psid_len;
|
||||
+ if (rule.style == NAT46_XLATE_MAP) {
|
||||
+
|
||||
+ /*
|
||||
+ * max ea_len is 48
|
||||
+ */
|
||||
+ if (rule.ea_len > EA_LEN_MAX) {
|
||||
+ nat46debug(3, "EA-length should not exceed 48");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (rule.v4_pref_len + rule.ea_len > IPV4_BITS_MAX) {
|
||||
+ psid_len = rule.ea_len - (IPV4_BITS_MAX - rule.v4_pref_len);
|
||||
+ } else {
|
||||
+ psid_len = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (psid_len + rule.psid_offset > PSID_LEN_MAX) {
|
||||
+ nat46debug(3, "psid_len + psid_offset should not exceed 16");
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+int nat46_validate_ipair_config(nat46_instance_t *nat46, nat46_xlate_rulepair_t *apair)
|
||||
+{
|
||||
+ if (!nat46_validate_RFC6052_style(nat46, apair->local)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (!nat46_validate_RFC6052_style(nat46, apair->remote)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (!nat46_validate_MAP_style(nat46, apair->local)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (!nat46_validate_MAP_style(nat46, apair->remote)) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Parse the config commands in the buffer,
|
||||
+ * destructive (puts zero between the args)
|
||||
+ */
|
||||
int nat46_set_ipair_config(nat46_instance_t *nat46, int ipair, char *buf, int count) {
|
||||
char *tail = buf;
|
||||
char *arg_name;
|
||||
@@ -210,7 +340,18 @@ int nat46_set_ipair_config(nat46_instanc
|
||||
err = try_parse_rule_arg(&apair->remote, arg_name, &tail);
|
||||
}
|
||||
}
|
||||
- return err;
|
||||
+
|
||||
+ err = nat46_validate_ipair_config(nat46, apair);
|
||||
+ if (err) {
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * sort nat46->pairs based on prefix length.
|
||||
+ */
|
||||
+ nat46_sort_rule_array(nat46);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
int nat46_set_config(nat46_instance_t *nat46, char *buf, int count) {
|
||||
@@ -854,37 +995,120 @@ int is_last_pair_in_group(nat46_xlate_ru
|
||||
return ( (apair->local.style != NAT46_XLATE_NONE) && (apair->remote.style != NAT46_XLATE_NONE) );
|
||||
}
|
||||
|
||||
+nat46_xlate_rulepair_t *nat46_lpm(nat46_instance_t *nat46, nat46_rule_type_t type, void *paddr) {
|
||||
+ int ipair = 0;
|
||||
+ nat46_xlate_rulepair_t *apair = NULL;
|
||||
+ uint32_t mask = 0;
|
||||
+ uint8_t *pa1;
|
||||
+ uint8_t *pa2;
|
||||
+
|
||||
+ if(!nat46 || !paddr) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case NAT46_IPV4_LOCAL:
|
||||
+ for (ipair = 0; ipair < nat46->npairs; ipair++) {
|
||||
+ apair = &nat46->sorted_ipv4_local_pairs[ipair];
|
||||
+
|
||||
+ /*
|
||||
+ * For a 32-bit number, if the shift count is 32, then the
|
||||
+ * result of the left shift operation is always 0.
|
||||
+ */
|
||||
+ if (apair->local.v4_pref_len) {
|
||||
+ mask = htonl(U32_MASK << (IPV4_BITS_MAX - apair->local.v4_pref_len));
|
||||
+ }
|
||||
+
|
||||
+ if((*(uint32_t *)paddr & mask) == (apair->local.v4_pref & mask)) {
|
||||
+ return apair;
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+ case NAT46_IPV4_REMOTE:
|
||||
+ for (ipair = 0; ipair < nat46->npairs; ipair++) {
|
||||
+ apair = &nat46->sorted_ipv4_remote_pairs[ipair];
|
||||
+
|
||||
+ /*
|
||||
+ * For a 32-bit number, if the shift count is 32, then the
|
||||
+ * result of the left shift operation is always 0.
|
||||
+ */
|
||||
+ if (apair->remote.v4_pref_len) {
|
||||
+ mask = htonl(U32_MASK << (IPV4_BITS_MAX - apair->remote.v4_pref_len));
|
||||
+ }
|
||||
+
|
||||
+ if((*(uint32_t *)paddr & mask) == (apair->remote.v4_pref & mask)) {
|
||||
+ return apair;
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+ case NAT46_IPV6_LOCAL:
|
||||
+ for (ipair = 0; ipair < nat46->npairs; ipair++) {
|
||||
+ apair = &nat46->sorted_ipv6_local_pairs[ipair];
|
||||
+ if(memcmp(paddr, &apair->local.v6_pref, apair->local.v6_pref_len / BITS_PER_BYTE)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if(apair->local.v6_pref_len % BITS_PER_BYTE) {
|
||||
+ mask = U8_MASK << (BITS_PER_BYTE - (apair->local.v6_pref_len % BITS_PER_BYTE));
|
||||
+ pa1 = (uint8_t *)paddr + (apair->local.v6_pref_len / BITS_PER_BYTE);
|
||||
+ pa2 = (uint8_t *)&apair->local.v6_pref + (apair->local.v6_pref_len / BITS_PER_BYTE);
|
||||
+
|
||||
+ if ((*pa1 & mask) == (*pa2 & mask)) {
|
||||
+ return apair;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ return apair;
|
||||
+ }
|
||||
+ break;
|
||||
+ case NAT46_IPV6_REMOTE:
|
||||
+ for (ipair = 0; ipair < nat46->npairs; ipair++) {
|
||||
+ apair = &nat46->sorted_ipv6_remote_pairs[ipair];
|
||||
+ if(memcmp(paddr, &apair->remote.v6_pref, apair->remote.v6_pref_len / BITS_PER_BYTE)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if(apair->remote.v6_pref_len % BITS_PER_BYTE) {
|
||||
+ mask = U8_MASK << (BITS_PER_BYTE - (apair->remote.v6_pref_len % BITS_PER_BYTE));
|
||||
+ pa1 = (uint8_t *)paddr + (apair->remote.v6_pref_len / BITS_PER_BYTE);
|
||||
+ pa2 = (uint8_t *)&apair->remote.v6_pref + (apair->remote.v6_pref_len / BITS_PER_BYTE);
|
||||
+
|
||||
+ if((*pa1 & mask) == (*pa2 & mask)) {
|
||||
+ return apair;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ return apair;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ nat46debug(0, "%s : Invalid prefix type.\n", __func__);
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
void pairs_xlate_v6_to_v4_inner(nat46_instance_t *nat46, struct ipv6hdr *ip6h, __u32 *pv4saddr, __u32 *pv4daddr) {
|
||||
int ipair = 0;
|
||||
nat46_xlate_rulepair_t *apair = NULL;
|
||||
int xlate_src = -1;
|
||||
int xlate_dst = -1;
|
||||
|
||||
- for(ipair = 0; ipair < nat46->npairs; ipair++) {
|
||||
- apair = &nat46->pairs[ipair];
|
||||
+ apair = nat46_lpm(nat46, NAT46_IPV6_REMOTE, &ip6h->daddr);
|
||||
+ if (!apair) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- if(-1 == xlate_dst) {
|
||||
- if(xlate_v6_to_v4(nat46, &apair->remote, &ip6h->daddr, pv4daddr)) {
|
||||
- xlate_dst = ipair;
|
||||
- }
|
||||
- }
|
||||
- if(-1 == xlate_src) {
|
||||
- if(xlate_v6_to_v4(nat46, &apair->local, &ip6h->saddr, pv4saddr)) {
|
||||
- xlate_src = ipair;
|
||||
- }
|
||||
- }
|
||||
- if((xlate_src >= 0) && (xlate_dst >= 0)) {
|
||||
- /* we did manage to translate it */
|
||||
- break;
|
||||
- } else {
|
||||
- /* We did not match fully and there are more rules */
|
||||
- if((ipair+1 < nat46->npairs) && is_last_pair_in_group(apair)) {
|
||||
- xlate_src = -1;
|
||||
- xlate_dst = -1;
|
||||
- }
|
||||
- }
|
||||
+ if (xlate_v6_to_v4(nat46, &apair->remote, &ip6h->daddr, pv4daddr)) {
|
||||
+ xlate_dst = ipair;
|
||||
+ }
|
||||
+ if (xlate_v6_to_v4(nat46, &apair->local, &ip6h->saddr, pv4saddr)) {
|
||||
+ xlate_src = ipair;
|
||||
+ }
|
||||
+
|
||||
+ if ((xlate_src >= 0) && (xlate_dst >= 0)) {
|
||||
+ /* we did manage to translate it */
|
||||
+ nat46debug(5, "[nat46payload] xlate results: src %d dst %d", xlate_src, xlate_dst);
|
||||
+ } else {
|
||||
+ nat46debug(1, "[nat46] Could not find a translation pair v6->v4 src %pI6c dst %pI6c", &ip6h->saddr, &ip6h->daddr);
|
||||
}
|
||||
- nat46debug(5, "[nat46payload] xlate results: src %d dst %d", xlate_src, xlate_dst);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1471,40 +1695,28 @@ static uint16_t nat46_fixup_icmp(nat46_i
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int pairs_xlate_v6_to_v4_outer(nat46_instance_t *nat46, struct ipv6hdr *ip6h, uint16_t proto, __u32 *pv4saddr, __u32 *pv4daddr) {
|
||||
+int pairs_xlate_v6_to_v4_outer(nat46_instance_t *nat46, nat46_xlate_rulepair_t *apair,
|
||||
+ struct ipv6hdr *ip6h, uint16_t proto, __u32 *pv4saddr, __u32 *pv4daddr) {
|
||||
int ipair = 0;
|
||||
- nat46_xlate_rulepair_t *apair = NULL;
|
||||
int xlate_src = -1;
|
||||
int xlate_dst = -1;
|
||||
|
||||
- for(ipair = 0; ipair < nat46->npairs; ipair++) {
|
||||
- apair = &nat46->pairs[ipair];
|
||||
+ apair = nat46_lpm(nat46, NAT46_IPV6_REMOTE, &ip6h->saddr);
|
||||
+ if (!apair) {
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- if(-1 == xlate_dst) {
|
||||
- if (xlate_v6_to_v4(nat46, &apair->local, &ip6h->daddr, pv4daddr)) {
|
||||
- nat46debug(5, "Dst addr %pI6 to %pI4 \n", &ip6h->daddr, pv4daddr);
|
||||
- xlate_dst = ipair;
|
||||
- }
|
||||
- }
|
||||
- if(-1 == xlate_src) {
|
||||
- if (xlate_v6_to_v4(nat46, &apair->remote, &ip6h->saddr, pv4saddr)) {
|
||||
- nat46debug(5, "Src addr %pI6 to %pI4 \n", &ip6h->saddr, pv4saddr);
|
||||
- xlate_src = ipair;
|
||||
- }
|
||||
- }
|
||||
- if( (xlate_src >= 0) && (xlate_dst >= 0) ) {
|
||||
- break;
|
||||
- } else {
|
||||
- /* We did not match fully and there are more rules */
|
||||
- if((ipair+1 < nat46->npairs) && is_last_pair_in_group(apair)) {
|
||||
- xlate_src = -1;
|
||||
- xlate_dst = -1;
|
||||
- }
|
||||
- }
|
||||
+ if (xlate_v6_to_v4(nat46, &apair->local, &ip6h->daddr, pv4daddr)) {
|
||||
+ nat46debug(5, "Dst addr %pI6 to %pI4 \n", &ip6h->daddr, pv4daddr);
|
||||
+ xlate_dst = ipair;
|
||||
+ }
|
||||
+ if (xlate_v6_to_v4(nat46, &apair->remote, &ip6h->saddr, pv4saddr)) {
|
||||
+ nat46debug(5, "Src addr %pI6 to %pI4 \n", &ip6h->saddr, pv4saddr);
|
||||
+ xlate_src = ipair;
|
||||
}
|
||||
if (xlate_dst >= 0) {
|
||||
if (xlate_src < 0) {
|
||||
- if(proto == NEXTHDR_ICMP) {
|
||||
+ if (proto == NEXTHDR_ICMP) {
|
||||
nat46debug(1, "[nat46] Could not translate remote address v6->v4, ipair %d, for ICMP6 use dest addr", ipair);
|
||||
*pv4saddr = *pv4daddr;
|
||||
xlate_src = xlate_dst;
|
||||
@@ -1520,12 +1732,14 @@ int pairs_xlate_v6_to_v4_outer(nat46_ins
|
||||
}
|
||||
|
||||
int xlate_6_to_4(struct net_device *dev, struct ipv6hdr *ip6h, uint16_t proto, __u32 *pv4saddr, __u32 *pv4daddr) {
|
||||
- return pairs_xlate_v6_to_v4_outer(netdev_nat46_instance(dev), ip6h, proto, pv4saddr, pv4daddr);
|
||||
+ nat46_xlate_rulepair_t apair;
|
||||
+ return pairs_xlate_v6_to_v4_outer(netdev_nat46_instance(dev), &apair, ip6h, proto, pv4saddr, pv4daddr);
|
||||
}
|
||||
EXPORT_SYMBOL(xlate_6_to_4);
|
||||
|
||||
void nat46_ipv6_input(struct sk_buff *old_skb) {
|
||||
struct ipv6hdr *ip6h = ipv6_hdr(old_skb);
|
||||
+ nat46_xlate_rulepair_t apair;
|
||||
nat46_instance_t *nat46 = get_nat46_instance(old_skb);
|
||||
uint16_t proto;
|
||||
uint16_t frag_off;
|
||||
@@ -1586,7 +1800,7 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
check_for_l4 = 1;
|
||||
}
|
||||
|
||||
- if(!pairs_xlate_v6_to_v4_outer(nat46, ip6h, proto, &v4saddr, &v4daddr)) {
|
||||
+ if (!pairs_xlate_v6_to_v4_outer(nat46, &apair, ip6h, proto, &v4saddr, &v4daddr)) {
|
||||
nat46debug(0, "[nat46] Could not translate v6->v4");
|
||||
goto done;
|
||||
}
|
||||
@@ -1730,56 +1944,44 @@ int ip4_input_not_interested(nat46_insta
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int pairs_xlate_v4_to_v6_outer(nat46_instance_t *nat46, struct iphdr *hdr4, uint16_t *sport, uint16_t *dport, void *v6saddr, void *v6daddr) {
|
||||
+int pairs_xlate_v4_to_v6_outer(nat46_instance_t *nat46, nat46_xlate_rulepair_t *apair,
|
||||
+ struct iphdr *hdr4, uint16_t *sport, uint16_t *dport, void *v6saddr, void *v6daddr) {
|
||||
int ipair = 0;
|
||||
- nat46_xlate_rulepair_t *apair = NULL;
|
||||
int xlate_src = -1;
|
||||
int xlate_dst = -1;
|
||||
+ int ret = 0;
|
||||
|
||||
- for(ipair = 0; ipair < nat46->npairs; ipair++) {
|
||||
- apair = &nat46->pairs[ipair];
|
||||
+ apair = nat46_lpm(nat46, NAT46_IPV4_REMOTE, &hdr4->daddr);
|
||||
+ if (!apair) {
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- if(-1 == xlate_src) {
|
||||
- if(xlate_v4_to_v6(nat46, &apair->local, &hdr4->saddr, v6saddr, sport)) {
|
||||
- nat46debug(5, "Src addr %pI4 to %pI6 \n", &hdr4->saddr, v6saddr);
|
||||
- xlate_src = ipair;
|
||||
- }
|
||||
- }
|
||||
- if(-1 == xlate_dst) {
|
||||
- if(xlate_v4_to_v6(nat46, &apair->remote, &hdr4->daddr, v6daddr, dport)) {
|
||||
- nat46debug(5, "Dst addr %pI4 to %pI6 \n", &hdr4->daddr, v6daddr);
|
||||
- xlate_dst = ipair;
|
||||
- }
|
||||
- }
|
||||
- if( (xlate_src >= 0) && (xlate_dst >= 0) ) {
|
||||
- break;
|
||||
- } else {
|
||||
- /* We did not match fully and there are more rules */
|
||||
- if((ipair+1 < nat46->npairs) && is_last_pair_in_group(apair)) {
|
||||
- xlate_src = -1;
|
||||
- xlate_dst = -1;
|
||||
- }
|
||||
- }
|
||||
+ if (xlate_v4_to_v6(nat46, &apair->local, &hdr4->saddr, v6saddr, sport)) {
|
||||
+ nat46debug(5, "Src addr %pI4 to %pI6 \n", &hdr4->saddr, v6saddr);
|
||||
+ xlate_src = ipair;
|
||||
+ }
|
||||
+ if (xlate_v4_to_v6(nat46, &apair->remote, &hdr4->daddr, v6daddr, dport)) {
|
||||
+ nat46debug(5, "Dst addr %pI4 to %pI6 \n", &hdr4->daddr, v6daddr);
|
||||
+ xlate_dst = ipair;
|
||||
}
|
||||
nat46debug(5, "[nat46] pairs_xlate_v4_to_v6_outer result: src %d dst %d", xlate_src, xlate_dst);
|
||||
if ( (xlate_src >= 0) && (xlate_dst >= 0) ) {
|
||||
- return 1;
|
||||
+ ret = 1;
|
||||
+ } else {
|
||||
+ nat46debug(1, "[nat46] Could not find a translation pair v4->v6");
|
||||
}
|
||||
-
|
||||
- nat46debug(1, "[nat46] Could not find a translation pair v4->v6");
|
||||
-
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
int xlate_4_to_6(struct net_device *dev, struct iphdr *hdr4, uint16_t sport, uint16_t dport, void *v6saddr, void *v6daddr) {
|
||||
- return pairs_xlate_v4_to_v6_outer(netdev_nat46_instance(dev), hdr4, &sport, &dport, v6saddr, v6daddr);
|
||||
+ nat46_xlate_rulepair_t apair;
|
||||
+ return pairs_xlate_v4_to_v6_outer(netdev_nat46_instance(dev), &apair, hdr4, &sport, &dport, v6saddr, v6daddr);
|
||||
}
|
||||
EXPORT_SYMBOL(xlate_4_to_6);
|
||||
|
||||
-/* FIXME: This is a workaround, till the LPM is not added. The sport & dport in inner header will be dport & sport of the outer
|
||||
- * header, respectively. Hence, dest. and source ips of inner header will be found in local & remote rules, respectively.
|
||||
- * Will work only for a pair of local & remote rules. Once LPM is brought in, this method can be removed and
|
||||
- * pairs_xlate_v4_to_v6_outer be used instead.
|
||||
+/*
|
||||
+ * The sport & dport in inner header will be dport & sport of the outer header, respectively.
|
||||
+ * Hence, dest. and source ips of inner header will be found in local & remote rules, respectively.
|
||||
*/
|
||||
int pairs_xlate_v4_to_v6_inner(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
uint16_t sport, uint16_t dport, void *v6saddr, void *v6daddr) {
|
||||
@@ -1788,35 +1990,27 @@ int pairs_xlate_v4_to_v6_inner(nat46_ins
|
||||
int xlate_src = -1;
|
||||
int xlate_dst = -1;
|
||||
|
||||
- for (ipair = 0; ipair < nat46->npairs; ipair++) {
|
||||
- apair = &nat46->pairs[ipair];
|
||||
+ apair = nat46_lpm(nat46, NAT46_IPV4_REMOTE, &iph->saddr);
|
||||
+ if (!apair) {
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- if (-1 == xlate_dst) {
|
||||
- if (xlate_v4_to_v6(nat46, &apair->local, &iph->daddr, v6daddr, &dport)) {
|
||||
- nat46debug(3, "Dst addr %pI4 to %pI6 \n", &iph->daddr, v6daddr);
|
||||
- xlate_dst = ipair;
|
||||
- }
|
||||
- }
|
||||
- if (-1 == xlate_src) {
|
||||
- if(xlate_v4_to_v6(nat46, &apair->remote, &iph->saddr, v6saddr, &sport)) {
|
||||
- nat46debug(3, "Src addr %pI4 to %pI6 \n", &iph->saddr, v6saddr);
|
||||
- xlate_src = ipair;
|
||||
- }
|
||||
- }
|
||||
- if ((xlate_src >= 0) && (xlate_dst >= 0)) {
|
||||
- /* we did manage to translate it */
|
||||
- nat46debug(5, "[nat46] Inner header xlate results: src %d dst %d", xlate_src, xlate_dst);
|
||||
- return 1;
|
||||
- } else {
|
||||
- /* We did not match fully and there are more rules */
|
||||
- if((ipair+1 < nat46->npairs) && is_last_pair_in_group(apair)) {
|
||||
- xlate_src = -1;
|
||||
- xlate_dst = -1;
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
+ if (xlate_v4_to_v6(nat46, &apair->local, &iph->daddr, v6daddr, &dport)) {
|
||||
+ nat46debug(3, "Dst addr %pI4 to %pI6 \n", &iph->daddr, v6daddr);
|
||||
+ xlate_dst = ipair;
|
||||
+ }
|
||||
+ if (xlate_v4_to_v6(nat46, &apair->remote, &iph->saddr, v6saddr, &sport)) {
|
||||
+ nat46debug(3, "Src addr %pI4 to %pI6 \n", &iph->saddr, v6saddr);
|
||||
+ xlate_src = ipair;
|
||||
+ }
|
||||
+ if ((xlate_src >= 0) && (xlate_dst >= 0)) {
|
||||
+ /* we did manage to translate it */
|
||||
+ nat46debug(5, "[nat46] Inner header xlate results: src %d dst %d", xlate_src, xlate_dst);
|
||||
+ return 1;
|
||||
+ } else {
|
||||
+ nat46debug(1, "[nat46] Could not find a translation pair v4->v6");
|
||||
+ }
|
||||
|
||||
- nat46debug(1, "[nat46] Could not find a translation pair v4->v6");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1913,6 +2107,7 @@ static uint16_t xlate_pkt_in_err_v4_to_v
|
||||
|
||||
void nat46_ipv4_input(struct sk_buff *old_skb) {
|
||||
nat46_instance_t *nat46 = get_nat46_instance(old_skb);
|
||||
+ nat46_xlate_rulepair_t apair;
|
||||
struct sk_buff *new_skb;
|
||||
uint16_t sport = 0, dport = 0, ret = 0;
|
||||
|
||||
@@ -1979,7 +2174,7 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
having_l4 = 1;
|
||||
}
|
||||
|
||||
- if(!pairs_xlate_v4_to_v6_outer(nat46, hdr4, having_l4 ? &sport : NULL, having_l4 ? &dport : NULL, v6saddr, v6daddr)) {
|
||||
+ if(!pairs_xlate_v4_to_v6_outer(nat46, &apair, hdr4, having_l4 ? &sport : NULL, having_l4 ? &dport : NULL, v6saddr, v6daddr)) {
|
||||
nat46debug(0, "[nat46] Could not translate v4->v6");
|
||||
goto done;
|
||||
}
|
||||
--- a/nat46/modules/nat46-core.h
|
||||
+++ b/nat46/modules/nat46-core.h
|
||||
@@ -23,6 +23,15 @@
|
||||
// #define nat46debug(level, format, ...)
|
||||
#define nat46debug(level, format, ...) do { if(nat46->debug >= level) { printk(format "\n", ##__VA_ARGS__); } } while (0)
|
||||
|
||||
+#define U8_MASK (uint8_t)(0xFF)
|
||||
+#define U32_MASK (uint32_t)(~0U)
|
||||
+#define BITS_PER_BYTE 8
|
||||
+#define PSID_LEN_MAX 16
|
||||
+#define NUM_RULE_PAIRS_MAX 32
|
||||
+#define IPV4_BITS_MAX 32
|
||||
+#define EA_LEN_MAX 48
|
||||
+#define IPV6_BITS_MAX 128
|
||||
+
|
||||
#define IPV6HDRSIZE 40
|
||||
#define IPV4HDRSIZE 20
|
||||
#define IPV6V4HDRDELTA (IPV6HDRSIZE - IPV4HDRSIZE)
|
||||
@@ -39,6 +48,17 @@ typedef enum {
|
||||
NAT46_XLATE_RFC6052
|
||||
} nat46_xlate_style_t;
|
||||
|
||||
+/*
|
||||
+ * Enumeration for sorting pairs based on
|
||||
+ * type of prefix length.
|
||||
+ */
|
||||
+typedef enum {
|
||||
+ NAT46_IPV4_LOCAL = 0,
|
||||
+ NAT46_IPV4_REMOTE,
|
||||
+ NAT46_IPV6_LOCAL,
|
||||
+ NAT46_IPV6_REMOTE
|
||||
+} nat46_rule_type_t;
|
||||
+
|
||||
#define NAT46_SIGNATURE 0x544e3634
|
||||
#define FREED_NAT46_SIGNATURE 0xdead544e
|
||||
|
||||
@@ -64,7 +84,11 @@ typedef struct {
|
||||
int debug;
|
||||
|
||||
int npairs;
|
||||
- nat46_xlate_rulepair_t pairs[0]; /* npairs */
|
||||
+ nat46_xlate_rulepair_t pairs[NUM_RULE_PAIRS_MAX]; /* npairs */
|
||||
+ nat46_xlate_rulepair_t sorted_ipv4_local_pairs[NUM_RULE_PAIRS_MAX]; /* npairs */
|
||||
+ nat46_xlate_rulepair_t sorted_ipv4_remote_pairs[NUM_RULE_PAIRS_MAX]; /* npairs */
|
||||
+ nat46_xlate_rulepair_t sorted_ipv6_local_pairs[NUM_RULE_PAIRS_MAX]; /* npairs */
|
||||
+ nat46_xlate_rulepair_t sorted_ipv6_remote_pairs[NUM_RULE_PAIRS_MAX]; /* npairs */
|
||||
} nat46_instance_t;
|
||||
|
||||
void nat46_ipv6_input(struct sk_buff *old_skb);
|
||||
--- a/nat46/modules/nat46-netdev.c
|
||||
+++ b/nat46/modules/nat46-netdev.c
|
||||
@@ -263,7 +263,13 @@ int nat46_insert(char *devname, char *bu
|
||||
int ret = -1;
|
||||
if(dev) {
|
||||
nat46_instance_t *nat46 = netdev_nat46_instance(dev);
|
||||
- nat46_instance_t *nat46_new = alloc_nat46_instance(nat46->npairs+1, nat46, 0, 1);
|
||||
+ nat46_instance_t *nat46_new;
|
||||
+ if(nat46->npairs == NUM_RULE_PAIRS_MAX) {
|
||||
+ printk("Could not insert a new rule on device %s\n", devname);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ nat46_new = alloc_nat46_instance(nat46->npairs+1, nat46, 0, 1);
|
||||
if(nat46_new) {
|
||||
netdev_nat46_set_instance(dev, nat46_new);
|
||||
ret = nat46_set_ipair_config(nat46_new, 0, buf, strlen(buf));
|
||||
100
nat46/patches/106-dummy_header.patch
Normal file
100
nat46/patches/106-dummy_header.patch
Normal file
@ -0,0 +1,100 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Aug 5 10:09:45 2020 +0530
|
||||
|
||||
nat46: Add dummy fragment header for DF=0 IPv4 packet.
|
||||
|
||||
This patch is propagated from 4.4 kernel commit
|
||||
b45f19e86ebcc19ea26d5e014bfdcb837148f99e.
|
||||
|
||||
Add dummy fragment header to IPv6 translated packet for
|
||||
every DF=0 IPv4 packet.
|
||||
|
||||
Change-Id: Id72945eefac030e95e4fd18305e48c46e525def3
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "nat46-glue.h"
|
||||
#include "nat46-core.h"
|
||||
+#include "nat46-module.h"
|
||||
|
||||
static uint16_t xlate_pkt_in_err_v4_to_v6(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
struct sk_buff *old_skb, uint16_t *sport, uint16_t *dport);
|
||||
@@ -2134,6 +2135,11 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
nat46debug(5, "nat46_ipv4_input protocol: %d, len: %d, flags: %02x", hdr4->protocol, old_skb->len, IPCB(old_skb)->flags);
|
||||
if(0 == (ntohs(hdr4->frag_off) & 0x3FFF) ) { /* Checking for MF */
|
||||
check_for_l4 = 1;
|
||||
+ if (add_dummy_header) {
|
||||
+ if (0 == (ntohs(hdr4->frag_off) & IP_DF)) {
|
||||
+ add_frag_header = 1;
|
||||
+ }
|
||||
+ }
|
||||
} else {
|
||||
add_frag_header = 1;
|
||||
if (0 == (ntohs(hdr4->frag_off) & 0x1FFF)) { /* Checking for Frag Offset */
|
||||
@@ -2263,3 +2269,24 @@ bool nat46_get_rule_config(struct net_de
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(nat46_get_rule_config);
|
||||
+
|
||||
+/*
|
||||
+ * Function to get MAP-T rules and flags.
|
||||
+ */
|
||||
+bool nat46_get_info(struct net_device *dev, nat46_xlate_rulepair_t **nat46_rule_pair,
|
||||
+ int *count, u8 *flag) {
|
||||
+ if ((!dev) || (!nat46_rule_pair) || (!count) || (!flag)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (!nat46_get_rule_config(dev, nat46_rule_pair, count)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Check add dummy header flag */
|
||||
+ if (add_dummy_header) {
|
||||
+ *flag = ADD_DUMMY_HEADER;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nat46_get_info);
|
||||
--- a/nat46/modules/nat46-core.h
|
||||
+++ b/nat46/modules/nat46-core.h
|
||||
@@ -32,6 +32,9 @@
|
||||
#define EA_LEN_MAX 48
|
||||
#define IPV6_BITS_MAX 128
|
||||
|
||||
+/* Flag definations for MAP-T */
|
||||
+#define ADD_DUMMY_HEADER 0x01
|
||||
+
|
||||
#define IPV6HDRSIZE 40
|
||||
#define IPV4HDRSIZE 20
|
||||
#define IPV6V4HDRDELTA (IPV6HDRSIZE - IPV4HDRSIZE)
|
||||
@@ -110,5 +113,6 @@ int xlate_6_to_4(struct net_device *dev,
|
||||
int xlate_4_to_6(struct net_device *dev, struct iphdr *hdr4, uint16_t sport, uint16_t dport, void *v6saddr, void *v6daddr);
|
||||
bool nat46_get_rule_config(struct net_device *dev, nat46_xlate_rulepair_t **nat46_rule_pair, int *count);
|
||||
int nat46_get_npairs(struct net_device *dev);
|
||||
-
|
||||
+bool nat46_get_info(struct net_device *dev, nat46_xlate_rulepair_t **nat46_rule_pair,
|
||||
+ int *count, u8 *flag);
|
||||
#endif
|
||||
--- a/nat46/modules/nat46-module.c
|
||||
+++ b/nat46/modules/nat46-module.c
|
||||
@@ -57,6 +57,9 @@ MODULE_DESCRIPTION("NAT46 stateless tran
|
||||
int debug = 0;
|
||||
module_param(debug, int, 0);
|
||||
MODULE_PARM_DESC(debug, "debugging messages level (default=1)");
|
||||
+bool add_dummy_header = 0;
|
||||
+module_param(add_dummy_header, bool, 0);
|
||||
+MODULE_PARM_DESC(add_dummy_header, "Add dummy fragment header");
|
||||
|
||||
static struct proc_dir_entry *nat46_proc_entry;
|
||||
static struct proc_dir_entry *nat46_proc_parent;
|
||||
--- a/nat46/modules/nat46-module.h
|
||||
+++ b/nat46/modules/nat46-module.h
|
||||
@@ -14,3 +14,4 @@
|
||||
*/
|
||||
|
||||
extern int debug;
|
||||
+extern bool add_dummy_header;
|
||||
134
nat46/patches/107-stats.patch
Normal file
134
nat46/patches/107-stats.patch
Normal file
@ -0,0 +1,134 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Aug 5 10:57:25 2020 +0530
|
||||
|
||||
nat46: Add support for 64-bits stats.
|
||||
|
||||
This patch is propagated from 4.4 kernel commit
|
||||
4a2d1dd9bc9331392c7a4947126c361217c82e0c
|
||||
|
||||
Add 64-bits stats functionality for MAP-T interface.
|
||||
|
||||
Change-Id: I4a6f9c7ed3554ac0ec672aa5fa283be2e95cfdc0
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-netdev.c
|
||||
+++ b/nat46/modules/nat46-netdev.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <net/ip6_route.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <linux/version.h>
|
||||
+#include <net/ip_tunnels.h>
|
||||
#include <linux/radix-tree.h>
|
||||
#include "nat46-core.h"
|
||||
#include "nat46-module.h"
|
||||
@@ -40,16 +41,40 @@ static u8 netdev_count = 0;
|
||||
|
||||
static int nat46_netdev_up(struct net_device *dev);
|
||||
static int nat46_netdev_down(struct net_device *dev);
|
||||
-
|
||||
+static int nat46_netdev_init(struct net_device *dev);
|
||||
+static void nat46_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *tot);
|
||||
static netdev_tx_t nat46_netdev_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
|
||||
|
||||
static const struct net_device_ops nat46_netdev_ops = {
|
||||
+ .ndo_init = nat46_netdev_init, /* device specific initialization */
|
||||
.ndo_open = nat46_netdev_up, /* Called at ifconfig nat46 up */
|
||||
.ndo_stop = nat46_netdev_down, /* Called at ifconfig nat46 down */
|
||||
.ndo_start_xmit = nat46_netdev_xmit, /* REQUIRED, must return NETDEV_TX_OK */
|
||||
+ .ndo_get_stats64 = nat46_get_stats64, /* 64 bit device stats */
|
||||
};
|
||||
|
||||
+static int nat46_netdev_init(struct net_device *dev)
|
||||
+{
|
||||
+ int i;
|
||||
+ dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
|
||||
+ if (!dev->tstats) {
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ for_each_possible_cpu(i) {
|
||||
+ struct pcpu_sw_netstats *ipt_stats;
|
||||
+ ipt_stats = per_cpu_ptr(dev->tstats, i);
|
||||
+ u64_stats_init(&ipt_stats->syncp);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void nat46_netdev_resource_free(struct net_device *dev)
|
||||
+{
|
||||
+ free_percpu(dev->tstats);
|
||||
+}
|
||||
+
|
||||
static int nat46_netdev_up(struct net_device *dev)
|
||||
{
|
||||
netif_start_queue(dev);
|
||||
@@ -64,8 +89,13 @@ static int nat46_netdev_down(struct net_
|
||||
|
||||
static netdev_tx_t nat46_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
- dev->stats.rx_packets++;
|
||||
- dev->stats.rx_bytes += skb->len;
|
||||
+ struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats);
|
||||
+
|
||||
+ u64_stats_update_begin(&tstats->syncp);
|
||||
+ tstats->rx_packets++;
|
||||
+ tstats->rx_bytes += skb->len;
|
||||
+ u64_stats_update_end(&tstats->syncp);
|
||||
+ put_cpu_ptr(tstats);
|
||||
if(ETH_P_IP == ntohs(skb->protocol)) {
|
||||
nat46_ipv4_input(skb);
|
||||
}
|
||||
@@ -77,22 +107,38 @@ static netdev_tx_t nat46_netdev_xmit(str
|
||||
}
|
||||
|
||||
void nat46_netdev_count_xmit(struct sk_buff *skb, struct net_device *dev) {
|
||||
- dev->stats.tx_packets++;
|
||||
- dev->stats.tx_bytes += skb->len;
|
||||
+ struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats);
|
||||
+
|
||||
+ u64_stats_update_begin(&tstats->syncp);
|
||||
+ tstats->tx_packets++;
|
||||
+ tstats->tx_bytes += skb->len;
|
||||
+ u64_stats_update_end(&tstats->syncp);
|
||||
+ put_cpu_ptr(tstats);
|
||||
}
|
||||
|
||||
void nat46_update_stats(struct net_device *dev, uint32_t rx_packets, uint32_t rx_bytes,
|
||||
uint32_t tx_packets, uint32_t tx_bytes, uint32_t rx_dropped, uint32_t tx_dropped)
|
||||
{
|
||||
- dev->stats.rx_packets += rx_packets;
|
||||
- dev->stats.rx_bytes += rx_bytes;
|
||||
- dev->stats.tx_packets += tx_packets;
|
||||
- dev->stats.tx_bytes += tx_bytes;
|
||||
+ struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats);
|
||||
+
|
||||
+ u64_stats_update_begin(&tstats->syncp);
|
||||
+ tstats->rx_packets += rx_packets;
|
||||
+ tstats->rx_bytes += rx_bytes;
|
||||
+ tstats->tx_packets += tx_packets;
|
||||
+ tstats->tx_bytes += tx_bytes;
|
||||
dev->stats.rx_dropped += rx_dropped;
|
||||
dev->stats.tx_dropped += tx_dropped;
|
||||
+ u64_stats_update_end(&tstats->syncp);
|
||||
+ put_cpu_ptr(tstats);
|
||||
}
|
||||
EXPORT_SYMBOL(nat46_update_stats);
|
||||
|
||||
+static void nat46_get_stats64(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *tot)
|
||||
+{
|
||||
+ dev_get_tstats64(dev, tot);
|
||||
+}
|
||||
+
|
||||
void *netdev_nat46_instance(struct net_device *dev) {
|
||||
nat46_netdev_priv_t *priv = netdev_priv(dev);
|
||||
return priv->nat46;
|
||||
@@ -116,6 +162,7 @@ static void nat46_netdev_setup(struct ne
|
||||
priv->nat46 = nat46;
|
||||
|
||||
dev->netdev_ops = &nat46_netdev_ops;
|
||||
+ dev->priv_destructor = nat46_netdev_resource_free;
|
||||
dev->type = ARPHRD_NONE;
|
||||
dev->hard_header_len = 0;
|
||||
dev->addr_len = 0;
|
||||
134
nat46/patches/108-ce_port.patch
Normal file
134
nat46/patches/108-ce_port.patch
Normal file
@ -0,0 +1,134 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Aug 5 18:59:20 2020 +0530
|
||||
|
||||
nat46: Copy CE's port number to IPv6 fragment header.
|
||||
|
||||
This patch is propagated from kernel 4.4 commit
|
||||
7886fd3eb081c7767b02685593bc1d19deaecba8
|
||||
|
||||
Copy CE's port number to the lower 16-bits of IPv6 identification
|
||||
number.
|
||||
|
||||
Change-Id: I6946e93bf8bed4c1378d19e75db0729097e0d9eb
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
static uint16_t xlate_pkt_in_err_v4_to_v6(nat46_instance_t *nat46, struct iphdr *iph,
|
||||
struct sk_buff *old_skb, uint16_t *sport, uint16_t *dport);
|
||||
+static DEFINE_SPINLOCK(port_id_lock);
|
||||
|
||||
void
|
||||
nat46debug_dump(nat46_instance_t *nat46, int level, void *addr, int len)
|
||||
@@ -2106,6 +2107,73 @@ static uint16_t xlate_pkt_in_err_v4_to_v
|
||||
return 1;
|
||||
}
|
||||
|
||||
+/* Return the port number from CE's port set */
|
||||
+static uint16_t nat46_get_ce_port(nat46_xlate_rulepair_t *pair, uint16_t sport)
|
||||
+{
|
||||
+ /*
|
||||
+ * 'psid_bits_len' represents number of bits in PSID.
|
||||
+ * 'offset' represents offset of PSID in a port number.
|
||||
+ */
|
||||
+ uint8_t psid_bits_len, offset, port_set_bitmask;
|
||||
+
|
||||
+ /*
|
||||
+ * 'psid16' represent PSID value.
|
||||
+ * 'm' represents number of bits in excluded port set.
|
||||
+ * 'a' represents number of bits in a 16-bit port number after PSID.
|
||||
+ * It is used to control number of port in one contiguous port set.
|
||||
+ *
|
||||
+ * Name of a variable 'a' and 'm' is as per Appendix B of [RFC7597].
|
||||
+ */
|
||||
+ uint16_t psid16, value, m, a;
|
||||
+ nat46_xlate_rule_t *rule;
|
||||
+
|
||||
+ /* stores to last port number from CE's port set */
|
||||
+ static uint16_t port_num;
|
||||
+
|
||||
+ rule = &pair->local;
|
||||
+ offset = rule->psid_offset;
|
||||
+
|
||||
+ if (rule->ea_len + rule->v4_pref_len > IPV4_BITS_MAX) {
|
||||
+ psid_bits_len = rule->ea_len - (IPV4_BITS_MAX - rule->v4_pref_len);
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ a = PSID_LEN_MAX - offset - psid_bits_len;
|
||||
+ psid16 = (ntohs(sport) >> a) & (0xffff >> (PSID_LEN_MAX - psid_bits_len));
|
||||
+
|
||||
+ spin_lock(&port_id_lock);
|
||||
+
|
||||
+ /* Start case */
|
||||
+ if (0 == port_num) {
|
||||
+ m = (offset) ? 1 : 0;
|
||||
+ port_num = (m << (PSID_LEN_MAX - offset)) | (psid16 << a);
|
||||
+ value = port_num;
|
||||
+ spin_unlock(&port_id_lock);
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+ /* End of one port set */
|
||||
+ port_set_bitmask = (1 << a) - 1;
|
||||
+ value = port_num & port_set_bitmask;
|
||||
+ if (0 == (value ^ port_set_bitmask)) {
|
||||
+ m = port_num >> (PSID_LEN_MAX - offset);
|
||||
+ m++;
|
||||
+ /* End case */
|
||||
+ if (m >= (1 << offset)) {
|
||||
+ m = (offset) ? 1 : 0;
|
||||
+ }
|
||||
+ port_num = (m << (PSID_LEN_MAX - offset)) | (psid16 << a);
|
||||
+ value = port_num;
|
||||
+ spin_unlock(&port_id_lock);
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+ port_num++;
|
||||
+ value = port_num;
|
||||
+ spin_unlock(&port_id_lock);
|
||||
+ return value;
|
||||
+}
|
||||
+
|
||||
void nat46_ipv4_input(struct sk_buff *old_skb) {
|
||||
nat46_instance_t *nat46 = get_nat46_instance(old_skb);
|
||||
nat46_xlate_rulepair_t apair;
|
||||
@@ -2226,9 +2294,34 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
|
||||
if (add_frag_header) {
|
||||
struct frag_hdr *fh = (struct frag_hdr*)(hdr6 + 1);
|
||||
+ uint16_t ce_port_num = 0;
|
||||
+
|
||||
+ /* Flag to represent whether PSID is assigned to MAP-T node or not */
|
||||
+ bool is_psid = false;
|
||||
+
|
||||
fh->frag_off = htons(((ntohs(hdr4->frag_off) >> 13) & 7) + ((ntohs(hdr4->frag_off) & 0x1FFF) << 3));
|
||||
fh->nexthdr = hdr4->protocol;
|
||||
- fh->identification = htonl(ntohs(hdr4->id));
|
||||
+
|
||||
+ /*
|
||||
+ * PSID assigned MAP-T node will have non-zero ea_len and we are currently
|
||||
+ * only supporting NAT46_XLATE_MAP as the CE's rule style.
|
||||
+ */
|
||||
+ is_psid = (apair.local.style == NAT46_XLATE_MAP) && apair.local.ea_len;
|
||||
+ if (is_psid) {
|
||||
+ ce_port_num = nat46_get_ce_port(nat46->pairs, sport);
|
||||
+ nat46debug(10, "\n ce port number is %02x\n", ce_port_num);
|
||||
+
|
||||
+ /* Assign CE's port number as the fragment identifier */
|
||||
+ if (ce_port_num) {
|
||||
+ fh->identification = htonl(ce_port_num);
|
||||
+ } else {
|
||||
+ fh->identification = htonl(ntohs(hdr4->id));
|
||||
+ }
|
||||
+ } else {
|
||||
+ fh->identification = htonl(ntohs(hdr4->id));
|
||||
+ }
|
||||
+
|
||||
+
|
||||
}
|
||||
ip6_update_csum(new_skb, hdr6, add_frag_header);
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Aug 5 19:26:48 2020 +0530
|
||||
|
||||
nat46: Fix the issue of packets not fragmented
|
||||
|
||||
This patch is propagated from the kernel 4.4 commit
|
||||
e598f9c249092abd7c7978fe99b6690884f225c9
|
||||
|
||||
when packets size is larger than the MTU of dst, if DF flag is not set,
|
||||
fragment it instead of dropping it with PktTooBig ICMPv6 message.
|
||||
|
||||
Change-Id: I380d42f59bb4f46a45e542f251f5710f2cca8b62
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -2203,10 +2203,11 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
nat46debug(5, "nat46_ipv4_input protocol: %d, len: %d, flags: %02x", hdr4->protocol, old_skb->len, IPCB(old_skb)->flags);
|
||||
if(0 == (ntohs(hdr4->frag_off) & 0x3FFF) ) { /* Checking for MF */
|
||||
check_for_l4 = 1;
|
||||
- if (add_dummy_header) {
|
||||
- if (0 == (ntohs(hdr4->frag_off) & IP_DF)) {
|
||||
+ if (0 == (ntohs(hdr4->frag_off) & IP_DF)) {
|
||||
+ if (add_dummy_header) {
|
||||
add_frag_header = 1;
|
||||
}
|
||||
+ old_skb->ignore_df = 1;
|
||||
}
|
||||
} else {
|
||||
add_frag_header = 1;
|
||||
99
nat46/patches/110-icmp_error_not_handled.patch
Normal file
99
nat46/patches/110-icmp_error_not_handled.patch
Normal file
@ -0,0 +1,99 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Aug 5 20:16:27 2020 +0530
|
||||
|
||||
nat46: fix ICMPv6 error message dropped locally
|
||||
|
||||
This patch is propagated from the kernel 4.4 commit
|
||||
1b96bd0e9ee9182566b119741854c03bf4b94a99
|
||||
|
||||
While routing IPv6 packets from a customer-side translated device (CLAT)
|
||||
to a provider-side translated device (PLAT), it is possible that the IPv6
|
||||
destination is unknown. In such a scenario, the IPv6 stack must send back
|
||||
an ICMP error. However, the source IPv6 address of this error message does
|
||||
not have a MAP-T translation. According to RFC2473, the translation layer
|
||||
should use the tunnel's own IPv4 address for the IPv6 ICMP packet's source
|
||||
address.
|
||||
|
||||
Change-Id: I784473cddf9214843c466d10763cb66852139ef6
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -1697,17 +1697,19 @@ static uint16_t nat46_fixup_icmp(nat46_i
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int pairs_xlate_v6_to_v4_outer(nat46_instance_t *nat46, nat46_xlate_rulepair_t *apair,
|
||||
+int pairs_xlate_v6_to_v4_outer(nat46_instance_t *nat46, nat46_xlate_rulepair_t **papair,
|
||||
struct ipv6hdr *ip6h, uint16_t proto, __u32 *pv4saddr, __u32 *pv4daddr) {
|
||||
int ipair = 0;
|
||||
int xlate_src = -1;
|
||||
int xlate_dst = -1;
|
||||
+ nat46_xlate_rulepair_t *apair;
|
||||
|
||||
apair = nat46_lpm(nat46, NAT46_IPV6_REMOTE, &ip6h->saddr);
|
||||
if (!apair) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ *papair = apair;
|
||||
if (xlate_v6_to_v4(nat46, &apair->local, &ip6h->daddr, pv4daddr)) {
|
||||
nat46debug(5, "Dst addr %pI6 to %pI4 \n", &ip6h->daddr, pv4daddr);
|
||||
xlate_dst = ipair;
|
||||
@@ -1734,14 +1736,14 @@ int pairs_xlate_v6_to_v4_outer(nat46_ins
|
||||
}
|
||||
|
||||
int xlate_6_to_4(struct net_device *dev, struct ipv6hdr *ip6h, uint16_t proto, __u32 *pv4saddr, __u32 *pv4daddr) {
|
||||
- nat46_xlate_rulepair_t apair;
|
||||
+ nat46_xlate_rulepair_t *apair;
|
||||
return pairs_xlate_v6_to_v4_outer(netdev_nat46_instance(dev), &apair, ip6h, proto, pv4saddr, pv4daddr);
|
||||
}
|
||||
EXPORT_SYMBOL(xlate_6_to_4);
|
||||
|
||||
void nat46_ipv6_input(struct sk_buff *old_skb) {
|
||||
struct ipv6hdr *ip6h = ipv6_hdr(old_skb);
|
||||
- nat46_xlate_rulepair_t apair;
|
||||
+ nat46_xlate_rulepair_t *apair;
|
||||
nat46_instance_t *nat46 = get_nat46_instance(old_skb);
|
||||
uint16_t proto;
|
||||
uint16_t frag_off;
|
||||
@@ -1803,8 +1805,37 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
}
|
||||
|
||||
if (!pairs_xlate_v6_to_v4_outer(nat46, &apair, ip6h, proto, &v4saddr, &v4daddr)) {
|
||||
- nat46debug(0, "[nat46] Could not translate v6->v4");
|
||||
- goto done;
|
||||
+ if (proto == NEXTHDR_ICMP) {
|
||||
+ struct icmp6hdr *icmp6h = add_offset(ip6h, v6packet_l3size);
|
||||
+ struct ipv6hdr *ip6h_inner = (struct ipv6hdr *) (icmp6h + 1);
|
||||
+ struct ipv6hdr hdr6;
|
||||
+ switch(icmp6h->icmp6_type) {
|
||||
+ case ICMPV6_DEST_UNREACH:
|
||||
+ case ICMPV6_PKT_TOOBIG:
|
||||
+ case ICMPV6_TIME_EXCEED:
|
||||
+ case ICMPV6_PARAMPROB:
|
||||
+ /*
|
||||
+ * For icmpv6 error message, using the original message
|
||||
+ * address to locate the apair one more time according
|
||||
+ * to the RFC 2473, and use the ipv4 address of the
|
||||
+ * tunnel as SRC ipv4 address
|
||||
+ */
|
||||
+ memcpy(&hdr6.saddr, &ip6h_inner->daddr, 16);
|
||||
+ memcpy(&hdr6.daddr, &ip6h_inner->saddr, 16);
|
||||
+ if (!pairs_xlate_v6_to_v4_outer(nat46, &apair, &hdr6, proto, &v4saddr, &v4daddr)) {
|
||||
+ nat46debug(0, "[nat46] Could not translate v6->v4");
|
||||
+ goto done;
|
||||
+ }
|
||||
+ v4saddr = apair->local.v4_pref;
|
||||
+ break;
|
||||
+ default:
|
||||
+ nat46debug(0, "[nat46] Could not translate v6->v4");
|
||||
+ goto done;
|
||||
+ }
|
||||
+ } else {
|
||||
+ nat46debug(0, "[nat46] Could not translate v6->v4");
|
||||
+ goto done;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (check_for_l4) {
|
||||
40
nat46/patches/111-fix_null_point_reference.patch
Normal file
40
nat46/patches/111-fix_null_point_reference.patch
Normal file
@ -0,0 +1,40 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Aug 5 20:35:00 2020 +0530
|
||||
|
||||
nat46: Fix null pointer dereference issue
|
||||
|
||||
This patch is propagated from the kernel 4.4 commit
|
||||
5bdf9bd5500c45ab5a3fd43e60c40a09d5e5a13d
|
||||
|
||||
get_nat46_instance possibly returns null point, before using the returning
|
||||
point, caller needs to check if it is null.
|
||||
|
||||
Change-Id: Id407a71ca8eccd60a713c34429e7e3f16e2cdd12
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -1758,6 +1758,11 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
int l3_infrag_payload_len = ntohs(ip6h->payload_len);
|
||||
int check_for_l4 = 0;
|
||||
|
||||
+ if (nat46 == NULL) {
|
||||
+ printk("nat46:%p skb is dropped for no valid instance found\n", old_skb);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
nat46debug(4, "nat46_ipv6_input packet");
|
||||
|
||||
if(ip6_input_not_interested(nat46, ip6h, old_skb)) {
|
||||
@@ -2222,6 +2227,11 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
|
||||
char v6saddr[16], v6daddr[16];
|
||||
|
||||
+ if (nat46 == NULL) {
|
||||
+ printk("nat46:%p skb is dropped for no valid instance found\n", old_skb);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
tclass = hdr4->tos;
|
||||
|
||||
memset(v6saddr, 1, 16);
|
||||
40
nat46/patches/112-fix_icmp_crash.patch
Normal file
40
nat46/patches/112-fix_icmp_crash.patch
Normal file
@ -0,0 +1,40 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Aug 5 20:57:33 2020 +0530
|
||||
|
||||
Fix crash of free skb
|
||||
|
||||
This patch is propagated from the 4.4 kernel commit
|
||||
b959b0d45c66ae004a5bfc1687980093fa5b8cc3.
|
||||
|
||||
This is caused by the translation of the inner ipv6 header, it
|
||||
move memory by the inner head's tot_len which is not exact that
|
||||
inner packet will be trimmed for icmp error packets size no more
|
||||
than 576.
|
||||
|
||||
Change-Id: Id5d41fa0721acdf6ea76721c45415fe3be432207
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -2115,7 +2115,9 @@ static uint16_t xlate_pkt_in_err_v4_to_v
|
||||
|
||||
if (skb_tailroom(old_skb) >= IPV6V4HDRDELTA){
|
||||
skb_put(old_skb, IPV6V4HDRDELTA);
|
||||
- memmove(((char *)iiph + IPV6HDRSIZE), (iiph + 1), ntohs(iiph->tot_len) - IPV4HDRSIZE);
|
||||
+ /* ErrorICMP size is less than 576, the inner ipv4 packet will be trimmed */
|
||||
+ memmove(((char *)iiph + IPV6HDRSIZE), (iiph + 1),
|
||||
+ ntohs(iph->tot_len) - 2 * IPV4HDRSIZE - sizeof(struct icmphdr));
|
||||
memcpy(iiph, &ip6h, IPV6HDRSIZE);
|
||||
}
|
||||
else {
|
||||
@@ -2128,7 +2130,9 @@ static uint16_t xlate_pkt_in_err_v4_to_v
|
||||
|
||||
skb_put(old_skb, IPV6V4HDRDELTA);
|
||||
iiph = (struct iphdr *)(icmp_hdr(old_skb) + 1);
|
||||
- memmove(((char *)iiph + IPV6HDRSIZE), (iiph + 1), ntohs(iiph->tot_len) - IPV4HDRSIZE);
|
||||
+ /* ErrorICMP size is less than 576, the inner ipv4 packet will be trimmed */
|
||||
+ memmove(((char *)iiph + IPV6HDRSIZE), (iiph + 1),
|
||||
+ ntohs(iph->tot_len) - 2 * IPV4HDRSIZE - sizeof(struct icmphdr));
|
||||
memcpy(iiph, &ip6h, IPV6HDRSIZE);
|
||||
nat46 = get_nat46_instance(old_skb);
|
||||
iph = ip_hdr(old_skb);
|
||||
52
nat46/patches/113-fix_delete_race_condition.patch
Normal file
52
nat46/patches/113-fix_delete_race_condition.patch
Normal file
@ -0,0 +1,52 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Aug 5 21:16:50 2020 +0530
|
||||
|
||||
nat46: fix nat46 crash during stability test
|
||||
|
||||
This patch is propagated from the kernel 4.4 commit
|
||||
8a2df2e4170f6f9b7eb0930d067e197bfec68129
|
||||
|
||||
when deleting the same device in a very close time, the first deletion
|
||||
is not finished yet, the second one will hit the BUG_ON.
|
||||
|
||||
Change-Id: I09ec95a132e925a304b57c35d1cb51619be37229
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-module.c
|
||||
+++ b/nat46/modules/nat46-module.c
|
||||
@@ -61,6 +61,7 @@ bool add_dummy_header = 0;
|
||||
module_param(add_dummy_header, bool, 0);
|
||||
MODULE_PARM_DESC(add_dummy_header, "Add dummy fragment header");
|
||||
|
||||
+static DEFINE_MUTEX(add_del_lock);
|
||||
static struct proc_dir_entry *nat46_proc_entry;
|
||||
static struct proc_dir_entry *nat46_proc_parent;
|
||||
|
||||
@@ -115,19 +116,27 @@ static ssize_t nat46_proc_write(struct f
|
||||
if (0 == strcmp(arg_name, "add")) {
|
||||
devname = get_devname(&tail);
|
||||
printk(KERN_INFO "nat46: adding device (%s)\n", devname);
|
||||
+ mutex_lock(&add_del_lock);
|
||||
nat46_create(devname);
|
||||
+ mutex_unlock(&add_del_lock);
|
||||
} else if (0 == strcmp(arg_name, "del")) {
|
||||
devname = get_devname(&tail);
|
||||
printk(KERN_INFO "nat46: deleting device (%s)\n", devname);
|
||||
+ mutex_lock(&add_del_lock);
|
||||
nat46_destroy(devname);
|
||||
+ mutex_unlock(&add_del_lock);
|
||||
} else if (0 == strcmp(arg_name, "config")) {
|
||||
devname = get_devname(&tail);
|
||||
printk(KERN_INFO "nat46: configure device (%s) with '%s'\n", devname, tail);
|
||||
+ mutex_lock(&add_del_lock);
|
||||
nat46_configure(devname, tail);
|
||||
+ mutex_unlock(&add_del_lock);
|
||||
} else if (0 == strcmp(arg_name, "insert")) {
|
||||
devname = get_devname(&tail);
|
||||
printk(KERN_INFO "nat46: insert new rule into device (%s) with '%s'\n", devname, tail);
|
||||
+ mutex_lock(&add_del_lock);
|
||||
nat46_insert(devname, tail);
|
||||
+ mutex_unlock(&add_del_lock);
|
||||
}
|
||||
}
|
||||
|
||||
51
nat46/patches/114-fix-get-release-instance-protect.patch
Normal file
51
nat46/patches/114-fix-get-release-instance-protect.patch
Normal file
@ -0,0 +1,51 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Thu Aug 13 12:59:50 2020 +0530
|
||||
|
||||
This patch is propogated from the kernel 4.4 commit
|
||||
56e2435c782e7cdb5c274ea012557f525d0a3b88
|
||||
|
||||
nat46: fix race condition in the get and release operation
|
||||
|
||||
when get and release the nat46 instance, it could run into race
|
||||
condition, use spin_lock protect them.
|
||||
|
||||
Change-Id: I7a38164699a5b856f3407dae592a3d8fc82e7ffe
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-glue.c
|
||||
+++ b/nat46/modules/nat46-glue.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "nat46-glue.h"
|
||||
#include "nat46-core.h"
|
||||
|
||||
+static DEFINE_MUTEX(ref_lock);
|
||||
int is_valid_nat46(nat46_instance_t *nat46) {
|
||||
return (nat46 && (nat46->sig == NAT46_SIGNATURE));
|
||||
}
|
||||
@@ -46,20 +47,25 @@ nat46_instance_t *alloc_nat46_instance(i
|
||||
|
||||
nat46_instance_t *get_nat46_instance(struct sk_buff *sk) {
|
||||
nat46_instance_t *nat46 = netdev_nat46_instance(sk->dev);
|
||||
+ mutex_lock(&ref_lock);
|
||||
if (is_valid_nat46(nat46)) {
|
||||
nat46->refcount++;
|
||||
+ mutex_unlock(&ref_lock);
|
||||
return nat46;
|
||||
} else {
|
||||
+ mutex_unlock(&ref_lock);
|
||||
printk("[nat46] get_nat46_instance: Could not find a valid NAT46 instance!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void release_nat46_instance(nat46_instance_t *nat46) {
|
||||
+ mutex_lock(&ref_lock);
|
||||
nat46->refcount--;
|
||||
if(0 == nat46->refcount) {
|
||||
- printk("[nat46] release_nat46_instance: freeing nat46 instance with %d pairs\n", nat46->npairs);
|
||||
nat46->sig = FREED_NAT46_SIGNATURE;
|
||||
+ printk("[nat46] release_nat46_instance: freeing nat46 instance with %d pairs\n", nat46->npairs);
|
||||
kfree(nat46);
|
||||
}
|
||||
+ mutex_unlock(&ref_lock);
|
||||
}
|
||||
33
nat46/patches/115-export-ip6_update_csm-api.patch
Normal file
33
nat46/patches/115-export-ip6_update_csm-api.patch
Normal file
@ -0,0 +1,33 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Tue Sep 22 10:49:35 2020 +0530
|
||||
|
||||
This patch is propogated from the kernel 4.4 commit
|
||||
0907c30387c89bbec23f426891a756ca17e421ed
|
||||
|
||||
nat46: export ip6_update_csum api
|
||||
|
||||
export ip6_update_csum for other modules.
|
||||
|
||||
Change-Id: I08de067f7a2d54d687c352154f1a1ab441652445
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -1972,6 +1972,7 @@ void ip6_update_csum(struct sk_buff * sk
|
||||
}
|
||||
}
|
||||
}
|
||||
+EXPORT_SYMBOL(ip6_update_csum);
|
||||
|
||||
int ip4_input_not_interested(nat46_instance_t *nat46, struct iphdr *iph, struct sk_buff *old_skb) {
|
||||
if (old_skb->protocol != htons(ETH_P_IP)) {
|
||||
--- a/nat46/modules/nat46-core.h
|
||||
+++ b/nat46/modules/nat46-core.h
|
||||
@@ -111,6 +111,7 @@ void release_nat46_instance(nat46_instan
|
||||
|
||||
int xlate_6_to_4(struct net_device *dev, struct ipv6hdr *ip6h, uint16_t proto, __u32 *pv4saddr, __u32 *pv4daddr);
|
||||
int xlate_4_to_6(struct net_device *dev, struct iphdr *hdr4, uint16_t sport, uint16_t dport, void *v6saddr, void *v6daddr);
|
||||
+void ip6_update_csum(struct sk_buff * skb, struct ipv6hdr * ip6hdr, int do_atomic_frag);
|
||||
bool nat46_get_rule_config(struct net_device *dev, nat46_xlate_rulepair_t **nat46_rule_pair, int *count);
|
||||
int nat46_get_npairs(struct net_device *dev);
|
||||
bool nat46_get_info(struct net_device *dev, nat46_xlate_rulepair_t **nat46_rule_pair,
|
||||
34
nat46/patches/116-rate-limit-the-print.patch
Normal file
34
nat46/patches/116-rate-limit-the-print.patch
Normal file
@ -0,0 +1,34 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Sep 30 14:05:50 2020 +0530
|
||||
|
||||
nat46: Add rate limit to a print.
|
||||
|
||||
This patch is propagated from the kernel 4.4 commit
|
||||
d47f62508d2c105f236470e56bedbe279db0e6f1
|
||||
|
||||
Change-Id: I2119fbe54d630c3ed39535f1cb1b8a0d9d3199b4
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -1828,7 +1828,9 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
memcpy(&hdr6.saddr, &ip6h_inner->daddr, 16);
|
||||
memcpy(&hdr6.daddr, &ip6h_inner->saddr, 16);
|
||||
if (!pairs_xlate_v6_to_v4_outer(nat46, &apair, &hdr6, proto, &v4saddr, &v4daddr)) {
|
||||
- nat46debug(0, "[nat46] Could not translate v6->v4");
|
||||
+ if (net_ratelimit()) {
|
||||
+ nat46debug(0, "[nat46] Could not translate v6->v4");
|
||||
+ }
|
||||
goto done;
|
||||
}
|
||||
v4saddr = apair->local.v4_pref;
|
||||
@@ -2296,7 +2298,9 @@ void nat46_ipv4_input(struct sk_buff *ol
|
||||
}
|
||||
|
||||
if(!pairs_xlate_v4_to_v6_outer(nat46, &apair, hdr4, having_l4 ? &sport : NULL, having_l4 ? &dport : NULL, v6saddr, v6daddr)) {
|
||||
- nat46debug(0, "[nat46] Could not translate v4->v6");
|
||||
+ if (net_ratelimit()) {
|
||||
+ nat46debug(0, "[nat46] Could not translate v4->v6");
|
||||
+ }
|
||||
goto done;
|
||||
}
|
||||
|
||||
34
nat46/patches/117-fix-icmp-no-payload-bug.patch
Normal file
34
nat46/patches/117-fix-icmp-no-payload-bug.patch
Normal file
@ -0,0 +1,34 @@
|
||||
Author: Pavithra R <pavir@codeaurora.org>
|
||||
Date: Wed Sep 30 14:27:37 2020 +0530
|
||||
|
||||
nat46: Fix for ICMP error packets with no payload.
|
||||
|
||||
This patch is propagated from the kernel 4.4 commit
|
||||
d8b29a8e31f948a5d7338aa69c36e0f654fcb9e4
|
||||
|
||||
When no payload is attached to the original packet, any
|
||||
ICMP error message generated in response to such packets
|
||||
gets dropped due to malformed packet at CE.
|
||||
|
||||
During the translation of packet-in-error in ICMP,
|
||||
the IPv6 header in ICMPv6 payload gets corrupted.
|
||||
Hence, the translated packet gets dropped at CE.
|
||||
|
||||
This fix updates the outer IPv4 header's total length
|
||||
before translating to IPv6 header.
|
||||
|
||||
Change-Id: Ifd9802afb50771de39b4c6fb734d36b0801613ec
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -2137,9 +2137,8 @@ static uint16_t xlate_pkt_in_err_v4_to_v
|
||||
memmove(((char *)iiph + IPV6HDRSIZE), (iiph + 1),
|
||||
ntohs(iph->tot_len) - 2 * IPV4HDRSIZE - sizeof(struct icmphdr));
|
||||
memcpy(iiph, &ip6h, IPV6HDRSIZE);
|
||||
- nat46 = get_nat46_instance(old_skb);
|
||||
- iph = ip_hdr(old_skb);
|
||||
}
|
||||
+ iph->tot_len = htons(ntohs(iph->tot_len) + IPV6V4HDRDELTA);
|
||||
|
||||
/* Swapping Ports for outer header */
|
||||
/* Another work-around till LPM is not present. */
|
||||
43
nat46/patches/117-fix-proc_create-to-file_operations.patch
Normal file
43
nat46/patches/117-fix-proc_create-to-file_operations.patch
Normal file
@ -0,0 +1,43 @@
|
||||
--- a/nat46/modules/nat46-module.c
|
||||
+++ b/nat46/modules/nat46-module.c
|
||||
@@ -15,6 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
+#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
@@ -82,7 +83,7 @@ static char *get_devname(char **ptail)
|
||||
{
|
||||
const int maxlen = IFNAMSIZ-1;
|
||||
char *devname = get_next_arg(ptail);
|
||||
- if(strlen(devname) > maxlen) {
|
||||
+ if(devname && (strlen(devname) > maxlen)) {
|
||||
printk(KERN_INFO "nat46: '%s' is "
|
||||
"longer than %d chars, truncating\n", devname, maxlen);
|
||||
devname[maxlen] = 0;
|
||||
@@ -144,6 +145,7 @@ static ssize_t nat46_proc_write(struct f
|
||||
return count;
|
||||
}
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,6,0)
|
||||
static const struct file_operations nat46_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = nat46_proc_open,
|
||||
@@ -152,6 +154,15 @@ static const struct file_operations nat4
|
||||
.release = single_release,
|
||||
.write = nat46_proc_write,
|
||||
};
|
||||
+#else
|
||||
+static const struct proc_ops nat46_proc_fops = {
|
||||
+ .proc_open = nat46_proc_open,
|
||||
+ .proc_read = seq_read,
|
||||
+ .proc_lseek = seq_lseek,
|
||||
+ .proc_release = single_release,
|
||||
+ .proc_write = nat46_proc_write,
|
||||
+};
|
||||
+#endif
|
||||
|
||||
|
||||
int create_nat46_proc_entry(void) {
|
||||
80
nat46/patches/118-add-nat46_remove.patch
Normal file
80
nat46/patches/118-add-nat46_remove.patch
Normal file
@ -0,0 +1,80 @@
|
||||
--- a/nat46/modules/nat46-module.c
|
||||
+++ b/nat46/modules/nat46-module.c
|
||||
@@ -138,6 +138,12 @@ static ssize_t nat46_proc_write(struct f
|
||||
mutex_lock(&add_del_lock);
|
||||
nat46_insert(devname, tail);
|
||||
mutex_unlock(&add_del_lock);
|
||||
+ } else if (0 == strcmp(arg_name, "remove")) {
|
||||
+ devname = get_devname(&tail);
|
||||
+ printk(KERN_INFO "nat46: remove a rule from the device (%s) with '%s'\n", devname, tail);
|
||||
+ mutex_lock(&add_del_lock);
|
||||
+ nat46_remove(devname, tail);
|
||||
+ mutex_unlock(&add_del_lock);
|
||||
}
|
||||
}
|
||||
|
||||
--- a/nat46/modules/nat46-netdev.c
|
||||
+++ b/nat46/modules/nat46-netdev.c
|
||||
@@ -337,6 +337,46 @@ int nat46_configure(char *devname, char
|
||||
}
|
||||
}
|
||||
|
||||
+int nat46_remove(char *devname, char *buf) {
|
||||
+ int ret = -1;
|
||||
+ char config_remove[NAT46_CFG_BUFLEN];
|
||||
+ struct net_device *dev;
|
||||
+ nat46_instance_t *nat46;
|
||||
+ nat46_instance_t *nat46_remove;
|
||||
+ int result_rem;
|
||||
+ int i;
|
||||
+
|
||||
+ if((dev = find_dev(devname)) == NULL ||
|
||||
+ (nat46 = netdev_nat46_instance(dev)) == NULL ||
|
||||
+ (nat46_remove = alloc_nat46_instance(1, NULL, -1, -1, -1)) == NULL) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if(nat46_set_ipair_config(nat46_remove, 0, buf, NAT46_CFG_BUFLEN) < 0) {
|
||||
+ release_nat46_instance(nat46_remove);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ result_rem = nat46_get_ipair_config(nat46_remove, 0, config_remove, NAT46_CFG_BUFLEN);
|
||||
+ for(i = 0; i < nat46->npairs; i++) {
|
||||
+ char config[NAT46_CFG_BUFLEN];
|
||||
+ int result = nat46_get_ipair_config(nat46, i, config, NAT46_CFG_BUFLEN);
|
||||
+
|
||||
+ if (result_rem == result && strncmp(config_remove, config, result_rem) == 0) {
|
||||
+ nat46_instance_t *nat46_new = alloc_nat46_instance(nat46->npairs-1, nat46, 0, 0, i);
|
||||
+ if(nat46_new) {
|
||||
+ netdev_nat46_set_instance(dev, nat46_new);
|
||||
+ ret = 0;
|
||||
+ } else {
|
||||
+ printk("Could not remove the rule from device %s\n", devname);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ release_nat46_instance(nat46_remove);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void nat64_show_all_configs(struct seq_file *m) {
|
||||
struct net_device *dev;
|
||||
read_lock(&dev_base_lock);
|
||||
--- a/nat46/modules/nat46-netdev.h
|
||||
+++ b/nat46/modules/nat46-netdev.h
|
||||
@@ -14,11 +14,13 @@
|
||||
*/
|
||||
|
||||
#define NAT46_DEVICE_SIGNATURE 0x544e36dd
|
||||
+#define NAT46_CFG_BUFLEN 200
|
||||
|
||||
int nat46_create(char *devname);
|
||||
int nat46_destroy(char *devname);
|
||||
int nat46_insert(char *devname, char *buf);
|
||||
int nat46_configure(char *devname, char *buf);
|
||||
+int nat46_remove(char *devname, char *buf);
|
||||
void nat46_destroy_all(void);
|
||||
void nat64_show_all_configs(struct seq_file *m);
|
||||
void nat46_netdev_count_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
56
nat46/patches/119-upgrade-alloc_nat46_instance.patch
Normal file
56
nat46/patches/119-upgrade-alloc_nat46_instance.patch
Normal file
@ -0,0 +1,56 @@
|
||||
--- a/nat46/modules/nat46-core.h
|
||||
+++ b/nat46/modules/nat46-core.h
|
||||
@@ -106,7 +106,7 @@ int nat46_get_config(nat46_instance_t *n
|
||||
char *get_next_arg(char **ptail);
|
||||
nat46_instance_t *get_nat46_instance(struct sk_buff *sk);
|
||||
|
||||
-nat46_instance_t *alloc_nat46_instance(int npairs, nat46_instance_t *old, int from_ipair, int to_ipair);
|
||||
+nat46_instance_t *alloc_nat46_instance(int npairs, nat46_instance_t *old, int from_ipair, int to_ipair, int remove_ipair);
|
||||
void release_nat46_instance(nat46_instance_t *nat46);
|
||||
|
||||
int xlate_6_to_4(struct net_device *dev, struct ipv6hdr *ip6h, uint16_t proto, __u32 *pv4saddr, __u32 *pv4daddr);
|
||||
--- a/nat46/modules/nat46-glue.c
|
||||
+++ b/nat46/modules/nat46-glue.c
|
||||
@@ -23,7 +23,7 @@ int is_valid_nat46(nat46_instance_t *nat
|
||||
return (nat46 && (nat46->sig == NAT46_SIGNATURE));
|
||||
}
|
||||
|
||||
-nat46_instance_t *alloc_nat46_instance(int npairs, nat46_instance_t *old, int from_ipair, int to_ipair) {
|
||||
+nat46_instance_t *alloc_nat46_instance(int npairs, nat46_instance_t *old, int from_ipair, int to_ipair, int remove_ipair) {
|
||||
nat46_instance_t *nat46 = kzalloc(sizeof(nat46_instance_t) + npairs*sizeof(nat46_xlate_rulepair_t), GFP_KERNEL);
|
||||
if (!nat46) {
|
||||
printk("[nat46] make_nat46_instance: can not alloc a nat46 instance with %d pairs\n", npairs);
|
||||
@@ -37,8 +37,11 @@ nat46_instance_t *alloc_nat46_instance(i
|
||||
if (old) {
|
||||
nat46->debug = old->debug;
|
||||
for(; (from_ipair >= 0) && (to_ipair >= 0) &&
|
||||
- (from_ipair < old->npairs) && (to_ipair < nat46->npairs); from_ipair++, to_ipair++) {
|
||||
- nat46->pairs[to_ipair] = old->pairs[from_ipair];
|
||||
+ (from_ipair < old->npairs) && (to_ipair < nat46->npairs); from_ipair++) {
|
||||
+ if (from_ipair != remove_ipair) {
|
||||
+ nat46->pairs[to_ipair] = old->pairs[from_ipair];
|
||||
+ to_ipair++;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
return nat46;
|
||||
--- a/nat46/modules/nat46-netdev.c
|
||||
+++ b/nat46/modules/nat46-netdev.c
|
||||
@@ -155,7 +155,7 @@ static void netdev_nat46_set_instance(st
|
||||
static void nat46_netdev_setup(struct net_device *dev)
|
||||
{
|
||||
nat46_netdev_priv_t *priv = netdev_priv(dev);
|
||||
- nat46_instance_t *nat46 = alloc_nat46_instance(1, NULL, -1, -1);
|
||||
+ nat46_instance_t *nat46 = alloc_nat46_instance(1, NULL, -1, -1, -1);
|
||||
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
priv->sig = NAT46_DEVICE_SIGNATURE;
|
||||
@@ -316,7 +316,7 @@ int nat46_insert(char *devname, char *bu
|
||||
return ret;
|
||||
}
|
||||
|
||||
- nat46_new = alloc_nat46_instance(nat46->npairs+1, nat46, 0, 1);
|
||||
+ nat46_new = alloc_nat46_instance(nat46->npairs+1, nat46, 0, 1, -1);
|
||||
if(nat46_new) {
|
||||
netdev_nat46_set_instance(dev, nat46_new);
|
||||
ret = nat46_set_ipair_config(nat46_new, 0, buf, strlen(buf));
|
||||
@ -0,0 +1,144 @@
|
||||
Author: Ken Zhu <guigenz@codeaurora.org>
|
||||
Date: Fri Mar 26 12:27:17 2021 -0700
|
||||
|
||||
[nat46]: fix icmp checksum error based on the correct packet length
|
||||
|
||||
UDP/TCP checksum includes the pseudo header in addition to the palyload.
|
||||
But in nat46 case, their length in the pseudo header could be ignored
|
||||
since it keeps unchanged between IPv4/IPv6 transition.
|
||||
|
||||
ICMPv6 checksum includes pseudo IPV6 header in addition to packet payload
|
||||
while ICMPv4 does not counter in the pseudo header.
|
||||
the length of pseudo header should count in all fragmented payload.
|
||||
|
||||
The change get the length by reassembling the fragments.
|
||||
|
||||
Change-Id: I56e59958aa21eed5b595ae1a9ab02285dba2185b
|
||||
Signed-off-by: Ken Zhu <guigenz@codeaurora.org>
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include <net/route.h>
|
||||
#include <linux/version.h>
|
||||
+#include <net/ipv6_frag.h>
|
||||
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
|
||||
|
||||
#include "nat46-glue.h"
|
||||
#include "nat46-core.h"
|
||||
@@ -1751,7 +1753,8 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
|
||||
struct iphdr * iph;
|
||||
__u32 v4saddr, v4daddr;
|
||||
- struct sk_buff * new_skb = 0;
|
||||
+ struct sk_buff *new_skb = NULL;
|
||||
+ struct sk_buff *reasm_skb = NULL;
|
||||
int truncSize = 0;
|
||||
int tailTruncSize = 0;
|
||||
int v6packet_l3size = sizeof(*ip6h);
|
||||
@@ -1802,6 +1805,46 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
frag_id = fold_ipv6_frag_id(fh->identification);
|
||||
nat46debug(2, "Not first fragment, frag_off: %04X, frag id: %04X orig frag_off: %04X", ntohs(frag_off), frag_id, ntohs(fh->frag_off));
|
||||
}
|
||||
+
|
||||
+ /* ICMPv6 counts the pseudo ipv6 header into its checksum, but ICMP doesn't
|
||||
+ * but the length filed of the pseudo header count in all fragmented
|
||||
+ * packets, so we need gather the framented packets into one packet to
|
||||
+ * get the l3 payload length.
|
||||
+ */
|
||||
+ if (proto == NEXTHDR_ICMP) {
|
||||
+ struct sk_buff *skb = skb_get(old_skb);
|
||||
+ int err;
|
||||
+ if (skb == NULL) {
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ err = nf_ct_frag6_gather(dev_net(old_skb->dev), skb, IP6_DEFRAG_LOCAL_DELIVER);
|
||||
+
|
||||
+ /* EINPROGRESS means the skb was queued but the gather not finished yet */
|
||||
+ if (err == -EINPROGRESS) {
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ reasm_skb = skb;
|
||||
+ /* other than EINPROGRESS error returned means the skb wasn't queued
|
||||
+ * 0 returned means that all fragments are all gathered
|
||||
+ * and the original skb was queued
|
||||
+ */
|
||||
+ if (err != 0) {
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ /* Use the reassembly packet as the input */
|
||||
+ ip6h = ipv6_hdr(reasm_skb);
|
||||
+ proto = ip6h->nexthdr;
|
||||
+ v6packet_l3size = sizeof(*ip6h);
|
||||
+
|
||||
+ /* No fragment header in the re-assembly packet */
|
||||
+ frag_off = 0;
|
||||
+ l3_infrag_payload_len = ntohs(ip6h->payload_len);
|
||||
+ old_skb = reasm_skb;
|
||||
+ check_for_l4 = 1;
|
||||
+ }
|
||||
}
|
||||
} else {
|
||||
frag_off = htons(IP_DF);
|
||||
@@ -1850,20 +1893,28 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
/* CHECKSUMS UPDATE */
|
||||
case NEXTHDR_TCP: {
|
||||
struct tcphdr *th = add_offset(ip6h, v6packet_l3size);
|
||||
- u16 sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, l3_infrag_payload_len, NEXTHDR_TCP, th->check);
|
||||
- u16 sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, l3_infrag_payload_len, NEXTHDR_TCP, sum1);
|
||||
+
|
||||
+ /* TCP payload length won't change, needn't unmagic its value. */
|
||||
+ u16 sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, 0, NEXTHDR_TCP, th->check);
|
||||
+ u16 sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, 0, NEXTHDR_TCP, sum1);
|
||||
th->check = sum2;
|
||||
break;
|
||||
}
|
||||
case NEXTHDR_UDP: {
|
||||
struct udphdr *udp = add_offset(ip6h, v6packet_l3size);
|
||||
- u16 sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, l3_infrag_payload_len, NEXTHDR_UDP, udp->check);
|
||||
- u16 sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, l3_infrag_payload_len, NEXTHDR_UDP, sum1);
|
||||
+
|
||||
+ /* UDP payload length won't change, needn't unmagic its value. */
|
||||
+ u16 sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, 0, NEXTHDR_UDP, udp->check);
|
||||
+ u16 sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, 0, NEXTHDR_UDP, sum1);
|
||||
udp->check = sum2;
|
||||
break;
|
||||
}
|
||||
case NEXTHDR_ICMP: {
|
||||
struct icmp6hdr *icmp6h = add_offset(ip6h, v6packet_l3size);
|
||||
+
|
||||
+ /* ICMPv6 count the pseudo IPv6 header into its checksum, but icmp
|
||||
+ * doesn't, unmagic the whole the pseudo IPv6 header from the checksum.
|
||||
+ */
|
||||
u16 sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, l3_infrag_payload_len, NEXTHDR_ICMP, icmp6h->icmp6_cksum);
|
||||
icmp6h->icmp6_cksum = sum1;
|
||||
nat46debug_dump(nat46, 10, icmp6h, l3_infrag_payload_len);
|
||||
@@ -1909,10 +1960,6 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
fill_v4hdr_from_v6hdr(iph, ip6h, v4saddr, v4daddr, frag_id, frag_off, proto, l3_infrag_payload_len);
|
||||
new_skb->protocol = htons(ETH_P_IP);
|
||||
|
||||
- if (ntohs(iph->tot_len) >= 2000) {
|
||||
- nat46debug(0, "Too big IP len: %d", ntohs(iph->tot_len));
|
||||
- }
|
||||
-
|
||||
nat46debug(5, "about to send v4 packet, flags: %02x", IPCB(new_skb)->flags);
|
||||
nat46_netdev_count_xmit(new_skb, old_skb->dev);
|
||||
|
||||
@@ -1924,11 +1971,12 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
/* TBD: should copy be released here? */
|
||||
|
||||
done:
|
||||
+ if (reasm_skb) {
|
||||
+ kfree_skb(reasm_skb);
|
||||
+ }
|
||||
release_nat46_instance(nat46);
|
||||
}
|
||||
|
||||
-
|
||||
-
|
||||
void ip6_update_csum(struct sk_buff * skb, struct ipv6hdr * ip6hdr, int do_atomic_frag)
|
||||
{
|
||||
u32 sum1=0;
|
||||
32
nat46/patches/17-add-support-ipv6-udp-checksum-0.patch
Normal file
32
nat46/patches/17-add-support-ipv6-udp-checksum-0.patch
Normal file
@ -0,0 +1,32 @@
|
||||
Author: Ken Zhu <guigenz@codeaurora.org>
|
||||
Date: Wed Feb 17 13:37:15 2021 -0800
|
||||
|
||||
nat46: keep ipv4 checksum zero when incoming ipv6 UDP checksum is zero
|
||||
|
||||
When an incoming ipv6 UDP packet has 0 checksum, the ipv4 checksum is
|
||||
kept zero after translation.
|
||||
|
||||
Change-Id: I8ddd0c586e5cfbd5a57dc5632e93543d6db5c312
|
||||
Signed-off-by: Ken Zhu <guigenz@codeaurora.org>
|
||||
|
||||
--- a/nat46/modules/nat46-core.c
|
||||
+++ b/nat46/modules/nat46-core.c
|
||||
@@ -1903,10 +1903,14 @@ void nat46_ipv6_input(struct sk_buff *ol
|
||||
case NEXTHDR_UDP: {
|
||||
struct udphdr *udp = add_offset(ip6h, v6packet_l3size);
|
||||
|
||||
- /* UDP payload length won't change, needn't unmagic its value. */
|
||||
- u16 sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, 0, NEXTHDR_UDP, udp->check);
|
||||
- u16 sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, 0, NEXTHDR_UDP, sum1);
|
||||
- udp->check = sum2;
|
||||
+ /* UDP payload length won't change, needn't unmagic its value.
|
||||
+ * UDP checksum zero then skip the calculation of the checksum.
|
||||
+ */
|
||||
+ if (udp->check) {
|
||||
+ u16 sum1 = csum_ipv6_unmagic(nat46, &ip6h->saddr, &ip6h->daddr, 0, NEXTHDR_UDP, udp->check);
|
||||
+ u16 sum2 = csum_tcpudp_remagic(v4saddr, v4daddr, 0, NEXTHDR_UDP, sum1);
|
||||
+ udp->check = sum2;
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
case NEXTHDR_ICMP: {
|
||||
@ -3,6 +3,7 @@ include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=libnl-nss
|
||||
PKG_RELEASE:=1
|
||||
PKG_BUILD_DEPENDS:=libnl
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ PKG_LICENSE:=GPL-2.0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define KernelPackage/nat46
|
||||
define KernelPackage/qca-nat46
|
||||
DEPENDS:=@IPV6 +kmod-nf-conntrack6
|
||||
TITLE:=Stateless NAT46 translation kernel module
|
||||
SECTION:=kernel
|
||||
@ -40,4 +40,4 @@ define Build/InstallDev
|
||||
$(CP) $(PKG_BUILD_DIR)/nat46/modules/*.h $(STAGING_DIR)/usr/include/nat46/
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,nat46))
|
||||
$(eval $(call KernelPackage,qca-nat46))
|
||||
|
||||
@ -55,8 +55,9 @@ define KernelPackage/qca-nss-drv-dtlsmgr
|
||||
CATEGORY:=Kernel modules
|
||||
SUBMENU:=Network Devices
|
||||
TITLE:=Kernel driver for NSS (connection manager) - dtlsmgr
|
||||
DEPENDS:=+@NSS_DRV_DTLS_ENABLE +kmod-qca-nss-cfi-cryptoapi \
|
||||
+PACKAGE_kmod-qca-nss-drv:kmod-qca-nss-drv
|
||||
DEPENDS:=+@NSS_DRV_DTLS_ENABLEi \
|
||||
+PACKAGE_kmod-qca-nss-drv:kmod-qca-nss-drv \
|
||||
+PACKAGE_kmod-qca-nss-cfi-cryptoapi:kmod-qca-nss-cfi-cryptoapi
|
||||
FILES:=$(PKG_BUILD_DIR)/dtls/$(DTLSMGR_DIR)/qca-nss-dtlsmgr.ko
|
||||
endef
|
||||
|
||||
@ -323,7 +324,6 @@ define KernelPackage/qca-nss-drv-netlink
|
||||
SUBMENU:=Network Devices
|
||||
DEPENDS:=@TARGET_ipq806x||TARGET_ipq807x||TARGET_ipq_ipq807x_64||TARGET_ipq_ipq60xx||TARGET_ipq_ipq60xx_64||TARGET_ipq60xx||TARGET_ipq_ipq50xx||TARGET_ipq_ipq50xx_64||TARGET_ipq50xx \
|
||||
+PACKAGE_kmod-qca-nss-drv:kmod-qca-nss-drv \
|
||||
+PACKAGE_kmod-qca-nss-drv-dtlsmgr:kmod-qca-nss-drv-dtlsmgr \
|
||||
+@NSS_DRV_GRE_REDIR_ENABLE
|
||||
TITLE:=NSS NETLINK Manager for QCA NSS driver
|
||||
FILES:=$(PKG_BUILD_DIR)/netlink/qca-nss-netlink.ko
|
||||
|
||||
Loading…
Reference in New Issue
Block a user