You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: net/mac80211/main.c
This commit is contained in:
@@ -112,8 +112,8 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
|
||||
if (sk) {
|
||||
sock_hold(sk);
|
||||
ax25_destroy_socket(ax25);
|
||||
sock_put(sk);
|
||||
bh_unlock_sock(sk);
|
||||
sock_put(sk);
|
||||
} else
|
||||
ax25_destroy_socket(ax25);
|
||||
return;
|
||||
|
||||
@@ -162,8 +162,8 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
|
||||
if (tmp) {
|
||||
memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info));
|
||||
atomic_set(&tmp->use, 1);
|
||||
nf_bridge_put(nf_bridge);
|
||||
}
|
||||
nf_bridge_put(nf_bridge);
|
||||
nf_bridge = tmp;
|
||||
}
|
||||
return nf_bridge;
|
||||
@@ -761,9 +761,11 @@ static int br_nf_dev_queue_xmit(struct sk_buff *skb)
|
||||
{
|
||||
if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) &&
|
||||
skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu &&
|
||||
!skb_is_gso(skb))
|
||||
!skb_is_gso(skb)) {
|
||||
/* BUG: Should really parse the IP options here. */
|
||||
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
|
||||
return ip_fragment(skb, br_dev_queue_push_xmit);
|
||||
else
|
||||
} else
|
||||
return br_dev_queue_push_xmit(skb);
|
||||
}
|
||||
#else
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/unaligned/le_byteshift.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <net/caif/caif_layer.h>
|
||||
#include <net/caif/cfsrvl.h>
|
||||
#include <net/caif/cfpkt.h>
|
||||
|
||||
+8
-8
@@ -2056,16 +2056,16 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int queue_index;
|
||||
struct sock *sk = skb->sk;
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
queue_index = sk_tx_queue_get(sk);
|
||||
if (queue_index < 0) {
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
if (ops->ndo_select_queue) {
|
||||
queue_index = ops->ndo_select_queue(dev, skb);
|
||||
queue_index = dev_cap_txqueue(dev, queue_index);
|
||||
} else {
|
||||
struct sock *sk = skb->sk;
|
||||
queue_index = sk_tx_queue_get(sk);
|
||||
if (queue_index < 0) {
|
||||
|
||||
if (ops->ndo_select_queue) {
|
||||
queue_index = ops->ndo_select_queue(dev, skb);
|
||||
queue_index = dev_cap_txqueue(dev, queue_index);
|
||||
} else {
|
||||
queue_index = 0;
|
||||
if (dev->real_num_tx_queues > 1)
|
||||
queue_index = skb_tx_hash(dev, skb);
|
||||
|
||||
@@ -232,7 +232,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
|
||||
est->last_packets = bstats->packets;
|
||||
est->avpps = rate_est->pps<<10;
|
||||
|
||||
spin_lock(&est_tree_lock);
|
||||
spin_lock_bh(&est_tree_lock);
|
||||
if (!elist[idx].timer.function) {
|
||||
INIT_LIST_HEAD(&elist[idx].list);
|
||||
setup_timer(&elist[idx].timer, est_timer, idx);
|
||||
@@ -243,7 +243,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
|
||||
|
||||
list_add_rcu(&est->list, &elist[idx].list);
|
||||
gen_add_node(est);
|
||||
spin_unlock(&est_tree_lock);
|
||||
spin_unlock_bh(&est_tree_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -270,7 +270,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
|
||||
{
|
||||
struct gen_estimator *e;
|
||||
|
||||
spin_lock(&est_tree_lock);
|
||||
spin_lock_bh(&est_tree_lock);
|
||||
while ((e = gen_find_node(bstats, rate_est))) {
|
||||
rb_erase(&e->node, &est_root);
|
||||
|
||||
@@ -281,7 +281,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
|
||||
list_del_rcu(&e->list);
|
||||
call_rcu(&e->e_rcu, __gen_kill_estimator);
|
||||
}
|
||||
spin_unlock(&est_tree_lock);
|
||||
spin_unlock_bh(&est_tree_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(gen_kill_estimator);
|
||||
|
||||
@@ -320,9 +320,9 @@ bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
spin_lock(&est_tree_lock);
|
||||
spin_lock_bh(&est_tree_lock);
|
||||
res = gen_find_node(bstats, rate_est) != NULL;
|
||||
spin_unlock(&est_tree_lock);
|
||||
spin_unlock_bh(&est_tree_lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
+5
-1
@@ -2569,6 +2569,10 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
|
||||
__copy_skb_header(nskb, skb);
|
||||
nskb->mac_len = skb->mac_len;
|
||||
|
||||
/* nskb and skb might have different headroom */
|
||||
if (nskb->ip_summed == CHECKSUM_PARTIAL)
|
||||
nskb->csum_start += skb_headroom(nskb) - headroom;
|
||||
|
||||
skb_reset_mac_header(nskb);
|
||||
skb_set_network_header(nskb, skb->mac_len);
|
||||
nskb->transport_header = (nskb->network_header +
|
||||
@@ -2699,7 +2703,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
|
||||
return -E2BIG;
|
||||
|
||||
headroom = skb_headroom(p);
|
||||
nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p));
|
||||
nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC);
|
||||
if (unlikely(!nskb))
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ config IP_ADVANCED_ROUTER
|
||||
rp_filter on use:
|
||||
|
||||
echo 1 > /proc/sys/net/ipv4/conf/<device>/rp_filter
|
||||
and
|
||||
or
|
||||
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
|
||||
|
||||
Note that some distributions enable it in startup scripts.
|
||||
|
||||
+4
-1
@@ -62,8 +62,11 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
}
|
||||
if (!inet->inet_saddr)
|
||||
inet->inet_saddr = rt->rt_src; /* Update source address */
|
||||
if (!inet->inet_rcv_saddr)
|
||||
if (!inet->inet_rcv_saddr) {
|
||||
inet->inet_rcv_saddr = rt->rt_src;
|
||||
if (sk->sk_prot->rehash)
|
||||
sk->sk_prot->rehash(sk);
|
||||
}
|
||||
inet->inet_daddr = rt->rt_dst;
|
||||
inet->inet_dport = usin->sin_port;
|
||||
sk->sk_state = TCP_ESTABLISHED;
|
||||
|
||||
+13
-2
@@ -246,6 +246,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
|
||||
|
||||
struct fib_result res;
|
||||
int no_addr, rpf, accept_local;
|
||||
bool dev_match;
|
||||
int ret;
|
||||
struct net *net;
|
||||
|
||||
@@ -273,12 +274,22 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
|
||||
}
|
||||
*spec_dst = FIB_RES_PREFSRC(res);
|
||||
fib_combine_itag(itag, &res);
|
||||
dev_match = false;
|
||||
|
||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||
if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
|
||||
for (ret = 0; ret < res.fi->fib_nhs; ret++) {
|
||||
struct fib_nh *nh = &res.fi->fib_nh[ret];
|
||||
|
||||
if (nh->nh_dev == dev) {
|
||||
dev_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (FIB_RES_DEV(res) == dev)
|
||||
dev_match = true;
|
||||
#endif
|
||||
{
|
||||
if (dev_match) {
|
||||
ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
|
||||
fib_res_put(&res);
|
||||
return ret;
|
||||
|
||||
+6
-2
@@ -186,7 +186,9 @@ static inline struct tnode *node_parent_rcu(struct node *node)
|
||||
{
|
||||
struct tnode *ret = node_parent(node);
|
||||
|
||||
return rcu_dereference(ret);
|
||||
return rcu_dereference_check(ret,
|
||||
rcu_read_lock_held() ||
|
||||
lockdep_rtnl_is_held());
|
||||
}
|
||||
|
||||
/* Same as rcu_assign_pointer
|
||||
@@ -1753,7 +1755,9 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
|
||||
|
||||
static struct leaf *trie_firstleaf(struct trie *t)
|
||||
{
|
||||
struct tnode *n = (struct tnode *) rcu_dereference(t->trie);
|
||||
struct tnode *n = (struct tnode *) rcu_dereference_check(t->trie,
|
||||
rcu_read_lock_held() ||
|
||||
lockdep_rtnl_is_held());
|
||||
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
@@ -1420,6 +1420,9 @@ static int translate_compat_table(const char *name,
|
||||
if (ret != 0)
|
||||
break;
|
||||
++i;
|
||||
if (strcmp(arpt_get_target(iter1)->u.user.name,
|
||||
XT_ERROR_TARGET) == 0)
|
||||
++newinfo->stacksize;
|
||||
}
|
||||
if (ret) {
|
||||
/*
|
||||
|
||||
@@ -1751,6 +1751,9 @@ translate_compat_table(struct net *net,
|
||||
if (ret != 0)
|
||||
break;
|
||||
++i;
|
||||
if (strcmp(ipt_get_target(iter1)->u.user.name,
|
||||
XT_ERROR_TARGET) == 0)
|
||||
++newinfo->stacksize;
|
||||
}
|
||||
if (ret) {
|
||||
/*
|
||||
|
||||
+6
-1
@@ -2731,6 +2731,11 @@ slow_output:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__ip_route_output_key);
|
||||
|
||||
static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
|
||||
{
|
||||
}
|
||||
@@ -2739,7 +2744,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
|
||||
.family = AF_INET,
|
||||
.protocol = cpu_to_be16(ETH_P_IP),
|
||||
.destroy = ipv4_dst_destroy,
|
||||
.check = ipv4_dst_check,
|
||||
.check = ipv4_blackhole_dst_check,
|
||||
.update_pmtu = ipv4_rt_blackhole_update_pmtu,
|
||||
.entries = ATOMIC_INIT(0),
|
||||
};
|
||||
|
||||
+10
-22
@@ -451,7 +451,8 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
|
||||
if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
|
||||
mask |= POLLOUT | POLLWRNORM;
|
||||
}
|
||||
}
|
||||
} else
|
||||
mask |= POLLOUT | POLLWRNORM;
|
||||
|
||||
if (tp->urg_data & TCP_URG_VALID)
|
||||
mask |= POLLPRI;
|
||||
@@ -2011,11 +2012,8 @@ adjudge_to_death:
|
||||
}
|
||||
}
|
||||
if (sk->sk_state != TCP_CLOSE) {
|
||||
int orphan_count = percpu_counter_read_positive(
|
||||
sk->sk_prot->orphan_count);
|
||||
|
||||
sk_mem_reclaim(sk);
|
||||
if (tcp_too_many_orphans(sk, orphan_count)) {
|
||||
if (tcp_too_many_orphans(sk, 0)) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_INFO "TCP: too many of orphaned "
|
||||
"sockets\n");
|
||||
@@ -3221,7 +3219,7 @@ void __init tcp_init(void)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
unsigned long nr_pages, limit;
|
||||
int order, i, max_share;
|
||||
int i, max_share, cnt;
|
||||
unsigned long jiffy = jiffies;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
|
||||
@@ -3270,22 +3268,12 @@ void __init tcp_init(void)
|
||||
INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
|
||||
}
|
||||
|
||||
/* Try to be a bit smarter and adjust defaults depending
|
||||
* on available memory.
|
||||
*/
|
||||
for (order = 0; ((1 << order) << PAGE_SHIFT) <
|
||||
(tcp_hashinfo.bhash_size * sizeof(struct inet_bind_hashbucket));
|
||||
order++)
|
||||
;
|
||||
if (order >= 4) {
|
||||
tcp_death_row.sysctl_max_tw_buckets = 180000;
|
||||
sysctl_tcp_max_orphans = 4096 << (order - 4);
|
||||
sysctl_max_syn_backlog = 1024;
|
||||
} else if (order < 3) {
|
||||
tcp_death_row.sysctl_max_tw_buckets >>= (3 - order);
|
||||
sysctl_tcp_max_orphans >>= (3 - order);
|
||||
sysctl_max_syn_backlog = 128;
|
||||
}
|
||||
|
||||
cnt = tcp_hashinfo.ehash_mask + 1;
|
||||
|
||||
tcp_death_row.sysctl_max_tw_buckets = cnt / 2;
|
||||
sysctl_tcp_max_orphans = cnt / 2;
|
||||
sysctl_max_syn_backlog = max(128, cnt / 256);
|
||||
|
||||
/* Set the pressure threshold to be a fraction of global memory that
|
||||
* is up to 1/2 at 256 MB, decreasing toward zero with the amount of
|
||||
|
||||
+3
-2
@@ -196,10 +196,10 @@ void tcp_get_allowed_congestion_control(char *buf, size_t maxlen)
|
||||
int tcp_set_allowed_congestion_control(char *val)
|
||||
{
|
||||
struct tcp_congestion_ops *ca;
|
||||
char *clone, *name;
|
||||
char *saved_clone, *clone, *name;
|
||||
int ret = 0;
|
||||
|
||||
clone = kstrdup(val, GFP_USER);
|
||||
saved_clone = clone = kstrdup(val, GFP_USER);
|
||||
if (!clone)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -226,6 +226,7 @@ int tcp_set_allowed_congestion_control(char *val)
|
||||
}
|
||||
out:
|
||||
spin_unlock(&tcp_cong_list_lock);
|
||||
kfree(saved_clone);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -66,18 +66,18 @@ static void tcp_write_err(struct sock *sk)
|
||||
static int tcp_out_of_resources(struct sock *sk, int do_reset)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
int orphans = percpu_counter_read_positive(&tcp_orphan_count);
|
||||
int shift = 0;
|
||||
|
||||
/* If peer does not open window for long time, or did not transmit
|
||||
* anything for long time, penalize it. */
|
||||
if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)
|
||||
orphans <<= 1;
|
||||
shift++;
|
||||
|
||||
/* If some dubious ICMP arrived, penalize even more. */
|
||||
if (sk->sk_err_soft)
|
||||
orphans <<= 1;
|
||||
shift++;
|
||||
|
||||
if (tcp_too_many_orphans(sk, orphans)) {
|
||||
if (tcp_too_many_orphans(sk, shift)) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_INFO "Out of socket memory\n");
|
||||
|
||||
|
||||
@@ -1260,6 +1260,49 @@ void udp_lib_unhash(struct sock *sk)
|
||||
}
|
||||
EXPORT_SYMBOL(udp_lib_unhash);
|
||||
|
||||
/*
|
||||
* inet_rcv_saddr was changed, we must rehash secondary hash
|
||||
*/
|
||||
void udp_lib_rehash(struct sock *sk, u16 newhash)
|
||||
{
|
||||
if (sk_hashed(sk)) {
|
||||
struct udp_table *udptable = sk->sk_prot->h.udp_table;
|
||||
struct udp_hslot *hslot, *hslot2, *nhslot2;
|
||||
|
||||
hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
|
||||
nhslot2 = udp_hashslot2(udptable, newhash);
|
||||
udp_sk(sk)->udp_portaddr_hash = newhash;
|
||||
if (hslot2 != nhslot2) {
|
||||
hslot = udp_hashslot(udptable, sock_net(sk),
|
||||
udp_sk(sk)->udp_port_hash);
|
||||
/* we must lock primary chain too */
|
||||
spin_lock_bh(&hslot->lock);
|
||||
|
||||
spin_lock(&hslot2->lock);
|
||||
hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node);
|
||||
hslot2->count--;
|
||||
spin_unlock(&hslot2->lock);
|
||||
|
||||
spin_lock(&nhslot2->lock);
|
||||
hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node,
|
||||
&nhslot2->head);
|
||||
nhslot2->count++;
|
||||
spin_unlock(&nhslot2->lock);
|
||||
|
||||
spin_unlock_bh(&hslot->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(udp_lib_rehash);
|
||||
|
||||
static void udp_v4_rehash(struct sock *sk)
|
||||
{
|
||||
u16 new_hash = udp4_portaddr_hash(sock_net(sk),
|
||||
inet_sk(sk)->inet_rcv_saddr,
|
||||
inet_sk(sk)->inet_num);
|
||||
udp_lib_rehash(sk, new_hash);
|
||||
}
|
||||
|
||||
static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
int rc;
|
||||
@@ -1843,6 +1886,7 @@ struct proto udp_prot = {
|
||||
.backlog_rcv = __udp_queue_rcv_skb,
|
||||
.hash = udp_lib_hash,
|
||||
.unhash = udp_lib_unhash,
|
||||
.rehash = udp_v4_rehash,
|
||||
.get_port = udp_v4_get_port,
|
||||
.memory_allocated = &udp_memory_allocated,
|
||||
.sysctl_mem = sysctl_udp_mem,
|
||||
|
||||
+6
-1
@@ -105,9 +105,12 @@ ipv4_connected:
|
||||
if (ipv6_addr_any(&np->saddr))
|
||||
ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
|
||||
|
||||
if (ipv6_addr_any(&np->rcv_saddr))
|
||||
if (ipv6_addr_any(&np->rcv_saddr)) {
|
||||
ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
|
||||
&np->rcv_saddr);
|
||||
if (sk->sk_prot->rehash)
|
||||
sk->sk_prot->rehash(sk);
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
@@ -181,6 +184,8 @@ ipv4_connected:
|
||||
if (ipv6_addr_any(&np->rcv_saddr)) {
|
||||
ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
|
||||
inet->inet_rcv_saddr = LOOPBACK4_IPV6;
|
||||
if (sk->sk_prot->rehash)
|
||||
sk->sk_prot->rehash(sk);
|
||||
}
|
||||
|
||||
ip6_dst_store(sk, dst,
|
||||
|
||||
@@ -1766,6 +1766,9 @@ translate_compat_table(struct net *net,
|
||||
if (ret != 0)
|
||||
break;
|
||||
++i;
|
||||
if (strcmp(ip6t_get_target(iter1)->u.user.name,
|
||||
XT_ERROR_TARGET) == 0)
|
||||
++newinfo->stacksize;
|
||||
}
|
||||
if (ret) {
|
||||
/*
|
||||
|
||||
@@ -113,14 +113,6 @@ static void nf_skb_free(struct sk_buff *skb)
|
||||
kfree_skb(NFCT_FRAG6_CB(skb)->orig);
|
||||
}
|
||||
|
||||
/* Memory Tracking Functions. */
|
||||
static void frag_kfree_skb(struct sk_buff *skb)
|
||||
{
|
||||
atomic_sub(skb->truesize, &nf_init_frags.mem);
|
||||
nf_skb_free(skb);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/* Destruction primitives. */
|
||||
|
||||
static __inline__ void fq_put(struct nf_ct_frag6_queue *fq)
|
||||
@@ -282,66 +274,22 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
found:
|
||||
/* We found where to put this one. Check for overlap with
|
||||
* preceding fragment, and, if needed, align things so that
|
||||
* any overlaps are eliminated.
|
||||
/* RFC5722, Section 4:
|
||||
* When reassembling an IPv6 datagram, if
|
||||
* one or more its constituent fragments is determined to be an
|
||||
* overlapping fragment, the entire datagram (and any constituent
|
||||
* fragments, including those not yet received) MUST be silently
|
||||
* discarded.
|
||||
*/
|
||||
if (prev) {
|
||||
int i = (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset;
|
||||
|
||||
if (i > 0) {
|
||||
offset += i;
|
||||
if (end <= offset) {
|
||||
pr_debug("overlap\n");
|
||||
goto err;
|
||||
}
|
||||
if (!pskb_pull(skb, i)) {
|
||||
pr_debug("Can't pull\n");
|
||||
goto err;
|
||||
}
|
||||
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
}
|
||||
}
|
||||
/* Check for overlap with preceding fragment. */
|
||||
if (prev &&
|
||||
(NFCT_FRAG6_CB(prev)->offset + prev->len) - offset > 0)
|
||||
goto discard_fq;
|
||||
|
||||
/* Look for overlap with succeeding segments.
|
||||
* If we can merge fragments, do it.
|
||||
*/
|
||||
while (next && NFCT_FRAG6_CB(next)->offset < end) {
|
||||
/* overlap is 'i' bytes */
|
||||
int i = end - NFCT_FRAG6_CB(next)->offset;
|
||||
|
||||
if (i < next->len) {
|
||||
/* Eat head of the next overlapped fragment
|
||||
* and leave the loop. The next ones cannot overlap.
|
||||
*/
|
||||
pr_debug("Eat head of the overlapped parts.: %d", i);
|
||||
if (!pskb_pull(next, i))
|
||||
goto err;
|
||||
|
||||
/* next fragment */
|
||||
NFCT_FRAG6_CB(next)->offset += i;
|
||||
fq->q.meat -= i;
|
||||
if (next->ip_summed != CHECKSUM_UNNECESSARY)
|
||||
next->ip_summed = CHECKSUM_NONE;
|
||||
break;
|
||||
} else {
|
||||
struct sk_buff *free_it = next;
|
||||
|
||||
/* Old fragmnet is completely overridden with
|
||||
* new one drop it.
|
||||
*/
|
||||
next = next->next;
|
||||
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
fq->q.fragments = next;
|
||||
|
||||
fq->q.meat -= free_it->len;
|
||||
frag_kfree_skb(free_it);
|
||||
}
|
||||
}
|
||||
/* Look for overlap with succeeding segment. */
|
||||
if (next && NFCT_FRAG6_CB(next)->offset < end)
|
||||
goto discard_fq;
|
||||
|
||||
NFCT_FRAG6_CB(skb)->offset = offset;
|
||||
|
||||
@@ -371,6 +319,8 @@ found:
|
||||
write_unlock(&nf_frags.lock);
|
||||
return 0;
|
||||
|
||||
discard_fq:
|
||||
fq_kill(fq);
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user