* [PATCH v1 1/2] ip6_tunnel: Adding support of mapping rules for MAP-E tunnel
@ 2018-11-20 1:31 Felix Jia
2018-11-20 1:31 ` [PATCH v1 2/2] netfilter: Add PSID mode to MASQUERADE Felix Jia
2018-11-20 1:46 ` [PATCH v1 1/2] ip6_tunnel: Adding support of mapping rules for MAP-E tunnel David Miller
0 siblings, 2 replies; 5+ messages in thread
From: Felix Jia @ 2018-11-20 1:31 UTC (permalink / raw)
To: David S . Miller, Pablo Neira Ayuso
Cc: Blair Steven, netdev, Felix Jia, Sheena Mira-ato, Masakazu Asama
From: Blair Steven <blair.steven@alliedtelesis.co.nz>
Mapping of Addresses and Ports with Encapsulation (MAP-E) is defined in
RFC7597, and is an IPv6 transition technology providing interoperability
between IPv4 and IPv6 networks.
MAP-E uses the encapsulation mode described in RFC2473 (IPv6 Tunneling)
to transport IPv4 and IPv6 packets over an IPv6 network. It requires a
list rules for mapping between IPv4 prefix/shared addresses and IPv6
addresses.
This patch also support the mapping rules define in the draft3 version of
the RFC.
Co-developed-by: Felix Jia <felix.jia@alliedtelesis.co.nz>
Co-developed-by: Sheena Mira-ato <sheena.mira-ato@alliedtelesis.co.nz>
Co-developed-by: Masakazu Asama <masakazu.asama@gmail.com>
Signed-off-by: Blair Steven <blair.steven@alliedtelesis.co.nz>
Signed-off-by: Felix Jia <felix.jia@alliedtelesis.co.nz>
Signed-off-by: Sheena Mira-ato <sheena.mira-ato@alliedtelesis.co.nz>
Signed-off-by: Masakazu Asama <masakazu.asama@gmail.com>
---
include/net/ip6_tunnel.h | 18 ++
include/uapi/linux/if_tunnel.h | 18 ++
net/ipv6/ip6_tunnel.c | 491 ++++++++++++++++++++++++++++++++-
3 files changed, 525 insertions(+), 2 deletions(-)
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index 69b4bcf880c9..daa159185228 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -18,6 +18,16 @@
/* determine capability on a per-packet basis */
#define IP6_TNL_F_CAP_PER_PACKET 0x40000
+struct ip6_tnl_rule {
+ u8 version;
+ struct in6_addr ipv6_subnet;
+ u8 ipv6_prefixlen;
+ struct in_addr ipv4_subnet;
+ u8 ipv4_prefixlen;
+ u8 ea_length;
+ u8 psid_offset;
+};
+
struct __ip6_tnl_parm {
char name[IFNAMSIZ]; /* name of tunnel device */
int link; /* ifindex of underlying L2 interface */
@@ -40,6 +50,13 @@ struct __ip6_tnl_parm {
__u8 erspan_ver; /* ERSPAN version */
__u8 dir; /* direction */
__u16 hwid; /* hwid */
+ __u8 rule_action;
+ struct ip6_tnl_rule rule;
+};
+
+struct ip6_rule_list {
+ struct list_head list;
+ struct ip6_tnl_rule data;
};
/* IPv6 tunnel */
@@ -63,6 +80,7 @@ struct ip6_tnl {
int encap_hlen; /* Encap header length (FOU,GUE) */
struct ip_tunnel_encap encap;
int mlink;
+ struct ip6_rule_list rules;
};
struct ip6_tnl_encap_ops {
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 1b3d148c4560..7cb09c8c4d8a 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -77,10 +77,28 @@ enum {
IFLA_IPTUN_ENCAP_DPORT,
IFLA_IPTUN_COLLECT_METADATA,
IFLA_IPTUN_FWMARK,
+ IFLA_IPTUN_RULE_VERSION,
+ IFLA_IPTUN_RULE_ACTION,
+ IFLA_IPTUN_RULE_IPV6_PREFIX,
+ IFLA_IPTUN_RULE_IPV6_PREFIXLEN,
+ IFLA_IPTUN_RULE_IPV4_PREFIX,
+ IFLA_IPTUN_RULE_IPV4_PREFIXLEN,
+ IFLA_IPTUN_RULE_EA_LENGTH,
+ IFLA_IPTUN_RULE_PSID_OFFSET,
__IFLA_IPTUN_MAX,
};
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
+enum map_rule_versions {
+ MAP_VERSION_RFC,
+ MAP_VERSION_DRAFT3,
+};
+
+enum tunnel_rule_actions {
+ TUNNEL_RULE_ACTION_ADD = 1,
+ TUNNEL_RULE_ACTION_DELETE = 2,
+};
+
enum tunnel_encap_types {
TUNNEL_ENCAP_NONE,
TUNNEL_ENCAP_FOU,
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a9d06d4dd057..e13dc5bd09b5 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -20,6 +20,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/list.h>
+#include <linux/list_sort.h>
#include <linux/module.h>
#include <linux/capability.h>
#include <linux/errno.h>
@@ -32,6 +34,7 @@
#include <linux/net.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
#include <linux/if_arp.h>
#include <linux/icmpv6.h>
#include <linux/init.h>
@@ -124,6 +127,228 @@ static struct net_device_stats *ip6_get_stats(struct net_device *dev)
return &dev->stats;
}
+int
+ip6_get_addrport(struct iphdr *iph, __be32 *saddr4, __be32 *daddr4,
+ __be16 *sport4, __be16 *dport4, __u8 *proto, int *icmperr)
+{
+ u8 *ptr;
+ struct iphdr *icmpiph = NULL;
+ struct tcphdr *tcph, *icmptcph;
+ struct udphdr *udph, *icmpudph;
+ struct icmphdr *icmph, *icmpicmph;
+
+ *icmperr = 0;
+ *saddr4 = iph->saddr;
+ *daddr4 = iph->daddr;
+ ptr = (u8 *)iph;
+ ptr += iph->ihl * 4;
+ switch (iph->protocol) {
+ case IPPROTO_TCP:
+ *proto = IPPROTO_TCP;
+ tcph = (struct tcphdr *)ptr;
+ *sport4 = tcph->source;
+ *dport4 = tcph->dest;
+ break;
+ case IPPROTO_UDP:
+ *proto = IPPROTO_UDP;
+ udph = (struct udphdr *)ptr;
+ *sport4 = udph->source;
+ *dport4 = udph->dest;
+ break;
+ case IPPROTO_ICMP:
+ *proto = IPPROTO_ICMP;
+ icmph = (struct icmphdr *)ptr;
+ switch (icmph->type) {
+ case ICMP_DEST_UNREACH:
+ case ICMP_SOURCE_QUENCH:
+ case ICMP_TIME_EXCEEDED:
+ case ICMP_PARAMETERPROB:
+ *icmperr = 1;
+ ptr = (u8 *)icmph;
+ ptr += sizeof(struct icmphdr);
+ icmpiph = (struct iphdr *)ptr;
+ *saddr4 = icmpiph->saddr;
+ *daddr4 = icmpiph->daddr;
+ if (ntohs(iph->tot_len) < icmpiph->ihl * 4 + 12)
+ return -1;
+ ptr += icmpiph->ihl * 4;
+ switch (icmpiph->protocol) {
+ case IPPROTO_TCP:
+ *proto = IPPROTO_TCP;
+ icmptcph = (struct tcphdr *)ptr;
+ *sport4 = icmptcph->source;
+ *dport4 = icmptcph->dest;
+ break;
+ case IPPROTO_UDP:
+ *proto = IPPROTO_UDP;
+ icmpudph = (struct udphdr *)ptr;
+ *sport4 = icmpudph->source;
+ *dport4 = icmpudph->dest;
+ break;
+ case IPPROTO_ICMP:
+ *proto = IPPROTO_ICMP;
+ icmpicmph = (struct icmphdr *)ptr;
+ *sport4 = icmpicmph->un.echo.id;
+ *dport4 = icmpicmph->un.echo.id;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ *sport4 = icmph->un.echo.id;
+ *dport4 = icmph->un.echo.id;
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ip6_mape_gen_addr6(struct ip6_tnl_rule *mr, struct in6_addr *addr6,
+ __be32 addr4, __be16 port4)
+{
+ int i, pbw0, pbi0, pbi1;
+ __u32 addr[4];
+ __u32 psid = 0;
+ __u32 mask = 0;
+ __u32 a = ntohl(addr4);
+ __u16 p = ntohs(port4);
+ int psid_prefix_length = 0;
+ int psid_mask;
+ __u32 id0 = 0;
+ __u32 id1 = 0;
+
+ /* If we have no rule then we can return immediately */
+ if (!mr)
+ return -1;
+
+ psid_prefix_length = mr->ea_length - (32 - mr->ipv4_prefixlen);
+
+ /* In some configurations the PSID can overlap the IPv4 address
+ * segment
+ */
+ if (psid_prefix_length < 0)
+ a &= 0xffffffff << (psid_prefix_length * -1);
+
+ /* Find the PSID from the port by shifting the non-PSID bits out */
+ if (psid_prefix_length > 0) {
+ mask = 0xffffffff >> (32 - psid_prefix_length);
+ psid =
+ (p >> (16 - psid_prefix_length - mr->psid_offset)) & mask;
+ }
+
+ /* We start with the IPv6 subnet provided for this rule */
+ for (i = 0; i < 4; ++i)
+ addr[i] = ntohl(mr->ipv6_subnet.s6_addr32[i]);
+
+ /* We then copy in the IPv4 host portion - pbw0 is the starting
+ * 32 bit chunk, pbi0 is the offset into that chunk
+ */
+ if (mr->ipv4_prefixlen < 32) {
+ pbw0 = mr->ipv6_prefixlen >> 5;
+ pbi0 = mr->ipv6_prefixlen & 0x1f;
+ addr[pbw0] |= (a << mr->ipv4_prefixlen) >> pbi0;
+ pbi1 = pbi0 - mr->ipv4_prefixlen;
+ if (pbi1 > 0)
+ addr[pbw0 + 1] |= a << (32 - pbi1);
+ }
+
+ /* The PSID may need to be inserted into the IPv6 address within the
+ * top 64 bits. Again: pbw0 is the chunk, pbi0 is the offset.
+ */
+ if ((psid_prefix_length - mr->psid_offset) > 0) {
+ psid_mask = mask;
+ pbw0 = (mr->ipv6_prefixlen + (32 - mr->ipv4_prefixlen)) >> 5;
+ pbi0 = (mr->ipv6_prefixlen + (32 - mr->ipv4_prefixlen)) & 0x1f;
+
+ pbi1 = pbi0 - (32 - psid_prefix_length);
+
+ if (pbi1 > 0) {
+ addr[pbw0] |= (psid >> pbi1);
+ addr[pbw0 + 1] |= (psid & psid_mask) << (32 - pbi1);
+ } else {
+ addr[pbw0] |= psid << (32 - pbi0 - psid_prefix_length);
+ }
+ }
+
+ /* The format of the interface id changes depending on version */
+ if (mr->version == MAP_VERSION_RFC) {
+ addr[2] |= (a >> 16);
+ addr[3] |= (a << 16);
+ addr[3] |= psid;
+ } else if (mr->version == MAP_VERSION_DRAFT3) {
+ id0 |= a >> 8;
+ id1 |= (a & 0xFF) << 24;
+ id1 |= psid << 8;
+ addr[2] |= id0;
+ addr[3] |= id1;
+ } else {
+ return -1;
+ }
+
+ /* Copy the formed address back into network order */
+ for (i = 0; i < 4; ++i)
+ addr6->s6_addr32[i] = htonl(addr[i]);
+
+ return 0;
+}
+
+static struct ip6_tnl_rule *ip6_tnl_rule_find(struct net_device *dev,
+ __be32 _dst)
+{
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct ip6_rule_list *pos = NULL;
+ u32 dst = ntohl(_dst);
+
+ list_for_each_entry(pos, &t->rules.list, list) {
+ int mask =
+ 0xFFFFFFFF ^ ((1 << (32 - pos->data.ipv4_prefixlen)) - 1);
+ if ((dst & mask) == ntohl(pos->data.ipv4_subnet.s_addr))
+ return &pos->data;
+ }
+ return NULL;
+}
+
+static void
+ip6_tnl_mape_dst(struct net_device *dev, struct sk_buff *skb,
+ struct flowi6 *fl6)
+{
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct iphdr *iph;
+ __be32 saddr4, daddr4, addr;
+ __be16 sport4, dport4, port;
+ __u8 proto;
+ int icmperr;
+ struct ip6_tnl_rule *mr = NULL;
+
+ /* If we have no rules then packets always go to the tunnel dst */
+ if (list_empty(&t->rules.list))
+ return;
+
+ /* Find the src / dst address / port (or ID for ICMP) */
+ iph = ip_hdr(skb);
+ ip6_get_addrport(iph, &saddr4, &daddr4, &sport4, &dport4, &proto,
+ &icmperr);
+
+ if (icmperr) {
+ mr = ip6_tnl_rule_find(dev, saddr4);
+ addr = saddr4;
+ port = sport4;
+ } else {
+ mr = ip6_tnl_rule_find(dev, daddr4);
+ addr = daddr4;
+ port = dport4;
+ }
+
+ /* Generate an destination IPv6 address from the internal packet */
+ if (mr)
+ ip6_mape_gen_addr6(mr, &fl6->daddr, addr, port);
+}
+
/**
* ip6_tnl_lookup - fetch tunnel matching the end-point addresses
* @remote: the address of the tunnel exit-point
@@ -207,6 +432,33 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct __ip6_tnl_parm *p)
return &ip6n->tnls[prio][h];
}
+/**
+ * ip6_tnl_bucket_r_any - get head of list matching given tunnel parameters
+ * @p: parameters containing tunnel end-points
+ *
+ * Description:
+ * ip6_tnl_bucket_r_any() returns the head of the list matching the
+ * &struct in6_addr entry laddr in @p.
+ *
+ * Return: head of IPv6 tunnel list
+ **/
+
+static struct ip6_tnl __rcu **
+ip6_tnl_bucket_r_any(struct ip6_tnl_net *ip6n, const struct __ip6_tnl_parm *p)
+{
+ const struct in6_addr *local = &p->laddr;
+ unsigned int h = 0;
+ int prio = 0;
+ struct in6_addr any;
+
+ if (!ipv6_addr_any(local)) {
+ memset(&any, 0, sizeof(any));
+ prio = 1;
+ h = HASH(&any, local);
+ }
+ return &ip6n->tnls[prio][h];
+}
+
/**
* ip6_tnl_link - add tunnel to hash table
* @t: tunnel to be added
@@ -215,7 +467,12 @@ ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct __ip6_tnl_parm *p)
static void
ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
{
- struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms);
+ struct ip6_tnl __rcu **tp;
+
+ if (!list_empty(&t->rules.list))
+ tp = ip6_tnl_bucket_r_any(ip6n, &t->parms);
+ else
+ tp = ip6_tnl_bucket(ip6n, &t->parms);
if (t->parms.collect_md)
rcu_assign_pointer(ip6n->collect_md_tun, t);
@@ -234,6 +491,15 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
struct ip6_tnl __rcu **tp;
struct ip6_tnl *iter;
+ for (tp = ip6_tnl_bucket_r_any(ip6n, &t->parms);
+ (iter = rtnl_dereference(*tp)) != NULL;
+ tp = &iter->next) {
+ if (t == iter) {
+ rcu_assign_pointer(*tp, t->next);
+ return;
+ }
+ }
+
if (t->parms.collect_md)
rcu_assign_pointer(ip6n->collect_md_tun, NULL);
@@ -352,6 +618,16 @@ static struct ip6_tnl *ip6_tnl_locate(struct net *net,
struct ip6_tnl *t;
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+ for (tp = ip6_tnl_bucket_r_any(ip6n, p);
+ (t = rtnl_dereference(*tp)) != NULL;
+ tp = &t->next) {
+ if (ipv6_addr_equal(local, &t->parms.laddr)) {
+ if (create)
+ return ERR_PTR(-EEXIST);
+ return t;
+ }
+ }
+
for (tp = ip6_tnl_bucket(ip6n, p);
(t = rtnl_dereference(*tp)) != NULL;
tp = &t->next) {
@@ -880,6 +1156,64 @@ static const struct tnl_ptk_info tpi_v4 = {
.proto = htons(ETH_P_IP),
};
+static int ip6_tnl_ipv4_addr_match(struct ip6_tnl *t, __be32 addr)
+{
+ struct in_device *ind;
+ int ret = 0;
+
+ ind = in_dev_get(t->dev);
+ if (!ind)
+ return 0;
+
+ for_ifa(ind) {
+ if (ifa->ifa_address == addr) {
+ ret = 1;
+ break;
+ }
+ }
+ endfor_ifa(ind);
+ in_dev_put(ind);
+
+ return ret;
+}
+
+static int ip6_tnl_map_rule_validate(struct ip6_tnl *t, struct sk_buff *skb)
+{
+ struct ipv6hdr *ipv6h;
+ struct iphdr *iph;
+ __be32 src, dst;
+ __be16 sport, dport;
+ __u8 proto;
+ int icmperr;
+ struct ip6_tnl_rule *mr = NULL;
+ struct in6_addr src6 = { };
+
+ if (likely(list_empty(&t->rules.list)))
+ return 1;
+
+ iph = ipip_hdr(skb);
+ ip6_get_addrport(iph, &src, &dst, &sport, &dport, &proto, &icmperr);
+
+ /* Check if the destination of the packet is for the MAP-E tunnel. */
+ if (!ip6_tnl_ipv4_addr_match(t, dst))
+ return 0;
+
+ /* if the packet's destination is for the tunnel, we need to check
+ * if the source ipv4 address matches any map rules. If there is
+ * no matching rule, just return success (the packet is from br).
+ * Otherwise, we check if the source ipv6 address is valid.
+ */
+ mr = ip6_tnl_rule_find(t->dev, src);
+ if (mr) {
+ ip6_mape_gen_addr6(mr, &src6, src, sport);
+ ipv6h = ipv6_hdr(skb);
+ if (!ipv6_addr_equal(&src6, &ipv6h->saddr))
+ return 0;
+ }
+
+ return 1;
+}
+
static int ipxip6_rcv(struct sk_buff *skb, u8 ipproto,
const struct tnl_ptk_info *tpi,
int (*dscp_ecn_decapsulate)(const struct ip6_tnl *t,
@@ -905,6 +1239,8 @@ static int ipxip6_rcv(struct sk_buff *skb, u8 ipproto,
goto drop;
if (iptunnel_pull_header(skb, 0, tpi->proto, false))
goto drop;
+ if (!ip6_tnl_map_rule_validate(t, skb))
+ goto drop;
if (t->parms.collect_md) {
tun_dst = ipv6_tun_rx_dst(skb, 0, 0, 0);
if (!tun_dst)
@@ -1092,6 +1428,12 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
use_cache = true;
}
+ /* In MAP-E mode we need to always do a route lookup */
+ if (!list_empty(&t->rules.list)) {
+ use_cache = false;
+ ip6_tnl_mape_dst(dev, skb, fl6);
+ }
+
if (use_cache)
dst = dst_cache_get(&t->dst_cache);
@@ -1863,6 +2205,8 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
dev->min_mtu = ETH_MIN_MTU;
dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len;
+ INIT_LIST_HEAD(&t->rules.list);
+
return 0;
destroy_dst:
@@ -1968,6 +2312,95 @@ static void ip6_tnl_netlink_parms(struct nlattr *data[],
if (data[IFLA_IPTUN_FWMARK])
parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]);
+
+ if (data[IFLA_IPTUN_RULE_ACTION])
+ parms->rule_action = nla_get_u8(data[IFLA_IPTUN_RULE_ACTION]);
+
+ if (data[IFLA_IPTUN_RULE_VERSION])
+ parms->rule.version = nla_get_u8(data[IFLA_IPTUN_RULE_VERSION]);
+
+ if (data[IFLA_IPTUN_RULE_IPV6_PREFIX])
+ parms->rule.ipv6_subnet =
+ nla_get_in6_addr(data[IFLA_IPTUN_RULE_IPV6_PREFIX]);
+
+ if (data[IFLA_IPTUN_RULE_IPV6_PREFIXLEN])
+ parms->rule.ipv6_prefixlen =
+ nla_get_u8(data[IFLA_IPTUN_RULE_IPV6_PREFIXLEN]);
+
+ if (data[IFLA_IPTUN_RULE_IPV4_PREFIX])
+ parms->rule.ipv4_subnet.s_addr =
+ nla_get_in_addr(data[IFLA_IPTUN_RULE_IPV4_PREFIX]);
+
+ if (data[IFLA_IPTUN_RULE_IPV4_PREFIXLEN])
+ parms->rule.ipv4_prefixlen =
+ nla_get_u8(data[IFLA_IPTUN_RULE_IPV4_PREFIXLEN]);
+
+ if (data[IFLA_IPTUN_RULE_EA_LENGTH])
+ parms->rule.ea_length =
+ nla_get_u8(data[IFLA_IPTUN_RULE_EA_LENGTH]);
+
+ if (data[IFLA_IPTUN_RULE_PSID_OFFSET])
+ parms->rule.psid_offset =
+ nla_get_u8(data[IFLA_IPTUN_RULE_PSID_OFFSET]);
+}
+
+static int ip6_tnl_rule_cmp(void *unused, struct list_head *_a,
+ struct list_head *_b)
+{
+ struct ip6_rule_list *a = list_entry(_a, struct ip6_rule_list, list);
+ struct ip6_rule_list *b = list_entry(_b, struct ip6_rule_list, list);
+ int diff;
+
+ diff = b->data.ipv4_prefixlen - a->data.ipv4_prefixlen;
+ if (!diff)
+ diff = b->data.ipv4_subnet.s_addr - a->data.ipv4_subnet.s_addr;
+
+ if (!diff)
+ diff = b->data.ipv6_prefixlen - a->data.ipv6_prefixlen;
+
+ if (!diff)
+ diff =
+ memcmp(&b->data.ipv6_subnet, &a->data.ipv6_subnet,
+ sizeof(b->data.ipv6_subnet));
+
+ if (!diff)
+ diff = b->data.ea_length - a->data.ea_length;
+
+ if (!diff)
+ diff = b->data.psid_offset - a->data.psid_offset;
+
+ return diff;
+}
+
+static void ip6_tnl_add_rule(struct net_device *dev,
+ struct __ip6_tnl_parm *new_cfg)
+{
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct ip6_rule_list *new_rule = kmalloc(sizeof(t->rules), GFP_KERNEL);
+
+ if (!new_rule)
+ return;
+
+ memcpy(&new_rule->data, &new_cfg->rule, sizeof(new_rule->data));
+ INIT_LIST_HEAD(&new_rule->list);
+ list_add(&new_rule->list, &t->rules.list);
+ list_sort(NULL, &t->rules.list, ip6_tnl_rule_cmp);
+}
+
+static void ip6_tnl_delete_rule(struct net_device *dev,
+ struct __ip6_tnl_parm *_old_rule)
+{
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct ip6_rule_list *pos = NULL;
+ struct ip6_rule_list old_rule = { .data = _old_rule->rule };
+ struct ip6_rule_list *iter = NULL;
+
+ list_for_each_entry_safe(pos, iter, &t->rules.list, list) {
+ if (ip6_tnl_rule_cmp(NULL, &pos->list, &old_rule.list) == 0) {
+ list_del(&pos->list);
+ break;
+ }
+ }
}
static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[],
@@ -2035,6 +2468,16 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
err = ip6_tnl_create2(dev);
if (!err && tb[IFLA_MTU])
ip6_tnl_change_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
+ if (!err && data[IFLA_IPTUN_RULE_ACTION]) {
+ switch (nla_get_u8(data[IFLA_IPTUN_RULE_ACTION])) {
+ case TUNNEL_RULE_ACTION_ADD:
+ ip6_tnl_add_rule(dev, &nt->parms);
+ break;
+ case TUNNEL_RULE_ACTION_DELETE:
+ ip6_tnl_delete_rule(dev, &nt->parms);
+ break;
+ }
+ }
return err;
}
@@ -2048,6 +2491,7 @@ static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
struct net *net = t->net;
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
struct ip_tunnel_encap ipencap;
+ int err;
if (dev == ip6n->fb_tnl_dev)
return -EINVAL;
@@ -2069,13 +2513,32 @@ static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
} else
t = netdev_priv(dev);
- return ip6_tnl_update(t, &p);
+ err = ip6_tnl_update(t, &p);
+ if (!err && data[IFLA_IPTUN_RULE_ACTION]) {
+ switch (nla_get_u8(data[IFLA_IPTUN_RULE_ACTION])) {
+ case TUNNEL_RULE_ACTION_ADD:
+ ip6_tnl_add_rule(dev, &p);
+ break;
+ case TUNNEL_RULE_ACTION_DELETE:
+ ip6_tnl_delete_rule(dev, &p);
+ break;
+ }
+ }
+
+ return err;
}
static void ip6_tnl_dellink(struct net_device *dev, struct list_head *head)
{
struct net *net = dev_net(dev);
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+ struct ip6_tnl *t = netdev_priv(dev);
+ struct ip6_rule_list *pos = NULL;
+ struct ip6_rule_list *iter = NULL;
+
+ list_for_each_entry_safe(pos, iter, &t->rules.list, list) {
+ list_del(&pos->list);
+ }
if (dev != ip6n->fb_tnl_dev)
unregister_netdevice_queue(dev, head);
@@ -2112,6 +2575,22 @@ static size_t ip6_tnl_get_size(const struct net_device *dev)
nla_total_size(0) +
/* IFLA_IPTUN_FWMARK */
nla_total_size(4) +
+ /* IFLA_IPTUN_RULE_VERSION */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_RULE_ACTION */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_RULE_IPV6_PREFIXLEN */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_RULE_IPV4_PREFIXLEN */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_RULE_EA_LENGTH */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_RULE_PSID_OFFSET */
+ nla_total_size(1) +
+ /* IFLA_IPTUN_RULE_IPV6_PREFIX */
+ nla_total_size(sizeof(struct in6_addr)) +
+ /* IFLA_IPTUN_RULE_IPV4_PREFIX */
+ nla_total_size(sizeof(struct in6_addr)) +
0;
}
@@ -2170,6 +2649,14 @@ static const struct nla_policy ip6_tnl_policy[IFLA_IPTUN_MAX + 1] = {
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
[IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG },
[IFLA_IPTUN_FWMARK] = { .type = NLA_U32 },
+ [IFLA_IPTUN_RULE_VERSION] = { .type = NLA_U8 },
+ [IFLA_IPTUN_RULE_ACTION] = { .type = NLA_U8 },
+ [IFLA_IPTUN_RULE_IPV6_PREFIXLEN] = { .type = NLA_U8 },
+ [IFLA_IPTUN_RULE_IPV4_PREFIXLEN] = { .type = NLA_U8 },
+ [IFLA_IPTUN_RULE_EA_LENGTH] = { .type = NLA_U8 },
+ [IFLA_IPTUN_RULE_PSID_OFFSET] = { .type = NLA_U8 },
+ [IFLA_IPTUN_RULE_IPV6_PREFIX] = { .len = sizeof(struct in6_addr) },
+ [IFLA_IPTUN_RULE_IPV4_PREFIX] = { .len = sizeof(struct in_addr) },
};
static struct rtnl_link_ops ip6_link_ops __read_mostly = {
--
2.19.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v1 2/2] netfilter: Add PSID mode to MASQUERADE
2018-11-20 1:31 [PATCH v1 1/2] ip6_tunnel: Adding support of mapping rules for MAP-E tunnel Felix Jia
@ 2018-11-20 1:31 ` Felix Jia
2018-11-20 11:31 ` kbuild test robot
2018-11-21 10:41 ` kbuild test robot
2018-11-20 1:46 ` [PATCH v1 1/2] ip6_tunnel: Adding support of mapping rules for MAP-E tunnel David Miller
1 sibling, 2 replies; 5+ messages in thread
From: Felix Jia @ 2018-11-20 1:31 UTC (permalink / raw)
To: David S . Miller, Pablo Neira Ayuso
Cc: Blair Steven, netdev, Anthony Lineham, Scott Parlane, Felix Jia
From: Blair Steven <blair.steven@alliedtelesis.co.nz>
This adds support for masquerading into a smaller subset of ports -
defined by the PSID values from RFC-7597 Section 5.1. This is part of
the support for MAP-E, which allows multiple devices to share an IPv4
address by splitting the L4 port / id into ranges by both masquerading
and encapsulating IPv4 packets inside an IPv6 carrier.
Co-developed-by: Anthony Lineham <anthony.lineham@alliedtelesis.co.nz>
Co-developed-by: Scott Parlane <scott.parlane@alliedtelesis.co.nz>
Signed-off-by: Blair Steven <blair.steven@alliedtelesis.co.nz>
Signed-off-by: Anthony Lineham <anthony.lineham@alliedtelesis.co.nz>
Signed-off-by: Scott Parlane <scott.parlane@alliedtelesis.co.nz>
Signed-off-by: Felix Jia <felix.jia@alliedtelesis.co.nz>
---
include/net/netfilter/nf_nat_l4proto.h | 6 +--
.../netfilter/nf_conntrack_tuple_common.h | 5 ++
include/uapi/linux/netfilter/nf_nat.h | 4 +-
net/ipv4/netfilter/nf_nat_proto_icmp.c | 51 ++++++++++++++++++-
net/netfilter/nf_nat_core.c | 25 ++++++---
net/netfilter/nf_nat_proto_common.c | 51 +++++++++++++++++--
net/netfilter/nf_nat_proto_unknown.c | 3 +-
7 files changed, 126 insertions(+), 19 deletions(-)
diff --git a/include/net/netfilter/nf_nat_l4proto.h b/include/net/netfilter/nf_nat_l4proto.h
index b4d6b29bca62..d3fb8f138d0a 100644
--- a/include/net/netfilter/nf_nat_l4proto.h
+++ b/include/net/netfilter/nf_nat_l4proto.h
@@ -24,8 +24,7 @@ struct nf_nat_l4proto {
/* Is the manipable part of the tuple between min and max incl? */
bool (*in_range)(const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype,
- const union nf_conntrack_man_proto *min,
- const union nf_conntrack_man_proto *max);
+ const struct nf_nat_range2 *range);
/* Alter the per-proto part of the tuple (depending on
* maniptype), to give a unique tuple in the given range if
@@ -67,8 +66,7 @@ extern const struct nf_nat_l4proto nf_nat_l4proto_udplite;
bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype,
- const union nf_conntrack_man_proto *min,
- const union nf_conntrack_man_proto *max);
+ const struct nf_nat_range2 *range);
void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple,
diff --git a/include/uapi/linux/netfilter/nf_conntrack_tuple_common.h b/include/uapi/linux/netfilter/nf_conntrack_tuple_common.h
index 64390fac6f7e..36d16d47c2b0 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_tuple_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_tuple_common.h
@@ -39,6 +39,11 @@ union nf_conntrack_man_proto {
struct {
__be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
} gre;
+ struct {
+ unsigned char psid_length;
+ unsigned char offset;
+ __be16 psid;
+ } psid;
};
#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
diff --git a/include/uapi/linux/netfilter/nf_nat.h b/include/uapi/linux/netfilter/nf_nat.h
index 4a95c0db14d4..d145d3eca25f 100644
--- a/include/uapi/linux/netfilter/nf_nat.h
+++ b/include/uapi/linux/netfilter/nf_nat.h
@@ -11,6 +11,7 @@
#define NF_NAT_RANGE_PERSISTENT (1 << 3)
#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4)
#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5)
+#define NF_NAT_RANGE_PSID (1 << 6)
#define NF_NAT_RANGE_PROTO_RANDOM_ALL \
(NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
@@ -18,7 +19,8 @@
#define NF_NAT_RANGE_MASK \
(NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \
NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \
- NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET)
+ NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET | \
+ NF_NAT_RANGE_PSID)
struct nf_nat_ipv4_range {
unsigned int flags;
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
index 6d7cf1d79baf..39efac4930b6 100644
--- a/net/ipv4/netfilter/nf_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
@@ -20,9 +20,23 @@
static bool
icmp_in_range(const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype,
- const union nf_conntrack_man_proto *min,
- const union nf_conntrack_man_proto *max)
+ const struct nf_nat_range2 *range)
{
+ const union nf_conntrack_man_proto *min = &range->min_proto;
+ const union nf_conntrack_man_proto *max = &range->max_proto;
+
+ /* In this case we are in PSID mode and the rules are all different */
+ if (range->flags & NF_NAT_RANGE_PSID) {
+ u16 offset_mask = ((1 << min->psid.offset) - 1) <<
+ (16 - min->psid.offset);
+ u16 psid_mask = ((1 << min->psid.psid_length) - 1) <<
+ (16 - min->psid.offset - min->psid.psid_length);
+ u16 id = ntohs(tuple->src.u.icmp.id);
+
+ return ((id & offset_mask) != 0) &&
+ ((id & psid_mask) == min->psid.psid);
+ }
+
return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) &&
ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
}
@@ -38,6 +52,39 @@ icmp_unique_tuple(const struct nf_nat_l3proto *l3proto,
unsigned int range_size;
unsigned int i;
+ if (range->flags & NF_NAT_RANGE_PSID) {
+ /* m = number of bits in each valid range */
+ u16 off;
+ int m = 16 - range->min_proto.psid.psid_length -
+ range->min_proto.psid.offset;
+
+ range_size = (1 << (16 - range->min_proto.psid.psid_length)) -
+ (1 << m);
+ off = ntohs(tuple->src.u.icmp.id);
+ for (i = 0; ; ++off) {
+ /* Find the non-PSID parts of the Index.
+ * To do this we look for an unused ID that is
+ * comprised of [t_chunk|PSID|b_chunk]. The size of
+ * these pieces is defined by the psid_length and
+ * offset.
+ */
+ int b_chunk = (off % range_size) & ((1 << (m)) - 1);
+ int t_chunk = (((off % range_size) >> m) &
+ ((1 << range->min_proto.psid.offset) -
+ 1)) <<
+ (m + range->min_proto.psid.psid_length);
+ /* Skip the all-zeroes reserved chunk */
+ t_chunk += (1 << (16 - range->min_proto.psid.offset));
+
+ tuple->src.u.icmp.id = htons(t_chunk |
+ (range->min_proto.psid.psid << m)
+ | b_chunk);
+
+ if (++i == range_size || !nf_nat_used_tuple(tuple, ct))
+ return;
+ }
+ }
+
range_size = ntohs(range->max_proto.icmp.id) -
ntohs(range->min_proto.icmp.id) + 1;
/* If no range specified... */
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index e2b196054dfc..18e39af3838d 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -187,9 +187,15 @@ static int in_range(const struct nf_nat_l3proto *l3proto,
!l3proto->in_range(tuple, range))
return 0;
+ /* If we are using PSID mode all protocols need to be checked
+ * to see that they fit inside the range.
+ */
+ if ((range->flags & NF_NAT_RANGE_PSID) &&
+ !l4proto->in_range(tuple, NF_NAT_MANIP_SRC, range))
+ return 0;
+
if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) ||
- l4proto->in_range(tuple, NF_NAT_MANIP_SRC,
- &range->min_proto, &range->max_proto))
+ l4proto->in_range(tuple, NF_NAT_MANIP_SRC, range))
return 1;
return 0;
@@ -369,11 +375,18 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
/* Only bother mapping if it's not already in range and unique */
if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM_ALL)) {
- if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
+ /* Now that the PSID mode is present we always need to check
+ * to see if the source ports are in range.
+ */
+ if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED ||
+ (range->flags & NF_NAT_RANGE_PSID &&
+ !in_range(l3proto, l4proto, orig_tuple, range))) {
+ /* The in_range prototype has been changed to take a
+ * whole range rather than min and max protocol
+ * information.
+ */
if (!(range->flags & NF_NAT_RANGE_PROTO_OFFSET) &&
- l4proto->in_range(tuple, maniptype,
- &range->min_proto,
- &range->max_proto) &&
+ l4proto->in_range(tuple, maniptype, range) &&
(range->min_proto.all == range->max_proto.all ||
!nf_nat_used_tuple(tuple, ct)))
goto out;
diff --git a/net/netfilter/nf_nat_proto_common.c b/net/netfilter/nf_nat_proto_common.c
index 5d849d835561..4ca3b2715e7c 100644
--- a/net/netfilter/nf_nat_proto_common.c
+++ b/net/netfilter/nf_nat_proto_common.c
@@ -19,16 +19,30 @@
bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype,
- const union nf_conntrack_man_proto *min,
- const union nf_conntrack_man_proto *max)
+ const struct nf_nat_range2 *range)
{
__be16 port;
+ const union nf_conntrack_man_proto *min = &range->min_proto;
+ const union nf_conntrack_man_proto *max = &range->max_proto;
if (maniptype == NF_NAT_MANIP_SRC)
port = tuple->src.u.all;
else
port = tuple->dst.u.all;
+ /* In this case we are in PSID mode and the rules are all different */
+ if (range->flags & NF_NAT_RANGE_PSID) {
+ /* m = number of bits in each valid range */
+ int m = 16 - min->psid.psid_length - min->psid.offset;
+ u16 offset_mask = ((1 << min->psid.offset) - 1) <<
+ (16 - min->psid.offset);
+ u16 psid_mask = ((1 << min->psid.psid_length) - 1) << m;
+
+ return ((ntohs(port) & offset_mask) != 0) &&
+ (((ntohs(port) & psid_mask) >> m) ==
+ min->psid.psid);
+ }
+
return ntohs(port) >= ntohs(min->all) &&
ntohs(port) <= ntohs(max->all);
}
@@ -46,9 +60,38 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
u_int16_t off;
if (maniptype == NF_NAT_MANIP_SRC)
- portptr = &tuple->src.u.all;
+ portptr = &tuple->src.u.tcp.port;
else
- portptr = &tuple->dst.u.all;
+ portptr = &tuple->dst.u.tcp.port;
+
+ if (range->flags & NF_NAT_RANGE_PSID) {
+ /* Find the non-PSID parts of the port.
+ * To do this we look for an unused port that is
+ * comprised of [t_chunk|PSID|b_chunk]. The size of
+ * these pieces is defined by the psid_length and
+ * offset.
+ */
+ int m = 16 - range->min_proto.psid.psid_length -
+ range->min_proto.psid.offset;
+ range_size = (1 << (16 - range->min_proto.psid.psid_length)) -
+ (1 << m);
+ off = ntohs(*portptr);
+ for (i = 0; ; ++off) {
+ int b_chunk = (off % range_size) & ((1 << (m)) - 1);
+ int t_chunk = (((off % range_size) >> m) &
+ ((1 << range->min_proto.psid.offset) -
+ 1)) <<
+ (m + range->min_proto.psid.psid_length);
+ /* Skip the all-zeroes reserved chunk */
+ t_chunk += (1 << (16 - range->min_proto.psid.offset));
+
+ *portptr = htons(t_chunk |
+ (range->min_proto.psid.psid << m)
+ | b_chunk);
+ if (++i == range_size || !nf_nat_used_tuple(tuple, ct))
+ return;
+ }
+ }
/* If no range specified... */
if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) {
diff --git a/net/netfilter/nf_nat_proto_unknown.c b/net/netfilter/nf_nat_proto_unknown.c
index c5db3e251232..82140ffc706d 100644
--- a/net/netfilter/nf_nat_proto_unknown.c
+++ b/net/netfilter/nf_nat_proto_unknown.c
@@ -19,8 +19,7 @@
static bool unknown_in_range(const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type manip_type,
- const union nf_conntrack_man_proto *min,
- const union nf_conntrack_man_proto *max)
+ const struct nf_nat_range2 *range)
{
return true;
}
--
2.19.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v1 1/2] ip6_tunnel: Adding support of mapping rules for MAP-E tunnel
2018-11-20 1:31 [PATCH v1 1/2] ip6_tunnel: Adding support of mapping rules for MAP-E tunnel Felix Jia
2018-11-20 1:31 ` [PATCH v1 2/2] netfilter: Add PSID mode to MASQUERADE Felix Jia
@ 2018-11-20 1:46 ` David Miller
1 sibling, 0 replies; 5+ messages in thread
From: David Miller @ 2018-11-20 1:46 UTC (permalink / raw)
To: felix.jia; +Cc: pablo, blair.steven, netdev, sheena.mira-ato, masakazu.asama
Please do not submit completely unrelated changes together in a patch
series.
Thank you.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1 2/2] netfilter: Add PSID mode to MASQUERADE
2018-11-20 1:31 ` [PATCH v1 2/2] netfilter: Add PSID mode to MASQUERADE Felix Jia
@ 2018-11-20 11:31 ` kbuild test robot
2018-11-21 10:41 ` kbuild test robot
1 sibling, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2018-11-20 11:31 UTC (permalink / raw)
To: Felix Jia
Cc: kbuild-all, David S . Miller, Pablo Neira Ayuso, Blair Steven,
netdev, Anthony Lineham, Scott Parlane, Felix Jia
[-- Attachment #1: Type: text/plain, Size: 2042 bytes --]
Hi Blair,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on nf-next/master]
[also build test ERROR on v4.20-rc3 next-20181120]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Felix-Jia/ip6_tunnel-Adding-support-of-mapping-rules-for-MAP-E-tunnel/20181120-173346
base: https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git master
config: sh-allyesconfig (attached as .config)
compiler: sh4-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=sh
All errors (new ones prefixed by >>):
>> net/ipv6/netfilter/nf_nat_proto_icmpv6.c:85:15: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
.in_range = icmpv6_in_range,
^~~~~~~~~~~~~~~
net/ipv6/netfilter/nf_nat_proto_icmpv6.c:85:15: note: (near initialization for 'nf_nat_l4proto_icmpv6.in_range')
cc1: some warnings being treated as errors
vim +85 net/ipv6/netfilter/nf_nat_proto_icmpv6.c
58a317f1 Patrick McHardy 2012-08-26 81
58a317f1 Patrick McHardy 2012-08-26 82 const struct nf_nat_l4proto nf_nat_l4proto_icmpv6 = {
58a317f1 Patrick McHardy 2012-08-26 83 .l4proto = IPPROTO_ICMPV6,
58a317f1 Patrick McHardy 2012-08-26 84 .manip_pkt = icmpv6_manip_pkt,
58a317f1 Patrick McHardy 2012-08-26 @85 .in_range = icmpv6_in_range,
:::::: The code at line 85 was first introduced by commit
:::::: 58a317f1061c894d2344c0b6a18ab4a64b69b815 netfilter: ipv6: add IPv6 NAT support
:::::: TO: Patrick McHardy <kaber@trash.net>
:::::: CC: Pablo Neira Ayuso <pablo@netfilter.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 50565 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1 2/2] netfilter: Add PSID mode to MASQUERADE
2018-11-20 1:31 ` [PATCH v1 2/2] netfilter: Add PSID mode to MASQUERADE Felix Jia
2018-11-20 11:31 ` kbuild test robot
@ 2018-11-21 10:41 ` kbuild test robot
1 sibling, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2018-11-21 10:41 UTC (permalink / raw)
To: Felix Jia
Cc: kbuild-all, David S . Miller, Pablo Neira Ayuso, Blair Steven,
netdev, Anthony Lineham, Scott Parlane, Felix Jia
[-- Attachment #1: Type: text/plain, Size: 2544 bytes --]
Hi Blair,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on nf-next/master]
[also build test ERROR on v4.20-rc3 next-20181121]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Felix-Jia/ip6_tunnel-Adding-support-of-mapping-rules-for-MAP-E-tunnel/20181120-173346
base: https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git master
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 8.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.1.0 make.cross ARCH=ia64
All errors (new ones prefixed by >>):
>> net/ipv6/netfilter/nf_nat_proto_icmpv6.c:85:15: error: initialization of 'bool (*)(const struct nf_conntrack_tuple *, enum nf_nat_manip_type, const struct nf_nat_range2 *)' {aka '_Bool (*)(const struct nf_conntrack_tuple *, enum nf_nat_manip_type, const struct nf_nat_range2 *)'} from incompatible pointer type 'bool (*)(const struct nf_conntrack_tuple *, enum nf_nat_manip_type, const union nf_conntrack_man_proto *, const union nf_conntrack_man_proto *)' {aka '_Bool (*)(const struct nf_conntrack_tuple *, enum nf_nat_manip_type, const union nf_conntrack_man_proto *, const union nf_conntrack_man_proto *)'} [-Werror=incompatible-pointer-types]
.in_range = icmpv6_in_range,
^~~~~~~~~~~~~~~
net/ipv6/netfilter/nf_nat_proto_icmpv6.c:85:15: note: (near initialization for 'nf_nat_l4proto_icmpv6.in_range')
cc1: some warnings being treated as errors
vim +85 net/ipv6/netfilter/nf_nat_proto_icmpv6.c
58a317f1 Patrick McHardy 2012-08-26 81
58a317f1 Patrick McHardy 2012-08-26 82 const struct nf_nat_l4proto nf_nat_l4proto_icmpv6 = {
58a317f1 Patrick McHardy 2012-08-26 83 .l4proto = IPPROTO_ICMPV6,
58a317f1 Patrick McHardy 2012-08-26 84 .manip_pkt = icmpv6_manip_pkt,
58a317f1 Patrick McHardy 2012-08-26 @85 .in_range = icmpv6_in_range,
:::::: The code at line 85 was first introduced by commit
:::::: 58a317f1061c894d2344c0b6a18ab4a64b69b815 netfilter: ipv6: add IPv6 NAT support
:::::: TO: Patrick McHardy <kaber@trash.net>
:::::: CC: Pablo Neira Ayuso <pablo@netfilter.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 52297 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-11-21 21:16 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-20 1:31 [PATCH v1 1/2] ip6_tunnel: Adding support of mapping rules for MAP-E tunnel Felix Jia
2018-11-20 1:31 ` [PATCH v1 2/2] netfilter: Add PSID mode to MASQUERADE Felix Jia
2018-11-20 11:31 ` kbuild test robot
2018-11-21 10:41 ` kbuild test robot
2018-11-20 1:46 ` [PATCH v1 1/2] ip6_tunnel: Adding support of mapping rules for MAP-E tunnel David Miller
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.