diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-04-18 05:39:23 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-04-18 05:39:23 -0400 |
commit | 9e73972cef1c0961c78b0e0b61c4ecc275b29f04 (patch) | |
tree | 27907bbd653504d71ff47cb00bdf8cd61e82f126 /net | |
parent | a890b15c0990cc8d686edcc85f5fccde71ad5ce9 (diff) | |
parent | 4741c336d27dec3ea68a35659abb8dc82b142388 (diff) |
Merge branch 'upstream'
Diffstat (limited to 'net')
-rw-r--r-- | net/atm/clip.c | 460 | ||||
-rw-r--r-- | net/bridge/br_input.c | 3 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 6 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 2 | ||||
-rw-r--r-- | net/ipv4/arp.c | 4 | ||||
-rw-r--r-- | net/ipv4/devinet.c | 1 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 1 | ||||
-rw-r--r-- | net/ipv4/inet_hashtables.c | 4 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 2 | ||||
-rw-r--r-- | net/ipv4/route.c | 5 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 3 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 18 | ||||
-rw-r--r-- | net/wanrouter/af_wanpipe.c | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 25 |
16 files changed, 260 insertions, 278 deletions
diff --git a/net/atm/clip.c b/net/atm/clip.c index 3ab4e7947ba..1a786bfaa41 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -2,7 +2,6 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ - #include <linux/config.h> #include <linux/string.h> #include <linux/errno.h> @@ -54,24 +53,24 @@ static struct net_device *clip_devs; static struct atm_vcc *atmarpd; static struct neigh_table clip_tbl; static struct timer_list idle_timer; -static int start_timer = 1; - -static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip) +static int to_atmarpd(enum atmarp_ctrl_type type, int itf, unsigned long ip) { struct sock *sk; struct atmarp_ctrl *ctrl; struct sk_buff *skb; - DPRINTK("to_atmarpd(%d)\n",type); - if (!atmarpd) return -EUNATCH; + DPRINTK("to_atmarpd(%d)\n", type); + if (!atmarpd) + return -EUNATCH; skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC); - if (!skb) return -ENOMEM; + if (!skb) + return -ENOMEM; ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl)); ctrl->type = type; ctrl->itf_num = itf; ctrl->ip = ip; - atm_force_charge(atmarpd,skb->truesize); + atm_force_charge(atmarpd, skb->truesize); sk = sk_atm(atmarpd); skb_queue_tail(&sk->sk_receive_queue, skb); @@ -79,26 +78,24 @@ static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip) return 0; } - -static void link_vcc(struct clip_vcc *clip_vcc,struct atmarp_entry *entry) +static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry) { - DPRINTK("link_vcc %p to entry %p (neigh %p)\n",clip_vcc,entry, - entry->neigh); + DPRINTK("link_vcc %p to entry %p (neigh %p)\n", clip_vcc, entry, + entry->neigh); clip_vcc->entry = entry; - clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */ + clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */ clip_vcc->next = entry->vccs; entry->vccs = clip_vcc; entry->neigh->used = jiffies; } - static void unlink_clip_vcc(struct clip_vcc *clip_vcc) { struct atmarp_entry *entry = clip_vcc->entry; struct clip_vcc **walk; if (!entry) { - printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc); + printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc); return; } spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block clip_start_xmit() */ @@ -107,24 +104,24 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc) if (*walk == clip_vcc) { int error; - *walk = clip_vcc->next; /* atomic */ + *walk = clip_vcc->next; /* atomic */ clip_vcc->entry = NULL; if (clip_vcc->xoff) netif_wake_queue(entry->neigh->dev); if (entry->vccs) goto out; - entry->expires = jiffies-1; - /* force resolution or expiration */ + entry->expires = jiffies - 1; + /* force resolution or expiration */ error = neigh_update(entry->neigh, NULL, NUD_NONE, NEIGH_UPDATE_F_ADMIN); if (error) printk(KERN_CRIT "unlink_clip_vcc: " - "neigh_update failed with %d\n",error); + "neigh_update failed with %d\n", error); goto out; } printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc " - "0x%p)\n",entry,clip_vcc); -out: + "0x%p)\n", entry, clip_vcc); + out: spin_unlock_bh(&entry->neigh->dev->xmit_lock); } @@ -153,13 +150,13 @@ static int neigh_check_cb(struct neighbour *n) DPRINTK("destruction postponed with ref %d\n", atomic_read(&n->refcnt)); - while ((skb = skb_dequeue(&n->arp_queue)) != NULL) + while ((skb = skb_dequeue(&n->arp_queue)) != NULL) dev_kfree_skb(skb); return 0; } - DPRINTK("expired neigh %p\n",n); + DPRINTK("expired neigh %p\n", n); return 1; } @@ -167,7 +164,7 @@ static void idle_timer_check(unsigned long dummy) { write_lock(&clip_tbl.lock); __neigh_for_each_release(&clip_tbl, neigh_check_cb); - mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ); + mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ); write_unlock(&clip_tbl.lock); } @@ -177,13 +174,13 @@ static int clip_arp_rcv(struct sk_buff *skb) DPRINTK("clip_arp_rcv\n"); vcc = ATM_SKB(skb)->vcc; - if (!vcc || !atm_charge(vcc,skb->truesize)) { + if (!vcc || !atm_charge(vcc, skb->truesize)) { dev_kfree_skb_any(skb); return 0; } - DPRINTK("pushing to %p\n",vcc); - DPRINTK("using %p\n",CLIP_VCC(vcc)->old_push); - CLIP_VCC(vcc)->old_push(vcc,skb); + DPRINTK("pushing to %p\n", vcc); + DPRINTK("using %p\n", CLIP_VCC(vcc)->old_push); + CLIP_VCC(vcc)->old_push(vcc, skb); return 0; } @@ -193,34 +190,38 @@ static const unsigned char llc_oui[] = { 0x03, /* Ctrl: Unnumbered Information Command PDU */ 0x00, /* OUI: EtherType */ 0x00, - 0x00 }; + 0x00 +}; -static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) +static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb) { struct clip_vcc *clip_vcc = CLIP_VCC(vcc); DPRINTK("clip push\n"); if (!skb) { - DPRINTK("removing VCC %p\n",clip_vcc); - if (clip_vcc->entry) unlink_clip_vcc(clip_vcc); - clip_vcc->old_push(vcc,NULL); /* pass on the bad news */ + DPRINTK("removing VCC %p\n", clip_vcc); + if (clip_vcc->entry) + unlink_clip_vcc(clip_vcc); + clip_vcc->old_push(vcc, NULL); /* pass on the bad news */ kfree(clip_vcc); return; } - atm_return(vcc,skb->truesize); + atm_return(vcc, skb->truesize); skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs; - /* clip_vcc->entry == NULL if we don't have an IP address yet */ + /* clip_vcc->entry == NULL if we don't have an IP address yet */ if (!skb->dev) { dev_kfree_skb_any(skb); return; } ATM_SKB(skb)->vcc = vcc; skb->mac.raw = skb->data; - if (!clip_vcc->encap || skb->len < RFC1483LLC_LEN || memcmp(skb->data, - llc_oui,sizeof(llc_oui))) skb->protocol = htons(ETH_P_IP); + if (!clip_vcc->encap + || skb->len < RFC1483LLC_LEN + || memcmp(skb->data, llc_oui, sizeof (llc_oui))) + skb->protocol = htons(ETH_P_IP); else { skb->protocol = ((u16 *) skb->data)[3]; - skb_pull(skb,RFC1483LLC_LEN); + skb_pull(skb, RFC1483LLC_LEN); if (skb->protocol == htons(ETH_P_ARP)) { PRIV(skb->dev)->stats.rx_packets++; PRIV(skb->dev)->stats.rx_bytes += skb->len; @@ -235,58 +236,54 @@ static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) netif_rx(skb); } - /* * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that * clip_pop is atomic with respect to the critical section in clip_start_xmit. */ - -static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb) +static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb) { struct clip_vcc *clip_vcc = CLIP_VCC(vcc); struct net_device *dev = skb->dev; int old; unsigned long flags; - DPRINTK("clip_pop(vcc %p)\n",vcc); - clip_vcc->old_pop(vcc,skb); + DPRINTK("clip_pop(vcc %p)\n", vcc); + clip_vcc->old_pop(vcc, skb); /* skb->dev == NULL in outbound ARP packets */ - if (!dev) return; - spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags); - if (atm_may_send(vcc,0)) { - old = xchg(&clip_vcc->xoff,0); - if (old) netif_wake_queue(dev); + if (!dev) + return; + spin_lock_irqsave(&PRIV(dev)->xoff_lock, flags); + if (atm_may_send(vcc, 0)) { + old = xchg(&clip_vcc->xoff, 0); + if (old) + netif_wake_queue(dev); } - spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags); + spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags); } - static void clip_neigh_destroy(struct neighbour *neigh) { - DPRINTK("clip_neigh_destroy (neigh %p)\n",neigh); + DPRINTK("clip_neigh_destroy (neigh %p)\n", neigh); if (NEIGH2ENTRY(neigh)->vccs) printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n"); NEIGH2ENTRY(neigh)->vccs = (void *) 0xdeadbeef; } - -static void clip_neigh_solicit(struct neighbour *neigh,struct sk_buff *skb) +static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb) { - DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n",neigh,skb); - to_atmarpd(act_need,PRIV(neigh->dev)->number,NEIGH2ENTRY(neigh)->ip); + DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb); + to_atmarpd(act_need, PRIV(neigh->dev)->number, NEIGH2ENTRY(neigh)->ip); } - -static void clip_neigh_error(struct neighbour *neigh,struct sk_buff *skb) +static void clip_neigh_error(struct neighbour *neigh, struct sk_buff *skb) { #ifndef CONFIG_ATM_CLIP_NO_ICMP - icmp_send(skb,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,0); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); #endif kfree_skb(skb); } - static struct neigh_ops clip_neigh_ops = { .family = AF_INET, .solicit = clip_neigh_solicit, @@ -297,7 +294,6 @@ static struct neigh_ops clip_neigh_ops = { .queue_xmit = dev_queue_xmit, }; - static int clip_constructor(struct neighbour *neigh) { struct atmarp_entry *entry = NEIGH2ENTRY(neigh); @@ -305,9 +301,10 @@ static int clip_constructor(struct neighbour *neigh) struct in_device *in_dev; struct neigh_parms *parms; - DPRINTK("clip_constructor (neigh %p, entry %p)\n",neigh,entry); + DPRINTK("clip_constructor (neigh %p, entry %p)\n", neigh, entry); neigh->type = inet_addr_type(entry->ip); - if (neigh->type != RTN_UNICAST) return -EINVAL; + if (neigh->type != RTN_UNICAST) + return -EINVAL; rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); @@ -326,13 +323,13 @@ static int clip_constructor(struct neighbour *neigh) neigh->ops->connected_output : neigh->ops->output; entry->neigh = neigh; entry->vccs = NULL; - entry->expires = jiffies-1; + entry->expires = jiffies - 1; return 0; } static u32 clip_hash(const void *pkey, const struct net_device *dev) { - return jhash_2words(*(u32 *)pkey, dev->ifindex, clip_tbl.hash_rnd); + return jhash_2words(*(u32 *) pkey, dev->ifindex, clip_tbl.hash_rnd); } static struct neigh_table clip_tbl = { @@ -366,7 +363,6 @@ static struct neigh_table clip_tbl = { .gc_thresh3 = 1024, }; - /* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */ /* @@ -376,15 +372,13 @@ static struct neigh_table clip_tbl = { * clip_setentry. */ - -static int clip_encap(struct atm_vcc *vcc,int mode) +static int clip_encap(struct atm_vcc *vcc, int mode) { CLIP_VCC(vcc)->encap = mode; return 0; } - -static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev) +static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct clip_priv *clip_priv = PRIV(dev); struct atmarp_entry *entry; @@ -392,7 +386,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev) int old; unsigned long flags; - DPRINTK("clip_start_xmit (skb %p)\n",skb); + DPRINTK("clip_start_xmit (skb %p)\n", skb); if (!skb->dst) { printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n"); dev_kfree_skb(skb); @@ -401,9 +395,9 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev) } if (!skb->dst->neighbour) { #if 0 - skb->dst->neighbour = clip_find_neighbour(skb->dst,1); + skb->dst->neighbour = clip_find_neighbour(skb->dst, 1); if (!skb->dst->neighbour) { - dev_kfree_skb(skb); /* lost that one */ + dev_kfree_skb(skb); /* lost that one */ clip_priv->stats.tx_dropped++; return 0; } @@ -417,73 +411,73 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev) if (!entry->vccs) { if (time_after(jiffies, entry->expires)) { /* should be resolved */ - entry->expires = jiffies+ATMARP_RETRY_DELAY*HZ; - to_atmarpd(act_need,PRIV(dev)->number,entry->ip); + entry->expires = jiffies + ATMARP_RETRY_DELAY * HZ; + to_atmarpd(act_need, PRIV(dev)->number, entry->ip); } if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS) - skb_queue_tail(&entry->neigh->arp_queue,skb); + skb_queue_tail(&entry->neigh->arp_queue, skb); else { dev_kfree_skb(skb); clip_priv->stats.tx_dropped++; } return 0; } - DPRINTK("neigh %p, vccs %p\n",entry,entry->vccs); + DPRINTK("neigh %p, vccs %p\n", entry, entry->vccs); ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc; - DPRINTK("using neighbour %p, vcc %p\n",skb->dst->neighbour,vcc); + DPRINTK("using neighbour %p, vcc %p\n", skb->dst->neighbour, vcc); if (entry->vccs->encap) { void *here; - here = skb_push(skb,RFC1483LLC_LEN); - memcpy(here,llc_oui,sizeof(llc_oui)); + here = skb_push(skb, RFC1483LLC_LEN); + memcpy(here, llc_oui, sizeof(llc_oui)); ((u16 *) here)[3] = skb->protocol; } atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); ATM_SKB(skb)->atm_options = vcc->atm_options; entry->vccs->last_use = jiffies; - DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev); - old = xchg(&entry->vccs->xoff,1); /* assume XOFF ... */ + DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev); + old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */ if (old) { printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n"); return 0; } clip_priv->stats.tx_packets++; clip_priv->stats.tx_bytes += skb->len; - (void) vcc->send(vcc,skb); - if (atm_may_send(vcc,0)) { + vcc->send(vcc, skb); + if (atm_may_send(vcc, 0)) { entry->vccs->xoff = 0; return 0; } - spin_lock_irqsave(&clip_priv->xoff_lock,flags); - netif_stop_queue(dev); /* XOFF -> throttle immediately */ + spin_lock_irqsave(&clip_priv->xoff_lock, flags); + netif_stop_queue(dev); /* XOFF -> throttle immediately */ barrier(); if (!entry->vccs->xoff) netif_start_queue(dev); - /* Oh, we just raced with clip_pop. netif_start_queue should be - good enough, because nothing should really be asleep because - of the brief netif_stop_queue. If this isn't true or if it - changes, use netif_wake_queue instead. */ - spin_unlock_irqrestore(&clip_priv->xoff_lock,flags); + /* Oh, we just raced with clip_pop. netif_start_queue should be + good enough, because nothing should really be asleep because + of the brief netif_stop_queue. If this isn't true or if it + changes, use netif_wake_queue instead. */ + spin_unlock_irqrestore(&clip_priv->xoff_lock, flags); return 0; } - static struct net_device_stats *clip_get_stats(struct net_device *dev) { return &PRIV(dev)->stats; } - -static int clip_mkip(struct atm_vcc *vcc,int timeout) +static int clip_mkip(struct atm_vcc *vcc, int timeout) { struct clip_vcc *clip_vcc; struct sk_buff_head copy; struct sk_buff *skb; - if (!vcc->push) return -EBADFD; - clip_vcc = kmalloc(sizeof(struct clip_vcc),GFP_KERNEL); - if (!clip_vcc) return -ENOMEM; - DPRINTK("mkip clip_vcc %p vcc %p\n",clip_vcc,vcc); + if (!vcc->push) + return -EBADFD; + clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL); + if (!clip_vcc) + return -ENOMEM; + DPRINTK("mkip clip_vcc %p vcc %p\n", clip_vcc, vcc); clip_vcc->vcc = vcc; vcc->user_back = clip_vcc; set_bit(ATM_VF_IS_CLIP, &vcc->flags); @@ -491,7 +485,7 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout) clip_vcc->xoff = 0; clip_vcc->encap = 1; clip_vcc->last_use = jiffies; - clip_vcc->idle_timeout = timeout*HZ; + clip_vcc->idle_timeout = timeout * HZ; clip_vcc->old_push = vcc->push; clip_vcc->old_pop = vcc->pop; vcc->push = clip_push; @@ -501,27 +495,25 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout) /* re-process everything received between connection setup and MKIP */ while ((skb = skb_dequeue(©)) != NULL) if (!clip_devs) { - atm_return(vcc,skb->truesize); + atm_return(vcc, skb->truesize); kfree_skb(skb); - } - else { + } else { unsigned int len = skb->len; - clip_push(vcc,skb); + clip_push(vcc, skb); PRIV(skb->dev)->stats.rx_packets--; PRIV(skb->dev)->stats.rx_bytes -= len; } return 0; } - -static int clip_setentry(struct atm_vcc *vcc,u32 ip) +static int clip_setentry(struct atm_vcc *vcc, u32 ip) { struct neighbour *neigh; struct atmarp_entry *entry; int error; struct clip_vcc *clip_vcc; - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } }; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} }; struct rtable *rt; if (vcc->push != clip_push) { @@ -538,28 +530,29 @@ static int clip_setentry(struct atm_vcc *vcc,u32 ip) unlink_clip_vcc(clip_vcc); return 0; } - error = ip_route_output_key(&rt,&fl); - if (error) return error; - neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1); + error = ip_route_output_key(&rt, &fl); + if (error) + return error; + neigh = __neigh_lookup(&clip_tbl, &ip, rt->u.dst.dev, 1); ip_rt_put(rt); if (!neigh) return -ENOMEM; entry = NEIGH2ENTRY(neigh); if (entry != clip_vcc->entry) { - if (!clip_vcc->entry) DPRINTK("setentry: add\n"); + if (!clip_vcc->entry) + DPRINTK("setentry: add\n"); else { DPRINTK("setentry: update\n"); unlink_clip_vcc(clip_vcc); } - link_vcc(clip_vcc,entry); + link_vcc(clip_vcc, entry); } - error = neigh_update(neigh, llc_oui, NUD_PERMANENT, - NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN); + error = neigh_update(neigh, llc_oui, NUD_PERMANENT, + NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN); neigh_release(neigh); return error; } - static void clip_setup(struct net_device *dev) { dev->hard_start_xmit = clip_start_xmit; @@ -568,15 +561,14 @@ static void clip_setup(struct net_device *dev) dev->type = ARPHRD_ATM; dev->hard_header_len = RFC1483LLC_LEN; dev->mtu = RFC1626_MTU; - dev->tx_queue_len = 100; /* "normal" queue (packets) */ - /* When using a "real" qdisc, the qdisc determines the queue */ - /* length. tx_queue_len is only used for the default case, */ - /* without any more elaborate queuing. 100 is a reasonable */ - /* compromise between decent burst-tolerance and protection */ - /* against memory hogs. */ + dev->tx_queue_len = 100; /* "normal" queue (packets) */ + /* When using a "real" qdisc, the qdisc determines the queue */ + /* length. tx_queue_len is only used for the default case, */ + /* without any more elaborate queuing. 100 is a reasonable */ + /* compromise between decent burst-tolerance and protection */ + /* against memory hogs. */ } - static int clip_create(int number) { struct net_device *dev; @@ -585,19 +577,19 @@ static int clip_create(int number) if (number != -1) { for (dev = clip_devs; dev; dev = PRIV(dev)->next) - if (PRIV(dev)->number == number) return -EEXIST; - } - else { + if (PRIV(dev)->number == number) + return -EEXIST; + } else { number = 0; for (dev = clip_devs; dev; dev = PRIV(dev)->next) if (PRIV(dev)->number >= number) - number = PRIV(dev)->number+1; + number = PRIV(dev)->number + 1; } dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup); if (!dev) return -ENOMEM; clip_priv = PRIV(dev); - sprintf(dev->name,"atm%d",number); + sprintf(dev->name, "atm%d", number); spin_lock_init(&clip_priv->xoff_lock); clip_priv->number = number; error = register_netdev(dev); @@ -607,53 +599,48 @@ static int clip_create(int number) } clip_priv->next = clip_devs; clip_devs = dev; - DPRINTK("registered (net:%s)\n",dev->name); + DPRINTK("registered (net:%s)\n", dev->name); return number; } - -static int clip_device_event(struct notifier_block *this,unsigned long event, - void *dev) +static int clip_device_event(struct notifier_block *this, unsigned long event, + void *arg) { + struct net_device *dev = arg; + + if (event == NETDEV_UNREGISTER) { + neigh_ifdown(&clip_tbl, dev); + return NOTIFY_DONE; + } + /* ignore non-CLIP devices */ - if (((struct net_device *) dev)->type != ARPHRD_ATM || - ((struct net_device *) dev)->hard_start_xmit != clip_start_xmit) + if (dev->type != ARPHRD_ATM || dev->hard_start_xmit != clip_start_xmit) return NOTIFY_DONE; + switch (event) { - case NETDEV_UP: - DPRINTK("clip_device_event NETDEV_UP\n"); - (void) to_atmarpd(act_up,PRIV(dev)->number,0); - break; - case NETDEV_GOING_DOWN: - DPRINTK("clip_device_event NETDEV_DOWN\n"); - (void) to_atmarpd(act_down,PRIV(dev)->number,0); - break; - case NETDEV_CHANGE: - case NETDEV_CHANGEMTU: - DPRINTK("clip_device_event NETDEV_CHANGE*\n"); - (void) to_atmarpd(act_change,PRIV(dev)->number,0); - break; - case NETDEV_REBOOT: - case NETDEV_REGISTER: - case NETDEV_DOWN: - DPRINTK("clip_device_event %ld\n",event); - /* ignore */ - break; - default: - printk(KERN_WARNING "clip_device_event: unknown event " - "%ld\n",event); - break; + case NETDEV_UP: + DPRINTK("clip_device_event NETDEV_UP\n"); + to_atmarpd(act_up, PRIV(dev)->number, 0); + break; + case NETDEV_GOING_DOWN: + DPRINTK("clip_device_event NETDEV_DOWN\n"); + to_atmarpd(act_down, PRIV(dev)->number, 0); + break; + case NETDEV_CHANGE: + case NETDEV_CHANGEMTU: + DPRINTK("clip_device_event NETDEV_CHANGE*\n"); + to_atmarpd(act_change, PRIV(dev)->number, 0); + break; } return NOTIFY_DONE; } - -static int clip_inet_event(struct notifier_block *this,unsigned long event, - void *ifa) +static int clip_inet_event(struct notifier_block *this, unsigned long event, + void *ifa) { struct in_device *in_dev; - in_dev = ((struct in_ifaddr *) ifa)->ifa_dev; + in_dev = ((struct in_ifaddr *)ifa)->ifa_dev; if (!in_dev || !in_dev->dev) { printk(KERN_WARNING "clip_inet_event: no device\n"); return NOTIFY_DONE; @@ -662,23 +649,20 @@ static int clip_inet_event(struct notifier_block *this,unsigned long event, * Transitions are of the down-change-up type, so it's sufficient to * handle the change on up. */ - if (event != NETDEV_UP) return NOTIFY_DONE; - return clip_device_event(this,NETDEV_CHANGE,in_dev->dev); + if (event != NETDEV_UP) + return NOTIFY_DONE; + return clip_device_event(this, NETDEV_CHANGE, in_dev->dev); } static struct notifier_block clip_dev_notifier = { - clip_device_event, - NULL, - 0 + .notifier_call = clip_device_event, }; static struct notifier_block clip_inet_notifier = { - clip_inet_event, - NULL, - 0 + .notifier_call = clip_inet_event, }; @@ -686,14 +670,12 @@ static struct notifier_block clip_inet_notifier = { static void atmarpd_close(struct atm_vcc *vcc) { DPRINTK("atmarpd_close\n"); - atmarpd = NULL; /* assumed to be atomic */ - barrier(); - unregister_inetaddr_notifier(&clip_inet_notifier); - unregister_netdevice_notifier(&clip_dev_notifier); - if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) - printk(KERN_ERR "atmarpd_close: closing with requests " - "pending\n"); + + rtnl_lock(); + atmarpd = NULL; skb_queue_purge(&sk_atm(vcc)->sk_receive_queue); + rtnl_unlock(); + DPRINTK("(done)\n"); module_put(THIS_MODULE); } @@ -714,14 +696,14 @@ static struct atm_dev atmarpd_dev = { static int atm_init_atmarp(struct atm_vcc *vcc) { - if (atmarpd) return -EADDRINUSE; - if (start_timer) { - start_timer = 0; - init_timer(&idle_timer); - idle_timer.expires = jiffies+CLIP_CHECK_INTERVAL*HZ; - idle_timer.function = idle_timer_check; - add_timer(&idle_timer); + rtnl_lock(); + if (atmarpd) { + rtnl_unlock(); + return -EADDRINUSE; } + + mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ); + atmarpd = vcc; set_bit(ATM_VF_META,&vcc->flags); set_bit(ATM_VF_READY,&vcc->flags); @@ -731,10 +713,7 @@ static int atm_init_atmarp(struct atm_vcc *vcc) vcc->push = NULL; vcc->pop = NULL; /* crash */ vcc->push_oam = NULL; /* crash */ - if (register_netdevice_notifier(&clip_dev_notifier)) - printk(KERN_ERR "register_netdevice_notifier failed\n"); - if (register_inetaddr_notifier(&clip_inet_notifier)) - printk(KERN_ERR "register_inetaddr_notifier failed\n"); + rtnl_unlock(); return 0; } @@ -744,53 +723,53 @@ static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) int err = 0; switch (cmd) { - case SIOCMKCLIP: - case ATMARPD_CTRL: - case ATMARP_MKIP: - case ATMARP_SETENTRY: - case ATMARP_ENCAP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - break; - default: - return -ENOIOCTLCMD; + case SIOCMKCLIP: + case ATMARPD_CTRL: + case ATMARP_MKIP: + case ATMARP_SETENTRY: + case ATMARP_ENCAP: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + break; + default: + return -ENOIOCTLCMD; } switch (cmd) { - case SIOCMKCLIP: - err = clip_create(arg); - break; - case ATMARPD_CTRL: - err = atm_init_atmarp(vcc); - if (!err) { - sock->state = SS_CONNECTED; - __module_get(THIS_MODULE); - } - break; - case ATMARP_MKIP: - err = clip_mkip(vcc ,arg); - break; - case ATMARP_SETENTRY: - err = clip_setentry(vcc, arg); - break; - case ATMARP_ENCAP: - err = clip_encap(vcc, arg); - break; + case SIOCMKCLIP: + err = clip_create(arg); + break; + case ATMARPD_CTRL: + err = atm_init_atmarp(vcc); + if (!err) { + sock->state = SS_CONNECTED; + __module_get(THIS_MODULE); + } + break; + case ATMARP_MKIP: + err = clip_mkip(vcc, arg); + break; + case ATMARP_SETENTRY: + err = clip_setentry(vcc, arg); + break; + case ATMARP_ENCAP: + err = clip_encap(vcc, arg); + break; } return err; } static struct atm_ioctl clip_ioctl_ops = { - .owner = THIS_MODULE, - .ioctl = clip_ioctl, + .owner = THIS_MODULE, + .ioctl = clip_ioctl, }; #ifdef CONFIG_PROC_FS static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr) { - static int code[] = { 1,2,10,6,1,0 }; - static int e164[] = { 1,8,4,6,1,0 }; + static int code[] = { 1, 2, 10, 6, 1, 0 }; + static int e164[] = { 1, 8, 4, 6, 1, 0 }; if (*addr->sas_addr.pub) { seq_printf(seq, "%s", addr->sas_addr.pub); @@ -809,7 +788,7 @@ static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr) for (i = 0; fields[i]; i++) { for (j = fields[i]; j; j--) seq_printf(seq, "%02X", *prv++); - if (fields[i+1]) + if (fields[i + 1]) seq_putc(seq, '.'); } } @@ -828,8 +807,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev, svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC)); - llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || - clip_vcc->encap); + llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || clip_vcc->encap); if (clip_vcc == SEQ_NO_VCC_TOKEN) exp = entry->neigh->used; @@ -839,10 +817,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev, exp = (jiffies - exp) / HZ; seq_printf(seq, "%-6s%-4s%-4s%5ld ", - dev->name, - svc ? "SVC" : "PVC", - llc ? "LLC" : "NULL", - exp); + dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp); off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d", NIPQUAD(entry->ip)); @@ -860,8 +835,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev, } else if (!svc) { seq_printf(seq, "%d.%d.%d\n", clip_vcc->vcc->dev->number, - clip_vcc->vcc->vpi, - clip_vcc->vcc->vci); + clip_vcc->vcc->vpi, clip_vcc->vcc->vci); } else { svc_addr(seq, &clip_vcc->vcc->remote); seq_putc(seq, '\n'); @@ -894,7 +868,7 @@ static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e, } static void *clip_seq_vcc_walk(struct clip_seq_state *state, - struct atmarp_entry *e, loff_t *pos) + struct atmarp_entry *e, loff_t * pos) { struct clip_vcc *vcc = state->vcc; @@ -911,24 +885,24 @@ static void *clip_seq_vcc_walk(struct clip_seq_state *state, return vcc; } - + static void *clip_seq_sub_iter(struct neigh_seq_state *_state, - struct neighbour *n, loff_t *pos) + struct neighbour *n, loff_t * pos) { - struct clip_seq_state *state = (struct clip_seq_state *) _state; + struct clip_seq_state *state = (struct clip_seq_state *)_state; return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos); } -static void *clip_seq_start(struct seq_file *seq, loff_t *pos) +static void *clip_seq_start(struct seq_file *seq, loff_t * pos) { return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY); } static int clip_seq_show(struct seq_file *seq, void *v) { - static char atm_arp_banner[] = - "IPitf TypeEncp Idle IP address ATM address\n"; + static char atm_arp_banner[] = + "IPitf TypeEncp Idle IP address ATM address\n"; if (v == SEQ_START_TOKEN) { seq_puts(seq, atm_arp_banner); @@ -939,7 +913,7 @@ static int clip_seq_show(struct seq_file *seq, void *v) atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc); } - return 0; + return 0; } static struct seq_operations arp_seq_ops = { @@ -988,20 +962,19 @@ static struct file_operations arp_seq_fops = { static int __init atm_clip_init(void) { + struct proc_dir_entry *p; neigh_table_init(&clip_tbl); clip_tbl_hook = &clip_tbl; register_atm_ioctl(&clip_ioctl_ops); + register_netdevice_notifier(&clip_dev_notifier); + register_inetaddr_notifier(&clip_inet_notifier); -#ifdef CONFIG_PROC_FS -{ - struct proc_dir_entry *p; + setup_timer(&idle_timer, idle_timer_check, 0); p = create_proc_entry("arp", S_IRUGO, atm_proc_root); if (p) p->proc_fops = &arp_seq_fops; -} -#endif return 0; } @@ -1012,13 +985,15 @@ static void __exit atm_clip_exit(void) remove_proc_entry("arp", atm_proc_root); + unregister_inetaddr_notifier(&clip_inet_notifier); + unregister_netdevice_notifier(&clip_dev_notifier); + deregister_atm_ioctl(&clip_ioctl_ops); /* First, stop the idle timer, so it stops banging * on the table. */ - if (start_timer == 0) - del_timer(&idle_timer); + del_timer_sync(&idle_timer); /* Next, purge the table, so that the device * unregister loop below does not hang due to @@ -1042,5 +1017,6 @@ static void __exit atm_clip_exit(void) module_init(atm_clip_init); module_exit(atm_clip_exit); - +MODULE_AUTHOR("Werner Almesberger"); +MODULE_DESCRIPTION("Classical/IP over ATM interface"); MODULE_LICENSE("GPL"); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index b7766562d72..b0b7f55c1ed 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -125,9 +125,6 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb) struct sk_buff *skb = *pskb; const unsigned char *dest = eth_hdr(skb)->h_dest; - if (p->state == BR_STATE_DISABLED) - goto err; - if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) goto err; diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 66bd93252c4..84b9af76f0a 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -824,9 +824,9 @@ static int translate_table(struct ebt_replace *repl, if (udc_cnt) { /* this will get free'd in do_replace()/ebt_register_table() if an error occurs */ - newinfo->chainstack = (struct ebt_chainstack **) - vmalloc((highest_possible_processor_id()+1) - * sizeof(struct ebt_chainstack)); + newinfo->chainstack = + vmalloc((highest_possible_processor_id()+1) + * sizeof(*(newinfo->chainstack))); if (!newinfo->chainstack) return -ENOMEM; for_each_possible_cpu(i) { diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 29047995c69..f2c011fd2ba 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -498,7 +498,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) goto drop; if (dccp_parse_options(sk, skb)) - goto drop; + goto drop_and_free; dccp_openreq_init(req, &dp, skb); diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 041dadde31a..4749d504c62 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -928,7 +928,8 @@ static void parp_redo(struct sk_buff *skb) * Receive an arp request from the device layer. */ -int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) +static int arp_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) { struct arphdr *arp; @@ -1417,7 +1418,6 @@ static int __init arp_proc_init(void) EXPORT_SYMBOL(arp_broken_ops); EXPORT_SYMBOL(arp_find); -EXPORT_SYMBOL(arp_rcv); EXPORT_SYMBOL(arp_create); EXPORT_SYMBOL(arp_xmit); EXPORT_SYMBOL(arp_send); diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 81c2f788529..54419b27686 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1556,7 +1556,6 @@ void __init devinet_init(void) #endif } -EXPORT_SYMBOL(devinet_ioctl); EXPORT_SYMBOL(in_dev_finish_destroy); EXPORT_SYMBOL(inet_select_addr); EXPORT_SYMBOL(inetdev_by_index); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 4e3d3811dea..cdde9639096 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -666,4 +666,3 @@ void __init ip_fib_init(void) } EXPORT_SYMBOL(inet_addr_type); -EXPORT_SYMBOL(ip_rt_ioctl); diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index ef7366fc132..ee9b5515b9a 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -43,8 +43,6 @@ struct inet_bind_bucket *inet_bind_bucket_create(kmem_cache_t *cachep, return tb; } -EXPORT_SYMBOL(inet_bind_bucket_create); - /* * Caller must hold hashbucket lock for this tb with local BH disabled */ @@ -64,8 +62,6 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, inet_csk(sk)->icsk_bind_hash = tb; } -EXPORT_SYMBOL(inet_bind_hash); - /* * Get rid of any references to a local port held by the given sock. */ diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8dcba3887f0..cff9c3a72da 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -904,7 +904,7 @@ alloc_new_skb: * because we have no idea what fragment will be * the last. */ - if (datalen == length) + if (datalen == length + fraggap) alloclen += rt->u.dst.trailer_len; if (transhdrlen) { diff --git a/net/ipv4/route.c b/net/ipv4/route.c index ff434821909..cc9423de731 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2741,7 +2741,10 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) /* Reserve room for dummy headers, this skb can pass through good chunk of routing engine. */ - skb->mac.raw = skb->data; + skb->mac.raw = skb->nh.raw = skb->data; + + /* Bugfix: need to give ip_route_input enough of an IP header to not gag. */ + skb->nh.iph->protocol = IPPROTO_ICMP; skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr)); if (rta[RTA_SRC - 1]) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 195d8358455..9f0cca4c4fa 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4559,7 +4559,6 @@ discard: EXPORT_SYMBOL(sysctl_tcp_ecn); EXPORT_SYMBOL(sysctl_tcp_reordering); -EXPORT_SYMBOL(sysctl_tcp_abc); EXPORT_SYMBOL(tcp_parse_options); EXPORT_SYMBOL(tcp_rcv_established); EXPORT_SYMBOL(tcp_rcv_state_process); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 9e85c041610..672950e54c4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1859,5 +1859,4 @@ EXPORT_SYMBOL(tcp_proc_unregister); #endif EXPORT_SYMBOL(sysctl_local_port_range); EXPORT_SYMBOL(sysctl_tcp_low_latency); -EXPORT_SYMBOL(sysctl_tcp_tw_reuse); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 9d79546d384..b871db6adc5 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -59,9 +59,6 @@ int sysctl_tcp_tso_win_divisor = 3; int sysctl_tcp_mtu_probing = 0; int sysctl_tcp_base_mss = 512; -EXPORT_SYMBOL(sysctl_tcp_mtu_probing); -EXPORT_SYMBOL(sysctl_tcp_base_mss); - static void update_send_head(struct sock *sk, struct tcp_sock *tp, struct sk_buff *skb) { diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index b67a45fb93e..eef985e010e 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -121,6 +121,10 @@ static __inline__ void fq_unlink(struct frag_queue *fq) write_unlock(&ip6_frag_lock); } +/* + * callers should be careful not to use the hash value outside the ipfrag_lock + * as doing so could race with ipfrag_hash_rnd being recalculated. + */ static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr, struct in6_addr *daddr) { @@ -324,15 +328,16 @@ out: /* Creation primitives. */ -static struct frag_queue *ip6_frag_intern(unsigned int hash, - struct frag_queue *fq_in) +static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in) { struct frag_queue *fq; + unsigned int hash; #ifdef CONFIG_SMP struct hlist_node *n; #endif write_lock(&ip6_frag_lock); + hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr); #ifdef CONFIG_SMP hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { if (fq->id == fq_in->id && @@ -362,7 +367,7 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash, static struct frag_queue * -ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst) +ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst) { struct frag_queue *fq; @@ -379,7 +384,7 @@ ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr spin_lock_init(&fq->lock); atomic_set(&fq->refcnt, 1); - return ip6_frag_intern(hash, fq); + return ip6_frag_intern(fq); oom: IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); @@ -391,9 +396,10 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) { struct frag_queue *fq; struct hlist_node *n; - unsigned int hash = ip6qhashfn(id, src, dst); + unsigned int hash; read_lock(&ip6_frag_lock); + hash = ip6qhashfn(id, src, dst); hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { if (fq->id == id && ipv6_addr_equal(src, &fq->saddr) && @@ -405,7 +411,7 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) } read_unlock(&ip6_frag_lock); - return ip6_frag_create(hash, id, src, dst); + return ip6_frag_create(id, src, dst); } diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c index 8b9bf4a763b..b1265187b4a 100644 --- a/net/wanrouter/af_wanpipe.c +++ b/net/wanrouter/af_wanpipe.c @@ -55,12 +55,10 @@ #include <asm/uaccess.h> #include <linux/module.h> #include <linux/init.h> -#include <linux/wanpipe.h> #include <linux/if_wanpipe.h> #include <linux/pkt_sched.h> #include <linux/tcp_states.h> #include <linux/if_wanpipe_common.h> -#include <linux/sdla_x25.h> #ifdef CONFIG_INET #include <net/inet_common.h> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a8e14dc1b04..3dc3e1f3b7a 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -805,16 +805,22 @@ void xfrm_replay_notify(struct xfrm_state *x, int event) case XFRM_REPLAY_UPDATE: if (x->replay_maxdiff && (x->replay.seq - x->preplay.seq < x->replay_maxdiff) && - (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) - return; + (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) { + if (x->xflags & XFRM_TIME_DEFER) + event = XFRM_REPLAY_TIMEOUT; + else + return; + } break; case XFRM_REPLAY_TIMEOUT: if ((x->replay.seq == x->preplay.seq) && (x->replay.bitmap == x->preplay.bitmap) && - (x->replay.oseq == x->preplay.oseq)) + (x->replay.oseq == x->preplay.oseq)) { + x->xflags |= XFRM_TIME_DEFER; return; + } break; } @@ -825,8 +831,10 @@ void xfrm_replay_notify(struct xfrm_state *x, int event) km_state_notify(x, &c); if (x->replay_maxage && - !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) + !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) { xfrm_state_hold(x); + x->xflags &= ~XFRM_TIME_DEFER; + } } EXPORT_SYMBOL(xfrm_replay_notify); @@ -836,10 +844,15 @@ static void xfrm_replay_timer_handler(unsigned long data) spin_lock(&x->lock); - if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID) - xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); + if (x->km.state == XFRM_STATE_VALID) { + if (xfrm_aevent_is_on()) + xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); + else + x->xflags |= XFRM_TIME_DEFER; + } spin_unlock(&x->lock); + xfrm_state_put(x); } int xfrm_replay_check(struct xfrm_state *x, u32 seq) |