Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Resolve conflicts with conntrack template fixes. Conflicts: net/netfilter/nf_conntrack_core.c net/netfilter/nf_synproxy_core.c net/netfilter/xt_CT.c Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
@@ -92,6 +92,25 @@ config IPV6_MIP6
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config IPV6_ILA
|
||||
tristate "IPv6: Identifier Locator Addressing (ILA)"
|
||||
select LWTUNNEL
|
||||
---help---
|
||||
Support for IPv6 Identifier Locator Addressing (ILA).
|
||||
|
||||
ILA is a mechanism to do network virtualization without
|
||||
encapsulation. The basic concept of ILA is that we split an
|
||||
IPv6 address into a 64 bit locator and 64 bit identifier. The
|
||||
identifier is the identity of an entity in communication
|
||||
("who") and the locator expresses the location of the
|
||||
entity ("where").
|
||||
|
||||
ILA can be configured using the "encap ila" option with
|
||||
"ip -6 route" command. ILA is described in
|
||||
https://tools.ietf.org/html/draft-herbert-nvo3-ila-00.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config INET6_XFRM_TUNNEL
|
||||
tristate
|
||||
select INET6_TUNNEL
|
||||
|
@@ -34,6 +34,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
|
||||
obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
|
||||
obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
|
||||
obj-$(CONFIG_IPV6_MIP6) += mip6.o
|
||||
obj-$(CONFIG_IPV6_ILA) += ila.o
|
||||
obj-$(CONFIG_NETFILTER) += netfilter/
|
||||
|
||||
obj-$(CONFIG_IPV6_VTI) += ip6_vti.o
|
||||
|
@@ -214,6 +214,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
|
||||
.initialized = false,
|
||||
},
|
||||
.use_oif_addrs_only = 0,
|
||||
.ignore_routes_with_linkdown = 0,
|
||||
};
|
||||
|
||||
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
|
||||
@@ -257,6 +258,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
|
||||
.initialized = false,
|
||||
},
|
||||
.use_oif_addrs_only = 0,
|
||||
.ignore_routes_with_linkdown = 0,
|
||||
};
|
||||
|
||||
/* Check if a valid qdisc is available */
|
||||
@@ -472,6 +474,9 @@ static int inet6_netconf_msgsize_devconf(int type)
|
||||
if (type == -1 || type == NETCONFA_PROXY_NEIGH)
|
||||
size += nla_total_size(4);
|
||||
|
||||
if (type == -1 || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN)
|
||||
size += nla_total_size(4);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -508,6 +513,11 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
|
||||
nla_put_s32(skb, NETCONFA_PROXY_NEIGH, devconf->proxy_ndp) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
if ((type == -1 || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) &&
|
||||
nla_put_s32(skb, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
|
||||
devconf->ignore_routes_with_linkdown) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
return 0;
|
||||
|
||||
@@ -544,6 +554,7 @@ static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
|
||||
[NETCONFA_IFINDEX] = { .len = sizeof(int) },
|
||||
[NETCONFA_FORWARDING] = { .len = sizeof(int) },
|
||||
[NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) },
|
||||
[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN] = { .len = sizeof(int) },
|
||||
};
|
||||
|
||||
static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
|
||||
@@ -766,6 +777,63 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
|
||||
rt6_purge_dflt_routers(net);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void addrconf_linkdown_change(struct net *net, __s32 newf)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct inet6_dev *idev;
|
||||
|
||||
for_each_netdev(net, dev) {
|
||||
idev = __in6_dev_get(dev);
|
||||
if (idev) {
|
||||
int changed = (!idev->cnf.ignore_routes_with_linkdown) ^ (!newf);
|
||||
|
||||
idev->cnf.ignore_routes_with_linkdown = newf;
|
||||
if (changed)
|
||||
inet6_netconf_notify_devconf(dev_net(dev),
|
||||
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
|
||||
dev->ifindex,
|
||||
&idev->cnf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int addrconf_fixup_linkdown(struct ctl_table *table, int *p, int newf)
|
||||
{
|
||||
struct net *net;
|
||||
int old;
|
||||
|
||||
if (!rtnl_trylock())
|
||||
return restart_syscall();
|
||||
|
||||
net = (struct net *)table->extra2;
|
||||
old = *p;
|
||||
*p = newf;
|
||||
|
||||
if (p == &net->ipv6.devconf_dflt->ignore_routes_with_linkdown) {
|
||||
if ((!newf) ^ (!old))
|
||||
inet6_netconf_notify_devconf(net,
|
||||
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
|
||||
NETCONFA_IFINDEX_DEFAULT,
|
||||
net->ipv6.devconf_dflt);
|
||||
rtnl_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (p == &net->ipv6.devconf_all->ignore_routes_with_linkdown) {
|
||||
net->ipv6.devconf_dflt->ignore_routes_with_linkdown = newf;
|
||||
addrconf_linkdown_change(net, newf);
|
||||
if ((!newf) ^ (!old))
|
||||
inet6_netconf_notify_devconf(net,
|
||||
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
|
||||
NETCONFA_IFINDEX_ALL,
|
||||
net->ipv6.devconf_all);
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Nobody refers to this ifaddr, destroy it */
|
||||
@@ -4616,6 +4684,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
|
||||
array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
|
||||
array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local;
|
||||
array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu;
|
||||
array[DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN] = cnf->ignore_routes_with_linkdown;
|
||||
/* we omit DEVCONF_STABLE_SECRET for now */
|
||||
array[DEVCONF_USE_OIF_ADDRS_ONLY] = cnf->use_oif_addrs_only;
|
||||
}
|
||||
@@ -4637,6 +4706,7 @@ static inline size_t inet6_if_nlmsg_size(void)
|
||||
+ nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
|
||||
+ nla_total_size(4) /* IFLA_MTU */
|
||||
+ nla_total_size(4) /* IFLA_LINK */
|
||||
+ nla_total_size(1) /* IFLA_OPERSTATE */
|
||||
+ nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */
|
||||
}
|
||||
|
||||
@@ -4893,7 +4963,9 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
|
||||
nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
|
||||
nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
|
||||
(dev->ifindex != dev_get_iflink(dev) &&
|
||||
nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))
|
||||
nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) ||
|
||||
nla_put_u8(skb, IFLA_OPERSTATE,
|
||||
netif_running(dev) ? dev->operstate : IF_OPER_DOWN))
|
||||
goto nla_put_failure;
|
||||
protoinfo = nla_nest_start(skb, IFLA_PROTINFO);
|
||||
if (!protoinfo)
|
||||
@@ -5338,6 +5410,34 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static
|
||||
int addrconf_sysctl_ignore_routes_with_linkdown(struct ctl_table *ctl,
|
||||
int write,
|
||||
void __user *buffer,
|
||||
size_t *lenp,
|
||||
loff_t *ppos)
|
||||
{
|
||||
int *valp = ctl->data;
|
||||
int val = *valp;
|
||||
loff_t pos = *ppos;
|
||||
struct ctl_table lctl;
|
||||
int ret;
|
||||
|
||||
/* ctl->data points to idev->cnf.ignore_routes_when_linkdown
|
||||
* we should not modify it until we get the rtnl lock.
|
||||
*/
|
||||
lctl = *ctl;
|
||||
lctl.data = &val;
|
||||
|
||||
ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
|
||||
|
||||
if (write)
|
||||
ret = addrconf_fixup_linkdown(ctl, valp, val);
|
||||
if (ret)
|
||||
*ppos = pos;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct addrconf_sysctl_table
|
||||
{
|
||||
struct ctl_table_header *sysctl_header;
|
||||
@@ -5629,7 +5729,13 @@ static struct addrconf_sysctl_table
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
|
||||
},
|
||||
{
|
||||
.procname = "ignore_routes_with_linkdown",
|
||||
.data = &ipv6_devconf.ignore_routes_with_linkdown,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = addrconf_sysctl_ignore_routes_with_linkdown,
|
||||
},
|
||||
{
|
||||
/* sentinel */
|
||||
|
216
net/ipv6/ila.c
Normal file
216
net/ipv6/ila.c
Normal file
@@ -0,0 +1,216 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/types.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ip6_fib.h>
|
||||
#include <net/lwtunnel.h>
|
||||
#include <net/protocol.h>
|
||||
#include <uapi/linux/ila.h>
|
||||
|
||||
struct ila_params {
|
||||
__be64 locator;
|
||||
};
|
||||
|
||||
static inline struct ila_params *ila_params_lwtunnel(
|
||||
struct lwtunnel_state *lwstate)
|
||||
{
|
||||
return (struct ila_params *)lwstate->data;
|
||||
}
|
||||
|
||||
static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to)
|
||||
{
|
||||
__be32 diff[] = {
|
||||
~from[0], ~from[1], to[0], to[1],
|
||||
};
|
||||
|
||||
return csum_partial(diff, sizeof(diff), 0);
|
||||
}
|
||||
|
||||
static inline __wsum get_csum_diff(struct ipv6hdr *ip6h, struct ila_params *p)
|
||||
{
|
||||
return compute_csum_diff8((__be32 *)&ip6h->daddr,
|
||||
(__be32 *)&p->locator);
|
||||
}
|
||||
|
||||
static void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p)
|
||||
{
|
||||
__wsum diff;
|
||||
struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||
size_t nhoff = sizeof(struct ipv6hdr);
|
||||
|
||||
/* First update checksum */
|
||||
switch (ip6h->nexthdr) {
|
||||
case NEXTHDR_TCP:
|
||||
if (likely(pskb_may_pull(skb, nhoff + sizeof(struct tcphdr)))) {
|
||||
struct tcphdr *th = (struct tcphdr *)
|
||||
(skb_network_header(skb) + nhoff);
|
||||
|
||||
diff = get_csum_diff(ip6h, p);
|
||||
inet_proto_csum_replace_by_diff(&th->check, skb,
|
||||
diff, true);
|
||||
}
|
||||
break;
|
||||
case NEXTHDR_UDP:
|
||||
if (likely(pskb_may_pull(skb, nhoff + sizeof(struct udphdr)))) {
|
||||
struct udphdr *uh = (struct udphdr *)
|
||||
(skb_network_header(skb) + nhoff);
|
||||
|
||||
if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
diff = get_csum_diff(ip6h, p);
|
||||
inet_proto_csum_replace_by_diff(&uh->check, skb,
|
||||
diff, true);
|
||||
if (!uh->check)
|
||||
uh->check = CSUM_MANGLED_0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NEXTHDR_ICMP:
|
||||
if (likely(pskb_may_pull(skb,
|
||||
nhoff + sizeof(struct icmp6hdr)))) {
|
||||
struct icmp6hdr *ih = (struct icmp6hdr *)
|
||||
(skb_network_header(skb) + nhoff);
|
||||
|
||||
diff = get_csum_diff(ip6h, p);
|
||||
inet_proto_csum_replace_by_diff(&ih->icmp6_cksum, skb,
|
||||
diff, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now change destination address */
|
||||
*(__be64 *)&ip6h->daddr = p->locator;
|
||||
}
|
||||
|
||||
static int ila_output(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
struct rt6_info *rt6 = NULL;
|
||||
|
||||
if (skb->protocol != htons(ETH_P_IPV6))
|
||||
goto drop;
|
||||
|
||||
rt6 = (struct rt6_info *)dst;
|
||||
|
||||
update_ipv6_locator(skb, ila_params_lwtunnel(rt6->rt6i_lwtstate));
|
||||
|
||||
return rt6->rt6i_lwtstate->orig_output(sk, skb);
|
||||
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ila_input(struct sk_buff *skb)
|
||||
{
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
struct rt6_info *rt6 = NULL;
|
||||
|
||||
if (skb->protocol != htons(ETH_P_IPV6))
|
||||
goto drop;
|
||||
|
||||
rt6 = (struct rt6_info *)dst;
|
||||
|
||||
update_ipv6_locator(skb, ila_params_lwtunnel(rt6->rt6i_lwtstate));
|
||||
|
||||
return rt6->rt6i_lwtstate->orig_input(skb);
|
||||
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
|
||||
[ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
|
||||
};
|
||||
|
||||
static int ila_build_state(struct net_device *dev, struct nlattr *nla,
|
||||
struct lwtunnel_state **ts)
|
||||
{
|
||||
struct ila_params *p;
|
||||
struct nlattr *tb[ILA_ATTR_MAX + 1];
|
||||
size_t encap_len = sizeof(*p);
|
||||
struct lwtunnel_state *newts;
|
||||
int ret;
|
||||
|
||||
ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla,
|
||||
ila_nl_policy);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!tb[ILA_ATTR_LOCATOR])
|
||||
return -EINVAL;
|
||||
|
||||
newts = lwtunnel_state_alloc(encap_len);
|
||||
if (!newts)
|
||||
return -ENOMEM;
|
||||
|
||||
newts->len = encap_len;
|
||||
p = ila_params_lwtunnel(newts);
|
||||
|
||||
p->locator = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);
|
||||
|
||||
newts->type = LWTUNNEL_ENCAP_ILA;
|
||||
newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
|
||||
LWTUNNEL_STATE_INPUT_REDIRECT;
|
||||
|
||||
*ts = newts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ila_fill_encap_info(struct sk_buff *skb,
|
||||
struct lwtunnel_state *lwtstate)
|
||||
{
|
||||
struct ila_params *p = ila_params_lwtunnel(lwtstate);
|
||||
|
||||
if (nla_put_u64(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator))
|
||||
goto nla_put_failure;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int ila_encap_nlsize(struct lwtunnel_state *lwtstate)
|
||||
{
|
||||
/* No encapsulation overhead */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ila_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
|
||||
{
|
||||
struct ila_params *a_p = ila_params_lwtunnel(a);
|
||||
struct ila_params *b_p = ila_params_lwtunnel(b);
|
||||
|
||||
return (a_p->locator != b_p->locator);
|
||||
}
|
||||
|
||||
static const struct lwtunnel_encap_ops ila_encap_ops = {
|
||||
.build_state = ila_build_state,
|
||||
.output = ila_output,
|
||||
.input = ila_input,
|
||||
.fill_encap = ila_fill_encap_info,
|
||||
.get_encap_size = ila_encap_nlsize,
|
||||
.cmp_encap = ila_encap_cmp,
|
||||
};
|
||||
|
||||
static int __init ila_init(void)
|
||||
{
|
||||
return lwtunnel_encap_add_ops(&ila_encap_ops, LWTUNNEL_ENCAP_ILA);
|
||||
}
|
||||
|
||||
static void __exit ila_fini(void)
|
||||
{
|
||||
lwtunnel_encap_del_ops(&ila_encap_ops, LWTUNNEL_ENCAP_ILA);
|
||||
}
|
||||
|
||||
module_init(ila_init);
|
||||
module_exit(ila_fini);
|
||||
MODULE_AUTHOR("Tom Herbert <tom@herbertland.com>");
|
||||
MODULE_LICENSE("GPL");
|
@@ -37,12 +37,13 @@ synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr,
|
||||
}
|
||||
|
||||
static void
|
||||
synproxy_send_tcp(const struct sk_buff *skb, struct sk_buff *nskb,
|
||||
synproxy_send_tcp(const struct synproxy_net *snet,
|
||||
const struct sk_buff *skb, struct sk_buff *nskb,
|
||||
struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo,
|
||||
struct ipv6hdr *niph, struct tcphdr *nth,
|
||||
unsigned int tcp_hdr_size)
|
||||
{
|
||||
struct net *net = nf_ct_net((struct nf_conn *)nfct);
|
||||
struct net *net = nf_ct_net(snet->tmpl);
|
||||
struct dst_entry *dst;
|
||||
struct flowi6 fl6;
|
||||
|
||||
@@ -83,7 +84,8 @@ free_nskb:
|
||||
}
|
||||
|
||||
static void
|
||||
synproxy_send_client_synack(const struct sk_buff *skb, const struct tcphdr *th,
|
||||
synproxy_send_client_synack(const struct synproxy_net *snet,
|
||||
const struct sk_buff *skb, const struct tcphdr *th,
|
||||
const struct synproxy_options *opts)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
@@ -119,7 +121,7 @@ synproxy_send_client_synack(const struct sk_buff *skb, const struct tcphdr *th,
|
||||
|
||||
synproxy_build_options(nth, opts);
|
||||
|
||||
synproxy_send_tcp(skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
|
||||
synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
|
||||
niph, nth, tcp_hdr_size);
|
||||
}
|
||||
|
||||
@@ -163,7 +165,7 @@ synproxy_send_server_syn(const struct synproxy_net *snet,
|
||||
|
||||
synproxy_build_options(nth, opts);
|
||||
|
||||
synproxy_send_tcp(skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
|
||||
synproxy_send_tcp(snet, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
|
||||
niph, nth, tcp_hdr_size);
|
||||
}
|
||||
|
||||
@@ -203,7 +205,7 @@ synproxy_send_server_ack(const struct synproxy_net *snet,
|
||||
|
||||
synproxy_build_options(nth, opts);
|
||||
|
||||
synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
|
||||
synproxy_send_tcp(snet, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -241,7 +243,8 @@ synproxy_send_client_ack(const struct synproxy_net *snet,
|
||||
|
||||
synproxy_build_options(nth, opts);
|
||||
|
||||
synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
|
||||
synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
|
||||
niph, nth, tcp_hdr_size);
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -301,7 +304,7 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
XT_SYNPROXY_OPT_SACK_PERM |
|
||||
XT_SYNPROXY_OPT_ECN);
|
||||
|
||||
synproxy_send_client_synack(skb, th, &opts);
|
||||
synproxy_send_client_synack(snet, skb, th, &opts);
|
||||
return NF_DROP;
|
||||
|
||||
} else if (th->ack && !(th->fin || th->rst || th->syn)) {
|
||||
|
@@ -124,7 +124,7 @@ static void nf_nat_ipv6_csum_update(struct sk_buff *skb,
|
||||
newip = &t->dst.u3.in6;
|
||||
}
|
||||
inet_proto_csum_replace16(check, skb, oldip->s6_addr32,
|
||||
newip->s6_addr32, 1);
|
||||
newip->s6_addr32, true);
|
||||
}
|
||||
|
||||
static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb,
|
||||
@@ -155,7 +155,7 @@ static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb,
|
||||
}
|
||||
} else
|
||||
inet_proto_csum_replace2(check, skb,
|
||||
htons(oldlen), htons(datalen), 1);
|
||||
htons(oldlen), htons(datalen), true);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
|
||||
|
@@ -73,7 +73,7 @@ icmpv6_manip_pkt(struct sk_buff *skb,
|
||||
hdr->icmp6_type == ICMPV6_ECHO_REPLY) {
|
||||
inet_proto_csum_replace2(&hdr->icmp6_cksum, skb,
|
||||
hdr->icmp6_identifier,
|
||||
tuple->src.u.icmp.id, 0);
|
||||
tuple->src.u.icmp.id, false);
|
||||
hdr->icmp6_identifier = tuple->src.u.icmp.id;
|
||||
}
|
||||
return true;
|
||||
|
@@ -665,6 +665,12 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
|
||||
{
|
||||
int m;
|
||||
bool match_do_rr = false;
|
||||
struct inet6_dev *idev = rt->rt6i_idev;
|
||||
struct net_device *dev = rt->dst.dev;
|
||||
|
||||
if (dev && !netif_carrier_ok(dev) &&
|
||||
idev->cnf.ignore_routes_with_linkdown)
|
||||
goto out;
|
||||
|
||||
if (rt6_check_expired(rt))
|
||||
goto out;
|
||||
@@ -1779,8 +1785,14 @@ int ip6_route_add(struct fib6_config *cfg)
|
||||
if (err)
|
||||
goto out;
|
||||
rt->rt6i_lwtstate = lwtstate_get(lwtstate);
|
||||
if (lwtunnel_output_redirect(rt->rt6i_lwtstate))
|
||||
if (lwtunnel_output_redirect(rt->rt6i_lwtstate)) {
|
||||
rt->rt6i_lwtstate->orig_output = rt->dst.output;
|
||||
rt->dst.output = lwtunnel_output6;
|
||||
}
|
||||
if (lwtunnel_input_redirect(rt->rt6i_lwtstate)) {
|
||||
rt->rt6i_lwtstate->orig_input = rt->dst.input;
|
||||
rt->dst.input = lwtunnel_input6;
|
||||
}
|
||||
}
|
||||
|
||||
ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
|
||||
@@ -1844,6 +1856,7 @@ int ip6_route_add(struct fib6_config *cfg)
|
||||
int gwa_type;
|
||||
|
||||
gw_addr = &cfg->fc_gateway;
|
||||
gwa_type = ipv6_addr_type(gw_addr);
|
||||
|
||||
/* if gw_addr is local we will fail to detect this in case
|
||||
* address is still TENTATIVE (DAD in progress). rt6_lookup()
|
||||
@@ -1851,11 +1864,12 @@ int ip6_route_add(struct fib6_config *cfg)
|
||||
* prefix route was assigned to, which might be non-loopback.
|
||||
*/
|
||||
err = -EINVAL;
|
||||
if (ipv6_chk_addr_and_flags(net, gw_addr, NULL, 0, 0))
|
||||
if (ipv6_chk_addr_and_flags(net, gw_addr,
|
||||
gwa_type & IPV6_ADDR_LINKLOCAL ?
|
||||
dev : NULL, 0, 0))
|
||||
goto out;
|
||||
|
||||
rt->rt6i_gateway = *gw_addr;
|
||||
gwa_type = ipv6_addr_type(gw_addr);
|
||||
|
||||
if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
|
||||
struct rt6_info *grt;
|
||||
@@ -2885,6 +2899,11 @@ static int rt6_fill_node(struct net *net,
|
||||
else
|
||||
rtm->rtm_type = RTN_UNICAST;
|
||||
rtm->rtm_flags = 0;
|
||||
if (!netif_carrier_ok(rt->dst.dev)) {
|
||||
rtm->rtm_flags |= RTNH_F_LINKDOWN;
|
||||
if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown)
|
||||
rtm->rtm_flags |= RTNH_F_DEAD;
|
||||
}
|
||||
rtm->rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
rtm->rtm_protocol = rt->rt6i_protocol;
|
||||
if (rt->rt6i_flags & RTF_DYNAMIC)
|
||||
|
@@ -742,7 +742,7 @@ static int ipip_rcv(struct sk_buff *skb)
|
||||
goto drop;
|
||||
if (iptunnel_pull_header(skb, 0, tpi.proto))
|
||||
goto drop;
|
||||
return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
|
||||
return ip_tunnel_rcv(tunnel, skb, &tpi, NULL, log_ecn_error);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@@ -943,7 +943,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb)
|
||||
&ipv6_hdr(skb)->daddr, tcp_v6_iif(skb));
|
||||
if (req) {
|
||||
nsk = tcp_check_req(sk, skb, req, false);
|
||||
if (!nsk)
|
||||
if (!nsk || nsk == sk)
|
||||
reqsk_put(req);
|
||||
return nsk;
|
||||
}
|
||||
|
@@ -1496,7 +1496,8 @@ int __net_init udp6_proc_init(struct net *net)
|
||||
return udp_proc_register(net, &udp6_seq_afinfo);
|
||||
}
|
||||
|
||||
void udp6_proc_exit(struct net *net) {
|
||||
void udp6_proc_exit(struct net *net)
|
||||
{
|
||||
udp_proc_unregister(net, &udp6_seq_afinfo);
|
||||
}
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
@@ -20,10 +20,9 @@
|
||||
|
||||
static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
|
||||
{
|
||||
const struct ipv6hdr *outer_iph = ipv6_hdr(skb);
|
||||
struct ipv6hdr *inner_iph = ipipv6_hdr(skb);
|
||||
|
||||
if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
|
||||
if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
|
||||
IP6_ECN_set_ce(inner_iph);
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,7 @@
|
||||
|
||||
static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
|
||||
|
||||
static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
|
||||
static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
|
||||
const xfrm_address_t *saddr,
|
||||
const xfrm_address_t *daddr)
|
||||
{
|
||||
@@ -35,6 +35,7 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
|
||||
int err;
|
||||
|
||||
memset(&fl6, 0, sizeof(fl6));
|
||||
fl6.flowi6_oif = oif;
|
||||
memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
|
||||
if (saddr)
|
||||
memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
|
||||
@@ -50,13 +51,13 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
|
||||
return dst;
|
||||
}
|
||||
|
||||
static int xfrm6_get_saddr(struct net *net,
|
||||
static int xfrm6_get_saddr(struct net *net, int oif,
|
||||
xfrm_address_t *saddr, xfrm_address_t *daddr)
|
||||
{
|
||||
struct dst_entry *dst;
|
||||
struct net_device *dev;
|
||||
|
||||
dst = xfrm6_dst_lookup(net, 0, NULL, daddr);
|
||||
dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr);
|
||||
if (IS_ERR(dst))
|
||||
return -EHOSTUNREACH;
|
||||
|
||||
|
Reference in New Issue
Block a user