Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Resolve conflict between commit264640fc2c
("ipv6: distinguish frag queues by device for multicast and link-local packets") from the net tree and commit029f7f3b87
("netfilter: ipv6: nf_defrag: avoid/free clone operations") from the nf-next tree. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Conflicts: net/ipv6/netfilter/nf_conntrack_reasm.c
This commit is contained in:
@@ -3287,7 +3287,8 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
|
||||
|
||||
case NETDEV_PRE_TYPE_CHANGE:
|
||||
case NETDEV_POST_TYPE_CHANGE:
|
||||
addrconf_type_change(dev, event);
|
||||
if (idev)
|
||||
addrconf_type_change(dev, event);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3642,7 +3643,7 @@ static void addrconf_dad_work(struct work_struct *w)
|
||||
|
||||
/* send a neighbour solicitation for our addr */
|
||||
addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
|
||||
ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any, NULL);
|
||||
ndisc_send_ns(ifp->idev->dev, &ifp->addr, &mcaddr, &in6addr_any);
|
||||
out:
|
||||
in6_ifa_put(ifp);
|
||||
rtnl_unlock();
|
||||
@@ -5199,6 +5200,20 @@ int addrconf_sysctl_forward(struct ctl_table *ctl, int write,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int addrconf_sysctl_hop_limit(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct ctl_table lctl;
|
||||
int min_hl = 1, max_hl = 255;
|
||||
|
||||
lctl = *ctl;
|
||||
lctl.extra1 = &min_hl;
|
||||
lctl.extra2 = &max_hl;
|
||||
|
||||
return proc_dointvec_minmax(&lctl, write, buffer, lenp, ppos);
|
||||
}
|
||||
|
||||
static
|
||||
int addrconf_sysctl_mtu(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
@@ -5454,7 +5469,7 @@ static struct addrconf_sysctl_table
|
||||
.data = &ipv6_devconf.hop_limit,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.proc_handler = addrconf_sysctl_hop_limit,
|
||||
},
|
||||
{
|
||||
.procname = "mtu",
|
||||
|
@@ -428,9 +428,11 @@ void inet6_destroy_sock(struct sock *sk)
|
||||
|
||||
/* Free tx options */
|
||||
|
||||
opt = xchg(&np->opt, NULL);
|
||||
if (opt)
|
||||
sock_kfree_s(sk, opt, opt->tot_len);
|
||||
opt = xchg((__force struct ipv6_txoptions **)&np->opt, NULL);
|
||||
if (opt) {
|
||||
atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
|
||||
txopt_put(opt);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(inet6_destroy_sock);
|
||||
|
||||
@@ -659,7 +661,10 @@ int inet6_sk_rebuild_header(struct sock *sk)
|
||||
fl6.fl6_sport = inet->inet_sport;
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
|
||||
|
||||
final_p = fl6_update_dst(&fl6, np->opt, &final);
|
||||
rcu_read_lock();
|
||||
final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt),
|
||||
&final);
|
||||
rcu_read_unlock();
|
||||
|
||||
dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
|
||||
if (IS_ERR(dst)) {
|
||||
@@ -668,7 +673,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
|
||||
return PTR_ERR(dst);
|
||||
}
|
||||
|
||||
__ip6_dst_store(sk, dst, NULL, NULL);
|
||||
ip6_dst_store(sk, dst, NULL, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@@ -167,8 +167,10 @@ ipv4_connected:
|
||||
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
|
||||
|
||||
opt = flowlabel ? flowlabel->opt : np->opt;
|
||||
rcu_read_lock();
|
||||
opt = flowlabel ? flowlabel->opt : rcu_dereference(np->opt);
|
||||
final_p = fl6_update_dst(&fl6, opt, &final);
|
||||
rcu_read_unlock();
|
||||
|
||||
dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
|
||||
err = 0;
|
||||
|
@@ -727,6 +727,7 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
|
||||
*((char **)&opt2->dst1opt) += dif;
|
||||
if (opt2->srcrt)
|
||||
*((char **)&opt2->srcrt) += dif;
|
||||
atomic_set(&opt2->refcnt, 1);
|
||||
}
|
||||
return opt2;
|
||||
}
|
||||
@@ -790,7 +791,7 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
|
||||
return ERR_PTR(-ENOBUFS);
|
||||
|
||||
memset(opt2, 0, tot_len);
|
||||
|
||||
atomic_set(&opt2->refcnt, 1);
|
||||
opt2->tot_len = tot_len;
|
||||
p = (char *)(opt2 + 1);
|
||||
|
||||
|
@@ -834,11 +834,6 @@ void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6,
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
|
||||
}
|
||||
|
||||
/*
|
||||
* Special lock-class for __icmpv6_sk:
|
||||
*/
|
||||
static struct lock_class_key icmpv6_socket_sk_dst_lock_key;
|
||||
|
||||
static int __net_init icmpv6_sk_init(struct net *net)
|
||||
{
|
||||
struct sock *sk;
|
||||
@@ -860,15 +855,6 @@ static int __net_init icmpv6_sk_init(struct net *net)
|
||||
|
||||
net->ipv6.icmp_sk[i] = sk;
|
||||
|
||||
/*
|
||||
* Split off their lock-class, because sk->sk_dst_lock
|
||||
* gets used from softirqs, which is safe for
|
||||
* __icmpv6_sk (because those never get directly used
|
||||
* via userspace syscalls), but unsafe for normal sockets.
|
||||
*/
|
||||
lockdep_set_class(&sk->sk_dst_lock,
|
||||
&icmpv6_socket_sk_dst_lock_key);
|
||||
|
||||
/* Enough space for 2 64K ICMP packets, including
|
||||
* sk_buff struct overhead.
|
||||
*/
|
||||
|
@@ -78,7 +78,9 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk,
|
||||
memset(fl6, 0, sizeof(*fl6));
|
||||
fl6->flowi6_proto = proto;
|
||||
fl6->daddr = ireq->ir_v6_rmt_addr;
|
||||
final_p = fl6_update_dst(fl6, np->opt, &final);
|
||||
rcu_read_lock();
|
||||
final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
|
||||
rcu_read_unlock();
|
||||
fl6->saddr = ireq->ir_v6_loc_addr;
|
||||
fl6->flowi6_oif = ireq->ir_iif;
|
||||
fl6->flowi6_mark = ireq->ir_mark;
|
||||
@@ -108,14 +110,6 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);
|
||||
|
||||
static inline
|
||||
void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
|
||||
const struct in6_addr *daddr,
|
||||
const struct in6_addr *saddr)
|
||||
{
|
||||
__ip6_dst_store(sk, dst, daddr, saddr);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)
|
||||
{
|
||||
@@ -142,14 +136,16 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
|
||||
fl6->fl6_dport = inet->inet_dport;
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
|
||||
|
||||
final_p = fl6_update_dst(fl6, np->opt, &final);
|
||||
rcu_read_lock();
|
||||
final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
|
||||
rcu_read_unlock();
|
||||
|
||||
dst = __inet6_csk_dst_check(sk, np->dst_cookie);
|
||||
if (!dst) {
|
||||
dst = ip6_dst_lookup_flow(sk, fl6, final_p);
|
||||
|
||||
if (!IS_ERR(dst))
|
||||
__inet6_csk_dst_store(sk, dst, NULL, NULL);
|
||||
ip6_dst_store(sk, dst, NULL, NULL);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
@@ -175,7 +171,8 @@ int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused
|
||||
/* Restore final destination back after routing done */
|
||||
fl6.daddr = sk->sk_v6_daddr;
|
||||
|
||||
res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass);
|
||||
res = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt),
|
||||
np->tclass);
|
||||
rcu_read_unlock();
|
||||
return res;
|
||||
}
|
||||
|
@@ -24,7 +24,6 @@
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/mroute.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/inetdevice.h>
|
||||
|
@@ -177,7 +177,7 @@ void ip6_tnl_dst_reset(struct ip6_tnl *t)
|
||||
int i;
|
||||
|
||||
for_each_possible_cpu(i)
|
||||
ip6_tnl_per_cpu_dst_set(raw_cpu_ptr(t->dst_cache), NULL);
|
||||
ip6_tnl_per_cpu_dst_set(per_cpu_ptr(t->dst_cache, i), NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip6_tnl_dst_reset);
|
||||
|
||||
|
@@ -118,7 +118,7 @@ static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc,
|
||||
int cmd);
|
||||
static int ip6mr_rtm_dumproute(struct sk_buff *skb,
|
||||
struct netlink_callback *cb);
|
||||
static void mroute_clean_tables(struct mr6_table *mrt);
|
||||
static void mroute_clean_tables(struct mr6_table *mrt, bool all);
|
||||
static void ipmr_expire_process(unsigned long arg);
|
||||
|
||||
#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
|
||||
@@ -334,7 +334,7 @@ static struct mr6_table *ip6mr_new_table(struct net *net, u32 id)
|
||||
static void ip6mr_free_table(struct mr6_table *mrt)
|
||||
{
|
||||
del_timer_sync(&mrt->ipmr_expire_timer);
|
||||
mroute_clean_tables(mrt);
|
||||
mroute_clean_tables(mrt, true);
|
||||
kfree(mrt);
|
||||
}
|
||||
|
||||
@@ -765,10 +765,6 @@ static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt)
|
||||
return dev;
|
||||
|
||||
failure:
|
||||
/* allow the register to be completed before unregistering. */
|
||||
rtnl_unlock();
|
||||
rtnl_lock();
|
||||
|
||||
unregister_netdevice(dev);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1542,7 +1538,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
|
||||
* Close the multicast socket, and clear the vif tables etc
|
||||
*/
|
||||
|
||||
static void mroute_clean_tables(struct mr6_table *mrt)
|
||||
static void mroute_clean_tables(struct mr6_table *mrt, bool all)
|
||||
{
|
||||
int i;
|
||||
LIST_HEAD(list);
|
||||
@@ -1552,8 +1548,9 @@ static void mroute_clean_tables(struct mr6_table *mrt)
|
||||
* Shut down all active vif entries
|
||||
*/
|
||||
for (i = 0; i < mrt->maxvif; i++) {
|
||||
if (!(mrt->vif6_table[i].flags & VIFF_STATIC))
|
||||
mif6_delete(mrt, i, &list);
|
||||
if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC))
|
||||
continue;
|
||||
mif6_delete(mrt, i, &list);
|
||||
}
|
||||
unregister_netdevice_many(&list);
|
||||
|
||||
@@ -1562,7 +1559,7 @@ static void mroute_clean_tables(struct mr6_table *mrt)
|
||||
*/
|
||||
for (i = 0; i < MFC6_LINES; i++) {
|
||||
list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) {
|
||||
if (c->mfc_flags & MFC_STATIC)
|
||||
if (!all && (c->mfc_flags & MFC_STATIC))
|
||||
continue;
|
||||
write_lock_bh(&mrt_lock);
|
||||
list_del(&c->list);
|
||||
@@ -1625,7 +1622,7 @@ int ip6mr_sk_done(struct sock *sk)
|
||||
net->ipv6.devconf_all);
|
||||
write_unlock_bh(&mrt_lock);
|
||||
|
||||
mroute_clean_tables(mrt);
|
||||
mroute_clean_tables(mrt, false);
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
@@ -111,7 +111,8 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
|
||||
icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
|
||||
}
|
||||
}
|
||||
opt = xchg(&inet6_sk(sk)->opt, opt);
|
||||
opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt,
|
||||
opt);
|
||||
sk_dst_reset(sk);
|
||||
|
||||
return opt;
|
||||
@@ -231,9 +232,12 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
sk->sk_socket->ops = &inet_dgram_ops;
|
||||
sk->sk_family = PF_INET;
|
||||
}
|
||||
opt = xchg(&np->opt, NULL);
|
||||
if (opt)
|
||||
sock_kfree_s(sk, opt, opt->tot_len);
|
||||
opt = xchg((__force struct ipv6_txoptions **)&np->opt,
|
||||
NULL);
|
||||
if (opt) {
|
||||
atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
|
||||
txopt_put(opt);
|
||||
}
|
||||
pktopt = xchg(&np->pktoptions, NULL);
|
||||
kfree_skb(pktopt);
|
||||
|
||||
@@ -403,7 +407,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW))
|
||||
break;
|
||||
|
||||
opt = ipv6_renew_options(sk, np->opt, optname,
|
||||
opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
|
||||
opt = ipv6_renew_options(sk, opt, optname,
|
||||
(struct ipv6_opt_hdr __user *)optval,
|
||||
optlen);
|
||||
if (IS_ERR(opt)) {
|
||||
@@ -432,8 +437,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
retv = 0;
|
||||
opt = ipv6_update_options(sk, opt);
|
||||
sticky_done:
|
||||
if (opt)
|
||||
sock_kfree_s(sk, opt, opt->tot_len);
|
||||
if (opt) {
|
||||
atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
|
||||
txopt_put(opt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -486,6 +493,7 @@ sticky_done:
|
||||
break;
|
||||
|
||||
memset(opt, 0, sizeof(*opt));
|
||||
atomic_set(&opt->refcnt, 1);
|
||||
opt->tot_len = sizeof(*opt) + optlen;
|
||||
retv = -EFAULT;
|
||||
if (copy_from_user(opt+1, optval, optlen))
|
||||
@@ -502,8 +510,10 @@ update:
|
||||
retv = 0;
|
||||
opt = ipv6_update_options(sk, opt);
|
||||
done:
|
||||
if (opt)
|
||||
sock_kfree_s(sk, opt, opt->tot_len);
|
||||
if (opt) {
|
||||
atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
|
||||
txopt_put(opt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPV6_UNICAST_HOPS:
|
||||
@@ -1110,10 +1120,11 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
case IPV6_RTHDR:
|
||||
case IPV6_DSTOPTS:
|
||||
{
|
||||
struct ipv6_txoptions *opt;
|
||||
|
||||
lock_sock(sk);
|
||||
len = ipv6_getsockopt_sticky(sk, np->opt,
|
||||
optname, optval, len);
|
||||
opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
|
||||
len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len);
|
||||
release_sock(sk);
|
||||
/* check if ipv6_getsockopt_sticky() returns err code */
|
||||
if (len < 0)
|
||||
|
@@ -556,8 +556,7 @@ static void ndisc_send_unsol_na(struct net_device *dev)
|
||||
}
|
||||
|
||||
void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
|
||||
const struct in6_addr *daddr, const struct in6_addr *saddr,
|
||||
struct sk_buff *oskb)
|
||||
const struct in6_addr *daddr, const struct in6_addr *saddr)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct in6_addr addr_buf;
|
||||
@@ -593,9 +592,6 @@ void ndisc_send_ns(struct net_device *dev, const struct in6_addr *solicit,
|
||||
ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
|
||||
dev->dev_addr);
|
||||
|
||||
if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE) && oskb)
|
||||
skb_dst_copy(skb, oskb);
|
||||
|
||||
ndisc_send_skb(skb, daddr, saddr);
|
||||
}
|
||||
|
||||
@@ -682,12 +678,12 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
|
||||
"%s: trying to ucast probe in NUD_INVALID: %pI6\n",
|
||||
__func__, target);
|
||||
}
|
||||
ndisc_send_ns(dev, target, target, saddr, skb);
|
||||
ndisc_send_ns(dev, target, target, saddr);
|
||||
} else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) {
|
||||
neigh_app_ns(neigh);
|
||||
} else {
|
||||
addrconf_addr_solict_mult(target, &mcaddr);
|
||||
ndisc_send_ns(dev, target, &mcaddr, saddr, skb);
|
||||
ndisc_send_ns(dev, target, &mcaddr, saddr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -183,7 +183,7 @@ static void nf_ct_frag6_expire(unsigned long data)
|
||||
/* Creation primitives. */
|
||||
static inline struct frag_queue *fq_find(struct net *net, __be32 id,
|
||||
u32 user, struct in6_addr *src,
|
||||
struct in6_addr *dst, u8 ecn)
|
||||
struct in6_addr *dst, int iif, u8 ecn)
|
||||
{
|
||||
struct inet_frag_queue *q;
|
||||
struct ip6_create_arg arg;
|
||||
@@ -193,6 +193,7 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id,
|
||||
arg.user = user;
|
||||
arg.src = src;
|
||||
arg.dst = dst;
|
||||
arg.iif = iif;
|
||||
arg.ecn = ecn;
|
||||
|
||||
local_bh_disable();
|
||||
@@ -589,9 +590,11 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
|
||||
fhdr = (struct frag_hdr *)skb_transport_header(skb);
|
||||
|
||||
fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr,
|
||||
ip6_frag_ecn(hdr));
|
||||
if (fq == NULL)
|
||||
skb->dev ? skb->dev->ifindex : 0, ip6_frag_ecn(hdr));
|
||||
if (fq == NULL) {
|
||||
pr_debug("Can't find and can't create new queue\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_bh(&fq->q.lock);
|
||||
|
||||
|
@@ -733,6 +733,7 @@ static int raw6_getfrag(void *from, char *to, int offset, int len, int odd,
|
||||
|
||||
static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
{
|
||||
struct ipv6_txoptions *opt_to_free = NULL;
|
||||
struct ipv6_txoptions opt_space;
|
||||
DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
|
||||
struct in6_addr *daddr, *final_p, final;
|
||||
@@ -839,8 +840,10 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
if (!(opt->opt_nflen|opt->opt_flen))
|
||||
opt = NULL;
|
||||
}
|
||||
if (!opt)
|
||||
opt = np->opt;
|
||||
if (!opt) {
|
||||
opt = txopt_get(np);
|
||||
opt_to_free = opt;
|
||||
}
|
||||
if (flowlabel)
|
||||
opt = fl6_merge_options(&opt_space, flowlabel, opt);
|
||||
opt = ipv6_fixup_options(&opt_space, opt);
|
||||
@@ -906,6 +909,7 @@ done:
|
||||
dst_release(dst);
|
||||
out:
|
||||
fl6_sock_release(flowlabel);
|
||||
txopt_put(opt_to_free);
|
||||
return err < 0 ? err : len;
|
||||
do_confirm:
|
||||
dst_confirm(dst);
|
||||
|
@@ -108,7 +108,10 @@ bool ip6_frag_match(const struct inet_frag_queue *q, const void *a)
|
||||
return fq->id == arg->id &&
|
||||
fq->user == arg->user &&
|
||||
ipv6_addr_equal(&fq->saddr, arg->src) &&
|
||||
ipv6_addr_equal(&fq->daddr, arg->dst);
|
||||
ipv6_addr_equal(&fq->daddr, arg->dst) &&
|
||||
(arg->iif == fq->iif ||
|
||||
!(ipv6_addr_type(arg->dst) & (IPV6_ADDR_MULTICAST |
|
||||
IPV6_ADDR_LINKLOCAL)));
|
||||
}
|
||||
EXPORT_SYMBOL(ip6_frag_match);
|
||||
|
||||
@@ -180,7 +183,7 @@ static void ip6_frag_expire(unsigned long data)
|
||||
|
||||
static struct frag_queue *
|
||||
fq_find(struct net *net, __be32 id, const struct in6_addr *src,
|
||||
const struct in6_addr *dst, u8 ecn)
|
||||
const struct in6_addr *dst, int iif, u8 ecn)
|
||||
{
|
||||
struct inet_frag_queue *q;
|
||||
struct ip6_create_arg arg;
|
||||
@@ -190,6 +193,7 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src,
|
||||
arg.user = IP6_DEFRAG_LOCAL_DELIVER;
|
||||
arg.src = src;
|
||||
arg.dst = dst;
|
||||
arg.iif = iif;
|
||||
arg.ecn = ecn;
|
||||
|
||||
hash = inet6_hash_frag(id, src, dst);
|
||||
@@ -551,7 +555,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr,
|
||||
ip6_frag_ecn(hdr));
|
||||
skb->dev ? skb->dev->ifindex : 0, ip6_frag_ecn(hdr));
|
||||
if (fq) {
|
||||
int ret;
|
||||
|
||||
|
@@ -524,7 +524,7 @@ static void rt6_probe_deferred(struct work_struct *w)
|
||||
container_of(w, struct __rt6_probe_work, work);
|
||||
|
||||
addrconf_addr_solict_mult(&work->target, &mcaddr);
|
||||
ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL, NULL);
|
||||
ndisc_send_ns(work->dev, &work->target, &mcaddr, NULL);
|
||||
dev_put(work->dev);
|
||||
kfree(work);
|
||||
}
|
||||
|
@@ -222,7 +222,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
|
||||
memset(&fl6, 0, sizeof(fl6));
|
||||
fl6.flowi6_proto = IPPROTO_TCP;
|
||||
fl6.daddr = ireq->ir_v6_rmt_addr;
|
||||
final_p = fl6_update_dst(&fl6, np->opt, &final);
|
||||
final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final);
|
||||
fl6.saddr = ireq->ir_v6_loc_addr;
|
||||
fl6.flowi6_oif = sk->sk_bound_dev_if;
|
||||
fl6.flowi6_mark = ireq->ir_mark;
|
||||
|
@@ -120,6 +120,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct in6_addr *saddr = NULL, *final_p, final;
|
||||
struct ipv6_txoptions *opt;
|
||||
struct flowi6 fl6;
|
||||
struct dst_entry *dst;
|
||||
int addr_type;
|
||||
@@ -235,7 +236,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
||||
fl6.fl6_dport = usin->sin6_port;
|
||||
fl6.fl6_sport = inet->inet_sport;
|
||||
|
||||
final_p = fl6_update_dst(&fl6, np->opt, &final);
|
||||
opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
|
||||
final_p = fl6_update_dst(&fl6, opt, &final);
|
||||
|
||||
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
|
||||
|
||||
@@ -255,7 +257,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
||||
inet->inet_rcv_saddr = LOOPBACK4_IPV6;
|
||||
|
||||
sk->sk_gso_type = SKB_GSO_TCPV6;
|
||||
__ip6_dst_store(sk, dst, NULL, NULL);
|
||||
ip6_dst_store(sk, dst, NULL, NULL);
|
||||
|
||||
if (tcp_death_row.sysctl_tw_recycle &&
|
||||
!tp->rx_opt.ts_recent_stamp &&
|
||||
@@ -263,9 +265,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
||||
tcp_fetch_timewait_stamp(sk, dst);
|
||||
|
||||
icsk->icsk_ext_hdr_len = 0;
|
||||
if (np->opt)
|
||||
icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
|
||||
np->opt->opt_nflen);
|
||||
if (opt)
|
||||
icsk->icsk_ext_hdr_len = opt->opt_flen +
|
||||
opt->opt_nflen;
|
||||
|
||||
tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
|
||||
|
||||
@@ -461,7 +463,8 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
|
||||
if (np->repflow && ireq->pktopts)
|
||||
fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
|
||||
|
||||
err = ip6_xmit(sk, skb, fl6, np->opt, np->tclass);
|
||||
err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
|
||||
np->tclass);
|
||||
err = net_xmit_eval(err);
|
||||
}
|
||||
|
||||
@@ -972,6 +975,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
||||
struct inet_request_sock *ireq;
|
||||
struct ipv6_pinfo *newnp;
|
||||
const struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct ipv6_txoptions *opt;
|
||||
struct tcp6_sock *newtcp6sk;
|
||||
struct inet_sock *newinet;
|
||||
struct tcp_sock *newtp;
|
||||
@@ -1056,7 +1060,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
||||
*/
|
||||
|
||||
newsk->sk_gso_type = SKB_GSO_TCPV6;
|
||||
__ip6_dst_store(newsk, dst, NULL, NULL);
|
||||
ip6_dst_store(newsk, dst, NULL, NULL);
|
||||
inet6_sk_rx_dst_set(newsk, skb);
|
||||
|
||||
newtcp6sk = (struct tcp6_sock *)newsk;
|
||||
@@ -1098,13 +1102,15 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
||||
but we make one more one thing there: reattach optmem
|
||||
to newsk.
|
||||
*/
|
||||
if (np->opt)
|
||||
newnp->opt = ipv6_dup_options(newsk, np->opt);
|
||||
|
||||
opt = rcu_dereference(np->opt);
|
||||
if (opt) {
|
||||
opt = ipv6_dup_options(newsk, opt);
|
||||
RCU_INIT_POINTER(newnp->opt, opt);
|
||||
}
|
||||
inet_csk(newsk)->icsk_ext_hdr_len = 0;
|
||||
if (newnp->opt)
|
||||
inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
|
||||
newnp->opt->opt_flen);
|
||||
if (opt)
|
||||
inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen +
|
||||
opt->opt_flen;
|
||||
|
||||
tcp_ca_openreq_child(newsk, dst);
|
||||
|
||||
@@ -1130,7 +1136,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
||||
*/
|
||||
tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr,
|
||||
AF_INET6, key->key, key->keylen,
|
||||
sk_gfp_atomic(sk, GFP_ATOMIC));
|
||||
sk_gfp_mask(sk, GFP_ATOMIC));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1146,7 +1152,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
|
||||
/* Clone pktoptions received with SYN, if we own the req */
|
||||
if (ireq->pktopts) {
|
||||
newnp->pktoptions = skb_clone(ireq->pktopts,
|
||||
sk_gfp_atomic(sk, GFP_ATOMIC));
|
||||
sk_gfp_mask(sk, GFP_ATOMIC));
|
||||
consume_skb(ireq->pktopts);
|
||||
ireq->pktopts = NULL;
|
||||
if (newnp->pktoptions)
|
||||
@@ -1212,7 +1218,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
--ANK (980728)
|
||||
*/
|
||||
if (np->rxopt.all)
|
||||
opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC));
|
||||
opt_skb = skb_clone(skb, sk_gfp_mask(sk, GFP_ATOMIC));
|
||||
|
||||
if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
|
||||
struct dst_entry *dst = sk->sk_rx_dst;
|
||||
|
@@ -1110,6 +1110,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
|
||||
struct in6_addr *daddr, *final_p, final;
|
||||
struct ipv6_txoptions *opt = NULL;
|
||||
struct ipv6_txoptions *opt_to_free = NULL;
|
||||
struct ip6_flowlabel *flowlabel = NULL;
|
||||
struct flowi6 fl6;
|
||||
struct dst_entry *dst;
|
||||
@@ -1263,8 +1264,10 @@ do_udp_sendmsg:
|
||||
opt = NULL;
|
||||
connected = 0;
|
||||
}
|
||||
if (!opt)
|
||||
opt = np->opt;
|
||||
if (!opt) {
|
||||
opt = txopt_get(np);
|
||||
opt_to_free = opt;
|
||||
}
|
||||
if (flowlabel)
|
||||
opt = fl6_merge_options(&opt_space, flowlabel, opt);
|
||||
opt = ipv6_fixup_options(&opt_space, opt);
|
||||
@@ -1373,6 +1376,7 @@ release_dst:
|
||||
out:
|
||||
dst_release(dst);
|
||||
fl6_sock_release(flowlabel);
|
||||
txopt_put(opt_to_free);
|
||||
if (!err)
|
||||
return len;
|
||||
/*
|
||||
|
Reference in New Issue
Block a user