diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/route.c | 28 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 18 | ||||
-rw-r--r-- | net/packet/af_packet.c | 6 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 7 | ||||
-rw-r--r-- | net/sched/sch_tbf.c | 1 |
6 files changed, 44 insertions, 18 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 0940729d2f9..4a62c47599b 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -129,11 +129,14 @@ static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const voi return neigh_create(&nd_tbl, daddr, dst->dev); } -static int rt6_bind_neighbour(struct rt6_info *rt) +static int rt6_bind_neighbour(struct rt6_info *rt, struct net_device *dev) { - struct neighbour *n = ip6_neigh_lookup(&rt->dst, &rt->rt6i_gateway); - if (IS_ERR(n)) - return PTR_ERR(n); + struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dev, &rt->rt6i_gateway); + if (!n) { + n = neigh_create(&nd_tbl, &rt->rt6i_gateway, dev); + if (IS_ERR(n)) + return PTR_ERR(n); + } dst_set_neighbour(&rt->dst, n); return 0; @@ -746,7 +749,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, #endif retry: - if (rt6_bind_neighbour(rt)) { + if (rt6_bind_neighbour(rt, rt->dst.dev)) { struct net *net = dev_net(rt->dst.dev); int saved_rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval; @@ -1397,7 +1400,7 @@ int ip6_route_add(struct fib6_config *cfg) rt->rt6i_prefsrc.plen = 0; if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { - err = rt6_bind_neighbour(rt); + err = rt6_bind_neighbour(rt, dev); if (err) goto out; } @@ -2084,7 +2087,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, rt->rt6i_flags |= RTF_ANYCAST; else rt->rt6i_flags |= RTF_LOCAL; - err = rt6_bind_neighbour(rt); + err = rt6_bind_neighbour(rt, rt->dst.dev); if (err) { dst_free(&rt->dst); return ERR_PTR(err); @@ -2360,11 +2363,13 @@ static int rt6_fill_node(struct net *net, int iif, int type, u32 pid, u32 seq, int prefix, int nowait, unsigned int flags) { + const struct inet_peer *peer; struct rtmsg *rtm; struct nlmsghdr *nlh; long expires; u32 table; struct neighbour *n; + u32 ts, tsage; if (prefix) { /* user wants prefix routes only */ if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { @@ -2471,7 +2476,14 @@ static int rt6_fill_node(struct net *net, else expires = INT_MAX; - if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, + peer = rt->rt6i_peer; + ts = tsage = 0; + if (peer && peer->tcp_ts_stamp) { + ts = peer->tcp_ts; + tsage = get_seconds() - peer->tcp_ts_stamp; + } + + if (rtnl_put_cacheinfo(skb, &rt->dst, 0, ts, tsage, expires, rt->dst.error) < 0) goto nla_put_failure; diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index f6275a0f1ea..f8ac4ef0b79 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -908,7 +908,7 @@ config NETFILTER_XT_MATCH_MULTIPORT config NETFILTER_XT_MATCH_NFACCT tristate '"nfacct" match support' - default m if NETFILTER_ADVANCED=n + depends on NETFILTER_ADVANCED select NETFILTER_NETLINK_ACCT help This option allows you to use the extended accounting through diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 85033344aed..bb10c077a01 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1367,12 +1367,15 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, nf_ct_protonum(ct)); if (helper == NULL) { rcu_read_unlock(); + spin_unlock_bh(&nf_conntrack_lock); #ifdef CONFIG_MODULES if (request_module("nfct-helper-%s", helpname) < 0) { + spin_lock_bh(&nf_conntrack_lock); err = -EOPNOTSUPP; goto err1; } + spin_lock_bh(&nf_conntrack_lock); rcu_read_lock(); helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), @@ -1880,25 +1883,30 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, err = -ENOMEM; skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (skb2 == NULL) + if (skb2 == NULL) { + nf_ct_expect_put(exp); goto out; + } rcu_read_lock(); err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp); rcu_read_unlock(); + nf_ct_expect_put(exp); if (err <= 0) goto free; - nf_ct_expect_put(exp); + err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); + if (err < 0) + goto out; - return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); + return 0; free: kfree_skb(skb2); out: - nf_ct_expect_put(exp); - return err; + /* this avoids a loop in nfnetlink. */ + return err == -EAGAIN ? -ENOBUFS : err; } static int diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e56ca75e3f4..2dbb32b988c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2453,8 +2453,12 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc { struct packet_sock *po = pkt_sk(sk); - if (po->fanout) + if (po->fanout) { + if (dev) + dev_put(dev); + return -EINVAL; + } lock_sock(sk); diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index ffcaa597594..a92c1b3dab8 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -532,7 +532,7 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) return -EINVAL; s = sizeof(struct disttable) + n * sizeof(s16); - d = kmalloc(s, GFP_KERNEL); + d = kmalloc(s, GFP_KERNEL | __GFP_NOWARN); if (!d) d = vmalloc(s); if (!d) @@ -545,9 +545,10 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) root_lock = qdisc_root_sleeping_lock(sch); spin_lock_bh(root_lock); - dist_free(q->delay_dist); - q->delay_dist = d; + swap(q->delay_dist, d); spin_unlock_bh(root_lock); + + dist_free(d); return 0; } diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 1dcfb5223a8..b8e156319d7 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -346,6 +346,7 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) struct nlattr *nest; struct tc_tbf_qopt opt; + sch->qstats.backlog = q->qdisc->qstats.backlog; nest = nla_nest_start(skb, TCA_OPTIONS); if (nest == NULL) goto nla_put_failure; |