diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-04-29 01:11:23 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-04-29 01:11:23 -0400 |
commit | 7b7e394185014e0f3bd8989cac937003f20ef9ce (patch) | |
tree | 3beda5f979bba0aa9822534e239cf1b45f3be69c /net | |
parent | ddc5d3414593e4d7ad7fbd33e7f7517fcc234544 (diff) | |
parent | 693f7d362055261882659475d2ef022e32edbff1 (diff) |
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'net')
133 files changed, 2848 insertions, 3334 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/bluetooth/sco.c b/net/bluetooth/sco.c index 6b61323ce23..0c2d13ad69b 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -255,7 +255,7 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) } if ((err = hci_send_sco(conn->hcon, skb)) < 0) - goto fail; + return err; return count; diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 2d24fb400e0..56f3aa47e75 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -16,6 +16,7 @@ #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/skbuff.h> +#include <linux/if_vlan.h> #include <linux/netfilter_bridge.h> #include "br_private.h" @@ -29,10 +30,15 @@ static inline int should_deliver(const struct net_bridge_port *p, return 1; } +static inline unsigned packet_length(const struct sk_buff *skb) +{ + return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0); +} + int br_dev_queue_push_xmit(struct sk_buff *skb) { /* drop mtu oversized packets except tso */ - if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size) + if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size) kfree_skb(skb); else { #ifdef CONFIG_BRIDGE_NETFILTER 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/br_netfilter.c b/net/bridge/br_netfilter.c index f29450b788b..3da9264449f 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -765,6 +765,15 @@ out: return NF_STOLEN; } +static int br_nf_dev_queue_xmit(struct sk_buff *skb) +{ + if (skb->protocol == htons(ETH_P_IP) && + skb->len > skb->dev->mtu && + !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) + return ip_fragment(skb, br_dev_queue_push_xmit); + else + return br_dev_queue_push_xmit(skb); +} /* PF_BRIDGE/POST_ROUTING ********************************************/ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, @@ -824,7 +833,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, realoutdev = nf_bridge->netoutdev; #endif NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, - br_dev_queue_push_xmit); + br_nf_dev_queue_xmit); return NF_STOLEN; @@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, if ((out->hard_start_xmit == br_dev_xmit && okfn != br_nf_forward_finish && - okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit) + okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit) #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) || ((out->priv_flags & IFF_802_1Q_VLAN) && VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 01eae97c53d..3a13ed64345 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -824,14 +824,14 @@ 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_cpu(i) { + for_each_possible_cpu(i) { newinfo->chainstack[i] = - vmalloc(udc_cnt * sizeof(struct ebt_chainstack)); + vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0]))); if (!newinfo->chainstack[i]) { while (i) vfree(newinfo->chainstack[--i]); @@ -841,8 +841,7 @@ static int translate_table(struct ebt_replace *repl, } } - cl_s = (struct ebt_cl_stack *) - vmalloc(udc_cnt * sizeof(struct ebt_cl_stack)); + cl_s = vmalloc(udc_cnt * sizeof(*cl_s)); if (!cl_s) return -ENOMEM; i = 0; /* the i'th udc */ @@ -901,7 +900,7 @@ static void get_counters(struct ebt_counter *oldcounters, sizeof(struct ebt_counter) * nentries); /* add other counters to those of cpu 0 */ - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { if (cpu == 0) continue; counter_base = COUNTER_BASE(oldcounters, nentries, cpu); @@ -944,8 +943,7 @@ static int do_replace(void __user *user, unsigned int len) countersize = COUNTER_OFFSET(tmp.nentries) * (highest_possible_processor_id()+1); - newinfo = (struct ebt_table_info *) - vmalloc(sizeof(struct ebt_table_info) + countersize); + newinfo = vmalloc(sizeof(*newinfo) + countersize); if (!newinfo) return -ENOMEM; @@ -967,8 +965,7 @@ static int do_replace(void __user *user, unsigned int len) /* the user wants counters back the check on the size is done later, when we have the lock */ if (tmp.num_counters) { - counterstmp = (struct ebt_counter *) - vmalloc(tmp.num_counters * sizeof(struct ebt_counter)); + counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp)); if (!counterstmp) { ret = -ENOMEM; goto free_entries; @@ -1036,7 +1033,7 @@ static int do_replace(void __user *user, unsigned int len) vfree(table->entries); if (table->chainstack) { - for_each_cpu(i) + for_each_possible_cpu(i) vfree(table->chainstack[i]); vfree(table->chainstack); } @@ -1054,7 +1051,7 @@ free_counterstmp: vfree(counterstmp); /* can be initialized in translate_table() */ if (newinfo->chainstack) { - for_each_cpu(i) + for_each_possible_cpu(i) vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack); } @@ -1148,8 +1145,7 @@ int ebt_register_table(struct ebt_table *table) countersize = COUNTER_OFFSET(table->table->nentries) * (highest_possible_processor_id()+1); - newinfo = (struct ebt_table_info *) - vmalloc(sizeof(struct ebt_table_info) + countersize); + newinfo = vmalloc(sizeof(*newinfo) + countersize); ret = -ENOMEM; if (!newinfo) return -ENOMEM; @@ -1201,7 +1197,7 @@ free_unlock: mutex_unlock(&ebt_mutex); free_chainstack: if (newinfo->chainstack) { - for_each_cpu(i) + for_each_possible_cpu(i) vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack); } @@ -1224,7 +1220,7 @@ void ebt_unregister_table(struct ebt_table *table) mutex_unlock(&ebt_mutex); vfree(table->private->entries); if (table->private->chainstack) { - for_each_cpu(i) + for_each_possible_cpu(i) vfree(table->private->chainstack[i]); vfree(table->private->chainstack); } @@ -1247,8 +1243,7 @@ static int update_counters(void __user *user, unsigned int len) if (hlp.num_counters == 0) return -EINVAL; - if ( !(tmp = (struct ebt_counter *) - vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){ + if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) { MEMPRINT("Update_counters && nomemory\n"); return -ENOMEM; } @@ -1377,8 +1372,7 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user, BUGPRINT("Num_counters wrong\n"); return -EINVAL; } - counterstmp = (struct ebt_counter *) - vmalloc(nentries * sizeof(struct ebt_counter)); + counterstmp = vmalloc(nentries * sizeof(*counterstmp)); if (!counterstmp) { MEMPRINT("Couldn't copy counters, out of memory\n"); return -ENOMEM; diff --git a/net/compat.c b/net/compat.c index 8fd37cd7b50..d5d69fa15d0 100644 --- a/net/compat.c +++ b/net/compat.c @@ -476,8 +476,7 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, int err; struct socket *sock; - /* SO_SET_REPLACE seems to be the same in all levels */ - if (optname == IPT_SO_SET_REPLACE) + if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE) return do_netfilter_replace(fd, level, optname, optval, optlen); diff --git a/net/core/dev.c b/net/core/dev.c index 434220d093a..3bad1afc89f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2698,7 +2698,8 @@ int dev_ioctl(unsigned int cmd, void __user *arg) /* If command is `set a parameter', or * `get the encoding parameters', check if * the user has the right to do it */ - if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE) { + if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE + || cmd == SIOCGIWENCODEEXT) { if (!capable(CAP_NET_ADMIN)) return -EPERM; } @@ -3042,11 +3043,11 @@ void netdev_run_todo(void) switch(dev->reg_state) { case NETREG_REGISTERING: + dev->reg_state = NETREG_REGISTERED; err = netdev_register_sysfs(dev); if (err) printk(KERN_ERR "%s: failed sysfs registration (%d)\n", dev->name, err); - dev->reg_state = NETREG_REGISTERED; break; case NETREG_UNREGISTERING: @@ -3100,12 +3101,11 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; - p = kmalloc(alloc_size, GFP_KERNEL); + p = kzalloc(alloc_size, GFP_KERNEL); if (!p) { printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); return NULL; } - memset(p, 0, alloc_size); dev = (struct net_device *) (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); @@ -3347,7 +3347,7 @@ static int __init net_dev_init(void) * Initialise the packet receive queues. */ - for_each_cpu(i) { + for_each_possible_cpu(i) { struct softnet_data *queue; queue = &per_cpu(softnet_data, i); diff --git a/net/core/dv.c b/net/core/dv.c index cf581407538..29ee77f1593 100644 --- a/net/core/dv.c +++ b/net/core/dv.c @@ -55,15 +55,12 @@ int alloc_divert_blk(struct net_device *dev) dev->divert = NULL; if (dev->type == ARPHRD_ETHER) { - dev->divert = (struct divert_blk *) - kmalloc(alloc_size, GFP_KERNEL); + dev->divert = kzalloc(alloc_size, GFP_KERNEL); if (dev->divert == NULL) { printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n", dev->name); return -ENOMEM; } - - memset(dev->divert, 0, sizeof(struct divert_blk)); dev_hold(dev); } diff --git a/net/core/filter.c b/net/core/filter.c index 93fbd01d225..5b4486a60cf 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -34,6 +34,7 @@ #include <linux/timer.h> #include <asm/system.h> #include <asm/uaccess.h> +#include <asm/unaligned.h> #include <linux/filter.h> /* No hurry in this branch */ @@ -177,7 +178,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int load_w: ptr = load_pointer(skb, k, 4, &tmp); if (ptr != NULL) { - A = ntohl(*(u32 *)ptr); + A = ntohl(get_unaligned((u32 *)ptr)); continue; } break; @@ -186,7 +187,7 @@ load_w: load_h: ptr = load_pointer(skb, k, 2, &tmp); if (ptr != NULL) { - A = ntohs(*(u16 *)ptr); + A = ntohs(get_unaligned((u16 *)ptr)); continue; } break; diff --git a/net/core/flow.c b/net/core/flow.c index 55789f832ed..2191af5f26a 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -79,7 +79,7 @@ static void flow_cache_new_hashrnd(unsigned long arg) { int i; - for_each_cpu(i) + for_each_possible_cpu(i) flow_hash_rnd_recalc(i) = 1; flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; @@ -318,12 +318,10 @@ static void __devinit flow_cache_cpu_prepare(int cpu) /* NOTHING */; flow_table(cpu) = (struct flow_cache_entry **) - __get_free_pages(GFP_KERNEL, order); + __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); if (!flow_table(cpu)) panic("NET: failed to allocate flow cache order %lu\n", order); - memset(flow_table(cpu), 0, PAGE_SIZE << order); - flow_hash_rnd_recalc(cpu) = 1; flow_count(cpu) = 0; @@ -363,7 +361,7 @@ static int __init flow_cache_init(void) flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; add_timer(&flow_hash_rnd_timer); - for_each_cpu(i) + for_each_possible_cpu(i) flow_cache_cpu_prepare(i); hotcpu_notifier(flow_cache_cpu, 0); diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index b07c029e821..3cad026764f 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -159,11 +159,10 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, if (parm->interval < -2 || parm->interval > 3) return -EINVAL; - est = kmalloc(sizeof(*est), GFP_KERNEL); + est = kzalloc(sizeof(*est), GFP_KERNEL); if (est == NULL) return -ENOBUFS; - memset(est, 0, sizeof(*est)); est->interval = parm->interval + 2; est->bstats = bstats; est->rate_est = rate_est; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0c8666872d1..4cf878efdb4 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -284,14 +284,11 @@ static struct neighbour **neigh_hash_alloc(unsigned int entries) struct neighbour **ret; if (size <= PAGE_SIZE) { - ret = kmalloc(size, GFP_ATOMIC); + ret = kzalloc(size, GFP_ATOMIC); } else { ret = (struct neighbour **) - __get_free_pages(GFP_ATOMIC, get_order(size)); + __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size)); } - if (ret) - memset(ret, 0, size); - return ret; } @@ -1089,8 +1086,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, if (hh->hh_type == protocol) break; - if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { - memset(hh, 0, sizeof(struct hh_cache)); + if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { rwlock_init(&hh->hh_lock); hh->hh_type = protocol; atomic_set(&hh->hh_refcnt, 0); @@ -1366,13 +1362,11 @@ void neigh_table_init(struct neigh_table *tbl) tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1); phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); - tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL); + tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); if (!tbl->hash_buckets || !tbl->phash_buckets) panic("cannot allocate neighbour cache hashes"); - memset(tbl->phash_buckets, 0, phsize); - get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); rwlock_init(&tbl->lock); @@ -1633,7 +1627,7 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, memset(&ndst, 0, sizeof(ndst)); - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { struct neigh_statistics *st; st = per_cpu_ptr(tbl->stats, cpu); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 21b68464cab..c12990c9c60 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -165,7 +165,7 @@ static ssize_t show_operstate(struct class_device *dev, char *buf) operstate = IF_OPER_DOWN; read_unlock(&dev_base_lock); - if (operstate >= sizeof(operstates)) + if (operstate >= ARRAY_SIZE(operstates)) return -EINVAL; /* should not happen */ return sprintf(buf, "%s\n", operstates[operstate]); diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 1e44eda1fda..79ebd75fbe4 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -38,13 +38,11 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, { const int lopt_size = sizeof(struct listen_sock) + nr_table_entries * sizeof(struct request_sock *); - struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL); + struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL); if (lopt == NULL) return -ENOMEM; - memset(lopt, 0, lopt_size); - for (lopt->max_qlen_log = 6; (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog; lopt->max_qlen_log++); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 09464fa8d72..fb3770f9c09 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -112,6 +112,14 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) BUG(); } +void skb_truesize_bug(struct sk_buff *skb) +{ + printk(KERN_ERR "SKB BUG: Invalid truesize (%u) " + "len=%u, sizeof(sk_buff)=%Zd\n", + skb->truesize, skb->len, sizeof(struct sk_buff)); +} +EXPORT_SYMBOL(skb_truesize_bug); + /* Allocate a new skbuff. We do this ourselves so we can fill in a few * 'private' fields and also do memory statistics to find all the * [BEEP] leaks. diff --git a/net/core/stream.c b/net/core/stream.c index 35e25259fd9..e9489696f69 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -176,6 +176,7 @@ void sk_stream_rfree(struct sk_buff *skb) { struct sock *sk = skb->sk; + skb_truesize_check(skb); atomic_sub(skb->truesize, &sk->sk_rmem_alloc); sk->sk_forward_alloc += skb->truesize; } diff --git a/net/core/utils.c b/net/core/utils.c index fdc4f38bc46..4f96f389243 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -121,7 +121,7 @@ void __init net_random_init(void) { int i; - for_each_cpu(i) { + for_each_possible_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); __net_srandom(state, i+jiffies); } @@ -133,7 +133,7 @@ static int net_random_reseed(void) unsigned long seed[NR_CPUS]; get_random_bytes(seed, sizeof(seed)); - for_each_cpu(i) { + for_each_possible_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); __net_srandom(state, seed[i]); } diff --git a/net/core/wireless.c b/net/core/wireless.c index 81d6995fcfd..d2bc72d318f 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -1726,6 +1726,14 @@ int wireless_rtnetlink_get(struct net_device * dev, if(!IW_IS_GET(request->cmd)) return -EOPNOTSUPP; + /* If command is `get the encoding parameters', check if + * the user has the right to do it */ + if (request->cmd == SIOCGIWENCODE || + request->cmd == SIOCGIWENCODEEXT) { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + } + /* Special cases */ if(request->cmd == SIOCGIWSTATS) /* Get Wireless Stats */ 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/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig index 6cd9f3427be..f2a27cc6ecb 100644 --- a/net/ieee80211/softmac/Kconfig +++ b/net/ieee80211/softmac/Kconfig @@ -1,6 +1,7 @@ config IEEE80211_SOFTMAC tristate "Software MAC add-on to the IEEE 802.11 networking stack" depends on IEEE80211 && EXPERIMENTAL + select WIRELESS_EXT ---help--- This option enables the hardware independent software MAC addon for the IEEE 802.11 networking stack. diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index be61de78dfa..fb79ce7d643 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -101,6 +101,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason) /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */ mac->associated = 0; mac->associnfo.associating = 0; + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); spin_unlock_irqrestore(&mac->lock, flags); } @@ -143,6 +144,12 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) return 0; + /* assume that users know what they're doing ... + * (note we don't let them select a net we're incompatible with) */ + if (mac->associnfo.bssfixed) { + return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN); + } + /* if 'ANY' network requested, take any that doesn't have privacy enabled */ if (mac->associnfo.req_essid.len == 0 && !(net->capability & WLAN_CAPABILITY_PRIVACY)) @@ -175,7 +182,7 @@ ieee80211softmac_assoc_work(void *d) ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); /* try to find the requested network in our list, if we found one already */ - if (mac->associnfo.bssvalid) + if (mac->associnfo.bssvalid || mac->associnfo.bssfixed) found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); /* Search the ieee80211 networks for this network if we didn't find it by bssid, @@ -240,19 +247,25 @@ ieee80211softmac_assoc_work(void *d) if (ieee80211softmac_start_scan(mac)) dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); return; - } - else { + } else { spin_lock_irqsave(&mac->lock, flags); mac->associnfo.associating = 0; mac->associated = 0; spin_unlock_irqrestore(&mac->lock, flags); dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); + /* reset the retry counter for the next user request since we + * break out and don't reschedule ourselves after this point. */ + mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); return; } } - + + /* reset the retry counter for the next user request since we + * now found a net and will try to associate to it, but not + * schedule this function again. */ + mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; mac->associnfo.bssvalid = 1; memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); /* copy the ESSID for displaying it */ @@ -373,6 +386,7 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, spin_lock_irqsave(&mac->lock, flags); mac->associnfo.bssvalid = 0; mac->associated = 0; + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); schedule_work(&mac->associnfo.work); spin_unlock_irqrestore(&mac->lock, flags); @@ -391,6 +405,7 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev, dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); return 0; } - ieee80211softmac_assoc(mac, network); + schedule_work(&mac->associnfo.work); + return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c index 0a52bbda1e4..8cc8f3f0f8e 100644 --- a/net/ieee80211/softmac/ieee80211softmac_event.c +++ b/net/ieee80211/softmac/ieee80211softmac_event.c @@ -67,6 +67,7 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = { "authenticating failed", "authenticating timed out", "associating failed because no suitable network was found", + "disassociated", }; @@ -128,13 +129,42 @@ void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx) { struct ieee80211softmac_event *eventptr, *tmp; - union iwreq_data wrqu; - char *msg; + struct ieee80211softmac_network *network; if (event >= 0) { - msg = event_descriptions[event]; - wrqu.data.length = strlen(msg); - wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg); + union iwreq_data wrqu; + int we_event; + char *msg = NULL; + + switch(event) { + case IEEE80211SOFTMAC_EVENT_ASSOCIATED: + network = (struct ieee80211softmac_network *)event_ctx; + wrqu.data.length = 0; + wrqu.data.flags = 0; + memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + we_event = SIOCGIWAP; + break; + case IEEE80211SOFTMAC_EVENT_DISASSOCIATED: + wrqu.data.length = 0; + wrqu.data.flags = 0; + memset(&wrqu, '\0', sizeof (union iwreq_data)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + we_event = SIOCGIWAP; + break; + case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED: + wrqu.data.length = 0; + wrqu.data.flags = 0; + memset(&wrqu, '\0', sizeof (union iwreq_data)); + we_event = SIOCGIWSCAN; + break; + default: + msg = event_descriptions[event]; + wrqu.data.length = strlen(msg); + we_event = IWEVCUSTOM; + break; + } + wireless_send_event(mac->dev, we_event, &wrqu, msg); } if (!list_empty(&mac->events)) diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c index febc51dbb41..cc6cd56c85b 100644 --- a/net/ieee80211/softmac/ieee80211softmac_io.c +++ b/net/ieee80211/softmac/ieee80211softmac_io.c @@ -180,9 +180,21 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt, ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); /* Fill in capability Info */ - (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ? - cpu_to_le16(WLAN_CAPABILITY_ESS) : - cpu_to_le16(WLAN_CAPABILITY_IBSS); + switch (mac->ieee->iw_mode) { + case IW_MODE_INFRA: + (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS); + break; + case IW_MODE_ADHOC: + (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS); + break; + case IW_MODE_AUTO: + (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS); + break; + default: + /* bleh. we don't ever go to these modes */ + printk(KERN_ERR PFX "invalid iw_mode!\n"); + break; + } /* Need to add this (*pkt)->capability |= mac->ieee->short_slot ? cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index 60f06a31f0d..be83bdc1644 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -45,6 +45,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; softmac->scaninfo = NULL; + softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; + /* TODO: initialise all the other callbacks in the ieee struct * (once they're written) */ diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index bb9ab8b45d0..2b9e7edfa3c 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -47,6 +47,7 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm) sm->scanning = 1; spin_unlock_irqrestore(&sm->lock, flags); + netif_tx_disable(sm->ieee->dev); ret = sm->start_scan(sm->dev); if (ret) { spin_lock_irqsave(&sm->lock, flags); @@ -239,6 +240,7 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm) if (net) sm->set_channel(sm->dev, net->channel); } + netif_wake_queue(sm->ieee->dev); ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); } EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index b559aa9b550..27edb2b5581 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -27,7 +27,8 @@ #include "ieee80211softmac_priv.h" #include <net/iw_handler.h> - +/* for is_broadcast_ether_addr and is_zero_ether_addr */ +#include <linux/etherdevice.h> int ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, @@ -41,13 +42,23 @@ ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan); +/* if we're still scanning, return -EAGAIN so that userspace tools + * can get the complete scan results, otherwise return 0. */ int ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, struct iw_request_info *info, union iwreq_data *data, char *extra) { + unsigned long flags; struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + + spin_lock_irqsave(&sm->lock, flags); + if (sm->scanning) { + spin_unlock_irqrestore(&sm->lock, flags); + return -EAGAIN; + } + spin_unlock_irqrestore(&sm->lock, flags); return ieee80211_wx_get_scan(sm->ieee, info, data, extra); } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results); @@ -73,7 +84,6 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, sm->associnfo.static_essid = 1; } } - sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; /* set our requested ESSID length. * If applicable, we have already copied the data in */ @@ -300,8 +310,6 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, char *extra) { struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; unsigned long flags; /* sanity check */ @@ -310,10 +318,17 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, } spin_lock_irqsave(&mac->lock, flags); - if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || - !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { - schedule_work(&mac->associnfo.work); - goto out; + if (is_broadcast_ether_addr(data->ap_addr.sa_data)) { + /* the bssid we have is not to be fixed any longer, + * and we should reassociate to the best AP. */ + mac->associnfo.bssfixed = 0; + /* force reassociation */ + mac->associnfo.bssvalid = 0; + if (mac->associated) + schedule_work(&mac->associnfo.work); + } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { + /* the bssid we have is no longer fixed */ + mac->associnfo.bssfixed = 0; } else { if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { if (mac->associnfo.associating || mac->associated) { @@ -323,12 +338,14 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, } else { /* copy new value in data->ap_addr.sa_data to bssid */ memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); - } + } + /* tell the other code that this bssid should be used no matter what */ + mac->associnfo.bssfixed = 1; /* queue associate if new bssid or (old one again and not associated) */ schedule_work(&mac->associnfo.work); } -out: + out: spin_unlock_irqrestore(&mac->lock, flags); return 0; } diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index e16d8b42b95..e2e4771fa4c 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -116,7 +116,7 @@ error: return err; } -static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int ah_input(struct xfrm_state *x, struct sk_buff *skb) { int ah_hlen; struct iphdr *iph; 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/esp4.c b/net/ipv4/esp4.c index bf88c620a95..9d1881c07a3 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -133,7 +133,7 @@ error: * expensive, so we only support truncated data, which is the recommended * and common case. */ -static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int esp_input(struct xfrm_state *x, struct sk_buff *skb) { struct iphdr *iph; struct ip_esp_hdr *esph; @@ -208,9 +208,6 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc struct xfrm_encap_tmpl *encap = x->encap; struct udphdr *uh; - if (encap->encap_type != decap->decap_type) - goto out; - uh = (struct udphdr *)(iph + 1); encap_len = (void*)esph - (void*)uh; 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/fib_trie.c b/net/ipv4/fib_trie.c index ccd3efc6a17..95a639f2e3d 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -50,7 +50,7 @@ * Patrick McHardy <kaber@trash.net> */ -#define VERSION "0.406" +#define VERSION "0.407" #include <linux/config.h> #include <asm/uaccess.h> @@ -314,11 +314,6 @@ static void __leaf_free_rcu(struct rcu_head *head) kfree(container_of(head, struct leaf, rcu)); } -static inline void free_leaf(struct leaf *leaf) -{ - call_rcu(&leaf->rcu, __leaf_free_rcu); -} - static void __leaf_info_free_rcu(struct rcu_head *head) { kfree(container_of(head, struct leaf_info, rcu)); @@ -357,7 +352,12 @@ static void __tnode_free_rcu(struct rcu_head *head) static inline void tnode_free(struct tnode *tn) { - call_rcu(&tn->rcu, __tnode_free_rcu); + if(IS_LEAF(tn)) { + struct leaf *l = (struct leaf *) tn; + call_rcu_bh(&l->rcu, __leaf_free_rcu); + } + else + call_rcu(&tn->rcu, __tnode_free_rcu); } static struct leaf *leaf_new(void) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 9831fd2c73a..2a0455911ee 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -1107,7 +1107,7 @@ void __init icmp_init(struct net_proto_family *ops) struct inet_sock *inet; int i; - for_each_cpu(i) { + for_each_possible_cpu(i) { int err; err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, 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_fragment.c b/net/ipv4/ip_fragment.c index 2a8adda15e1..da734c43917 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -304,13 +304,17 @@ out: /* Creation primitives. */ -static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) +static struct ipq *ip_frag_intern(struct ipq *qp_in) { struct ipq *qp; #ifdef CONFIG_SMP struct hlist_node *n; #endif + unsigned int hash; + write_lock(&ipfrag_lock); + hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr, + qp_in->protocol); #ifdef CONFIG_SMP /* With SMP race we have to recheck hash table, because * such entry could be created on other cpu, while we @@ -345,7 +349,7 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) } /* Add an entry to the 'ipq' queue for a newly received IP datagram. */ -static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) +static struct ipq *ip_frag_create(struct iphdr *iph, u32 user) { struct ipq *qp; @@ -371,7 +375,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) spin_lock_init(&qp->lock); atomic_set(&qp->refcnt, 1); - return ip_frag_intern(hash, qp); + return ip_frag_intern(qp); out_nomem: LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n"); @@ -387,11 +391,12 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user) __u32 saddr = iph->saddr; __u32 daddr = iph->daddr; __u8 protocol = iph->protocol; - unsigned int hash = ipqhashfn(id, saddr, daddr, protocol); + unsigned int hash; struct ipq *qp; struct hlist_node *n; read_lock(&ipfrag_lock); + hash = ipqhashfn(id, saddr, daddr, protocol); hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { if(qp->id == id && qp->saddr == saddr && @@ -405,7 +410,7 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user) } read_unlock(&ipfrag_lock); - return ip_frag_create(hash, iph, user); + return ip_frag_create(iph, user); } /* Is the fragment too far ahead to be part of ipq? */ diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 9981dcd68f1..ab99bebdcdc 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -656,7 +656,7 @@ static int ipgre_rcv(struct sk_buff *skb) read_unlock(&ipgre_lock); return(0); } - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); drop: read_unlock(&ipgre_lock); diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index f75ff1d9655..cff9c3a72da 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -86,8 +86,6 @@ int sysctl_ip_default_ttl = IPDEFTTL; -static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)); - /* Generate a checksum for an outgoing IP datagram. */ __inline__ void ip_send_check(struct iphdr *iph) { @@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) * single device frame, and queue such a frame for sending. */ -static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) +int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) { struct iphdr *iph; int raw = 0; @@ -673,6 +671,8 @@ fail: return err; } +EXPORT_SYMBOL(ip_fragment); + int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) { @@ -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/ipcomp.c b/net/ipv4/ipcomp.c index c95020f7c81..cd810f41af1 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -81,8 +81,7 @@ out: return err; } -static int ipcomp_input(struct xfrm_state *x, - struct xfrm_decap_state *decap, struct sk_buff *skb) +static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) { u8 nexthdr; int err = 0; @@ -291,11 +290,8 @@ static void ipcomp_free_scratches(void) if (!scratches) return; - for_each_cpu(i) { - void *scratch = *per_cpu_ptr(scratches, i); - if (scratch) - vfree(scratch); - } + for_each_possible_cpu(i) + vfree(*per_cpu_ptr(scratches, i)); free_percpu(scratches); } @@ -314,7 +310,7 @@ static void **ipcomp_alloc_scratches(void) ipcomp_scratches = scratches; - for_each_cpu(i) { + for_each_possible_cpu(i) { void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE); if (!scratch) return NULL; @@ -345,7 +341,7 @@ static void ipcomp_free_tfms(struct crypto_tfm **tfms) if (!tfms) return; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu); crypto_free_tfm(tfm); } @@ -385,7 +381,7 @@ static struct crypto_tfm **ipcomp_alloc_tfms(const char *alg_name) if (!tfms) goto error; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0); if (!tfm) goto error; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index eef07b0916a..ea398ee43f2 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -474,9 +474,6 @@ static int ipip_rcv(struct sk_buff *skb) struct iphdr *iph; struct ip_tunnel *tunnel; - if (!pskb_may_pull(skb, sizeof(struct iphdr))) - goto out; - iph = skb->nh.iph; read_lock(&ipip_lock); @@ -508,7 +505,6 @@ static int ipip_rcv(struct sk_buff *skb) } read_unlock(&ipip_lock); -out: return -1; } diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index b5ad9ac2fbc..6a9e34b794b 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -133,7 +133,7 @@ struct ip_rt_info { u_int8_t tos; }; -static void queue_save(const struct sk_buff *skb, struct nf_info *info) +static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info) { struct ip_rt_info *rt_info = nf_info_reroute(info); @@ -146,7 +146,7 @@ static void queue_save(const struct sk_buff *skb, struct nf_info *info) } } -static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) +static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) { const struct ip_rt_info *rt_info = nf_info_reroute(info); @@ -161,20 +161,54 @@ static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } -static struct nf_queue_rerouter ip_reroute = { - .rer_size = sizeof(struct ip_rt_info), - .save = queue_save, - .reroute = queue_reroute, +unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) +{ + struct iphdr *iph = skb->nh.iph; + unsigned int csum = 0; + + switch (skb->ip_summed) { + case CHECKSUM_HW: + if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN) + break; + if ((protocol == 0 && !(u16)csum_fold(skb->csum)) || + !csum_tcpudp_magic(iph->saddr, iph->daddr, + skb->len - dataoff, protocol, + skb->csum)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } + /* fall through */ + case CHECKSUM_NONE: + if (protocol == 0) + skb->csum = 0; + else + skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, + skb->len - dataoff, + protocol, 0); + csum = __skb_checksum_complete(skb); + } + return csum; +} + +EXPORT_SYMBOL(nf_ip_checksum); + +static struct nf_afinfo nf_ip_afinfo = { + .family = AF_INET, + .checksum = nf_ip_checksum, + .saveroute = nf_ip_saveroute, + .reroute = nf_ip_reroute, + .route_key_size = sizeof(struct ip_rt_info), }; static int ipv4_netfilter_init(void) { - return nf_register_queue_rerouter(PF_INET, &ip_reroute); + return nf_register_afinfo(&nf_ip_afinfo); } static void ipv4_netfilter_fini(void) { - nf_unregister_queue_rerouter(PF_INET); + nf_unregister_afinfo(&nf_ip_afinfo); } module_init(ipv4_netfilter_init); diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 882b842c25d..3d560dec63a 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -69,6 +69,7 @@ config IP_NF_CONNTRACK_NETLINK tristate 'Connection tracking netlink interface (EXPERIMENTAL)' depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m + depends on IP_NF_NAT=n || IP_NF_NAT help This option enables support for a netlink-based userspace interface @@ -221,16 +222,6 @@ config IP_NF_MATCH_IPRANGE To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_MULTIPORT - tristate "Multiple port match support" - depends on IP_NF_IPTABLES - help - Multiport matching allows you to match TCP or UDP packets based on - a series of source or destination ports: normally a rule can only - match a single range of ports. - - To compile it as a module, choose M here. If unsure, say N. - config IP_NF_MATCH_TOS tristate "TOS match support" depends on IP_NF_IPTABLES @@ -272,12 +263,12 @@ config IP_NF_MATCH_DSCP To compile it as a module, choose M here. If unsure, say N. -config IP_NF_MATCH_AH_ESP - tristate "AH/ESP match support" +config IP_NF_MATCH_AH + tristate "AH match support" depends on IP_NF_IPTABLES help - These two match extensions (`ah' and `esp') allow you to match a - range of SPIs inside AH or ESP headers of IPSec packets. + This match extension allows you to match a range of SPIs + inside AH header of IPSec packets. To compile it as a module, choose M here. If unsure, say N. @@ -354,7 +345,7 @@ config IP_NF_TARGET_LOG To compile it as a module, choose M here. If unsure, say N. config IP_NF_TARGET_ULOG - tristate "ULOG target support (OBSOLETE)" + tristate "ULOG target support" depends on IP_NF_IPTABLES ---help--- diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index f2cd9a6c5b9..461cb1eb5de 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -53,13 +53,12 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o # matches obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o -obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o -obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o +obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index a44a5d73457..c2d92f99a2b 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -646,7 +646,7 @@ static int translate_table(const char *name, } /* And one copy for every other CPU */ - for_each_cpu(i) { + for_each_possible_cpu(i) { if (newinfo->entries[i] && newinfo->entries[i] != entry0) memcpy(newinfo->entries[i], entry0, newinfo->size); } @@ -696,7 +696,7 @@ static void get_counters(const struct xt_table_info *t, counters, &i); - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { if (cpu == curcpu) continue; i = 0; diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index d0d379c7df9..d7c472faa53 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -181,33 +181,26 @@ static struct nf_hook_ops arpt_ops[] = { static int __init arptable_filter_init(void) { - int ret, i; + int ret; /* Register table */ ret = arpt_register_table(&packet_filter, &initial_table.repl); if (ret < 0) return ret; - for (i = 0; i < ARRAY_SIZE(arpt_ops); i++) - if ((ret = nf_register_hook(&arpt_ops[i])) < 0) - goto cleanup_hooks; + ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); + if (ret < 0) + goto cleanup_table; return ret; -cleanup_hooks: - while (--i >= 0) - nf_unregister_hook(&arpt_ops[i]); - +cleanup_table: arpt_unregister_table(&packet_filter); return ret; } static void __exit arptable_filter_fini(void) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(arpt_ops); i++) - nf_unregister_hook(&arpt_ops[i]); - + nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); arpt_unregister_table(&packet_filter); } diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index ceaabc18202..979a2eac6f0 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -133,7 +133,7 @@ static void ip_ct_event_cache_flush(void) struct ip_conntrack_ecache *ecache; int cpu; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { ecache = &per_cpu(ip_conntrack_ecache, cpu); if (ecache->ct) ip_conntrack_put(ecache->ct); diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index daeb1395faa..2c2fb700d83 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -9,37 +9,6 @@ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> * * For more information, please see http://nath323.sourceforge.net/ - * - * Changes: - * 2006-02-01 - initial version 0.1 - * - * 2006-02-20 - version 0.2 - * 1. Changed source format to follow kernel conventions - * 2. Deleted some unnecessary structures - * 3. Minor fixes - * - * 2006-03-10 - version 0.3 - * 1. Added support for multiple TPKTs in one packet (suggested by - * Patrick McHardy) - * 2. Avoid excessive stack usage (based on Patrick McHardy's patch) - * 3. Added support for non-linear skb (based on Patrick McHardy's patch) - * 4. Fixed missing H.245 module owner (Patrick McHardy) - * 5. Avoid long RAS expectation chains (Patrick McHardy) - * 6. Fixed incorrect __exit attribute (Patrick McHardy) - * 7. Eliminated unnecessary return code - * 8. Fixed incorrect use of NAT data from conntrack code (suggested by - * Patrick McHardy) - * 9. Fixed TTL calculation error in RCF - * 10. Added TTL support in RRQ - * 11. Better support for separate TPKT header and data - * - * 2006-03-15 - version 0.4 - * 1. Added support for T.120 channels - * 2. Added parameter gkrouted_only (suggested by Patrick McHardy) - * 3. Splitted ASN.1 code and data (suggested by Patrick McHardy) - * 4. Sort ASN.1 data to avoid forwarding declarations (suggested by - * Patrick McHardy) - * 5. Reset next TPKT data length in get_tpkt_data() */ #include <linux/config.h> @@ -54,8 +23,6 @@ #include <linux/netfilter_ipv4/ip_conntrack_h323.h> #include <linux/moduleparam.h> -#include "ip_conntrack_helper_h323_asn1.h" - #if 0 #define DEBUGP printk #else @@ -63,6 +30,10 @@ #endif /* Parameters */ +static unsigned int default_rrq_ttl = 300; +module_param(default_rrq_ttl, uint, 0600); +MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ"); + static int gkrouted_only = 1; module_param(gkrouted_only, int, 0600); MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); @@ -222,8 +193,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct, } /****************************************************************************/ -int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, - u_int32_t * ip, u_int16_t * port) +static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, + u_int32_t * ip, u_int16_t * port) { unsigned char *p; @@ -1302,7 +1273,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct, DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); info->timeout = rrq->timeToLive; } else - info->timeout = 0; + info->timeout = default_rrq_ttl; return 0; } @@ -1713,18 +1684,17 @@ static int __init init(void) module_init(init); module_exit(fini); -EXPORT_SYMBOL(get_h245_addr); -EXPORT_SYMBOL(get_h225_addr); -EXPORT_SYMBOL(ip_conntrack_h245_expect); -EXPORT_SYMBOL(ip_conntrack_q931_expect); -EXPORT_SYMBOL(set_h245_addr_hook); -EXPORT_SYMBOL(set_h225_addr_hook); -EXPORT_SYMBOL(set_sig_addr_hook); -EXPORT_SYMBOL(set_ras_addr_hook); -EXPORT_SYMBOL(nat_rtp_rtcp_hook); -EXPORT_SYMBOL(nat_t120_hook); -EXPORT_SYMBOL(nat_h245_hook); -EXPORT_SYMBOL(nat_q931_hook); +EXPORT_SYMBOL_GPL(get_h225_addr); +EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect); +EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect); +EXPORT_SYMBOL_GPL(set_h245_addr_hook); +EXPORT_SYMBOL_GPL(set_h225_addr_hook); +EXPORT_SYMBOL_GPL(set_sig_addr_hook); +EXPORT_SYMBOL_GPL(set_ras_addr_hook); +EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook); +EXPORT_SYMBOL_GPL(nat_t120_hook); +EXPORT_SYMBOL_GPL(nat_h245_hook); +EXPORT_SYMBOL_GPL(nat_q931_hook); MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); MODULE_DESCRIPTION("H.323 connection tracking helper"); diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c index afa525129b5..48078002e45 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c @@ -15,7 +15,7 @@ #else #include <stdio.h> #endif -#include "ip_conntrack_helper_h323_asn1.h" +#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h> /* Trace Flag */ #ifndef H323_TRACE diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h deleted file mode 100644 index 0bd828081c0..00000000000 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** - * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323 - * conntrack/NAT module. - * - * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com> - * - * This source code is licensed under General Public License version 2. - * - * - * This library is based on H.225 version 4, H.235 version 2 and H.245 - * version 7. It is extremely optimized to decode only the absolutely - * necessary objects in a signal for Linux kernel NAT module use, so don't - * expect it to be a full ASN.1 library. - * - * Features: - * - * 1. Small. The total size of code plus data is less than 20 KB (IA32). - * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866 - * takes only 3.9 seconds. - * 3. No memory allocation. It uses a static object. No need to initialize or - * cleanup. - * 4. Thread safe. - * 5. Support embedded architectures that has no misaligned memory access - * support. - * - * Limitations: - * - * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU. - * If a Setup signal contains more than 30 faststart, the packet size will - * very likely exceed the MTU size, then the TPKT will be fragmented. I - * don't know how to handle this in a Netfilter module. Anybody can help? - * Although I think 30 is enough for most of the cases. - * 2. IPv4 addresses only. - * - ****************************************************************************/ - -#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_ -#define _IP_CONNTRACK_HELPER_H323_ASN1_H_ - -/***************************************************************************** - * H.323 Types - ****************************************************************************/ -#include "ip_conntrack_helper_h323_types.h" - -typedef struct { - enum { - Q931_NationalEscape = 0x00, - Q931_Alerting = 0x01, - Q931_CallProceeding = 0x02, - Q931_Connect = 0x07, - Q931_ConnectAck = 0x0F, - Q931_Progress = 0x03, - Q931_Setup = 0x05, - Q931_SetupAck = 0x0D, - Q931_Resume = 0x26, - Q931_ResumeAck = 0x2E, - Q931_ResumeReject = 0x22, - Q931_Suspend = 0x25, - Q931_SuspendAck = 0x2D, - Q931_SuspendReject = 0x21, - Q931_UserInformation = 0x20, - Q931_Disconnect = 0x45, - Q931_Release = 0x4D, - Q931_ReleaseComplete = 0x5A, - Q931_Restart = 0x46, - Q931_RestartAck = 0x4E, - Q931_Segment = 0x60, - Q931_CongestionCtrl = 0x79, - Q931_Information = 0x7B, - Q931_Notify = 0x6E, - Q931_Status = 0x7D, - Q931_StatusEnquiry = 0x75, - Q931_Facility = 0x62 - } MessageType; - H323_UserInformation UUIE; -} Q931; - -/***************************************************************************** - * Decode Functions Return Codes - ****************************************************************************/ - -#define H323_ERROR_NONE 0 /* Decoded successfully */ -#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */ -#define H323_ERROR_BOUND -1 -#define H323_ERROR_RANGE -2 - - -/***************************************************************************** - * Decode Functions - ****************************************************************************/ - -int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras); -int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931); -int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, - MultimediaSystemControlMessage * - mscm); - -#endif diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h deleted file mode 100644 index cc98f7aa5ab..00000000000 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h +++ /dev/null @@ -1,938 +0,0 @@ -/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006 - * - * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net> - * - * This source code is licensed under General Public License version 2. - */ - -typedef struct TransportAddress_ipAddress { /* SEQUENCE */ - int options; /* No use */ - unsigned ip; -} TransportAddress_ipAddress; - -typedef struct TransportAddress { /* CHOICE */ - enum { - eTransportAddress_ipAddress, - eTransportAddress_ipSourceRoute, - eTransportAddress_ipxAddress, - eTransportAddress_ip6Address, - eTransportAddress_netBios, - eTransportAddress_nsap, - eTransportAddress_nonStandardAddress, - } choice; - union { - TransportAddress_ipAddress ipAddress; - }; -} TransportAddress; - -typedef struct DataProtocolCapability { /* CHOICE */ - enum { - eDataProtocolCapability_nonStandard, - eDataProtocolCapability_v14buffered, - eDataProtocolCapability_v42lapm, - eDataProtocolCapability_hdlcFrameTunnelling, - eDataProtocolCapability_h310SeparateVCStack, - eDataProtocolCapability_h310SingleVCStack, - eDataProtocolCapability_transparent, - eDataProtocolCapability_segmentationAndReassembly, - eDataProtocolCapability_hdlcFrameTunnelingwSAR, - eDataProtocolCapability_v120, - eDataProtocolCapability_separateLANStack, - eDataProtocolCapability_v76wCompression, - eDataProtocolCapability_tcp, - eDataProtocolCapability_udp, - } choice; -} DataProtocolCapability; - -typedef struct DataApplicationCapability_application { /* CHOICE */ - enum { - eDataApplicationCapability_application_nonStandard, - eDataApplicationCapability_application_t120, - eDataApplicationCapability_application_dsm_cc, - eDataApplicationCapability_application_userData, - eDataApplicationCapability_application_t84, - eDataApplicationCapability_application_t434, - eDataApplicationCapability_application_h224, - eDataApplicationCapability_application_nlpid, - eDataApplicationCapability_application_dsvdControl, - eDataApplicationCapability_application_h222DataPartitioning, - eDataApplicationCapability_application_t30fax, - eDataApplicationCapability_application_t140, - eDataApplicationCapability_application_t38fax, - eDataApplicationCapability_application_genericDataCapability, - } choice; - union { - DataProtocolCapability t120; - }; -} DataApplicationCapability_application; - -typedef struct DataApplicationCapability { /* SEQUENCE */ - int options; /* No use */ - DataApplicationCapability_application application; -} DataApplicationCapability; - -typedef struct DataType { /* CHOICE */ - enum { - eDataType_nonStandard, - eDataType_nullData, - eDataType_videoData, - eDataType_audioData, - eDataType_data, - eDataType_encryptionData, - eDataType_h235Control, - eDataType_h235Media, - eDataType_multiplexedStream, - } choice; - union { - DataApplicationCapability data; - }; -} DataType; - -typedef struct UnicastAddress_iPAddress { /* SEQUENCE */ - int options; /* No use */ - unsigned network; -} UnicastAddress_iPAddress; - -typedef struct UnicastAddress { /* CHOICE */ - enum { - eUnicastAddress_iPAddress, - eUnicastAddress_iPXAddress, - eUnicastAddress_iP6Address, - eUnicastAddress_netBios, - eUnicastAddress_iPSourceRouteAddress, - eUnicastAddress_nsap, - eUnicastAddress_nonStandardAddress, - } choice; - union { - UnicastAddress_iPAddress iPAddress; - }; -} UnicastAddress; - -typedef struct H245_TransportAddress { /* CHOICE */ - enum { - eH245_TransportAddress_unicastAddress, - eH245_TransportAddress_multicastAddress, - } choice; - union { - UnicastAddress unicastAddress; - }; -} H245_TransportAddress; - -typedef struct H2250LogicalChannelParameters { /* SEQUENCE */ - enum { - eH2250LogicalChannelParameters_nonStandard = (1 << 31), - eH2250LogicalChannelParameters_associatedSessionID = - (1 << 30), - eH2250LogicalChannelParameters_mediaChannel = (1 << 29), - eH2250LogicalChannelParameters_mediaGuaranteedDelivery = - (1 << 28), - eH2250LogicalChannelParameters_mediaControlChannel = - (1 << 27), - eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery - = (1 << 26), - eH2250LogicalChannelParameters_silenceSuppression = (1 << 25), - eH2250LogicalChannelParameters_destination = (1 << 24), - eH2250LogicalChannelParameters_dynamicRTPPayloadType = - (1 << 23), - eH2250LogicalChannelParameters_mediaPacketization = (1 << 22), - eH2250LogicalChannelParameters_transportCapability = - (1 << 21), - eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20), - eH2250LogicalChannelParameters_source = (1 << 19), - } options; - H245_TransportAddress mediaChannel; - H245_TransportAddress mediaControlChannel; -} H2250LogicalChannelParameters; - -typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */ - enum { - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none, - } choice; - union { - H2250LogicalChannelParameters h2250LogicalChannelParameters; - }; -} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters; - -typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */ - enum { - eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber - = (1 << 31), - eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency - = (1 << 30), - eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor - = (1 << 29), - } options; - DataType dataType; - OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters - multiplexParameters; -} OpenLogicalChannel_forwardLogicalChannelParameters; - -typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ - enum { - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, - } choice; - union { - H2250LogicalChannelParameters h2250LogicalChannelParameters; - }; -} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters; - -typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */ - enum { - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters - = (1 << 31), - eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency - = (1 << 30), - eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor - = (1 << 29), - } options; - OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters - multiplexParameters; -} OpenLogicalChannel_reverseLogicalChannelParameters; - -typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */ - enum { - eNetworkAccessParameters_networkAddress_q2931Address, - eNetworkAccessParameters_networkAddress_e164Address, - eNetworkAccessParameters_networkAddress_localAreaAddress, - } choice; - union { - H245_TransportAddress localAreaAddress; - }; -} NetworkAccessParameters_networkAddress; - -typedef struct NetworkAccessParameters { /* SEQUENCE */ - enum { - eNetworkAccessParameters_distribution = (1 << 31), - eNetworkAccessParameters_externalReference = (1 << 30), - eNetworkAccessParameters_t120SetupProcedure = (1 << 29), - } options; - NetworkAccessParameters_networkAddress networkAddress; -} NetworkAccessParameters; - -typedef struct OpenLogicalChannel { /* SEQUENCE */ - enum { - eOpenLogicalChannel_reverseLogicalChannelParameters = - (1 << 31), - eOpenLogicalChannel_separateStack = (1 << 30), - eOpenLogicalChannel_encryptionSync = (1 << 29), - } options; - OpenLogicalChannel_forwardLogicalChannelParameters - forwardLogicalChannelParameters; - OpenLogicalChannel_reverseLogicalChannelParameters - reverseLogicalChannelParameters; - NetworkAccessParameters separateStack; -} OpenLogicalChannel; - -typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Setup_UUIE_fastStart; - -typedef struct Setup_UUIE { /* SEQUENCE */ - enum { - eSetup_UUIE_h245Address = (1 << 31), - eSetup_UUIE_sourceAddress = (1 << 30), - eSetup_UUIE_destinationAddress = (1 << 29), - eSetup_UUIE_destCallSignalAddress = (1 << 28), - eSetup_UUIE_destExtraCallInfo = (1 << 27), - eSetup_UUIE_destExtraCRV = (1 << 26), - eSetup_UUIE_callServices = (1 << 25), - eSetup_UUIE_sourceCallSignalAddress = (1 << 24), - eSetup_UUIE_remoteExtensionAddress = (1 << 23), - eSetup_UUIE_callIdentifier = (1 << 22), - eSetup_UUIE_h245SecurityCapability = (1 << 21), - eSetup_UUIE_tokens = (1 << 20), - eSetup_UUIE_cryptoTokens = (1 << 19), - eSetup_UUIE_fastStart = (1 << 18), - eSetup_UUIE_mediaWaitForConnect = (1 << 17), - eSetup_UUIE_canOverlapSend = (1 << 16), - eSetup_UUIE_endpointIdentifier = (1 << 15), - eSetup_UUIE_multipleCalls = (1 << 14), - eSetup_UUIE_maintainConnection = (1 << 13), - eSetup_UUIE_connectionParameters = (1 << 12), - eSetup_UUIE_language = (1 << 11), - eSetup_UUIE_presentationIndicator = (1 << 10), - eSetup_UUIE_screeningIndicator = (1 << 9), - eSetup_UUIE_serviceControl = (1 << 8), - eSetup_UUIE_symmetricOperationRequired = (1 << 7), - eSetup_UUIE_capacity = (1 << 6), - eSetup_UUIE_circuitInfo = (1 << 5), - eSetup_UUIE_desiredProtocols = (1 << 4), - eSetup_UUIE_neededFeatures = (1 << 3), - eSetup_UUIE_desiredFeatures = (1 << 2), - eSetup_UUIE_supportedFeatures = (1 << 1), - eSetup_UUIE_parallelH245Control = (1 << 0), - } options; - TransportAddress h245Address; - TransportAddress destCallSignalAddress; - TransportAddress sourceCallSignalAddress; - Setup_UUIE_fastStart fastStart; -} Setup_UUIE; - -typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} CallProceeding_UUIE_fastStart; - -typedef struct CallProceeding_UUIE { /* SEQUENCE */ - enum { - eCallProceeding_UUIE_h245Address = (1 << 31), - eCallProceeding_UUIE_callIdentifier = (1 << 30), - eCallProceeding_UUIE_h245SecurityMode = (1 << 29), - eCallProceeding_UUIE_tokens = (1 << 28), - eCallProceeding_UUIE_cryptoTokens = (1 << 27), - eCallProceeding_UUIE_fastStart = (1 << 26), - eCallProceeding_UUIE_multipleCalls = (1 << 25), - eCallProceeding_UUIE_maintainConnection = (1 << 24), - eCallProceeding_UUIE_fastConnectRefused = (1 << 23), - eCallProceeding_UUIE_featureSet = (1 << 22), - } options; - TransportAddress h245Address; - CallProceeding_UUIE_fastStart fastStart; -} CallProceeding_UUIE; - -typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Connect_UUIE_fastStart; - -typedef struct Connect_UUIE { /* SEQUENCE */ - enum { - eConnect_UUIE_h245Address = (1 << 31), - eConnect_UUIE_callIdentifier = (1 << 30), - eConnect_UUIE_h245SecurityMode = (1 << 29), - eConnect_UUIE_tokens = (1 << 28), - eConnect_UUIE_cryptoTokens = (1 << 27), - eConnect_UUIE_fastStart = (1 << 26), - eConnect_UUIE_multipleCalls = (1 << 25), - eConnect_UUIE_maintainConnection = (1 << 24), - eConnect_UUIE_language = (1 << 23), - eConnect_UUIE_connectedAddress = (1 << 22), - eConnect_UUIE_presentationIndicator = (1 << 21), - eConnect_UUIE_screeningIndicator = (1 << 20), - eConnect_UUIE_fastConnectRefused = (1 << 19), - eConnect_UUIE_serviceControl = (1 << 18), - eConnect_UUIE_capacity = (1 << 17), - eConnect_UUIE_featureSet = (1 << 16), - } options; - TransportAddress h245Address; - Connect_UUIE_fastStart fastStart; -} Connect_UUIE; - -typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Alerting_UUIE_fastStart; - -typedef struct Alerting_UUIE { /* SEQUENCE */ - enum { - eAlerting_UUIE_h245Address = (1 << 31), - eAlerting_UUIE_callIdentifier = (1 << 30), - eAlerting_UUIE_h245SecurityMode = (1 << 29), - eAlerting_UUIE_tokens = (1 << 28), - eAlerting_UUIE_cryptoTokens = (1 << 27), - eAlerting_UUIE_fastStart = (1 << 26), - eAlerting_UUIE_multipleCalls = (1 << 25), - eAlerting_UUIE_maintainConnection = (1 << 24), - eAlerting_UUIE_alertingAddress = (1 << 23), - eAlerting_UUIE_presentationIndicator = (1 << 22), - eAlerting_UUIE_screeningIndicator = (1 << 21), - eAlerting_UUIE_fastConnectRefused = (1 << 20), - eAlerting_UUIE_serviceControl = (1 << 19), - eAlerting_UUIE_capacity = (1 << 18), - eAlerting_UUIE_featureSet = (1 << 17), - } options; - TransportAddress h245Address; - Alerting_UUIE_fastStart fastStart; -} Alerting_UUIE; - -typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Information_UUIE_fastStart; - -typedef struct Information_UUIE { /* SEQUENCE */ - enum { - eInformation_UUIE_callIdentifier = (1 << 31), - eInformation_UUIE_tokens = (1 << 30), - eInformation_UUIE_cryptoTokens = (1 << 29), - eInformation_UUIE_fastStart = (1 << 28), - eInformation_UUIE_fastConnectRefused = (1 << 27), - eInformation_UUIE_circuitInfo = (1 << 26), - } options; - Information_UUIE_fastStart fastStart; -} Information_UUIE; - -typedef struct FacilityReason { /* CHOICE */ - enum { - eFacilityReason_routeCallToGatekeeper, - eFacilityReason_callForwarded, - eFacilityReason_routeCallToMC, - eFacilityReason_undefinedReason, - eFacilityReason_conferenceListChoice, - eFacilityReason_startH245, - eFacilityReason_noH245, - eFacilityReason_newTokens, - eFacilityReason_featureSetUpdate, - eFacilityReason_forwardedElements, - eFacilityReason_transportedInformation, - } choice; -} FacilityReason; - -typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Facility_UUIE_fastStart; - -typedef struct Facility_UUIE { /* SEQUENCE */ - enum { - eFacility_UUIE_alternativeAddress = (1 << 31), - eFacility_UUIE_alternativeAliasAddress = (1 << 30), - eFacility_UUIE_conferenceID = (1 << 29), - eFacility_UUIE_callIdentifier = (1 << 28), - eFacility_UUIE_destExtraCallInfo = (1 << 27), - eFacility_UUIE_remoteExtensionAddress = (1 << 26), - eFacility_UUIE_tokens = (1 << 25), - eFacility_UUIE_cryptoTokens = (1 << 24), - eFacility_UUIE_conferences = (1 << 23), - eFacility_UUIE_h245Address = (1 << 22), - eFacility_UUIE_fastStart = (1 << 21), - eFacility_UUIE_multipleCalls = (1 << 20), - eFacility_UUIE_maintainConnection = (1 << 19), - eFacility_UUIE_fastConnectRefused = (1 << 18), - eFacility_UUIE_serviceControl = (1 << 17), - eFacility_UUIE_circuitInfo = (1 << 16), - eFacility_UUIE_featureSet = (1 << 15), - eFacility_UUIE_destinationInfo = (1 << 14), - eFacility_UUIE_h245SecurityMode = (1 << 13), - } options; - FacilityReason reason; - TransportAddress h245Address; - Facility_UUIE_fastStart fastStart; -} Facility_UUIE; - -typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Progress_UUIE_fastStart; - -typedef struct Progress_UUIE { /* SEQUENCE */ - enum { - eProgress_UUIE_h245Address = (1 << 31), - eProgress_UUIE_h245SecurityMode = (1 << 30), - eProgress_UUIE_tokens = (1 << 29), - eProgress_UUIE_cryptoTokens = (1 << 28), - eProgress_UUIE_fastStart = (1 << 27), - eProgress_UUIE_multipleCalls = (1 << 26), - eProgress_UUIE_maintainConnection = (1 << 25), - eProgress_UUIE_fastConnectRefused = (1 << 24), - } options; - TransportAddress h245Address; - Progress_UUIE_fastStart fastStart; -} Progress_UUIE; - -typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */ - enum { - eH323_UU_PDU_h323_message_body_setup, - eH323_UU_PDU_h323_message_body_callProceeding, - eH323_UU_PDU_h323_message_body_connect, - eH323_UU_PDU_h323_message_body_alerting, - eH323_UU_PDU_h323_message_body_information, - eH323_UU_PDU_h323_message_body_releaseComplete, - eH323_UU_PDU_h323_message_body_facility, - eH323_UU_PDU_h323_message_body_progress, - eH323_UU_PDU_h323_message_body_empty, - eH323_UU_PDU_h323_message_body_status, - eH323_UU_PDU_h323_message_body_statusInquiry, - eH323_UU_PDU_h323_message_body_setupAcknowledge, - eH323_UU_PDU_h323_message_body_notify, - } choice; - union { - Setup_UUIE setup; - CallProceeding_UUIE callProceeding; - Connect_UUIE connect; - Alerting_UUIE alerting; - Information_UUIE information; - Facility_UUIE facility; - Progress_UUIE progress; - }; -} H323_UU_PDU_h323_message_body; - -typedef struct RequestMessage { /* CHOICE */ - enum { - eRequestMessage_nonStandard, - eRequestMessage_masterSlaveDetermination, - eRequestMessage_terminalCapabilitySet, - eRequestMessage_openLogicalChannel, - eRequestMessage_closeLogicalChannel, - eRequestMessage_requestChannelClose, - eRequestMessage_multiplexEntrySend, - eRequestMessage_requestMultiplexEntry, - eRequestMessage_requestMode, - eRequestMessage_roundTripDelayRequest, - eRequestMessage_maintenanceLoopRequest, - eRequestMessage_communicationModeRequest, - eRequestMessage_conferenceRequest, - eRequestMessage_multilinkRequest, - eRequestMessage_logicalChannelRateRequest, - } choice; - union { - OpenLogicalChannel openLogicalChannel; - }; -} RequestMessage; - -typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ - enum { - eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, - eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, - } choice; - union { - H2250LogicalChannelParameters h2250LogicalChannelParameters; - }; -} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters; - -typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */ - enum { - eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber - = (1 << 31), - eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters - = (1 << 30), - eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor - = (1 << 29), - } options; - OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters - multiplexParameters; -} OpenLogicalChannelAck_reverseLogicalChannelParameters; - -typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */ - enum { - eH2250LogicalChannelAckParameters_nonStandard = (1 << 31), - eH2250LogicalChannelAckParameters_sessionID = (1 << 30), - eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29), - eH2250LogicalChannelAckParameters_mediaControlChannel = - (1 << 28), - eH2250LogicalChannelAckParameters_dynamicRTPPayloadType = - (1 << 27), - eH2250LogicalChannelAckParameters_flowControlToZero = - (1 << 26), - eH2250LogicalChannelAckParameters_portNumber = (1 << 25), - } options; - H245_TransportAddress mediaChannel; - H245_TransportAddress mediaControlChannel; -} H2250LogicalChannelAckParameters; - -typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */ - enum { - eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters, - } choice; - union { - H2250LogicalChannelAckParameters - h2250LogicalChannelAckParameters; - }; -} OpenLogicalChannelAck_forwardMultiplexAckParameters; - -typedef struct OpenLogicalChannelAck { /* SEQUENCE */ - enum { - eOpenLogicalChannelAck_reverseLogicalChannelParameters = - (1 << 31), - eOpenLogicalChannelAck_separateStack = (1 << 30), - eOpenLogicalChannelAck_forwardMultiplexAckParameters = - (1 << 29), - eOpenLogicalChannelAck_encryptionSync = (1 << 28), - } options; - OpenLogicalChannelAck_reverseLogicalChannelParameters - reverseLogicalChannelParameters; - OpenLogicalChannelAck_forwardMultiplexAckParameters - forwardMultiplexAckParameters; -} OpenLogicalChannelAck; - -typedef struct ResponseMessage { /* CHOICE */ - enum { - eResponseMessage_nonStandard, - eResponseMessage_masterSlaveDeterminationAck, - eResponseMessage_masterSlaveDeterminationReject, - eResponseMessage_terminalCapabilitySetAck, - eResponseMessage_terminalCapabilitySetReject, - eResponseMessage_openLogicalChannelAck, - eResponseMessage_openLogicalChannelReject, - eResponseMessage_closeLogicalChannelAck, - eResponseMessage_requestChannelCloseAck, - eResponseMessage_requestChannelCloseReject, - eResponseMessage_multiplexEntrySendAck, - eResponseMessage_multiplexEntrySendReject, - eResponseMessage_requestMultiplexEntryAck, - eResponseMessage_requestMultiplexEntryReject, - eResponseMessage_requestModeAck, - eResponseMessage_requestModeReject, - eResponseMessage_roundTripDelayResponse, - eResponseMessage_maintenanceLoopAck, - eResponseMessage_maintenanceLoopReject, - eResponseMessage_communicationModeResponse, - eResponseMessage_conferenceResponse, - eResponseMessage_multilinkResponse, - eResponseMessage_logicalChannelRateAcknowledge, - eResponseMessage_logicalChannelRateReject, - } choice; - union { - OpenLogicalChannelAck openLogicalChannelAck; - }; -} ResponseMessage; - -typedef struct MultimediaSystemControlMessage { /* CHOICE */ - enum { - eMultimediaSystemControlMessage_request, - eMultimediaSystemControlMessage_response, - eMultimediaSystemControlMessage_command, - eMultimediaSystemControlMessage_indication, - } choice; - union { - RequestMessage request; - ResponseMessage response; - }; -} MultimediaSystemControlMessage; - -typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */ - int count; - MultimediaSystemControlMessage item[4]; -} H323_UU_PDU_h245Control; - -typedef struct H323_UU_PDU { /* SEQUENCE */ - enum { - eH323_UU_PDU_nonStandardData = (1 << 31), - eH323_UU_PDU_h4501SupplementaryService = (1 << 30), - eH323_UU_PDU_h245Tunneling = (1 << 29), - eH323_UU_PDU_h245Control = (1 << 28), - eH323_UU_PDU_nonStandardControl = (1 << 27), - eH323_UU_PDU_callLinkage = (1 << 26), - eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25), - eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24), - eH323_UU_PDU_stimulusControl = (1 << 23), - eH323_UU_PDU_genericData = (1 << 22), - } options; - H323_UU_PDU_h323_message_body h323_message_body; - H323_UU_PDU_h245Control h245Control; -} H323_UU_PDU; - -typedef struct H323_UserInformation { /* SEQUENCE */ - enum { - eH323_UserInformation_user_data = (1 << 31), - } options; - H323_UU_PDU h323_uu_pdu; -} H323_UserInformation; - -typedef struct GatekeeperRequest { /* SEQUENCE */ - enum { - eGatekeeperRequest_nonStandardData = (1 << 31), - eGatekeeperRequest_gatekeeperIdentifier = (1 << 30), - eGatekeeperRequest_callServices = (1 << 29), - eGatekeeperRequest_endpointAlias = (1 << 28), - eGatekeeperRequest_alternateEndpoints = (1 << 27), - eGatekeeperRequest_tokens = (1 << 26), - eGatekeeperRequest_cryptoTokens = (1 << 25), - eGatekeeperRequest_authenticationCapability = (1 << 24), - eGatekeeperRequest_algorithmOIDs = (1 << 23), - eGatekeeperRequest_integrity = (1 << 22), - eGatekeeperRequest_integrityCheckValue = (1 << 21), - eGatekeeperRequest_supportsAltGK = (1 << 20), - eGatekeeperRequest_featureSet = (1 << 19), - eGatekeeperRequest_genericData = (1 << 18), - } options; - TransportAddress rasAddress; -} GatekeeperRequest; - -typedef struct GatekeeperConfirm { /* SEQUENCE */ - enum { - eGatekeeperConfirm_nonStandardData = (1 << 31), - eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30), - eGatekeeperConfirm_alternateGatekeeper = (1 << 29), - eGatekeeperConfirm_authenticationMode = (1 << 28), - eGatekeeperConfirm_tokens = (1 << 27), - eGatekeeperConfirm_cryptoTokens = (1 << 26), - eGatekeeperConfirm_algorithmOID = (1 << 25), - eGatekeeperConfirm_integrity = (1 << 24), - eGatekeeperConfirm_integrityCheckValue = (1 << 23), - eGatekeeperConfirm_featureSet = (1 << 22), - eGatekeeperConfirm_genericData = (1 << 21), - } options; - TransportAddress rasAddress; -} GatekeeperConfirm; - -typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} RegistrationRequest_callSignalAddress; - -typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} RegistrationRequest_rasAddress; - -typedef struct RegistrationRequest { /* SEQUENCE */ - enum { - eRegistrationRequest_nonStandardData = (1 << 31), - eRegistrationRequest_terminalAlias = (1 << 30), - eRegistrationRequest_gatekeeperIdentifier = (1 << 29), - eRegistrationRequest_alternateEndpoints = (1 << 28), - eRegistrationRequest_timeToLive = (1 << 27), - eRegistrationRequest_tokens = (1 << 26), - eRegistrationRequest_cryptoTokens = (1 << 25), - eRegistrationRequest_integrityCheckValue = (1 << 24), - eRegistrationRequest_keepAlive = (1 << 23), - eRegistrationRequest_endpointIdentifier = (1 << 22), - eRegistrationRequest_willSupplyUUIEs = (1 << 21), - eRegistrationRequest_maintainConnection = (1 << 20), - eRegistrationRequest_alternateTransportAddresses = (1 << 19), - eRegistrationRequest_additiveRegistration = (1 << 18), - eRegistrationRequest_terminalAliasPattern = (1 << 17), - eRegistrationRequest_supportsAltGK = (1 << 16), - eRegistrationRequest_usageReportingCapability = (1 << 15), - eRegistrationRequest_multipleCalls = (1 << 14), - eRegistrationRequest_supportedH248Packages = (1 << 13), - eRegistrationRequest_callCreditCapability = (1 << 12), - eRegistrationRequest_capacityReportingCapability = (1 << 11), - eRegistrationRequest_capacity = (1 << 10), - eRegistrationRequest_featureSet = (1 << 9), - eRegistrationRequest_genericData = (1 << 8), - } options; - RegistrationRequest_callSignalAddress callSignalAddress; - RegistrationRequest_rasAddress rasAddress; - unsigned timeToLive; -} RegistrationRequest; - -typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} RegistrationConfirm_callSignalAddress; - -typedef struct RegistrationConfirm { /* SEQUENCE */ - enum { - eRegistrationConfirm_nonStandardData = (1 << 31), - eRegistrationConfirm_terminalAlias = (1 << 30), - eRegistrationConfirm_gatekeeperIdentifier = (1 << 29), - eRegistrationConfirm_alternateGatekeeper = (1 << 28), - eRegistrationConfirm_timeToLive = (1 << 27), - eRegistrationConfirm_tokens = (1 << 26), - eRegistrationConfirm_cryptoTokens = (1 << 25), - eRegistrationConfirm_integrityCheckValue = (1 << 24), - eRegistrationConfirm_willRespondToIRR = (1 << 23), - eRegistrationConfirm_preGrantedARQ = (1 << 22), - eRegistrationConfirm_maintainConnection = (1 << 21), - eRegistrationConfirm_serviceControl = (1 << 20), - eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19), - eRegistrationConfirm_terminalAliasPattern = (1 << 18), - eRegistrationConfirm_supportedPrefixes = (1 << 17), - eRegistrationConfirm_usageSpec = (1 << 16), - eRegistrationConfirm_featureServerAlias = (1 << 15), - eRegistrationConfirm_capacityReportingSpec = (1 << 14), - eRegistrationConfirm_featureSet = (1 << 13), - eRegistrationConfirm_genericData = (1 << 12), - } options; - RegistrationConfirm_callSignalAddress callSignalAddress; - unsigned timeToLive; -} RegistrationConfirm; - -typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} UnregistrationRequest_callSignalAddress; - -typedef struct UnregistrationRequest { /* SEQUENCE */ - enum { - eUnregistrationRequest_endpointAlias = (1 << 31), - eUnregistrationRequest_nonStandardData = (1 << 30), - eUnregistrationRequest_endpointIdentifier = (1 << 29), - eUnregistrationRequest_alternateEndpoints = (1 << 28), - eUnregistrationRequest_gatekeeperIdentifier = (1 << 27), - eUnregistrationRequest_tokens = (1 << 26), - eUnregistrationRequest_cryptoTokens = (1 << 25), - eUnregistrationRequest_integrityCheckValue = (1 << 24), - eUnregistrationRequest_reason = (1 << 23), - eUnregistrationRequest_endpointAliasPattern = (1 << 22), - eUnregistrationRequest_supportedPrefixes = (1 << 21), - eUnregistrationRequest_alternateGatekeeper = (1 << 20), - eUnregistrationRequest_genericData = (1 << 19), - } options; - UnregistrationRequest_callSignalAddress callSignalAddress; -} UnregistrationRequest; - -typedef struct AdmissionRequest { /* SEQUENCE */ - enum { - eAdmissionRequest_callModel = (1 << 31), - eAdmissionRequest_destinationInfo = (1 << 30), - eAdmissionRequest_destCallSignalAddress = (1 << 29), - eAdmissionRequest_destExtraCallInfo = (1 << 28), - eAdmissionRequest_srcCallSignalAddress = (1 << 27), - eAdmissionRequest_nonStandardData = (1 << 26), - eAdmissionRequest_callServices = (1 << 25), - eAdmissionRequest_canMapAlias = (1 << 24), - eAdmissionRequest_callIdentifier = (1 << 23), - eAdmissionRequest_srcAlternatives = (1 << 22), - eAdmissionRequest_destAlternatives = (1 << 21), - eAdmissionRequest_gatekeeperIdentifier = (1 << 20), - eAdmissionRequest_tokens = (1 << 19), - eAdmissionRequest_cryptoTokens = (1 << 18), - eAdmissionRequest_integrityCheckValue = (1 << 17), - eAdmissionRequest_transportQOS = (1 << 16), - eAdmissionRequest_willSupplyUUIEs = (1 << 15), - eAdmissionRequest_callLinkage = (1 << 14), - eAdmissionRequest_gatewayDataRate = (1 << 13), - eAdmissionRequest_capacity = (1 << 12), - eAdmissionRequest_circuitInfo = (1 << 11), - eAdmissionRequest_desiredProtocols = (1 << 10), - eAdmissionRequest_desiredTunnelledProtocol = (1 << 9), - eAdmissionRequest_featureSet = (1 << 8), - eAdmissionRequest_genericData = (1 << 7), - } options; - TransportAddress destCallSignalAddress; - TransportAddress srcCallSignalAddress; -} AdmissionRequest; - -typedef struct AdmissionConfirm { /* SEQUENCE */ - enum { - eAdmissionConfirm_irrFrequency = (1 << 31), - eAdmissionConfirm_nonStandardData = (1 << 30), - eAdmissionConfirm_destinationInfo = (1 << 29), - eAdmissionConfirm_destExtraCallInfo = (1 << 28), - eAdmissionConfirm_destinationType = (1 << 27), - eAdmissionConfirm_remoteExtensionAddress = (1 << 26), - eAdmissionConfirm_alternateEndpoints = (1 << 25), - eAdmissionConfirm_tokens = (1 << 24), - eAdmissionConfirm_cryptoTokens = (1 << 23), - eAdmissionConfirm_integrityCheckValue = (1 << 22), - eAdmissionConfirm_transportQOS = (1 << 21), - eAdmissionConfirm_willRespondToIRR = (1 << 20), - eAdmissionConfirm_uuiesRequested = (1 << 19), - eAdmissionConfirm_language = (1 << 18), - eAdmissionConfirm_alternateTransportAddresses = (1 << 17), - eAdmissionConfirm_useSpecifiedTransport = (1 << 16), - eAdmissionConfirm_circuitInfo = (1 << 15), - eAdmissionConfirm_usageSpec = (1 << 14), - eAdmissionConfirm_supportedProtocols = (1 << 13), - eAdmissionConfirm_serviceControl = (1 << 12), - eAdmissionConfirm_multipleCalls = (1 << 11), - eAdmissionConfirm_featureSet = (1 << 10), - eAdmissionConfirm_genericData = (1 << 9), - } options; - TransportAddress destCallSignalAddress; -} AdmissionConfirm; - -typedef struct LocationRequest { /* SEQUENCE */ - enum { - eLocationRequest_endpointIdentifier = (1 << 31), - eLocationRequest_nonStandardData = (1 << 30), - eLocationRequest_sourceInfo = (1 << 29), - eLocationRequest_canMapAlias = (1 << 28), - eLocationRequest_gatekeeperIdentifier = (1 << 27), - eLocationRequest_tokens = (1 << 26), - eLocationRequest_cryptoTokens = (1 << 25), - eLocationRequest_integrityCheckValue = (1 << 24), - eLocationRequest_desiredProtocols = (1 << 23), - eLocationRequest_desiredTunnelledProtocol = (1 << 22), - eLocationRequest_featureSet = (1 << 21), - eLocationRequest_genericData = (1 << 20), - eLocationRequest_hopCount = (1 << 19), - eLocationRequest_circuitInfo = (1 << 18), - } options; - TransportAddress replyAddress; -} LocationRequest; - -typedef struct LocationConfirm { /* SEQUENCE */ - enum { - eLocationConfirm_nonStandardData = (1 << 31), - eLocationConfirm_destinationInfo = (1 << 30), - eLocationConfirm_destExtraCallInfo = (1 << 29), - eLocationConfirm_destinationType = (1 << 28), - eLocationConfirm_remoteExtensionAddress = (1 << 27), - eLocationConfirm_alternateEndpoints = (1 << 26), - eLocationConfirm_tokens = (1 << 25), - eLocationConfirm_cryptoTokens = (1 << 24), - eLocationConfirm_integrityCheckValue = (1 << 23), - eLocationConfirm_alternateTransportAddresses = (1 << 22), - eLocationConfirm_supportedProtocols = (1 << 21), - eLocationConfirm_multipleCalls = (1 << 20), - eLocationConfirm_featureSet = (1 << 19), - eLocationConfirm_genericData = (1 << 18), - eLocationConfirm_circuitInfo = (1 << 17), - eLocationConfirm_serviceControl = (1 << 16), - } options; - TransportAddress callSignalAddress; - TransportAddress rasAddress; -} LocationConfirm; - -typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} InfoRequestResponse_callSignalAddress; - -typedef struct InfoRequestResponse { /* SEQUENCE */ - enum { - eInfoRequestResponse_nonStandardData = (1 << 31), - eInfoRequestResponse_endpointAlias = (1 << 30), - eInfoRequestResponse_perCallInfo = (1 << 29), - eInfoRequestResponse_tokens = (1 << 28), - eInfoRequestResponse_cryptoTokens = (1 << 27), - eInfoRequestResponse_integrityCheckValue = (1 << 26), - eInfoRequestResponse_needResponse = (1 << 25), - eInfoRequestResponse_capacity = (1 << 24), - eInfoRequestResponse_irrStatus = (1 << 23), - eInfoRequestResponse_unsolicited = (1 << 22), - eInfoRequestResponse_genericData = (1 << 21), - } options; - TransportAddress rasAddress; - InfoRequestResponse_callSignalAddress callSignalAddress; -} InfoRequestResponse; - -typedef struct RasMessage { /* CHOICE */ - enum { - eRasMessage_gatekeeperRequest, - eRasMessage_gatekeeperConfirm, - eRasMessage_gatekeeperReject, - eRasMessage_registrationRequest, - eRasMessage_registrationConfirm, - eRasMessage_registrationReject, - eRasMessage_unregistrationRequest, - eRasMessage_unregistrationConfirm, - eRasMessage_unregistrationReject, - eRasMessage_admissionRequest, - eRasMessage_admissionConfirm, - eRasMessage_admissionReject, - eRasMessage_bandwidthRequest, - eRasMessage_bandwidthConfirm, - eRasMessage_bandwidthReject, - eRasMessage_disengageRequest, - eRasMessage_disengageConfirm, - eRasMessage_disengageReject, - eRasMessage_locationRequest, - eRasMessage_locationConfirm, - eRasMessage_locationReject, - eRasMessage_infoRequest, - eRasMessage_infoRequestResponse, - eRasMessage_nonStandardMessage, - eRasMessage_unknownMessageResponse, - eRasMessage_requestInProgress, - eRasMessage_resourcesAvailableIndicate, - eRasMessage_resourcesAvailableConfirm, - eRasMessage_infoRequestAck, - eRasMessage_infoRequestNak, - eRasMessage_serviceControlIndication, - eRasMessage_serviceControlResponse, - } choice; - union { - GatekeeperRequest gatekeeperRequest; - GatekeeperConfirm gatekeeperConfirm; - RegistrationRequest registrationRequest; - RegistrationConfirm registrationConfirm; - UnregistrationRequest unregistrationRequest; - AdmissionRequest admissionRequest; - AdmissionConfirm admissionConfirm; - LocationRequest locationRequest; - LocationConfirm locationConfirm; - InfoRequestResponse infoRequestResponse; - }; -} RasMessage; diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 9b6e19bae90..01bd7cab936 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -1658,7 +1658,7 @@ static void __exit ctnetlink_exit(void) printk("ctnetlink: unregistering from nfnetlink.\n"); #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS - ip_conntrack_unregister_notifier(&ctnl_notifier_exp); + ip_conntrack_expect_unregister_notifier(&ctnl_notifier_exp); ip_conntrack_unregister_notifier(&ctnl_notifier); #endif diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c index 3021af0910f..d8b14a9010a 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c @@ -224,25 +224,14 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, } /* See ip_conntrack_proto_tcp.c */ - if (hooknum != NF_IP_PRE_ROUTING) - goto checksum_skipped; - - switch (skb->ip_summed) { - case CHECKSUM_HW: - if (!(u16)csum_fold(skb->csum)) - break; - /* fall through */ - case CHECKSUM_NONE: - skb->csum = 0; - if (__skb_checksum_complete(skb)) { - if (LOG_INVALID(IPPROTO_ICMP)) - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, - "ip_ct_icmp: bad ICMP checksum "); - return -NF_ACCEPT; - } + if (hooknum == NF_IP_PRE_ROUTING && + nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) { + if (LOG_INVALID(IPPROTO_ICMP)) + nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, + "ip_ct_icmp: bad ICMP checksum "); + return -NF_ACCEPT; } -checksum_skipped: /* * 18 is the highest 'known' ICMP type. Anything else is a mystery * diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index e0dc3706354..062b252b58a 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -870,11 +870,8 @@ static int tcp_error(struct sk_buff *skb, * and moreover root might send raw packets. */ /* FIXME: Source route IP option packets --RR */ - if (hooknum == NF_IP_PRE_ROUTING - && skb->ip_summed != CHECKSUM_UNNECESSARY - && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP, - skb->ip_summed == CHECKSUM_HW ? skb->csum - : skb_checksum(skb, iph->ihl*4, tcplen, 0))) { + if (hooknum == NF_IP_PRE_ROUTING && + nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) { if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, "ip_ct_tcp: bad TCP checksum "); diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c index 55b7d3210ad..70899868783 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c @@ -120,11 +120,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, * because the semantic of CHECKSUM_HW is different there * and moreover root might send raw packets. * FIXME: Source route IP option packets --RR */ - if (hooknum == NF_IP_PRE_ROUTING - && skb->ip_summed != CHECKSUM_UNNECESSARY - && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP, - skb->ip_summed == CHECKSUM_HW ? skb->csum - : skb_checksum(skb, iph->ihl*4, udplen, 0))) { + if (hooknum == NF_IP_PRE_ROUTING && + nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) { if (LOG_INVALID(IPPROTO_UDP)) nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, "ip_ct_udp: bad UDP checksum "); diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 52076026db3..929d61f7be9 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -469,70 +469,63 @@ static unsigned int ip_conntrack_local(unsigned int hooknum, /* Connection tracking may drop packets, but never alters them, so make it the first hook. */ -static struct nf_hook_ops ip_conntrack_defrag_ops = { - .hook = ip_conntrack_defrag, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, - .priority = NF_IP_PRI_CONNTRACK_DEFRAG, -}; - -static struct nf_hook_ops ip_conntrack_in_ops = { - .hook = ip_conntrack_in, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, - .priority = NF_IP_PRI_CONNTRACK, -}; - -static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = { - .hook = ip_conntrack_defrag, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, - .priority = NF_IP_PRI_CONNTRACK_DEFRAG, -}; - -static struct nf_hook_ops ip_conntrack_local_out_ops = { - .hook = ip_conntrack_local, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, - .priority = NF_IP_PRI_CONNTRACK, -}; - -/* helpers */ -static struct nf_hook_ops ip_conntrack_helper_out_ops = { - .hook = ip_conntrack_help, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, - .priority = NF_IP_PRI_CONNTRACK_HELPER, -}; - -static struct nf_hook_ops ip_conntrack_helper_in_ops = { - .hook = ip_conntrack_help, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, - .priority = NF_IP_PRI_CONNTRACK_HELPER, -}; - -/* Refragmenter; last chance. */ -static struct nf_hook_ops ip_conntrack_out_ops = { - .hook = ip_confirm, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, - .priority = NF_IP_PRI_CONNTRACK_CONFIRM, -}; - -static struct nf_hook_ops ip_conntrack_local_in_ops = { - .hook = ip_confirm, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, - .priority = NF_IP_PRI_CONNTRACK_CONFIRM, +static struct nf_hook_ops ip_conntrack_ops[] = { + { + .hook = ip_conntrack_defrag, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_PRE_ROUTING, + .priority = NF_IP_PRI_CONNTRACK_DEFRAG, + }, + { + .hook = ip_conntrack_in, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_PRE_ROUTING, + .priority = NF_IP_PRI_CONNTRACK, + }, + { + .hook = ip_conntrack_defrag, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_OUT, + .priority = NF_IP_PRI_CONNTRACK_DEFRAG, + }, + { + .hook = ip_conntrack_local, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_OUT, + .priority = NF_IP_PRI_CONNTRACK, + }, + { + .hook = ip_conntrack_help, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_CONNTRACK_HELPER, + }, + { + .hook = ip_conntrack_help, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_CONNTRACK_HELPER, + }, + { + .hook = ip_confirm, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_CONNTRACK_CONFIRM, + }, + { + .hook = ip_confirm, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_CONNTRACK_CONFIRM, + }, }; /* Sysctl support */ @@ -783,18 +776,46 @@ static ctl_table ip_ct_net_table[] = { EXPORT_SYMBOL(ip_ct_log_invalid); #endif /* CONFIG_SYSCTL */ -static int init_or_cleanup(int init) +/* FIXME: Allow NULL functions and sub in pointers to generic for + them. --RR */ +int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto) +{ + int ret = 0; + + write_lock_bh(&ip_conntrack_lock); + if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) { + ret = -EBUSY; + goto out; + } + ip_ct_protos[proto->proto] = proto; + out: + write_unlock_bh(&ip_conntrack_lock); + return ret; +} + +void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto) +{ + write_lock_bh(&ip_conntrack_lock); + ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol; + write_unlock_bh(&ip_conntrack_lock); + + /* Somebody could be still looking at the proto in bh. */ + synchronize_net(); + + /* Remove all contrack entries for this protocol */ + ip_ct_iterate_cleanup(kill_proto, &proto->proto); +} + +static int __init ip_conntrack_standalone_init(void) { #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc, *proc_exp, *proc_stat; #endif int ret = 0; - if (!init) goto cleanup; - ret = ip_conntrack_init(); if (ret < 0) - goto cleanup_nothing; + return ret; #ifdef CONFIG_PROC_FS ret = -ENOMEM; @@ -813,78 +834,25 @@ static int init_or_cleanup(int init) proc_stat->owner = THIS_MODULE; #endif - ret = nf_register_hook(&ip_conntrack_defrag_ops); + ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops)); if (ret < 0) { - printk("ip_conntrack: can't register pre-routing defrag hook.\n"); + printk("ip_conntrack: can't register hooks.\n"); goto cleanup_proc_stat; } - ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops); - if (ret < 0) { - printk("ip_conntrack: can't register local_out defrag hook.\n"); - goto cleanup_defragops; - } - ret = nf_register_hook(&ip_conntrack_in_ops); - if (ret < 0) { - printk("ip_conntrack: can't register pre-routing hook.\n"); - goto cleanup_defraglocalops; - } - ret = nf_register_hook(&ip_conntrack_local_out_ops); - if (ret < 0) { - printk("ip_conntrack: can't register local out hook.\n"); - goto cleanup_inops; - } - ret = nf_register_hook(&ip_conntrack_helper_in_ops); - if (ret < 0) { - printk("ip_conntrack: can't register local in helper hook.\n"); - goto cleanup_inandlocalops; - } - ret = nf_register_hook(&ip_conntrack_helper_out_ops); - if (ret < 0) { - printk("ip_conntrack: can't register postrouting helper hook.\n"); - goto cleanup_helperinops; - } - ret = nf_register_hook(&ip_conntrack_out_ops); - if (ret < 0) { - printk("ip_conntrack: can't register post-routing hook.\n"); - goto cleanup_helperoutops; - } - ret = nf_register_hook(&ip_conntrack_local_in_ops); - if (ret < 0) { - printk("ip_conntrack: can't register local in hook.\n"); - goto cleanup_inoutandlocalops; - } #ifdef CONFIG_SYSCTL ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0); if (ip_ct_sysctl_header == NULL) { printk("ip_conntrack: can't register to sysctl.\n"); ret = -ENOMEM; - goto cleanup_localinops; + goto cleanup_hooks; } #endif - return ret; - cleanup: - synchronize_net(); #ifdef CONFIG_SYSCTL - unregister_sysctl_table(ip_ct_sysctl_header); - cleanup_localinops: + cleanup_hooks: + nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops)); #endif - nf_unregister_hook(&ip_conntrack_local_in_ops); - cleanup_inoutandlocalops: - nf_unregister_hook(&ip_conntrack_out_ops); - cleanup_helperoutops: - nf_unregister_hook(&ip_conntrack_helper_out_ops); - cleanup_helperinops: - nf_unregister_hook(&ip_conntrack_helper_in_ops); - cleanup_inandlocalops: - nf_unregister_hook(&ip_conntrack_local_out_ops); - cleanup_inops: - nf_unregister_hook(&ip_conntrack_in_ops); - cleanup_defraglocalops: - nf_unregister_hook(&ip_conntrack_defrag_local_out_ops); - cleanup_defragops: - nf_unregister_hook(&ip_conntrack_defrag_ops); cleanup_proc_stat: #ifdef CONFIG_PROC_FS remove_proc_entry("ip_conntrack", proc_net_stat); @@ -895,48 +863,22 @@ static int init_or_cleanup(int init) cleanup_init: #endif /* CONFIG_PROC_FS */ ip_conntrack_cleanup(); - cleanup_nothing: - return ret; -} - -/* FIXME: Allow NULL functions and sub in pointers to generic for - them. --RR */ -int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto) -{ - int ret = 0; - - write_lock_bh(&ip_conntrack_lock); - if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) { - ret = -EBUSY; - goto out; - } - ip_ct_protos[proto->proto] = proto; - out: - write_unlock_bh(&ip_conntrack_lock); return ret; } -void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto) -{ - write_lock_bh(&ip_conntrack_lock); - ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol; - write_unlock_bh(&ip_conntrack_lock); - - /* Somebody could be still looking at the proto in bh. */ - synchronize_net(); - - /* Remove all contrack entries for this protocol */ - ip_ct_iterate_cleanup(kill_proto, &proto->proto); -} - -static int __init ip_conntrack_standalone_init(void) -{ - return init_or_cleanup(1); -} - static void __exit ip_conntrack_standalone_fini(void) { - init_or_cleanup(0); + synchronize_net(); +#ifdef CONFIG_SYSCTL + unregister_sysctl_table(ip_ct_sysctl_header); +#endif + nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops)); +#ifdef CONFIG_PROC_FS + remove_proc_entry("ip_conntrack", proc_net_stat); + proc_net_remove("ip_conntrack_expect"); + proc_net_remove("ip_conntrack"); +#endif /* CONFIG_PROC_FS */ + ip_conntrack_cleanup(); } module_init(ip_conntrack_standalone_init); diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c index a0bc883928c..d45663d137a 100644 --- a/net/ipv4/netfilter/ip_nat_helper_h323.c +++ b/net/ipv4/netfilter/ip_nat_helper_h323.c @@ -7,24 +7,6 @@ * * Based on the 'brute force' H.323 NAT module by * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> - * - * Changes: - * 2006-02-01 - initial version 0.1 - * - * 2006-02-20 - version 0.2 - * 1. Changed source format to follow kernel conventions - * 2. Deleted some unnecessary structures - * 3. Minor fixes - * - * 2006-03-10 - version 0.3 - * 1. Added support for multiple TPKTs in one packet (suggested by - * Patrick McHardy) - * 2. Added support for non-linear skb (based on Patrick McHardy's patch) - * 3. Eliminated unnecessary return code - * - * 2006-03-15 - version 0.4 - * 1. Added support for T.120 channels - * 2. Added parameter gkrouted_only (suggested by Patrick McHardy) */ #include <linux/module.h> @@ -41,65 +23,12 @@ #include <linux/netfilter_ipv4/ip_conntrack_h323.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h> -#include "ip_conntrack_helper_h323_asn1.h" - #if 0 #define DEBUGP printk #else #define DEBUGP(format, args...) #endif -extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, - u_int32_t * ip, u_int16_t * port); -extern int get_h225_addr(unsigned char *data, TransportAddress * addr, - u_int32_t * ip, u_int16_t * port); -extern void ip_conntrack_h245_expect(struct ip_conntrack *new, - struct ip_conntrack_expect *this); -extern void ip_conntrack_q931_expect(struct ip_conntrack *new, - struct ip_conntrack_expect *this); -extern int (*set_h245_addr_hook) (struct sk_buff ** pskb, - unsigned char **data, int dataoff, - H245_TransportAddress * addr, - u_int32_t ip, u_int16_t port); -extern int (*set_h225_addr_hook) (struct sk_buff ** pskb, - unsigned char **data, int dataoff, - TransportAddress * addr, - u_int32_t ip, u_int16_t port); -extern int (*set_sig_addr_hook) (struct sk_buff ** pskb, - struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, - TransportAddress * addr, int count); -extern int (*set_ras_addr_hook) (struct sk_buff ** pskb, - struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, - TransportAddress * addr, int count); -extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb, - struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, int dataoff, - H245_TransportAddress * addr, - u_int16_t port, u_int16_t rtp_port, - struct ip_conntrack_expect * rtp_exp, - struct ip_conntrack_expect * rtcp_exp); -extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, int dataoff, - H245_TransportAddress * addr, u_int16_t port, - struct ip_conntrack_expect * exp); -extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, int dataoff, - TransportAddress * addr, u_int16_t port, - struct ip_conntrack_expect * exp); -extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, TransportAddress * addr, - int idx, u_int16_t port, - struct ip_conntrack_expect * exp); - - /****************************************************************************/ static int set_addr(struct sk_buff **pskb, unsigned char **data, int dataoff, diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index efba8c4e42e..1aba926c1cb 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c @@ -279,7 +279,7 @@ static struct ipt_target ipt_dnat_reg = { .target = ipt_dnat_target, .targetsize = sizeof(struct ip_nat_multi_range_compat), .table = "nat", - .hooks = 1 << NF_IP_PRE_ROUTING, + .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT), .checkentry = ipt_dnat_checkentry, }; diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 3505b0de2e0..8f760b28617 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -299,69 +299,63 @@ ip_nat_adjust(unsigned int hooknum, /* We must be after connection tracking and before packet filtering. */ -/* Before packet filtering, change destination */ -static struct nf_hook_ops ip_nat_in_ops = { - .hook = ip_nat_in, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, - .priority = NF_IP_PRI_NAT_DST, +static struct nf_hook_ops ip_nat_ops[] = { + /* Before packet filtering, change destination */ + { + .hook = ip_nat_in, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_PRE_ROUTING, + .priority = NF_IP_PRI_NAT_DST, + }, + /* After packet filtering, change source */ + { + .hook = ip_nat_out, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_NAT_SRC, + }, + /* After conntrack, adjust sequence number */ + { + .hook = ip_nat_adjust, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_NAT_SEQ_ADJUST, + }, + /* Before packet filtering, change destination */ + { + .hook = ip_nat_local_fn, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_OUT, + .priority = NF_IP_PRI_NAT_DST, + }, + /* After packet filtering, change source */ + { + .hook = ip_nat_fn, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_NAT_SRC, + }, + /* After conntrack, adjust sequence number */ + { + .hook = ip_nat_adjust, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_NAT_SEQ_ADJUST, + }, }; -/* After packet filtering, change source */ -static struct nf_hook_ops ip_nat_out_ops = { - .hook = ip_nat_out, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, - .priority = NF_IP_PRI_NAT_SRC, -}; - -/* After conntrack, adjust sequence number */ -static struct nf_hook_ops ip_nat_adjust_out_ops = { - .hook = ip_nat_adjust, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, - .priority = NF_IP_PRI_NAT_SEQ_ADJUST, -}; - -/* Before packet filtering, change destination */ -static struct nf_hook_ops ip_nat_local_out_ops = { - .hook = ip_nat_local_fn, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, - .priority = NF_IP_PRI_NAT_DST, -}; - -/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */ -static struct nf_hook_ops ip_nat_local_in_ops = { - .hook = ip_nat_fn, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, - .priority = NF_IP_PRI_NAT_SRC, -}; - -/* After conntrack, adjust sequence number */ -static struct nf_hook_ops ip_nat_adjust_in_ops = { - .hook = ip_nat_adjust, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, - .priority = NF_IP_PRI_NAT_SEQ_ADJUST, -}; - - -static int init_or_cleanup(int init) +static int __init ip_nat_standalone_init(void) { int ret = 0; need_conntrack(); - if (!init) goto cleanup; - #ifdef CONFIG_XFRM BUG_ON(ip_nat_decode_session != NULL); ip_nat_decode_session = nat_decode_session; @@ -371,50 +365,13 @@ static int init_or_cleanup(int init) printk("ip_nat_init: can't setup rules.\n"); goto cleanup_decode_session; } - ret = nf_register_hook(&ip_nat_in_ops); + ret = nf_register_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops)); if (ret < 0) { - printk("ip_nat_init: can't register in hook.\n"); + printk("ip_nat_init: can't register hooks.\n"); goto cleanup_rule_init; } - ret = nf_register_hook(&ip_nat_out_ops); - if (ret < 0) { - printk("ip_nat_init: can't register out hook.\n"); - goto cleanup_inops; - } - ret = nf_register_hook(&ip_nat_adjust_in_ops); - if (ret < 0) { - printk("ip_nat_init: can't register adjust in hook.\n"); - goto cleanup_outops; - } - ret = nf_register_hook(&ip_nat_adjust_out_ops); - if (ret < 0) { - printk("ip_nat_init: can't register adjust out hook.\n"); - goto cleanup_adjustin_ops; - } - ret = nf_register_hook(&ip_nat_local_out_ops); - if (ret < 0) { - printk("ip_nat_init: can't register local out hook.\n"); - goto cleanup_adjustout_ops; - } - ret = nf_register_hook(&ip_nat_local_in_ops); - if (ret < 0) { - printk("ip_nat_init: can't register local in hook.\n"); - goto cleanup_localoutops; - } return ret; - cleanup: - nf_unregister_hook(&ip_nat_local_in_ops); - cleanup_localoutops: - nf_unregister_hook(&ip_nat_local_out_ops); - cleanup_adjustout_ops: - nf_unregister_hook(&ip_nat_adjust_out_ops); - cleanup_adjustin_ops: - nf_unregister_hook(&ip_nat_adjust_in_ops); - cleanup_outops: - nf_unregister_hook(&ip_nat_out_ops); - cleanup_inops: - nf_unregister_hook(&ip_nat_in_ops); cleanup_rule_init: ip_nat_rule_cleanup(); cleanup_decode_session: @@ -425,14 +382,14 @@ static int init_or_cleanup(int init) return ret; } -static int __init ip_nat_standalone_init(void) -{ - return init_or_cleanup(1); -} - static void __exit ip_nat_standalone_fini(void) { - init_or_cleanup(0); + nf_unregister_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops)); + ip_nat_rule_cleanup(); +#ifdef CONFIG_XFRM + ip_nat_decode_session = NULL; + synchronize_net(); +#endif } module_init(ip_nat_standalone_init); diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 896a244f8f9..b93f0494362 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -662,15 +662,11 @@ static struct nf_queue_handler nfqh = { .outfn = &ipq_enqueue_packet, }; -static int -init_or_cleanup(int init) +static int __init ip_queue_init(void) { int status = -ENOMEM; struct proc_dir_entry *proc; - if (!init) - goto cleanup; - netlink_register_notifier(&ipq_nl_notifier); ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk, THIS_MODULE); @@ -697,11 +693,6 @@ init_or_cleanup(int init) } return status; -cleanup: - nf_unregister_queue_handlers(&nfqh); - synchronize_net(); - ipq_flush(NF_DROP); - cleanup_sysctl: unregister_sysctl_table(ipq_sysctl_header); unregister_netdevice_notifier(&ipq_dev_notifier); @@ -717,15 +708,21 @@ cleanup_netlink_notifier: return status; } -static int __init ip_queue_init(void) -{ - - return init_or_cleanup(1); -} - static void __exit ip_queue_fini(void) { - init_or_cleanup(0); + nf_unregister_queue_handlers(&nfqh); + synchronize_net(); + ipq_flush(NF_DROP); + + unregister_sysctl_table(ipq_sysctl_header); + unregister_netdevice_notifier(&ipq_dev_notifier); + proc_net_remove(IPQ_PROC_FS_NAME); + + sock_release(ipqnl->sk_socket); + mutex_lock(&ipqnl_mutex); + mutex_unlock(&ipqnl_mutex); + + netlink_unregister_notifier(&ipq_nl_notifier); } MODULE_DESCRIPTION("IPv4 packet queue handler"); diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 460fd905fad..d25ac8ba6eb 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/icmp.h> #include <net/ip.h> +#include <net/compat.h> #include <asm/uaccess.h> #include <linux/mutex.h> #include <linux/proc_fs.h> @@ -734,7 +735,7 @@ translate_table(const char *name, } /* And one copy for every other CPU */ - for_each_cpu(i) { + for_each_possible_cpu(i) { if (newinfo->entries[i] && newinfo->entries[i] != entry0) memcpy(newinfo->entries[i], entry0, newinfo->size); } @@ -787,7 +788,7 @@ get_counters(const struct xt_table_info *t, counters, &i); - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { if (cpu == curcpu) continue; i = 0; @@ -799,17 +800,11 @@ get_counters(const struct xt_table_info *t, } } -static int -copy_entries_to_user(unsigned int total_size, - struct ipt_table *table, - void __user *userptr) +static inline struct xt_counters * alloc_counters(struct ipt_table *table) { - unsigned int off, num, countersize; - struct ipt_entry *e; + unsigned int countersize; struct xt_counters *counters; struct xt_table_info *private = table->private; - int ret = 0; - void *loc_cpu_entry; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care @@ -818,13 +813,32 @@ copy_entries_to_user(unsigned int total_size, counters = vmalloc_node(countersize, numa_node_id()); if (counters == NULL) - return -ENOMEM; + return ERR_PTR(-ENOMEM); /* First, sum counters... */ write_lock_bh(&table->lock); get_counters(private, counters); write_unlock_bh(&table->lock); + return counters; +} + +static int +copy_entries_to_user(unsigned int total_size, + struct ipt_table *table, + void __user *userptr) +{ + unsigned int off, num; + struct ipt_entry *e; + struct xt_counters *counters; + struct xt_table_info *private = table->private; + int ret = 0; + void *loc_cpu_entry; + + counters = alloc_counters(table); + if (IS_ERR(counters)) + return PTR_ERR(counters); + /* choose the copy that is on our node/cpu, ... * This choice is lazy (because current thread is * allowed to migrate to another cpu) @@ -884,25 +898,278 @@ copy_entries_to_user(unsigned int total_size, return ret; } +#ifdef CONFIG_COMPAT +struct compat_delta { + struct compat_delta *next; + u_int16_t offset; + short delta; +}; + +static struct compat_delta *compat_offsets = NULL; + +static int compat_add_offset(u_int16_t offset, short delta) +{ + struct compat_delta *tmp; + + tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + tmp->offset = offset; + tmp->delta = delta; + if (compat_offsets) { + tmp->next = compat_offsets->next; + compat_offsets->next = tmp; + } else { + compat_offsets = tmp; + tmp->next = NULL; + } + return 0; +} + +static void compat_flush_offsets(void) +{ + struct compat_delta *tmp, *next; + + if (compat_offsets) { + for(tmp = compat_offsets; tmp; tmp = next) { + next = tmp->next; + kfree(tmp); + } + compat_offsets = NULL; + } +} + +static short compat_calc_jump(u_int16_t offset) +{ + struct compat_delta *tmp; + short delta; + + for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next) + if (tmp->offset < offset) + delta += tmp->delta; + return delta; +} + +struct compat_ipt_standard_target +{ + struct compat_xt_entry_target target; + compat_int_t verdict; +}; + +#define IPT_ST_OFFSET (sizeof(struct ipt_standard_target) - \ + sizeof(struct compat_ipt_standard_target)) + +struct compat_ipt_standard +{ + struct compat_ipt_entry entry; + struct compat_ipt_standard_target target; +}; + +static int compat_ipt_standard_fn(void *target, + void **dstptr, int *size, int convert) +{ + struct compat_ipt_standard_target compat_st, *pcompat_st; + struct ipt_standard_target st, *pst; + int ret; + + ret = 0; + switch (convert) { + case COMPAT_TO_USER: + pst = (struct ipt_standard_target *)target; + memcpy(&compat_st.target, &pst->target, + sizeof(struct ipt_entry_target)); + compat_st.verdict = pst->verdict; + if (compat_st.verdict > 0) + compat_st.verdict -= + compat_calc_jump(compat_st.verdict); + compat_st.target.u.user.target_size = + sizeof(struct compat_ipt_standard_target); + if (__copy_to_user(*dstptr, &compat_st, + sizeof(struct compat_ipt_standard_target))) + ret = -EFAULT; + *size -= IPT_ST_OFFSET; + *dstptr += sizeof(struct compat_ipt_standard_target); + break; + case COMPAT_FROM_USER: + pcompat_st = + (struct compat_ipt_standard_target *)target; + memcpy(&st.target, &pcompat_st->target, + sizeof(struct ipt_entry_target)); + st.verdict = pcompat_st->verdict; + if (st.verdict > 0) + st.verdict += compat_calc_jump(st.verdict); + st.target.u.user.target_size = + sizeof(struct ipt_standard_target); + memcpy(*dstptr, &st, + sizeof(struct ipt_standard_target)); + *size += IPT_ST_OFFSET; + *dstptr += sizeof(struct ipt_standard_target); + break; + case COMPAT_CALC_SIZE: + *size += IPT_ST_OFFSET; + break; + default: + ret = -ENOPROTOOPT; + break; + } + return ret; +} + +static inline int +compat_calc_match(struct ipt_entry_match *m, int * size) +{ + if (m->u.kernel.match->compat) + m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE); + else + xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE); + return 0; +} + +static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info, + void *base, struct xt_table_info *newinfo) +{ + struct ipt_entry_target *t; + u_int16_t entry_offset; + int off, i, ret; + + off = 0; + entry_offset = (void *)e - base; + IPT_MATCH_ITERATE(e, compat_calc_match, &off); + t = ipt_get_target(e); + if (t->u.kernel.target->compat) + t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE); + else + xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE); + newinfo->size -= off; + ret = compat_add_offset(entry_offset, off); + if (ret) + return ret; + + for (i = 0; i< NF_IP_NUMHOOKS; i++) { + if (info->hook_entry[i] && (e < (struct ipt_entry *) + (base + info->hook_entry[i]))) + newinfo->hook_entry[i] -= off; + if (info->underflow[i] && (e < (struct ipt_entry *) + (base + info->underflow[i]))) + newinfo->underflow[i] -= off; + } + return 0; +} + +static int compat_table_info(struct xt_table_info *info, + struct xt_table_info *newinfo) +{ + void *loc_cpu_entry; + int i; + + if (!newinfo || !info) + return -EINVAL; + + memset(newinfo, 0, sizeof(struct xt_table_info)); + newinfo->size = info->size; + newinfo->number = info->number; + for (i = 0; i < NF_IP_NUMHOOKS; i++) { + newinfo->hook_entry[i] = info->hook_entry[i]; + newinfo->underflow[i] = info->underflow[i]; + } + loc_cpu_entry = info->entries[raw_smp_processor_id()]; + return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size, + compat_calc_entry, info, loc_cpu_entry, newinfo); +} +#endif + +static int get_info(void __user *user, int *len, int compat) +{ + char name[IPT_TABLE_MAXNAMELEN]; + struct ipt_table *t; + int ret; + + if (*len != sizeof(struct ipt_getinfo)) { + duprintf("length %u != %u\n", *len, + (unsigned int)sizeof(struct ipt_getinfo)); + return -EINVAL; + } + + if (copy_from_user(name, user, sizeof(name)) != 0) + return -EFAULT; + + name[IPT_TABLE_MAXNAMELEN-1] = '\0'; +#ifdef CONFIG_COMPAT + if (compat) + xt_compat_lock(AF_INET); +#endif + t = try_then_request_module(xt_find_table_lock(AF_INET, name), + "iptable_%s", name); + if (t && !IS_ERR(t)) { + struct ipt_getinfo info; + struct xt_table_info *private = t->private; + +#ifdef CONFIG_COMPAT + if (compat) { + struct xt_table_info tmp; + ret = compat_table_info(private, &tmp); + compat_flush_offsets(); + private = &tmp; + } +#endif + info.valid_hooks = t->valid_hooks; + memcpy(info.hook_entry, private->hook_entry, + sizeof(info.hook_entry)); + memcpy(info.underflow, private->underflow, + sizeof(info.underflow)); + info.num_entries = private->number; + info.size = private->size; + strcpy(info.name, name); + + if (copy_to_user(user, &info, *len) != 0) + ret = -EFAULT; + else + ret = 0; + + xt_table_unlock(t); + module_put(t->me); + } else + ret = t ? PTR_ERR(t) : -ENOENT; +#ifdef CONFIG_COMPAT + if (compat) + xt_compat_unlock(AF_INET); +#endif + return ret; +} + static int -get_entries(const struct ipt_get_entries *entries, - struct ipt_get_entries __user *uptr) +get_entries(struct ipt_get_entries __user *uptr, int *len) { int ret; + struct ipt_get_entries get; struct ipt_table *t; - t = xt_find_table_lock(AF_INET, entries->name); + if (*len < sizeof(get)) { + duprintf("get_entries: %u < %d\n", *len, + (unsigned int)sizeof(get)); + return -EINVAL; + } + if (copy_from_user(&get, uptr, sizeof(get)) != 0) + return -EFAULT; + if (*len != sizeof(struct ipt_get_entries) + get.size) { + duprintf("get_entries: %u != %u\n", *len, + (unsigned int)(sizeof(struct ipt_get_entries) + + get.size)); + return -EINVAL; + } + + t = xt_find_table_lock(AF_INET, get.name); if (t && !IS_ERR(t)) { struct xt_table_info *private = t->private; duprintf("t->private->number = %u\n", private->number); - if (entries->size == private->size) + if (get.size == private->size) ret = copy_entries_to_user(private->size, t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", private->size, - entries->size); + get.size); ret = -EINVAL; } module_put(t->me); @@ -914,79 +1181,47 @@ get_entries(const struct ipt_get_entries *entries, } static int -do_replace(void __user *user, unsigned int len) +__do_replace(const char *name, unsigned int valid_hooks, + struct xt_table_info *newinfo, unsigned int num_counters, + void __user *counters_ptr) { int ret; - struct ipt_replace tmp; struct ipt_table *t; - struct xt_table_info *newinfo, *oldinfo; + struct xt_table_info *oldinfo; struct xt_counters *counters; - void *loc_cpu_entry, *loc_cpu_old_entry; + void *loc_cpu_old_entry; - if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) - return -EFAULT; - - /* Hack: Causes ipchains to give correct error msg --RR */ - if (len != sizeof(tmp) + tmp.size) - return -ENOPROTOOPT; - - /* overflow check */ - if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - - SMP_CACHE_BYTES) - return -ENOMEM; - if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) - return -ENOMEM; - - newinfo = xt_alloc_table_info(tmp.size); - if (!newinfo) - return -ENOMEM; - - /* choose the copy that is our node/cpu */ - loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; - if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), - tmp.size) != 0) { - ret = -EFAULT; - goto free_newinfo; - } - - counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); + ret = 0; + counters = vmalloc(num_counters * sizeof(struct xt_counters)); if (!counters) { ret = -ENOMEM; - goto free_newinfo; + goto out; } - ret = translate_table(tmp.name, tmp.valid_hooks, - newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, - tmp.hook_entry, tmp.underflow); - if (ret != 0) - goto free_newinfo_counters; - - duprintf("ip_tables: Translated table\n"); - - t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name), - "iptable_%s", tmp.name); + t = try_then_request_module(xt_find_table_lock(AF_INET, name), + "iptable_%s", name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free_newinfo_counters_untrans; } /* You lied! */ - if (tmp.valid_hooks != t->valid_hooks) { + if (valid_hooks != t->valid_hooks) { duprintf("Valid hook crap: %08X vs %08X\n", - tmp.valid_hooks, t->valid_hooks); + valid_hooks, t->valid_hooks); ret = -EINVAL; goto put_module; } - oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); + oldinfo = xt_replace_table(t, num_counters, newinfo, &ret); if (!oldinfo) goto put_module; /* Update module usage count based on number of rules */ duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", oldinfo->number, oldinfo->initial_entries, newinfo->number); - if ((oldinfo->number > oldinfo->initial_entries) || - (newinfo->number <= oldinfo->initial_entries)) + if ((oldinfo->number > oldinfo->initial_entries) || + (newinfo->number <= oldinfo->initial_entries)) module_put(t->me); if ((oldinfo->number > oldinfo->initial_entries) && (newinfo->number <= oldinfo->initial_entries)) @@ -998,8 +1233,8 @@ do_replace(void __user *user, unsigned int len) loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); xt_free_table_info(oldinfo); - if (copy_to_user(tmp.counters, counters, - sizeof(struct xt_counters) * tmp.num_counters) != 0) + if (copy_to_user(counters_ptr, counters, + sizeof(struct xt_counters) * num_counters) != 0) ret = -EFAULT; vfree(counters); xt_table_unlock(t); @@ -1009,9 +1244,62 @@ do_replace(void __user *user, unsigned int len) module_put(t->me); xt_table_unlock(t); free_newinfo_counters_untrans: - IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); - free_newinfo_counters: vfree(counters); + out: + return ret; +} + +static int +do_replace(void __user *user, unsigned int len) +{ + int ret; + struct ipt_replace tmp; + struct xt_table_info *newinfo; + void *loc_cpu_entry; + + if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) + return -EFAULT; + + /* Hack: Causes ipchains to give correct error msg --RR */ + if (len != sizeof(tmp) + tmp.size) + return -ENOPROTOOPT; + + /* overflow check */ + if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; + + newinfo = xt_alloc_table_info(tmp.size); + if (!newinfo) + return -ENOMEM; + + /* choose the copy that is our node/cpu */ + loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; + if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), + tmp.size) != 0) { + ret = -EFAULT; + goto free_newinfo; + } + + ret = translate_table(tmp.name, tmp.valid_hooks, + newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, + tmp.hook_entry, tmp.underflow); + if (ret != 0) + goto free_newinfo; + + duprintf("ip_tables: Translated table\n"); + + ret = __do_replace(tmp.name, tmp.valid_hooks, + newinfo, tmp.num_counters, + tmp.counters); + if (ret) + goto free_newinfo_untrans; + return 0; + + free_newinfo_untrans: + IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1040,31 +1328,59 @@ add_counter_to_entry(struct ipt_entry *e, } static int -do_add_counters(void __user *user, unsigned int len) +do_add_counters(void __user *user, unsigned int len, int compat) { unsigned int i; - struct xt_counters_info tmp, *paddc; + struct xt_counters_info tmp; + struct xt_counters *paddc; + unsigned int num_counters; + char *name; + int size; + void *ptmp; struct ipt_table *t; struct xt_table_info *private; int ret = 0; void *loc_cpu_entry; +#ifdef CONFIG_COMPAT + struct compat_xt_counters_info compat_tmp; - if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) + if (compat) { + ptmp = &compat_tmp; + size = sizeof(struct compat_xt_counters_info); + } else +#endif + { + ptmp = &tmp; + size = sizeof(struct xt_counters_info); + } + + if (copy_from_user(ptmp, user, size) != 0) return -EFAULT; - if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) +#ifdef CONFIG_COMPAT + if (compat) { + num_counters = compat_tmp.num_counters; + name = compat_tmp.name; + } else +#endif + { + num_counters = tmp.num_counters; + name = tmp.name; + } + + if (len != size + num_counters * sizeof(struct xt_counters)) return -EINVAL; - paddc = vmalloc_node(len, numa_node_id()); + paddc = vmalloc_node(len - size, numa_node_id()); if (!paddc) return -ENOMEM; - if (copy_from_user(paddc, user, len) != 0) { + if (copy_from_user(paddc, user + size, len - size) != 0) { ret = -EFAULT; goto free; } - t = xt_find_table_lock(AF_INET, tmp.name); + t = xt_find_table_lock(AF_INET, name); if (!t || IS_ERR(t)) { ret = t ? PTR_ERR(t) : -ENOENT; goto free; @@ -1072,7 +1388,7 @@ do_add_counters(void __user *user, unsigned int len) write_lock_bh(&t->lock); private = t->private; - if (private->number != paddc->num_counters) { + if (private->number != num_counters) { ret = -EINVAL; goto unlock_up_free; } @@ -1083,7 +1399,7 @@ do_add_counters(void __user *user, unsigned int len) IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, add_counter_to_entry, - paddc->counters, + paddc, &i); unlock_up_free: write_unlock_bh(&t->lock); @@ -1095,8 +1411,438 @@ do_add_counters(void __user *user, unsigned int len) return ret; } +#ifdef CONFIG_COMPAT +struct compat_ipt_replace { + char name[IPT_TABLE_MAXNAMELEN]; + u32 valid_hooks; + u32 num_entries; + u32 size; + u32 hook_entry[NF_IP_NUMHOOKS]; + u32 underflow[NF_IP_NUMHOOKS]; + u32 num_counters; + compat_uptr_t counters; /* struct ipt_counters * */ + struct compat_ipt_entry entries[0]; +}; + +static inline int compat_copy_match_to_user(struct ipt_entry_match *m, + void __user **dstptr, compat_uint_t *size) +{ + if (m->u.kernel.match->compat) + return m->u.kernel.match->compat(m, dstptr, size, + COMPAT_TO_USER); + else + return xt_compat_match(m, dstptr, size, COMPAT_TO_USER); +} + +static int compat_copy_entry_to_user(struct ipt_entry *e, + void __user **dstptr, compat_uint_t *size) +{ + struct ipt_entry_target __user *t; + struct compat_ipt_entry __user *ce; + u_int16_t target_offset, next_offset; + compat_uint_t origsize; + int ret; + + ret = -EFAULT; + origsize = *size; + ce = (struct compat_ipt_entry __user *)*dstptr; + if (__copy_to_user(ce, e, sizeof(struct ipt_entry))) + goto out; + + *dstptr += sizeof(struct compat_ipt_entry); + ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size); + target_offset = e->target_offset - (origsize - *size); + if (ret) + goto out; + t = ipt_get_target(e); + if (t->u.kernel.target->compat) + ret = t->u.kernel.target->compat(t, dstptr, size, + COMPAT_TO_USER); + else + ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER); + if (ret) + goto out; + ret = -EFAULT; + next_offset = e->next_offset - (origsize - *size); + if (__put_user(target_offset, &ce->target_offset)) + goto out; + if (__put_user(next_offset, &ce->next_offset)) + goto out; + return 0; +out: + return ret; +} + +static inline int +compat_check_calc_match(struct ipt_entry_match *m, + const char *name, + const struct ipt_ip *ip, + unsigned int hookmask, + int *size, int *i) +{ + struct ipt_match *match; + + match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, + m->u.user.revision), + "ipt_%s", m->u.user.name); + if (IS_ERR(match) || !match) { + duprintf("compat_check_calc_match: `%s' not found\n", + m->u.user.name); + return match ? PTR_ERR(match) : -ENOENT; + } + m->u.kernel.match = match; + + if (m->u.kernel.match->compat) + m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE); + else + xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE); + + (*i)++; + return 0; +} + +static inline int +check_compat_entry_size_and_hooks(struct ipt_entry *e, + struct xt_table_info *newinfo, + unsigned int *size, + unsigned char *base, + unsigned char *limit, + unsigned int *hook_entries, + unsigned int *underflows, + unsigned int *i, + const char *name) +{ + struct ipt_entry_target *t; + struct ipt_target *target; + u_int16_t entry_offset; + int ret, off, h, j; + + duprintf("check_compat_entry_size_and_hooks %p\n", e); + if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 + || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) { + duprintf("Bad offset %p, limit = %p\n", e, limit); + return -EINVAL; + } + + if (e->next_offset < sizeof(struct compat_ipt_entry) + + sizeof(struct compat_xt_entry_target)) { + duprintf("checking: element %p size %u\n", + e, e->next_offset); + return -EINVAL; + } + + if (!ip_checkentry(&e->ip)) { + duprintf("ip_tables: ip check failed %p %s.\n", e, name); + return -EINVAL; + } + + off = 0; + entry_offset = (void *)e - (void *)base; + j = 0; + ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip, + e->comefrom, &off, &j); + if (ret != 0) + goto out; + + t = ipt_get_target(e); + target = try_then_request_module(xt_find_target(AF_INET, + t->u.user.name, + t->u.user.revision), + "ipt_%s", t->u.user.name); + if (IS_ERR(target) || !target) { + duprintf("check_entry: `%s' not found\n", t->u.user.name); + ret = target ? PTR_ERR(target) : -ENOENT; + goto out; + } + t->u.kernel.target = target; + + if (t->u.kernel.target->compat) + t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE); + else + xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE); + *size += off; + ret = compat_add_offset(entry_offset, off); + if (ret) + goto out; + + /* Check hooks & underflows */ + for (h = 0; h < NF_IP_NUMHOOKS; h++) { + if ((unsigned char *)e - base == hook_entries[h]) + newinfo->hook_entry[h] = hook_entries[h]; + if ((unsigned char *)e - base == underflows[h]) + newinfo->underflow[h] = underflows[h]; + } + + /* Clear counters and comefrom */ + e->counters = ((struct ipt_counters) { 0, 0 }); + e->comefrom = 0; + + (*i)++; + return 0; +out: + IPT_MATCH_ITERATE(e, cleanup_match, &j); + return ret; +} + +static inline int compat_copy_match_from_user(struct ipt_entry_match *m, + void **dstptr, compat_uint_t *size, const char *name, + const struct ipt_ip *ip, unsigned int hookmask) +{ + struct ipt_entry_match *dm; + struct ipt_match *match; + int ret; + + dm = (struct ipt_entry_match *)*dstptr; + match = m->u.kernel.match; + if (match->compat) + match->compat(m, dstptr, size, COMPAT_FROM_USER); + else + xt_compat_match(m, dstptr, size, COMPAT_FROM_USER); + + ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm), + name, hookmask, ip->proto, + ip->invflags & IPT_INV_PROTO); + if (ret) + return ret; + + if (m->u.kernel.match->checkentry + && !m->u.kernel.match->checkentry(name, ip, match, dm->data, + dm->u.match_size - sizeof(*dm), + hookmask)) { + duprintf("ip_tables: check failed for `%s'.\n", + m->u.kernel.match->name); + return -EINVAL; + } + return 0; +} + +static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, + unsigned int *size, const char *name, + struct xt_table_info *newinfo, unsigned char *base) +{ + struct ipt_entry_target *t; + struct ipt_target *target; + struct ipt_entry *de; + unsigned int origsize; + int ret, h; + + ret = 0; + origsize = *size; + de = (struct ipt_entry *)*dstptr; + memcpy(de, e, sizeof(struct ipt_entry)); + + *dstptr += sizeof(struct compat_ipt_entry); + ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size, + name, &de->ip, de->comefrom); + if (ret) + goto out; + de->target_offset = e->target_offset - (origsize - *size); + t = ipt_get_target(e); + target = t->u.kernel.target; + if (target->compat) + target->compat(t, dstptr, size, COMPAT_FROM_USER); + else + xt_compat_target(t, dstptr, size, COMPAT_FROM_USER); + + de->next_offset = e->next_offset - (origsize - *size); + for (h = 0; h < NF_IP_NUMHOOKS; h++) { + if ((unsigned char *)de - base < newinfo->hook_entry[h]) + newinfo->hook_entry[h] -= origsize - *size; + if ((unsigned char *)de - base < newinfo->underflow[h]) + newinfo->underflow[h] -= origsize - *size; + } + + t = ipt_get_target(de); + target = t->u.kernel.target; + ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), + name, e->comefrom, e->ip.proto, + e->ip.invflags & IPT_INV_PROTO); + if (ret) + goto out; + + ret = -EINVAL; + if (t->u.kernel.target == &ipt_standard_target) { + if (!standard_check(t, *size)) + goto out; + } else if (t->u.kernel.target->checkentry + && !t->u.kernel.target->checkentry(name, de, target, + t->data, t->u.target_size - sizeof(*t), + de->comefrom)) { + duprintf("ip_tables: compat: check failed for `%s'.\n", + t->u.kernel.target->name); + goto out; + } + ret = 0; +out: + return ret; +} + static int -do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) +translate_compat_table(const char *name, + unsigned int valid_hooks, + struct xt_table_info **pinfo, + void **pentry0, + unsigned int total_size, + unsigned int number, + unsigned int *hook_entries, + unsigned int *underflows) +{ + unsigned int i; + struct xt_table_info *newinfo, *info; + void *pos, *entry0, *entry1; + unsigned int size; + int ret; + + info = *pinfo; + entry0 = *pentry0; + size = total_size; + info->number = number; + + /* Init all hooks to impossible value. */ + for (i = 0; i < NF_IP_NUMHOOKS; i++) { + info->hook_entry[i] = 0xFFFFFFFF; + info->underflow[i] = 0xFFFFFFFF; + } + + duprintf("translate_compat_table: size %u\n", info->size); + i = 0; + xt_compat_lock(AF_INET); + /* Walk through entries, checking offsets. */ + ret = IPT_ENTRY_ITERATE(entry0, total_size, + check_compat_entry_size_and_hooks, + info, &size, entry0, + entry0 + total_size, + hook_entries, underflows, &i, name); + if (ret != 0) + goto out_unlock; + + ret = -EINVAL; + if (i != number) { + duprintf("translate_compat_table: %u not %u entries\n", + i, number); + goto out_unlock; + } + + /* Check hooks all assigned */ + for (i = 0; i < NF_IP_NUMHOOKS; i++) { + /* Only hooks which are valid */ + if (!(valid_hooks & (1 << i))) + continue; + if (info->hook_entry[i] == 0xFFFFFFFF) { + duprintf("Invalid hook entry %u %u\n", + i, hook_entries[i]); + goto out_unlock; + } + if (info->underflow[i] == 0xFFFFFFFF) { + duprintf("Invalid underflow %u %u\n", + i, underflows[i]); + goto out_unlock; + } + } + + ret = -ENOMEM; + newinfo = xt_alloc_table_info(size); + if (!newinfo) + goto out_unlock; + + newinfo->number = number; + for (i = 0; i < NF_IP_NUMHOOKS; i++) { + newinfo->hook_entry[i] = info->hook_entry[i]; + newinfo->underflow[i] = info->underflow[i]; + } + entry1 = newinfo->entries[raw_smp_processor_id()]; + pos = entry1; + size = total_size; + ret = IPT_ENTRY_ITERATE(entry0, total_size, + compat_copy_entry_from_user, &pos, &size, + name, newinfo, entry1); + compat_flush_offsets(); + xt_compat_unlock(AF_INET); + if (ret) + goto free_newinfo; + + ret = -ELOOP; + if (!mark_source_chains(newinfo, valid_hooks, entry1)) + goto free_newinfo; + + /* And one copy for every other CPU */ + for_each_cpu(i) + if (newinfo->entries[i] && newinfo->entries[i] != entry1) + memcpy(newinfo->entries[i], entry1, newinfo->size); + + *pinfo = newinfo; + *pentry0 = entry1; + xt_free_table_info(info); + return 0; + +free_newinfo: + xt_free_table_info(newinfo); +out: + return ret; +out_unlock: + xt_compat_unlock(AF_INET); + goto out; +} + +static int +compat_do_replace(void __user *user, unsigned int len) +{ + int ret; + struct compat_ipt_replace tmp; + struct xt_table_info *newinfo; + void *loc_cpu_entry; + + if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) + return -EFAULT; + + /* Hack: Causes ipchains to give correct error msg --RR */ + if (len != sizeof(tmp) + tmp.size) + return -ENOPROTOOPT; + + /* overflow check */ + if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS - + SMP_CACHE_BYTES) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) + return -ENOMEM; + + newinfo = xt_alloc_table_info(tmp.size); + if (!newinfo) + return -ENOMEM; + + /* choose the copy that is our node/cpu */ + loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; + if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), + tmp.size) != 0) { + ret = -EFAULT; + goto free_newinfo; + } + + ret = translate_compat_table(tmp.name, tmp.valid_hooks, + &newinfo, &loc_cpu_entry, tmp.size, + tmp.num_entries, tmp.hook_entry, tmp.underflow); + if (ret != 0) + goto free_newinfo; + + duprintf("compat_do_replace: Translated table\n"); + + ret = __do_replace(tmp.name, tmp.valid_hooks, + newinfo, tmp.num_counters, + compat_ptr(tmp.counters)); + if (ret) + goto free_newinfo_untrans; + return 0; + + free_newinfo_untrans: + IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); + free_newinfo: + xt_free_table_info(newinfo); + return ret; +} + +static int +compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, + unsigned int len) { int ret; @@ -1105,11 +1851,11 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) switch (cmd) { case IPT_SO_SET_REPLACE: - ret = do_replace(user, len); + ret = compat_do_replace(user, len); break; case IPT_SO_SET_ADD_COUNTERS: - ret = do_add_counters(user, len); + ret = do_add_counters(user, len, 1); break; default: @@ -1120,75 +1866,196 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) return ret; } +struct compat_ipt_get_entries +{ + char name[IPT_TABLE_MAXNAMELEN]; + compat_uint_t size; + struct compat_ipt_entry entrytable[0]; +}; + +static int compat_copy_entries_to_user(unsigned int total_size, + struct ipt_table *table, void __user *userptr) +{ + unsigned int off, num; + struct compat_ipt_entry e; + struct xt_counters *counters; + struct xt_table_info *private = table->private; + void __user *pos; + unsigned int size; + int ret = 0; + void *loc_cpu_entry; + + counters = alloc_counters(table); + if (IS_ERR(counters)) + return PTR_ERR(counters); + + /* choose the copy that is on our node/cpu, ... + * This choice is lazy (because current thread is + * allowed to migrate to another cpu) + */ + loc_cpu_entry = private->entries[raw_smp_processor_id()]; + pos = userptr; + size = total_size; + ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size, + compat_copy_entry_to_user, &pos, &size); + if (ret) + goto free_counters; + + /* ... then go back and fix counters and names */ + for (off = 0, num = 0; off < size; off += e.next_offset, num++) { + unsigned int i; + struct ipt_entry_match m; + struct ipt_entry_target t; + + ret = -EFAULT; + if (copy_from_user(&e, userptr + off, + sizeof(struct compat_ipt_entry))) + goto free_counters; + if (copy_to_user(userptr + off + + offsetof(struct compat_ipt_entry, counters), + &counters[num], sizeof(counters[num]))) + goto free_counters; + + for (i = sizeof(struct compat_ipt_entry); + i < e.target_offset; i += m.u.match_size) { + if (copy_from_user(&m, userptr + off + i, + sizeof(struct ipt_entry_match))) + goto free_counters; + if (copy_to_user(userptr + off + i + + offsetof(struct ipt_entry_match, u.user.name), + m.u.kernel.match->name, + strlen(m.u.kernel.match->name) + 1)) + goto free_counters; + } + + if (copy_from_user(&t, userptr + off + e.target_offset, + sizeof(struct ipt_entry_target))) + goto free_counters; + if (copy_to_user(userptr + off + e.target_offset + + offsetof(struct ipt_entry_target, u.user.name), + t.u.kernel.target->name, + strlen(t.u.kernel.target->name) + 1)) + goto free_counters; + } + ret = 0; +free_counters: + vfree(counters); + return ret; +} + static int -do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) +compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len) { int ret; + struct compat_ipt_get_entries get; + struct ipt_table *t; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - switch (cmd) { - case IPT_SO_GET_INFO: { - char name[IPT_TABLE_MAXNAMELEN]; - struct ipt_table *t; + if (*len < sizeof(get)) { + duprintf("compat_get_entries: %u < %u\n", + *len, (unsigned int)sizeof(get)); + return -EINVAL; + } + + if (copy_from_user(&get, uptr, sizeof(get)) != 0) + return -EFAULT; + + if (*len != sizeof(struct compat_ipt_get_entries) + get.size) { + duprintf("compat_get_entries: %u != %u\n", *len, + (unsigned int)(sizeof(struct compat_ipt_get_entries) + + get.size)); + return -EINVAL; + } - if (*len != sizeof(struct ipt_getinfo)) { - duprintf("length %u != %u\n", *len, - sizeof(struct ipt_getinfo)); + xt_compat_lock(AF_INET); + t = xt_find_table_lock(AF_INET, get.name); + if (t && !IS_ERR(t)) { + struct xt_table_info *private = t->private; + struct xt_table_info info; + duprintf("t->private->number = %u\n", + private->number); + ret = compat_table_info(private, &info); + if (!ret && get.size == info.size) { + ret = compat_copy_entries_to_user(private->size, + t, uptr->entrytable); + } else if (!ret) { + duprintf("compat_get_entries: I've got %u not %u!\n", + private->size, + get.size); ret = -EINVAL; - break; } + compat_flush_offsets(); + module_put(t->me); + xt_table_unlock(t); + } else + ret = t ? PTR_ERR(t) : -ENOENT; - if (copy_from_user(name, user, sizeof(name)) != 0) { - ret = -EFAULT; - break; - } - name[IPT_TABLE_MAXNAMELEN-1] = '\0'; - - t = try_then_request_module(xt_find_table_lock(AF_INET, name), - "iptable_%s", name); - if (t && !IS_ERR(t)) { - struct ipt_getinfo info; - struct xt_table_info *private = t->private; - - info.valid_hooks = t->valid_hooks; - memcpy(info.hook_entry, private->hook_entry, - sizeof(info.hook_entry)); - memcpy(info.underflow, private->underflow, - sizeof(info.underflow)); - info.num_entries = private->number; - info.size = private->size; - memcpy(info.name, name, sizeof(info.name)); - - if (copy_to_user(user, &info, *len) != 0) - ret = -EFAULT; - else - ret = 0; - xt_table_unlock(t); - module_put(t->me); - } else - ret = t ? PTR_ERR(t) : -ENOENT; + xt_compat_unlock(AF_INET); + return ret; +} + +static int +compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) +{ + int ret; + + switch (cmd) { + case IPT_SO_GET_INFO: + ret = get_info(user, len, 1); + break; + case IPT_SO_GET_ENTRIES: + ret = compat_get_entries(user, len); + break; + default: + duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd); + ret = -EINVAL; } - break; + return ret; +} +#endif - case IPT_SO_GET_ENTRIES: { - struct ipt_get_entries get; +static int +do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) +{ + int ret; - if (*len < sizeof(get)) { - duprintf("get_entries: %u < %u\n", *len, sizeof(get)); - ret = -EINVAL; - } else if (copy_from_user(&get, user, sizeof(get)) != 0) { - ret = -EFAULT; - } else if (*len != sizeof(struct ipt_get_entries) + get.size) { - duprintf("get_entries: %u != %u\n", *len, - sizeof(struct ipt_get_entries) + get.size); - ret = -EINVAL; - } else - ret = get_entries(&get, user); + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + switch (cmd) { + case IPT_SO_SET_REPLACE: + ret = do_replace(user, len); break; + + case IPT_SO_SET_ADD_COUNTERS: + ret = do_add_counters(user, len, 0); + break; + + default: + duprintf("do_ipt_set_ctl: unknown request %i\n", cmd); + ret = -EINVAL; } + return ret; +} + +static int +do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) +{ + int ret; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + switch (cmd) { + case IPT_SO_GET_INFO: + ret = get_info(user, len, 0); + break; + + case IPT_SO_GET_ENTRIES: + ret = get_entries(user, len); + break; + case IPT_SO_GET_REVISION_MATCH: case IPT_SO_GET_REVISION_TARGET: { struct ipt_get_revision rev; @@ -1336,6 +2203,9 @@ static struct ipt_target ipt_standard_target = { .name = IPT_STANDARD_TARGET, .targetsize = sizeof(int), .family = AF_INET, +#ifdef CONFIG_COMPAT + .compat = &compat_ipt_standard_fn, +#endif }; static struct ipt_target ipt_error_target = { @@ -1350,9 +2220,15 @@ static struct nf_sockopt_ops ipt_sockopts = { .set_optmin = IPT_BASE_CTL, .set_optmax = IPT_SO_SET_MAX+1, .set = do_ipt_set_ctl, +#ifdef CONFIG_COMPAT + .compat_set = compat_do_ipt_set_ctl, +#endif .get_optmin = IPT_BASE_CTL, .get_optmax = IPT_SO_GET_MAX+1, .get = do_ipt_get_ctl, +#ifdef CONFIG_COMPAT + .compat_get = compat_do_ipt_get_ctl, +#endif }; static struct ipt_match icmp_matchstruct = { diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index e4768a31718..aad9d28c8d7 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -725,22 +725,17 @@ static struct file_operations clusterip_proc_fops = { #endif /* CONFIG_PROC_FS */ -static int init_or_cleanup(int fini) +static int __init ipt_clusterip_init(void) { int ret; - if (fini) - goto cleanup; - - if (ipt_register_target(&clusterip_tgt)) { - ret = -EINVAL; - goto cleanup_none; - } + ret = ipt_register_target(&clusterip_tgt); + if (ret < 0) + return ret; - if (nf_register_hook(&cip_arp_ops) < 0) { - ret = -EINVAL; + ret = nf_register_hook(&cip_arp_ops); + if (ret < 0) goto cleanup_target; - } #ifdef CONFIG_PROC_FS clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net); @@ -753,31 +748,24 @@ static int init_or_cleanup(int fini) printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n", CLUSTERIP_VERSION); - return 0; -cleanup: - printk(KERN_NOTICE "ClusterIP Version %s unloading\n", - CLUSTERIP_VERSION); -#ifdef CONFIG_PROC_FS - remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent); -#endif cleanup_hook: nf_unregister_hook(&cip_arp_ops); cleanup_target: ipt_unregister_target(&clusterip_tgt); -cleanup_none: - return -EINVAL; -} - -static int __init ipt_clusterip_init(void) -{ - return init_or_cleanup(0); + return ret; } static void __exit ipt_clusterip_fini(void) { - init_or_cleanup(1); + printk(KERN_NOTICE "ClusterIP Version %s unloading\n", + CLUSTERIP_VERSION); +#ifdef CONFIG_PROC_FS + remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent); +#endif + nf_unregister_hook(&cip_arp_ops); + ipt_unregister_target(&clusterip_tgt); } module_init(ipt_clusterip_init); diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 4269a5440d4..0bba3c2bb78 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -106,7 +106,6 @@ static void send_reset(struct sk_buff *oldskb, int hook) struct rtable *rt; u_int16_t tmp_port; u_int32_t tmp_addr; - unsigned int tcplen; int needs_ack; int hh_len; @@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) return; /* Check checksum */ - tcplen = oldskb->len - iph->ihl * 4; - if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) || - (hook == NF_IP_LOCAL_IN && - oldskb->ip_summed != CHECKSUM_UNNECESSARY)) && - csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP, - oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum : - skb_checksum(oldskb, iph->ihl * 4, tcplen, 0))) + if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP)) return; if ((rt = route_reverse(oldskb, oth, hook)) == NULL) diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c deleted file mode 100644 index ac95d8390bc..00000000000 --- a/net/ipv4/netfilter/ipt_multiport.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Kernel module to match one of a list of TCP/UDP ports: ports are in - the same place so we can treat them as equal. */ - -/* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/udp.h> -#include <linux/skbuff.h> - -#include <linux/netfilter_ipv4/ipt_multiport.h> -#include <linux/netfilter_ipv4/ip_tables.h> - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); -MODULE_DESCRIPTION("iptables multiple port match module"); - -#if 0 -#define duprintf(format, args...) printk(format , ## args) -#else -#define duprintf(format, args...) -#endif - -/* Returns 1 if the port is matched by the test, 0 otherwise. */ -static inline int -ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags, - u_int8_t count, u_int16_t src, u_int16_t dst) -{ - unsigned int i; - for (i=0; i<count; i++) { - if (flags != IPT_MULTIPORT_DESTINATION - && portlist[i] == src) - return 1; - - if (flags != IPT_MULTIPORT_SOURCE - && portlist[i] == dst) - return 1; - } - - return 0; -} - -/* Returns 1 if the port is matched by the test, 0 otherwise. */ -static inline int -ports_match_v1(const struct ipt_multiport_v1 *minfo, - u_int16_t src, u_int16_t dst) -{ - unsigned int i; - u_int16_t s, e; - - for (i=0; i < minfo->count; i++) { - s = minfo->ports[i]; - - if (minfo->pflags[i]) { - /* range port matching */ - e = minfo->ports[++i]; - duprintf("src or dst matches with %d-%d?\n", s, e); - - if (minfo->flags == IPT_MULTIPORT_SOURCE - && src >= s && src <= e) - return 1 ^ minfo->invert; - if (minfo->flags == IPT_MULTIPORT_DESTINATION - && dst >= s && dst <= e) - return 1 ^ minfo->invert; - if (minfo->flags == IPT_MULTIPORT_EITHER - && ((dst >= s && dst <= e) - || (src >= s && src <= e))) - return 1 ^ minfo->invert; - } else { - /* exact port matching */ - duprintf("src or dst matches with %d?\n", s); - - if (minfo->flags == IPT_MULTIPORT_SOURCE - && src == s) - return 1 ^ minfo->invert; - if (minfo->flags == IPT_MULTIPORT_DESTINATION - && dst == s) - return 1 ^ minfo->invert; - if (minfo->flags == IPT_MULTIPORT_EITHER - && (src == s || dst == s)) - return 1 ^ minfo->invert; - } - } - - return minfo->invert; -} - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - u16 _ports[2], *pptr; - const struct ipt_multiport *multiinfo = matchinfo; - - if (offset) - return 0; - - pptr = skb_header_pointer(skb, protoff, - sizeof(_ports), _ports); - if (pptr == NULL) { - /* We've been asked to examine this packet, and we - * can't. Hence, no choice but to drop. - */ - duprintf("ipt_multiport:" - " Dropping evil offset=0 tinygram.\n"); - *hotdrop = 1; - return 0; - } - - return ports_match(multiinfo->ports, - multiinfo->flags, multiinfo->count, - ntohs(pptr[0]), ntohs(pptr[1])); -} - -static int -match_v1(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - u16 _ports[2], *pptr; - const struct ipt_multiport_v1 *multiinfo = matchinfo; - - if (offset) - return 0; - - pptr = skb_header_pointer(skb, protoff, - sizeof(_ports), _ports); - if (pptr == NULL) { - /* We've been asked to examine this packet, and we - * can't. Hence, no choice but to drop. - */ - duprintf("ipt_multiport:" - " Dropping evil offset=0 tinygram.\n"); - *hotdrop = 1; - return 0; - } - - return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); -} - -static struct ipt_match multiport_match = { - .name = "multiport", - .revision = 0, - .match = match, - .matchsize = sizeof(struct ipt_multiport), - .me = THIS_MODULE, -}; - -static struct ipt_match multiport_match_v1 = { - .name = "multiport", - .revision = 1, - .match = match_v1, - .matchsize = sizeof(struct ipt_multiport_v1), - .me = THIS_MODULE, -}; - -static int __init ipt_multiport_init(void) -{ - int err; - - err = ipt_register_match(&multiport_match); - if (!err) { - err = ipt_register_match(&multiport_match_v1); - if (err) - ipt_unregister_match(&multiport_match); - } - - return err; -} - -static void __exit ipt_multiport_fini(void) -{ - ipt_unregister_match(&multiport_match); - ipt_unregister_match(&multiport_match_v1); -} - -module_init(ipt_multiport_init); -module_exit(ipt_multiport_fini); diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 3d80aefe9cf..7f417484bfb 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -157,37 +157,20 @@ static int __init iptable_filter_init(void) return ret; /* Register hooks */ - ret = nf_register_hook(&ipt_ops[0]); + ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); if (ret < 0) goto cleanup_table; - ret = nf_register_hook(&ipt_ops[1]); - if (ret < 0) - goto cleanup_hook0; - - ret = nf_register_hook(&ipt_ops[2]); - if (ret < 0) - goto cleanup_hook1; - return ret; - cleanup_hook1: - nf_unregister_hook(&ipt_ops[1]); - cleanup_hook0: - nf_unregister_hook(&ipt_ops[0]); cleanup_table: ipt_unregister_table(&packet_filter); - return ret; } static void __exit iptable_filter_fini(void) { - unsigned int i; - - for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++) - nf_unregister_hook(&ipt_ops[i]); - + nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); ipt_unregister_table(&packet_filter); } diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 412fc96cc89..397b95cc026 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -211,49 +211,20 @@ static int __init iptable_mangle_init(void) return ret; /* Register hooks */ - ret = nf_register_hook(&ipt_ops[0]); + ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); if (ret < 0) goto cleanup_table; - ret = nf_register_hook(&ipt_ops[1]); - if (ret < 0) - goto cleanup_hook0; - - ret = nf_register_hook(&ipt_ops[2]); - if (ret < 0) - goto cleanup_hook1; - - ret = nf_register_hook(&ipt_ops[3]); - if (ret < 0) - goto cleanup_hook2; - - ret = nf_register_hook(&ipt_ops[4]); - if (ret < 0) - goto cleanup_hook3; - return ret; - cleanup_hook3: - nf_unregister_hook(&ipt_ops[3]); - cleanup_hook2: - nf_unregister_hook(&ipt_ops[2]); - cleanup_hook1: - nf_unregister_hook(&ipt_ops[1]); - cleanup_hook0: - nf_unregister_hook(&ipt_ops[0]); cleanup_table: ipt_unregister_table(&packet_mangler); - return ret; } static void __exit iptable_mangle_fini(void) { - unsigned int i; - - for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++) - nf_unregister_hook(&ipt_ops[i]); - + nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); ipt_unregister_table(&packet_mangler); } diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 03cc79a6160..7912cce1e1b 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -101,18 +101,18 @@ ipt_hook(unsigned int hook, /* 'raw' is the very first table. */ static struct nf_hook_ops ipt_ops[] = { { - .hook = ipt_hook, - .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, - .priority = NF_IP_PRI_RAW, - .owner = THIS_MODULE, + .hook = ipt_hook, + .pf = PF_INET, + .hooknum = NF_IP_PRE_ROUTING, + .priority = NF_IP_PRI_RAW, + .owner = THIS_MODULE, }, { - .hook = ipt_hook, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, - .priority = NF_IP_PRI_RAW, - .owner = THIS_MODULE, + .hook = ipt_hook, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_OUT, + .priority = NF_IP_PRI_RAW, + .owner = THIS_MODULE, }, }; @@ -126,31 +126,20 @@ static int __init iptable_raw_init(void) return ret; /* Register hooks */ - ret = nf_register_hook(&ipt_ops[0]); + ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); if (ret < 0) goto cleanup_table; - ret = nf_register_hook(&ipt_ops[1]); - if (ret < 0) - goto cleanup_hook0; - return ret; - cleanup_hook0: - nf_unregister_hook(&ipt_ops[0]); cleanup_table: ipt_unregister_table(&packet_raw); - return ret; } static void __exit iptable_raw_fini(void) { - unsigned int i; - - for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++) - nf_unregister_hook(&ipt_ops[i]); - + nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); ipt_unregister_table(&packet_raw); } diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 4afbc699d3b..5bc9f64d7b5 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -210,71 +210,63 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum, /* Connection tracking may drop packets, but never alters them, so make it the first hook. */ -static struct nf_hook_ops ipv4_conntrack_defrag_ops = { - .hook = ipv4_conntrack_defrag, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, - .priority = NF_IP_PRI_CONNTRACK_DEFRAG, -}; - -static struct nf_hook_ops ipv4_conntrack_in_ops = { - .hook = ipv4_conntrack_in, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_PRE_ROUTING, - .priority = NF_IP_PRI_CONNTRACK, -}; - -static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = { - .hook = ipv4_conntrack_defrag, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, - .priority = NF_IP_PRI_CONNTRACK_DEFRAG, -}; - -static struct nf_hook_ops ipv4_conntrack_local_out_ops = { - .hook = ipv4_conntrack_local, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_OUT, - .priority = NF_IP_PRI_CONNTRACK, -}; - -/* helpers */ -static struct nf_hook_ops ipv4_conntrack_helper_out_ops = { - .hook = ipv4_conntrack_help, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, - .priority = NF_IP_PRI_CONNTRACK_HELPER, -}; - -static struct nf_hook_ops ipv4_conntrack_helper_in_ops = { - .hook = ipv4_conntrack_help, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, - .priority = NF_IP_PRI_CONNTRACK_HELPER, -}; - - -/* Refragmenter; last chance. */ -static struct nf_hook_ops ipv4_conntrack_out_ops = { - .hook = ipv4_confirm, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, - .priority = NF_IP_PRI_CONNTRACK_CONFIRM, -}; - -static struct nf_hook_ops ipv4_conntrack_local_in_ops = { - .hook = ipv4_confirm, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, - .priority = NF_IP_PRI_CONNTRACK_CONFIRM, +static struct nf_hook_ops ipv4_conntrack_ops[] = { + { + .hook = ipv4_conntrack_defrag, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_PRE_ROUTING, + .priority = NF_IP_PRI_CONNTRACK_DEFRAG, + }, + { + .hook = ipv4_conntrack_in, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_PRE_ROUTING, + .priority = NF_IP_PRI_CONNTRACK, + }, + { + .hook = ipv4_conntrack_defrag, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_OUT, + .priority = NF_IP_PRI_CONNTRACK_DEFRAG, + }, + { + .hook = ipv4_conntrack_local, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_OUT, + .priority = NF_IP_PRI_CONNTRACK, + }, + { + .hook = ipv4_conntrack_help, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_CONNTRACK_HELPER, + }, + { + .hook = ipv4_conntrack_help, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_CONNTRACK_HELPER, + }, + { + .hook = ipv4_confirm, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_POST_ROUTING, + .priority = NF_IP_PRI_CONNTRACK_CONFIRM, + }, + { + .hook = ipv4_confirm, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_IP_LOCAL_IN, + .priority = NF_IP_PRI_CONNTRACK_CONFIRM, + }, }; #ifdef CONFIG_SYSCTL @@ -440,16 +432,20 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4; extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp; -static int init_or_cleanup(int init) + +MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); +MODULE_LICENSE("GPL"); + +static int __init nf_conntrack_l3proto_ipv4_init(void) { int ret = 0; - if (!init) goto cleanup; + need_conntrack(); ret = nf_register_sockopt(&so_getorigdst); if (ret < 0) { printk(KERN_ERR "Unable to register netfilter socket option\n"); - goto cleanup_nothing; + return ret; } ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4); @@ -476,84 +472,26 @@ static int init_or_cleanup(int init) goto cleanup_icmp; } - ret = nf_register_hook(&ipv4_conntrack_defrag_ops); + ret = nf_register_hooks(ipv4_conntrack_ops, + ARRAY_SIZE(ipv4_conntrack_ops)); if (ret < 0) { - printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n"); + printk("nf_conntrack_ipv4: can't register hooks.\n"); goto cleanup_ipv4; } - ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops); - if (ret < 0) { - printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n"); - goto cleanup_defragops; - } - - ret = nf_register_hook(&ipv4_conntrack_in_ops); - if (ret < 0) { - printk("nf_conntrack_ipv4: can't register pre-routing hook.\n"); - goto cleanup_defraglocalops; - } - - ret = nf_register_hook(&ipv4_conntrack_local_out_ops); - if (ret < 0) { - printk("nf_conntrack_ipv4: can't register local out hook.\n"); - goto cleanup_inops; - } - - ret = nf_register_hook(&ipv4_conntrack_helper_in_ops); - if (ret < 0) { - printk("nf_conntrack_ipv4: can't register local helper hook.\n"); - goto cleanup_inandlocalops; - } - - ret = nf_register_hook(&ipv4_conntrack_helper_out_ops); - if (ret < 0) { - printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n"); - goto cleanup_helperinops; - } - - ret = nf_register_hook(&ipv4_conntrack_out_ops); - if (ret < 0) { - printk("nf_conntrack_ipv4: can't register post-routing hook.\n"); - goto cleanup_helperoutops; - } - - ret = nf_register_hook(&ipv4_conntrack_local_in_ops); - if (ret < 0) { - printk("nf_conntrack_ipv4: can't register local in hook.\n"); - goto cleanup_inoutandlocalops; - } - #ifdef CONFIG_SYSCTL nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); if (nf_ct_ipv4_sysctl_header == NULL) { printk("nf_conntrack: can't register to sysctl.\n"); ret = -ENOMEM; - goto cleanup_localinops; + goto cleanup_hooks; } #endif return ret; - cleanup: - synchronize_net(); #ifdef CONFIG_SYSCTL - unregister_sysctl_table(nf_ct_ipv4_sysctl_header); - cleanup_localinops: + cleanup_hooks: + nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); #endif - nf_unregister_hook(&ipv4_conntrack_local_in_ops); - cleanup_inoutandlocalops: - nf_unregister_hook(&ipv4_conntrack_out_ops); - cleanup_helperoutops: - nf_unregister_hook(&ipv4_conntrack_helper_out_ops); - cleanup_helperinops: - nf_unregister_hook(&ipv4_conntrack_helper_in_ops); - cleanup_inandlocalops: - nf_unregister_hook(&ipv4_conntrack_local_out_ops); - cleanup_inops: - nf_unregister_hook(&ipv4_conntrack_in_ops); - cleanup_defraglocalops: - nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops); - cleanup_defragops: - nf_unregister_hook(&ipv4_conntrack_defrag_ops); cleanup_ipv4: nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); cleanup_icmp: @@ -564,22 +502,21 @@ static int init_or_cleanup(int init) nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); cleanup_sockopt: nf_unregister_sockopt(&so_getorigdst); - cleanup_nothing: return ret; } -MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); -MODULE_LICENSE("GPL"); - -static int __init nf_conntrack_l3proto_ipv4_init(void) -{ - need_conntrack(); - return init_or_cleanup(1); -} - static void __exit nf_conntrack_l3proto_ipv4_fini(void) { - init_or_cleanup(0); + synchronize_net(); +#ifdef CONFIG_SYSCTL + unregister_sysctl_table(nf_ct_ipv4_sysctl_header); +#endif + nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); + nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); + nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp); + nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4); + nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); + nf_unregister_sockopt(&so_getorigdst); } module_init(nf_conntrack_l3proto_ipv4_init); diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 52dc175be39..4b0d361cc6e 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -235,30 +235,14 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff, } /* See ip_conntrack_proto_tcp.c */ - if (hooknum != NF_IP_PRE_ROUTING) - goto checksum_skipped; - - switch (skb->ip_summed) { - case CHECKSUM_HW: - if (!(u16)csum_fold(skb->csum)) - break; + if (hooknum == NF_IP_PRE_ROUTING && + nf_ip_checksum(skb, hooknum, dataoff, 0)) { if (LOG_INVALID(IPPROTO_ICMP)) nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, "nf_ct_icmp: bad HW ICMP checksum "); return -NF_ACCEPT; - case CHECKSUM_NONE: - if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) { - if (LOG_INVALID(IPPROTO_ICMP)) - nf_log_packet(PF_INET, 0, skb, NULL, NULL, - NULL, - "nf_ct_icmp: bad ICMP checksum "); - return -NF_ACCEPT; - } - default: - break; } -checksum_skipped: /* * 18 is the highest 'known' ICMP type. Anything else is a mystery * diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 1b167c4bb3b..d61e2a9d394 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -49,7 +49,7 @@ static int fold_prot_inuse(struct proto *proto) int res = 0; int cpu; - for_each_cpu(cpu) + for_each_possible_cpu(cpu) res += proto->stats[cpu].inuse; return res; @@ -91,7 +91,7 @@ fold_field(void *mib[], int offt) unsigned long res = 0; int i; - for_each_cpu(i) { + for_each_possible_cpu(i) { res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt); res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt); } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 94fcbc5e5a1..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]) @@ -3083,7 +3086,7 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset, memcpy(dst, src, length); /* Add the other cpus in, one int at a time */ - for_each_cpu(i) { + for_each_possible_cpu(i) { unsigned int j; src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset; 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..a28ae593b97 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) { @@ -536,6 +533,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *buff; int nsize, old_factor; + int nlen; u16 flags; BUG_ON(len > skb->len); @@ -554,7 +552,11 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC); if (buff == NULL) return -ENOMEM; /* We'll just try again later. */ + sk_charge_skb(sk, buff); + nlen = skb->len - len - nsize; + buff->truesize += nlen; + skb->truesize -= nlen; /* Correct the sequence numbers. */ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len; @@ -1040,7 +1042,8 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, if (unlikely(buff == NULL)) return -ENOMEM; - buff->truesize = nlen; + sk_charge_skb(sk, buff); + buff->truesize += nlen; skb->truesize -= nlen; /* Correct the sequence numbers. */ diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c index 0d7d386dac2..8d30c48f090 100644 --- a/net/ipv4/tunnel4.c +++ b/net/ipv4/tunnel4.c @@ -8,6 +8,8 @@ #include <linux/mutex.h> #include <linux/netdevice.h> #include <linux/skbuff.h> +#include <net/icmp.h> +#include <net/ip.h> #include <net/protocol.h> #include <net/xfrm.h> @@ -70,10 +72,16 @@ static int tunnel4_rcv(struct sk_buff *skb) { struct xfrm_tunnel *handler; + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto drop; + for (handler = tunnel4_handlers; handler; handler = handler->next) if (!handler->handler(skb)) return 0; + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); + +drop: kfree_skb(skb); return 0; } diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 850d919591d..3e174c83bfe 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -37,8 +37,6 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) { switch (nexthdr) { case IPPROTO_IPIP: - if (!pskb_may_pull(skb, sizeof(struct iphdr))) - return -EINVAL; *spi = skb->nh.iph->saddr; *seq = 0; return 0; @@ -68,7 +66,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) { int err; u32 spi, seq; - struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH]; + struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; struct xfrm_state *x; int xfrm_nr = 0; int decaps = 0; @@ -90,14 +88,16 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) if (unlikely(x->km.state != XFRM_STATE_VALID)) goto drop_unlock; + if ((x->encap ? x->encap->encap_type : 0) != encap_type) + goto drop_unlock; + if (x->props.replay_window && xfrm_replay_check(x, seq)) goto drop_unlock; if (xfrm_state_check_expire(x)) goto drop_unlock; - xfrm_vec[xfrm_nr].decap.decap_type = encap_type; - if (x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb)) + if (x->type->input(x, skb)) goto drop_unlock; /* only the first xfrm gets the encap type */ @@ -111,7 +111,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) spin_unlock(&x->lock); - xfrm_vec[xfrm_nr++].xvec = x; + xfrm_vec[xfrm_nr++] = x; iph = skb->nh.iph; @@ -153,7 +153,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) goto drop; - memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); + memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec, + xfrm_nr * sizeof(xfrm_vec[0])); skb->sp->len += xfrm_nr; nf_reset(skb); @@ -184,7 +185,7 @@ drop_unlock: xfrm_state_put(x); drop: while (--xfrm_nr >= 0) - xfrm_state_put(xfrm_vec[xfrm_nr].xvec); + xfrm_state_put(xfrm_vec[xfrm_nr]); kfree_skb(skb); return 0; diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 2d670935c2b..f8ceaa127c8 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -21,7 +21,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) return 0; } -static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) { return 0; } diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index cf58251df4b..6778173a3dd 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -229,7 +229,7 @@ error: return err; } -static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) { /* * Before process AH diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 3dcaac7a097..22f04607903 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -130,7 +130,7 @@ error: return err; } -static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) { struct ipv6hdr *iph; struct ipv6_esp_hdr *esph; diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 2a1e7e45b89..a18d4256372 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = { { -1, } }; -int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) +int ipv6_parse_hopopts(struct sk_buff *skb) { struct inet6_skb_parm *opt = IP6CB(skb); + /* + * skb->nh.raw is equal to skb->data, and + * skb->h.raw - skb->nh.raw is always equal to + * sizeof(struct ipv6hdr) by definition of + * hop-by-hop options. + */ + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) || + !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) { + kfree_skb(skb); + return -1; + } + opt->hop = sizeof(struct ipv6hdr); if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { skb->h.raw += (skb->h.raw[1]+1)<<3; opt->nhoff = sizeof(struct ipv6hdr); - return sizeof(struct ipv6hdr); + return 1; } return -1; } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 21eb725e885..1044b6fce0d 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -717,7 +717,7 @@ int __init icmpv6_init(struct net_proto_family *ops) struct sock *sk; int err, i, j; - for_each_cpu(i) { + for_each_possible_cpu(i) { err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &per_cpu(__icmpv6_socket, i)); if (err < 0) { @@ -763,7 +763,7 @@ void icmpv6_cleanup(void) { int i; - for_each_cpu(i) { + for_each_possible_cpu(i) { sock_release(per_cpu(__icmpv6_socket, i)); } inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index bb8ffb8a14c..2ae84c96167 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -23,6 +23,86 @@ #include <net/inet6_hashtables.h> #include <net/ip.h> +void __inet6_hash(struct inet_hashinfo *hashinfo, + struct sock *sk) +{ + struct hlist_head *list; + rwlock_t *lock; + + BUG_TRAP(sk_unhashed(sk)); + + if (sk->sk_state == TCP_LISTEN) { + list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)]; + lock = &hashinfo->lhash_lock; + inet_listen_wlock(hashinfo); + } else { + unsigned int hash; + sk->sk_hash = hash = inet6_sk_ehashfn(sk); + hash &= (hashinfo->ehash_size - 1); + list = &hashinfo->ehash[hash].chain; + lock = &hashinfo->ehash[hash].lock; + write_lock(lock); + } + + __sk_add_node(sk, list); + sock_prot_inc_use(sk->sk_prot); + write_unlock(lock); +} +EXPORT_SYMBOL(__inet6_hash); + +/* + * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so + * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM + * + * The sockhash lock must be held as a reader here. + */ +struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, + const struct in6_addr *saddr, + const u16 sport, + const struct in6_addr *daddr, + const u16 hnum, + const int dif) +{ + struct sock *sk; + const struct hlist_node *node; + const __u32 ports = INET_COMBINED_PORTS(sport, hnum); + /* Optimize here for direct hit, only listening connections can + * have wildcards anyways. + */ + unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport); + struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash); + + prefetch(head->chain.first); + read_lock(&head->lock); + sk_for_each(sk, node, &head->chain) { + /* For IPV6 do the cheaper port and family tests first. */ + if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif)) + goto hit; /* You sunk my battleship! */ + } + /* Must check for a TIME_WAIT'er before going to listener hash. */ + sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { + const struct inet_timewait_sock *tw = inet_twsk(sk); + + if(*((__u32 *)&(tw->tw_dport)) == ports && + sk->sk_family == PF_INET6) { + const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); + + if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) && + ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) && + (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif)) + goto hit; + } + } + read_unlock(&head->lock); + return NULL; + +hit: + sock_hold(sk); + read_unlock(&head->lock); + return sk; +} +EXPORT_SYMBOL(__inet6_lookup_established); + struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, const struct in6_addr *daddr, const unsigned short hnum, const int dif) diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 29f73592e68..aceee252503 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -114,11 +114,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt } if (hdr->nexthdr == NEXTHDR_HOP) { - if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) { + if (ipv6_parse_hopopts(skb) < 0) { IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); return 0; } - hdr = skb->nh.ipv6h; } return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index ff9040c9255..a995796b5a5 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -519,9 +519,6 @@ ip6ip6_rcv(struct sk_buff *skb) struct ipv6hdr *ipv6h; struct ip6_tnl *t; - if (!pskb_may_pull(skb, sizeof (*ipv6h))) - goto discard; - ipv6h = skb->nh.ipv6h; read_lock(&ip6ip6_lock); @@ -529,8 +526,7 @@ ip6ip6_rcv(struct sk_buff *skb) if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { read_unlock(&ip6ip6_lock); - kfree_skb(skb); - return 0; + goto discard; } if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { @@ -557,9 +553,11 @@ ip6ip6_rcv(struct sk_buff *skb) return 0; } read_unlock(&ip6ip6_lock); - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); -discard: return 1; + +discard: + kfree_skb(skb); + return 0; } static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index d4cfec3f414..05eb67def39 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -63,7 +63,7 @@ static void **ipcomp6_scratches; static int ipcomp6_scratch_users; static LIST_HEAD(ipcomp6_tfms_list); -static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) { int err = 0; u8 nexthdr = 0; @@ -290,7 +290,7 @@ static void ipcomp6_free_scratches(void) if (!scratches) return; - for_each_cpu(i) { + for_each_possible_cpu(i) { void *scratch = *per_cpu_ptr(scratches, i); vfree(scratch); @@ -313,7 +313,7 @@ static void **ipcomp6_alloc_scratches(void) ipcomp6_scratches = scratches; - for_each_cpu(i) { + for_each_possible_cpu(i) { void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE); if (!scratch) return NULL; @@ -344,7 +344,7 @@ static void ipcomp6_free_tfms(struct crypto_tfm **tfms) if (!tfms) return; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu); crypto_free_tfm(tfm); } @@ -384,7 +384,7 @@ static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name) if (!tfms) goto error; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0); if (!tfm) goto error; diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index d750cfc019d..395a417ba95 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -7,6 +7,7 @@ #include <net/ipv6.h> #include <net/ip6_route.h> #include <net/xfrm.h> +#include <net/ip6_checksum.h> int ip6_route_me_harder(struct sk_buff *skb) { @@ -54,7 +55,7 @@ struct ip6_rt_info { struct in6_addr saddr; }; -static void save(const struct sk_buff *skb, struct nf_info *info) +static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info) { struct ip6_rt_info *rt_info = nf_info_reroute(info); @@ -66,7 +67,7 @@ static void save(const struct sk_buff *skb, struct nf_info *info) } } -static int reroute(struct sk_buff **pskb, const struct nf_info *info) +static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) { struct ip6_rt_info *rt_info = nf_info_reroute(info); @@ -79,15 +80,50 @@ static int reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } -static struct nf_queue_rerouter ip6_reroute = { - .rer_size = sizeof(struct ip6_rt_info), - .save = &save, - .reroute = &reroute, +unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) +{ + struct ipv6hdr *ip6h = skb->nh.ipv6h; + unsigned int csum = 0; + + switch (skb->ip_summed) { + case CHECKSUM_HW: + if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN) + break; + if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->len - dataoff, protocol, + csum_sub(skb->csum, + skb_checksum(skb, 0, + dataoff, 0)))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } + /* fall through */ + case CHECKSUM_NONE: + skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->len - dataoff, + protocol, + csum_sub(0, + skb_checksum(skb, 0, + dataoff, 0))); + csum = __skb_checksum_complete(skb); + } + return csum; +} + +EXPORT_SYMBOL(nf_ip6_checksum); + +static struct nf_afinfo nf_ip6_afinfo = { + .family = AF_INET6, + .checksum = nf_ip6_checksum, + .saveroute = nf_ip6_saveroute, + .reroute = nf_ip6_reroute, + .route_key_size = sizeof(struct ip6_rt_info), }; int __init ipv6_netfilter_init(void) { - return nf_register_queue_rerouter(PF_INET6, &ip6_reroute); + return nf_register_afinfo(&nf_ip6_afinfo); } /* This can be called from inet6_init() on errors, so it cannot @@ -95,5 +131,5 @@ int __init ipv6_netfilter_init(void) */ void ipv6_netfilter_fini(void) { - nf_unregister_queue_rerouter(PF_INET6); + nf_unregister_afinfo(&nf_ip6_afinfo); } diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 98f78759f1a..4bc4e5b3379 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -87,16 +87,6 @@ config IP6_NF_MATCH_HL To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_MULTIPORT - tristate "Multiple port match support" - depends on IP6_NF_IPTABLES - help - Multiport matching allows you to match TCP or UDP packets based on - a series of source or destination ports: normally a rule can only - match a single range of ports. - - To compile it as a module, choose M here. If unsure, say N. - config IP6_NF_MATCH_OWNER tristate "Owner match support" depends on IP6_NF_IPTABLES @@ -115,11 +105,11 @@ config IP6_NF_MATCH_IPV6HEADER To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_MATCH_AHESP - tristate "AH/ESP match support" +config IP6_NF_MATCH_AH + tristate "AH match support" depends on IP6_NF_IPTABLES help - This module allows one to match AH and ESP packets. + This module allows one to match AH packets. To compile it as a module, choose M here. If unsure, say N. diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 8436a1a1731..eeeb57d4c9c 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -8,9 +8,8 @@ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o -obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o +obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o -obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index e81c6a9dab8..b4b7d441af2 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -658,15 +658,11 @@ static struct nf_queue_handler nfqh = { .outfn = &ipq_enqueue_packet, }; -static int -init_or_cleanup(int init) +static int __init ip6_queue_init(void) { int status = -ENOMEM; struct proc_dir_entry *proc; - if (!init) - goto cleanup; - netlink_register_notifier(&ipq_nl_notifier); ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, THIS_MODULE); @@ -693,11 +689,6 @@ init_or_cleanup(int init) } return status; -cleanup: - nf_unregister_queue_handlers(&nfqh); - synchronize_net(); - ipq_flush(NF_DROP); - cleanup_sysctl: unregister_sysctl_table(ipq_sysctl_header); unregister_netdevice_notifier(&ipq_dev_notifier); @@ -713,15 +704,21 @@ cleanup_netlink_notifier: return status; } -static int __init ip6_queue_init(void) -{ - - return init_or_cleanup(1); -} - static void __exit ip6_queue_fini(void) { - init_or_cleanup(0); + nf_unregister_queue_handlers(&nfqh); + synchronize_net(); + ipq_flush(NF_DROP); + + unregister_sysctl_table(ipq_sysctl_header); + unregister_netdevice_notifier(&ipq_dev_notifier); + proc_net_remove(IPQ_PROC_FS_NAME); + + sock_release(ipqnl->sk_socket); + mutex_lock(&ipqnl_mutex); + mutex_unlock(&ipqnl_mutex); + + netlink_unregister_notifier(&ipq_nl_notifier); } MODULE_DESCRIPTION("IPv6 packet queue handler"); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 3ecf2db841f..0a673038344 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -288,19 +288,6 @@ ip6t_do_table(struct sk_buff **pskb, table_base = (void *)private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); -#ifdef CONFIG_NETFILTER_DEBUG - /* Check noone else using our table */ - if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac - && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) { - printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n", - smp_processor_id(), - table->name, - &((struct ip6t_entry *)table_base)->comefrom, - ((struct ip6t_entry *)table_base)->comefrom); - } - ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001; -#endif - /* For return from builtin chain */ back = get_entry(table_base, private->underflow[hook]); @@ -788,7 +775,7 @@ translate_table(const char *name, } /* And one copy for every other CPU */ - for_each_cpu(i) { + for_each_possible_cpu(i) { if (newinfo->entries[i] && newinfo->entries[i] != entry0) memcpy(newinfo->entries[i], entry0, newinfo->size); } @@ -841,7 +828,7 @@ get_counters(const struct xt_table_info *t, counters, &i); - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { if (cpu == curcpu) continue; i = 0; diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c deleted file mode 100644 index 36bedad2c6f..00000000000 --- a/net/ipv6/netfilter/ip6t_esp.c +++ /dev/null @@ -1,115 +0,0 @@ -/* Kernel module to match ESP parameters. */ -/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - - -#include <linux/module.h> -#include <linux/skbuff.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <linux/types.h> -#include <net/checksum.h> -#include <net/ipv6.h> - -#include <linux/netfilter_ipv6/ip6_tables.h> -#include <linux/netfilter_ipv6/ip6t_esp.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("IPv6 ESP match"); -MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - -/* Returns 1 if the spi is matched by the range, 0 otherwise */ -static inline int -spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) -{ - int r=0; - DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', - min,spi,max); - r=(spi >= min && spi <= max) ^ invert; - DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n"); - return r; -} - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - struct ip_esp_hdr _esp, *eh; - const struct ip6t_esp *espinfo = matchinfo; - unsigned int ptr; - - /* Make sure this isn't an evil packet */ - /*DEBUGP("ipv6_esp entered \n");*/ - - if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP, NULL) < 0) - return 0; - - eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); - if (eh == NULL) { - *hotdrop = 1; - return 0; - } - - DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); - - return (eh != NULL) - && spi_match(espinfo->spis[0], espinfo->spis[1], - ntohl(eh->spi), - !!(espinfo->invflags & IP6T_ESP_INV_SPI)); -} - -/* Called when user tries to insert an entry of this type. */ -static int -checkentry(const char *tablename, - const void *ip, - const struct xt_match *match, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) -{ - const struct ip6t_esp *espinfo = matchinfo; - - if (espinfo->invflags & ~IP6T_ESP_INV_MASK) { - DEBUGP("ip6t_esp: unknown flags %X\n", - espinfo->invflags); - return 0; - } - return 1; -} - -static struct ip6t_match esp_match = { - .name = "esp", - .match = match, - .matchsize = sizeof(struct ip6t_esp), - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init ip6t_esp_init(void) -{ - return ip6t_register_match(&esp_match); -} - -static void __exit ip6t_esp_fini(void) -{ - ip6t_unregister_match(&esp_match); -} - -module_init(ip6t_esp_init); -module_exit(ip6t_esp_fini); diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c deleted file mode 100644 index 10c48ba596d..00000000000 --- a/net/ipv6/netfilter/ip6t_multiport.c +++ /dev/null @@ -1,125 +0,0 @@ -/* Kernel module to match one of a list of TCP/UDP ports: ports are in - the same place so we can treat them as equal. */ - -/* (C) 1999-2001 Paul `Rusty' Russell - * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/udp.h> -#include <linux/skbuff.h> -#include <linux/in.h> - -#include <linux/netfilter_ipv6/ip6t_multiport.h> -#include <linux/netfilter_ipv6/ip6_tables.h> - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); -MODULE_DESCRIPTION("ip6tables match for multiple ports"); - -#if 0 -#define duprintf(format, args...) printk(format , ## args) -#else -#define duprintf(format, args...) -#endif - -/* Returns 1 if the port is matched by the test, 0 otherwise. */ -static inline int -ports_match(const u_int16_t *portlist, enum ip6t_multiport_flags flags, - u_int8_t count, u_int16_t src, u_int16_t dst) -{ - unsigned int i; - for (i=0; i<count; i++) { - if (flags != IP6T_MULTIPORT_DESTINATION - && portlist[i] == src) - return 1; - - if (flags != IP6T_MULTIPORT_SOURCE - && portlist[i] == dst) - return 1; - } - - return 0; -} - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - u16 _ports[2], *pptr; - const struct ip6t_multiport *multiinfo = matchinfo; - - /* Must not be a fragment. */ - if (offset) - return 0; - - /* Must be big enough to read ports (both UDP and TCP have - them at the start). */ - pptr = skb_header_pointer(skb, protoff, sizeof(_ports), &_ports[0]); - if (pptr == NULL) { - /* We've been asked to examine this packet, and we - * can't. Hence, no choice but to drop. - */ - duprintf("ip6t_multiport:" - " Dropping evil offset=0 tinygram.\n"); - *hotdrop = 1; - return 0; - } - - return ports_match(multiinfo->ports, - multiinfo->flags, multiinfo->count, - ntohs(pptr[0]), ntohs(pptr[1])); -} - -/* Called when user tries to insert an entry of this type. */ -static int -checkentry(const char *tablename, - const void *info, - const struct xt_match *match, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) -{ - const struct ip6t_ip6 *ip = info; - const struct ip6t_multiport *multiinfo = matchinfo; - - /* Must specify proto == TCP/UDP, no unknown flags or bad count */ - return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP) - && !(ip->invflags & IP6T_INV_PROTO) - && (multiinfo->flags == IP6T_MULTIPORT_SOURCE - || multiinfo->flags == IP6T_MULTIPORT_DESTINATION - || multiinfo->flags == IP6T_MULTIPORT_EITHER) - && multiinfo->count <= IP6T_MULTI_PORTS; -} - -static struct ip6t_match multiport_match = { - .name = "multiport", - .match = match, - .matchsize = sizeof(struct ip6t_multiport), - .checkentry = checkentry, - .me = THIS_MODULE, -}; - -static int __init ip6t_multiport_init(void) -{ - return ip6t_register_match(&multiport_match); -} - -static void __exit ip6t_multiport_fini(void) -{ - ip6t_unregister_match(&multiport_match); -} - -module_init(ip6t_multiport_init); -module_exit(ip6t_multiport_fini); diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index e5e724d9ee6..60976c0c58e 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -177,37 +177,20 @@ static int __init ip6table_filter_init(void) return ret; /* Register hooks */ - ret = nf_register_hook(&ip6t_ops[0]); + ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); if (ret < 0) goto cleanup_table; - ret = nf_register_hook(&ip6t_ops[1]); - if (ret < 0) - goto cleanup_hook0; - - ret = nf_register_hook(&ip6t_ops[2]); - if (ret < 0) - goto cleanup_hook1; - return ret; - cleanup_hook1: - nf_unregister_hook(&ip6t_ops[1]); - cleanup_hook0: - nf_unregister_hook(&ip6t_ops[0]); cleanup_table: ip6t_unregister_table(&packet_filter); - return ret; } static void __exit ip6table_filter_fini(void) { - unsigned int i; - - for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++) - nf_unregister_hook(&ip6t_ops[i]); - + nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); ip6t_unregister_table(&packet_filter); } diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index e1f0f6ae984..03a13eab1da 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -238,49 +238,20 @@ static int __init ip6table_mangle_init(void) return ret; /* Register hooks */ - ret = nf_register_hook(&ip6t_ops[0]); + ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); if (ret < 0) goto cleanup_table; - ret = nf_register_hook(&ip6t_ops[1]); - if (ret < 0) - goto cleanup_hook0; - - ret = nf_register_hook(&ip6t_ops[2]); - if (ret < 0) - goto cleanup_hook1; - - ret = nf_register_hook(&ip6t_ops[3]); - if (ret < 0) - goto cleanup_hook2; - - ret = nf_register_hook(&ip6t_ops[4]); - if (ret < 0) - goto cleanup_hook3; - return ret; - cleanup_hook3: - nf_unregister_hook(&ip6t_ops[3]); - cleanup_hook2: - nf_unregister_hook(&ip6t_ops[2]); - cleanup_hook1: - nf_unregister_hook(&ip6t_ops[1]); - cleanup_hook0: - nf_unregister_hook(&ip6t_ops[0]); cleanup_table: ip6t_unregister_table(&packet_mangler); - return ret; } static void __exit ip6table_mangle_fini(void) { - unsigned int i; - - for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++) - nf_unregister_hook(&ip6t_ops[i]); - + nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); ip6t_unregister_table(&packet_mangler); } diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 54d1fffd62b..61a7c58e99f 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -152,31 +152,20 @@ static int __init ip6table_raw_init(void) return ret; /* Register hooks */ - ret = nf_register_hook(&ip6t_ops[0]); + ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); if (ret < 0) goto cleanup_table; - ret = nf_register_hook(&ip6t_ops[1]); - if (ret < 0) - goto cleanup_hook0; - return ret; - cleanup_hook0: - nf_unregister_hook(&ip6t_ops[0]); cleanup_table: ip6t_unregister_table(&packet_raw); - return ret; } static void __exit ip6table_raw_fini(void) { - unsigned int i; - - for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++) - nf_unregister_hook(&ip6t_ops[i]); - + nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); ip6t_unregister_table(&packet_raw); } diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index c8b5a96cbb0..93bae36f266 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -286,55 +286,49 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum, return ipv6_conntrack_in(hooknum, pskb, in, out, okfn); } -/* Connection tracking may drop packets, but never alters them, so - make it the first hook. */ -static struct nf_hook_ops ipv6_conntrack_defrag_ops = { - .hook = ipv6_defrag, - .owner = THIS_MODULE, - .pf = PF_INET6, - .hooknum = NF_IP6_PRE_ROUTING, - .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, -}; - -static struct nf_hook_ops ipv6_conntrack_in_ops = { - .hook = ipv6_conntrack_in, - .owner = THIS_MODULE, - .pf = PF_INET6, - .hooknum = NF_IP6_PRE_ROUTING, - .priority = NF_IP6_PRI_CONNTRACK, -}; - -static struct nf_hook_ops ipv6_conntrack_local_out_ops = { - .hook = ipv6_conntrack_local, - .owner = THIS_MODULE, - .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_OUT, - .priority = NF_IP6_PRI_CONNTRACK, -}; - -static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = { - .hook = ipv6_defrag, - .owner = THIS_MODULE, - .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_OUT, - .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, -}; - -/* Refragmenter; last chance. */ -static struct nf_hook_ops ipv6_conntrack_out_ops = { - .hook = ipv6_confirm, - .owner = THIS_MODULE, - .pf = PF_INET6, - .hooknum = NF_IP6_POST_ROUTING, - .priority = NF_IP6_PRI_LAST, -}; - -static struct nf_hook_ops ipv6_conntrack_local_in_ops = { - .hook = ipv6_confirm, - .owner = THIS_MODULE, - .pf = PF_INET6, - .hooknum = NF_IP6_LOCAL_IN, - .priority = NF_IP6_PRI_LAST-1, +static struct nf_hook_ops ipv6_conntrack_ops[] = { + { + .hook = ipv6_defrag, + .owner = THIS_MODULE, + .pf = PF_INET6, + .hooknum = NF_IP6_PRE_ROUTING, + .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, + }, + { + .hook = ipv6_conntrack_in, + .owner = THIS_MODULE, + .pf = PF_INET6, + .hooknum = NF_IP6_PRE_ROUTING, + .priority = NF_IP6_PRI_CONNTRACK, + }, + { + .hook = ipv6_conntrack_local, + .owner = THIS_MODULE, + .pf = PF_INET6, + .hooknum = NF_IP6_LOCAL_OUT, + .priority = NF_IP6_PRI_CONNTRACK, + }, + { + .hook = ipv6_defrag, + .owner = THIS_MODULE, + .pf = PF_INET6, + .hooknum = NF_IP6_LOCAL_OUT, + .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, + }, + { + .hook = ipv6_confirm, + .owner = THIS_MODULE, + .pf = PF_INET6, + .hooknum = NF_IP6_POST_ROUTING, + .priority = NF_IP6_PRI_LAST, + }, + { + .hook = ipv6_confirm, + .owner = THIS_MODULE, + .pf = PF_INET6, + .hooknum = NF_IP6_LOCAL_IN, + .priority = NF_IP6_PRI_LAST-1, + }, }; #ifdef CONFIG_SYSCTL @@ -470,16 +464,21 @@ extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6; extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6; extern int nf_ct_frag6_init(void); extern void nf_ct_frag6_cleanup(void); -static int init_or_cleanup(int init) + +MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); + +static int __init nf_conntrack_l3proto_ipv6_init(void) { int ret = 0; - if (!init) goto cleanup; + need_conntrack(); ret = nf_ct_frag6_init(); if (ret < 0) { printk("nf_conntrack_ipv6: can't initialize frag6.\n"); - goto cleanup_nothing; + return ret; } ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6); if (ret < 0) { @@ -505,71 +504,27 @@ static int init_or_cleanup(int init) goto cleanup_icmpv6; } - ret = nf_register_hook(&ipv6_conntrack_defrag_ops); + ret = nf_register_hooks(ipv6_conntrack_ops, + ARRAY_SIZE(ipv6_conntrack_ops)); if (ret < 0) { printk("nf_conntrack_ipv6: can't register pre-routing defrag " "hook.\n"); goto cleanup_ipv6; } - - ret = nf_register_hook(&ipv6_conntrack_defrag_local_out_ops); - if (ret < 0) { - printk("nf_conntrack_ipv6: can't register local_out defrag " - "hook.\n"); - goto cleanup_defragops; - } - - ret = nf_register_hook(&ipv6_conntrack_in_ops); - if (ret < 0) { - printk("nf_conntrack_ipv6: can't register pre-routing hook.\n"); - goto cleanup_defraglocalops; - } - - ret = nf_register_hook(&ipv6_conntrack_local_out_ops); - if (ret < 0) { - printk("nf_conntrack_ipv6: can't register local out hook.\n"); - goto cleanup_inops; - } - - ret = nf_register_hook(&ipv6_conntrack_out_ops); - if (ret < 0) { - printk("nf_conntrack_ipv6: can't register post-routing hook.\n"); - goto cleanup_inandlocalops; - } - - ret = nf_register_hook(&ipv6_conntrack_local_in_ops); - if (ret < 0) { - printk("nf_conntrack_ipv6: can't register local in hook.\n"); - goto cleanup_inoutandlocalops; - } - #ifdef CONFIG_SYSCTL nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); if (nf_ct_ipv6_sysctl_header == NULL) { printk("nf_conntrack: can't register to sysctl.\n"); ret = -ENOMEM; - goto cleanup_localinops; + goto cleanup_hooks; } #endif return ret; - cleanup: - synchronize_net(); #ifdef CONFIG_SYSCTL - unregister_sysctl_table(nf_ct_ipv6_sysctl_header); - cleanup_localinops: + cleanup_hooks: + nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); #endif - nf_unregister_hook(&ipv6_conntrack_local_in_ops); - cleanup_inoutandlocalops: - nf_unregister_hook(&ipv6_conntrack_out_ops); - cleanup_inandlocalops: - nf_unregister_hook(&ipv6_conntrack_local_out_ops); - cleanup_inops: - nf_unregister_hook(&ipv6_conntrack_in_ops); - cleanup_defraglocalops: - nf_unregister_hook(&ipv6_conntrack_defrag_local_out_ops); - cleanup_defragops: - nf_unregister_hook(&ipv6_conntrack_defrag_ops); cleanup_ipv6: nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); cleanup_icmpv6: @@ -580,23 +535,21 @@ static int init_or_cleanup(int init) nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); cleanup_frag6: nf_ct_frag6_cleanup(); - cleanup_nothing: return ret; } -MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); - -static int __init nf_conntrack_l3proto_ipv6_init(void) -{ - need_conntrack(); - return init_or_cleanup(1); -} - static void __exit nf_conntrack_l3proto_ipv6_fini(void) { - init_or_cleanup(0); + synchronize_net(); +#ifdef CONFIG_SYSCTL + unregister_sysctl_table(nf_ct_ipv6_sysctl_header); +#endif + nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); + nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); + nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6); + nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6); + nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); + nf_ct_frag6_cleanup(); } module_init(nf_conntrack_l3proto_ipv6_init); diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 09945c33305..86c6703265d 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -233,21 +233,13 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff, return -NF_ACCEPT; } - if (hooknum != NF_IP6_PRE_ROUTING) - goto skipped; - - /* Ignore it if the checksum's bogus. */ - if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, - skb->len - dataoff, IPPROTO_ICMPV6, - skb_checksum(skb, dataoff, - skb->len - dataoff, 0))) { + if (hooknum == NF_IP6_PRE_ROUTING && + nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, "nf_ct_icmpv6: ICMPv6 checksum failed\n"); return -NF_ACCEPT; } -skipped: - /* is not error message ? */ if (icmp6h->icmp6_type >= 128) return NF_ACCEPT; diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 4238b1ed886..779ddf77f4d 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -38,7 +38,7 @@ static int fold_prot_inuse(struct proto *proto) int res = 0; int cpu; - for_each_cpu(cpu) + for_each_possible_cpu(cpu) res += proto->stats[cpu].inuse; return res; @@ -140,7 +140,7 @@ fold_field(void *mib[], int offt) unsigned long res = 0; int i; - for_each_cpu(i) { + for_each_possible_cpu(i) { res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt); res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt); } 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/ipv6/sit.c b/net/ipv6/sit.c index c2d3e17beae..6578c3080f4 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -397,7 +397,7 @@ static int ipip6_rcv(struct sk_buff *skb) return 0; } - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); kfree_skb(skb); read_unlock(&ipip6_lock); out: diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 5659b52284b..0ef9a35798d 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c @@ -19,11 +19,13 @@ * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> */ +#include <linux/icmpv6.h> #include <linux/init.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/netdevice.h> #include <linux/skbuff.h> +#include <net/ipv6.h> #include <net/protocol.h> #include <net/xfrm.h> @@ -87,10 +89,16 @@ static int tunnel6_rcv(struct sk_buff **pskb) struct sk_buff *skb = *pskb; struct xfrm6_tunnel *handler; + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) + goto drop; + for (handler = tunnel6_handlers; handler; handler = handler->next) if (!handler->handler(skb)) return 0; + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev); + +drop: kfree_skb(skb); return 0; } diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index cccf8b76f04..00cfdee18dc 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -32,7 +32,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) { int err; u32 seq; - struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH]; + struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; struct xfrm_state *x; int xfrm_nr = 0; int decaps = 0; @@ -65,7 +65,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) if (xfrm_state_check_expire(x)) goto drop_unlock; - nexthdr = x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb); + nexthdr = x->type->input(x, skb); if (nexthdr <= 0) goto drop_unlock; @@ -79,7 +79,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) spin_unlock(&x->lock); - xfrm_vec[xfrm_nr++].xvec = x; + xfrm_vec[xfrm_nr++] = x; if (x->props.mode) { /* XXX */ if (nexthdr != IPPROTO_IPV6) @@ -118,7 +118,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) goto drop; - memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); + memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec, + xfrm_nr * sizeof(xfrm_vec[0])); skb->sp->len += xfrm_nr; skb->ip_summed = CHECKSUM_NONE; @@ -149,7 +150,7 @@ drop_unlock: xfrm_state_put(x); drop: while (--xfrm_nr >= 0) - xfrm_state_put(xfrm_vec[xfrm_nr].xvec); + xfrm_state_put(xfrm_vec[xfrm_nr]); kfree_skb(skb); return -1; } diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 91cce8b2d7a..88c840f1beb 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -191,16 +191,18 @@ error: static inline void _decode_session6(struct sk_buff *skb, struct flowi *fl) { - u16 offset = sizeof(struct ipv6hdr); + u16 offset = skb->h.raw - skb->nh.raw; struct ipv6hdr *hdr = skb->nh.ipv6h; - struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); - u8 nexthdr = skb->nh.ipv6h->nexthdr; + struct ipv6_opt_hdr *exthdr; + u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff]; memset(fl, 0, sizeof(struct flowi)); ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr); ipv6_addr_copy(&fl->fl6_src, &hdr->saddr); while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) { + exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); + switch (nexthdr) { case NEXTHDR_ROUTING: case NEXTHDR_HOP: diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index a8f6776c518..d37768e5064 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -351,7 +351,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) return 0; } -static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) { return 0; } diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 8f3addf0724..d62e0f9b9da 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -118,7 +118,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb) u16 pdulen = eth_hdr(skb)->h_proto, data_size = ntohs(pdulen) - llc_len; - skb_trim(skb, data_size); + if (unlikely(pskb_trim_rcsum(skb, data_size))) + return 0; } return 1; } diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 332acb37b38..e2893effdfa 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -231,6 +231,15 @@ config NETFILTER_XT_MATCH_DCCP If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. If unsure, say `N'. +config NETFILTER_XT_MATCH_ESP + tristate '"ESP" match support' + depends on NETFILTER_XTABLES + help + This match extension allows you to match a range of SPIs + inside ESP header of IPSec packets. + + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XT_MATCH_HELPER tristate '"helper" match support' depends on NETFILTER_XTABLES @@ -289,6 +298,16 @@ config NETFILTER_XT_MATCH_POLICY To compile it as a module, choose M here. If unsure, say N. +config NETFILTER_XT_MATCH_MULTIPORT + tristate "Multiple port match support" + depends on NETFILTER_XTABLES + help + Multiport matching allows you to match TCP or UDP packets based on + a series of source or destination ports: normally a rule can only + match a single range of ports. + + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XT_MATCH_PHYSDEV tristate '"physdev" match support' depends on NETFILTER_XTABLES && BRIDGE_NETFILTER diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 9558727f5e7..95b7e416512 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -35,11 +35,13 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o +obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o +obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 1ceb1a6c254..8455a32ea5c 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -27,6 +27,29 @@ #include "nf_internals.h" +static DEFINE_SPINLOCK(afinfo_lock); + +struct nf_afinfo *nf_afinfo[NPROTO]; +EXPORT_SYMBOL(nf_afinfo); + +int nf_register_afinfo(struct nf_afinfo *afinfo) +{ + spin_lock(&afinfo_lock); + rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo); + spin_unlock(&afinfo_lock); + return 0; +} +EXPORT_SYMBOL_GPL(nf_register_afinfo); + +void nf_unregister_afinfo(struct nf_afinfo *afinfo) +{ + spin_lock(&afinfo_lock); + rcu_assign_pointer(nf_afinfo[afinfo->family], NULL); + spin_unlock(&afinfo_lock); + synchronize_rcu(); +} +EXPORT_SYMBOL_GPL(nf_unregister_afinfo); + /* In this code, we can be waiting indefinitely for userspace to * service a packet if a hook returns NF_QUEUE. We could keep a count * of skbuffs queued for userspace, and not deregister a hook unless @@ -63,6 +86,34 @@ void nf_unregister_hook(struct nf_hook_ops *reg) } EXPORT_SYMBOL(nf_unregister_hook); +int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n) +{ + unsigned int i; + int err = 0; + + for (i = 0; i < n; i++) { + err = nf_register_hook(®[i]); + if (err) + goto err; + } + return err; + +err: + if (i > 0) + nf_unregister_hooks(reg, i); + return err; +} +EXPORT_SYMBOL(nf_register_hooks); + +void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) +{ + unsigned int i; + + for (i = 0; i < n; i++) + nf_unregister_hook(®[i]); +} +EXPORT_SYMBOL(nf_unregister_hooks); + unsigned int nf_iterate(struct list_head *head, struct sk_buff **skb, int hook, diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 56389c83557..f9b83f91371 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -146,7 +146,7 @@ static void nf_ct_event_cache_flush(void) struct nf_conntrack_ecache *ecache; int cpu; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { ecache = &per_cpu(nf_conntrack_ecache, cpu); if (ecache->ct) nf_ct_put(ecache->ct); @@ -178,9 +178,6 @@ static struct { /* allocated slab cache + modules which uses this slab cache */ int use; - /* Initialization */ - int (*init_conntrack)(struct nf_conn *, u_int32_t); - } nf_ct_cache[NF_CT_F_NUM]; /* protect members of nf_ct_cache except of "use" */ @@ -208,10 +205,8 @@ nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol) preempt_disable(); p = __nf_ct_proto_find(l3proto, protocol); - if (p) { - if (!try_module_get(p->me)) - p = &nf_conntrack_generic_protocol; - } + if (!try_module_get(p->me)) + p = &nf_conntrack_generic_protocol; preempt_enable(); return p; @@ -229,10 +224,8 @@ nf_ct_l3proto_find_get(u_int16_t l3proto) preempt_disable(); p = __nf_ct_l3proto_find(l3proto); - if (p) { - if (!try_module_get(p->me)) - p = &nf_conntrack_generic_l3proto; - } + if (!try_module_get(p->me)) + p = &nf_conntrack_generic_l3proto; preempt_enable(); return p; diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index 7de4f06c63c..3fc58e454d4 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c @@ -94,5 +94,4 @@ struct nf_conntrack_l3proto nf_conntrack_generic_l3proto = { .print_conntrack = generic_print_conntrack, .prepare = generic_prepare, .get_features = generic_get_features, - .me = THIS_MODULE, }; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 0e0e9d7b34c..bd10eb944b6 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1022,7 +1022,7 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[]) return err; } -#if defined(CONFIG_IP_NF_CONNTRACK_MARK) +#if defined(CONFIG_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif @@ -1062,7 +1062,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[], return err; } -#if defined(CONFIG_IP_NF_CONNTRACK_MARK) +#if defined(CONFIG_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif @@ -1687,7 +1687,7 @@ static void __exit ctnetlink_exit(void) printk("ctnetlink: unregistering from nfnetlink.\n"); #ifdef CONFIG_NF_CONNTRACK_EVENTS - nf_conntrack_unregister_notifier(&ctnl_notifier_exp); + nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp); nf_conntrack_unregister_notifier(&ctnl_notifier); #endif diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 6492ed66fb3..69899f27d26 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -799,8 +799,7 @@ static int tcp_error(struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info *ctinfo, int pf, - unsigned int hooknum, - int(*csum)(const struct sk_buff *,unsigned int)) + unsigned int hooknum) { struct tcphdr _tcph, *th; unsigned int tcplen = skb->len - dataoff; @@ -830,9 +829,8 @@ static int tcp_error(struct sk_buff *skb, */ /* FIXME: Source route IP option packets --RR */ if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || - (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) - && skb->ip_summed != CHECKSUM_UNNECESSARY - && csum(skb, dataoff)) { + (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) && + nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) { if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: bad TCP checksum "); @@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb, return NF_ACCEPT; } -static int csum4(const struct sk_buff *skb, unsigned int dataoff) -{ - return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, - skb->len - dataoff, IPPROTO_TCP, - skb->ip_summed == CHECKSUM_HW ? skb->csum - : skb_checksum(skb, dataoff, - skb->len - dataoff, 0)); -} - -static int csum6(const struct sk_buff *skb, unsigned int dataoff) -{ - return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, - skb->len - dataoff, IPPROTO_TCP, - skb->ip_summed == CHECKSUM_HW - ? csum_sub(skb->csum, - skb_checksum(skb, 0, dataoff, 0)) - : skb_checksum(skb, dataoff, skb->len - dataoff, - 0)); -} - -static int tcp_error4(struct sk_buff *skb, - unsigned int dataoff, - enum ip_conntrack_info *ctinfo, - int pf, - unsigned int hooknum) -{ - return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4); -} - -static int tcp_error6(struct sk_buff *skb, - unsigned int dataoff, - enum ip_conntrack_info *ctinfo, - int pf, - unsigned int hooknum) -{ - return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6); -} - /* Returns verdict for packet, or -1 for invalid. */ static int tcp_packet(struct nf_conn *conntrack, const struct sk_buff *skb, @@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 = .print_conntrack = tcp_print_conntrack, .packet = tcp_packet, .new = tcp_new, - .error = tcp_error4, + .error = tcp_error, #if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nfattr = tcp_to_nfattr, @@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 = .print_conntrack = tcp_print_conntrack, .packet = tcp_packet, .new = tcp_new, - .error = tcp_error6, + .error = tcp_error, #if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nfattr = tcp_to_nfattr, diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 831d206344e..d93edbfde9e 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -103,8 +103,7 @@ static int udp_new(struct nf_conn *conntrack, const struct sk_buff *skb, static int udp_error(struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info *ctinfo, int pf, - unsigned int hooknum, - int (*csum)(const struct sk_buff *, unsigned int)) + unsigned int hooknum) { unsigned int udplen = skb->len - dataoff; struct udphdr _hdr, *hdr; @@ -136,9 +135,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff, * and moreover root might send raw packets. * FIXME: Source route IP option packets --RR */ if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || - (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) - && skb->ip_summed != CHECKSUM_UNNECESSARY - && csum(skb, dataoff)) { + (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) && + nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) { if (LOG_INVALID(IPPROTO_UDP)) nf_log_packet(pf, 0, skb, NULL, NULL, NULL, "nf_ct_udp: bad UDP checksum "); @@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff, return NF_ACCEPT; } -static int csum4(const struct sk_buff *skb, unsigned int dataoff) -{ - return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, - skb->len - dataoff, IPPROTO_UDP, - skb->ip_summed == CHECKSUM_HW ? skb->csum - : skb_checksum(skb, dataoff, - skb->len - dataoff, 0)); -} - -static int csum6(const struct sk_buff *skb, unsigned int dataoff) -{ - return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, - skb->len - dataoff, IPPROTO_UDP, - skb->ip_summed == CHECKSUM_HW - ? csum_sub(skb->csum, - skb_checksum(skb, 0, dataoff, 0)) - : skb_checksum(skb, dataoff, skb->len - dataoff, - 0)); -} - -static int udp_error4(struct sk_buff *skb, - unsigned int dataoff, - enum ip_conntrack_info *ctinfo, - int pf, - unsigned int hooknum) -{ - return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4); -} - -static int udp_error6(struct sk_buff *skb, - unsigned int dataoff, - enum ip_conntrack_info *ctinfo, - int pf, - unsigned int hooknum) -{ - return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6); -} - struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = { .l3proto = PF_INET, @@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = .print_conntrack = udp_print_conntrack, .packet = udp_packet, .new = udp_new, - .error = udp_error4, + .error = udp_error, #if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, @@ -216,7 +176,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 = .print_conntrack = udp_print_conntrack, .packet = udp_packet, .new = udp_new, - .error = udp_error6, + .error = udp_error, #if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index c72aa3cd22e..408960c6a54 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -649,63 +649,6 @@ static ctl_table nf_ct_net_table[] = { EXPORT_SYMBOL(nf_ct_log_invalid); #endif /* CONFIG_SYSCTL */ -static int init_or_cleanup(int init) -{ -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc, *proc_exp, *proc_stat; -#endif - int ret = 0; - - if (!init) goto cleanup; - - ret = nf_conntrack_init(); - if (ret < 0) - goto cleanup_nothing; - -#ifdef CONFIG_PROC_FS - proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops); - if (!proc) goto cleanup_init; - - proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440, - &exp_file_ops); - if (!proc_exp) goto cleanup_proc; - - proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat); - if (!proc_stat) - goto cleanup_proc_exp; - - proc_stat->proc_fops = &ct_cpu_seq_fops; - proc_stat->owner = THIS_MODULE; -#endif -#ifdef CONFIG_SYSCTL - nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); - if (nf_ct_sysctl_header == NULL) { - printk("nf_conntrack: can't register to sysctl.\n"); - ret = -ENOMEM; - goto cleanup_proc_stat; - } -#endif - - return ret; - - cleanup: -#ifdef CONFIG_SYSCTL - unregister_sysctl_table(nf_ct_sysctl_header); - cleanup_proc_stat: -#endif -#ifdef CONFIG_PROC_FS - remove_proc_entry("nf_conntrack", proc_net_stat); - cleanup_proc_exp: - proc_net_remove("nf_conntrack_expect"); - cleanup_proc: - proc_net_remove("nf_conntrack"); - cleanup_init: -#endif /* CNFIG_PROC_FS */ - nf_conntrack_cleanup(); - cleanup_nothing: - return ret; -} - int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) { int ret = 0; @@ -808,12 +751,66 @@ void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto) static int __init nf_conntrack_standalone_init(void) { - return init_or_cleanup(1); +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc, *proc_exp, *proc_stat; +#endif + int ret = 0; + + ret = nf_conntrack_init(); + if (ret < 0) + return ret; + +#ifdef CONFIG_PROC_FS + proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops); + if (!proc) goto cleanup_init; + + proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440, + &exp_file_ops); + if (!proc_exp) goto cleanup_proc; + + proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat); + if (!proc_stat) + goto cleanup_proc_exp; + + proc_stat->proc_fops = &ct_cpu_seq_fops; + proc_stat->owner = THIS_MODULE; +#endif +#ifdef CONFIG_SYSCTL + nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); + if (nf_ct_sysctl_header == NULL) { + printk("nf_conntrack: can't register to sysctl.\n"); + ret = -ENOMEM; + goto cleanup_proc_stat; + } +#endif + return ret; + +#ifdef CONFIG_SYSCTL + cleanup_proc_stat: +#endif +#ifdef CONFIG_PROC_FS + remove_proc_entry("nf_conntrack", proc_net_stat); + cleanup_proc_exp: + proc_net_remove("nf_conntrack_expect"); + cleanup_proc: + proc_net_remove("nf_conntrack"); + cleanup_init: +#endif /* CNFIG_PROC_FS */ + nf_conntrack_cleanup(); + return ret; } static void __exit nf_conntrack_standalone_fini(void) { - init_or_cleanup(0); +#ifdef CONFIG_SYSCTL + unregister_sysctl_table(nf_ct_sysctl_header); +#endif +#ifdef CONFIG_PROC_FS + remove_proc_entry("nf_conntrack", proc_net_stat); + proc_net_remove("nf_conntrack_expect"); + proc_net_remove("nf_conntrack"); +#endif /* CNFIG_PROC_FS */ + nf_conntrack_cleanup(); } module_init(nf_conntrack_standalone_init); diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index d9f0d7ef103..ee8f70889f4 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -17,7 +17,6 @@ * for queueing and must reinject all packets it receives, no matter what. */ static struct nf_queue_handler *queue_handler[NPROTO]; -static struct nf_queue_rerouter *queue_rerouter[NPROTO]; static DEFINE_RWLOCK(queue_handler_lock); @@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf) } EXPORT_SYMBOL(nf_unregister_queue_handler); -int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer) -{ - if (pf >= NPROTO) - return -EINVAL; - - write_lock_bh(&queue_handler_lock); - rcu_assign_pointer(queue_rerouter[pf], rer); - write_unlock_bh(&queue_handler_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(nf_register_queue_rerouter); - -int nf_unregister_queue_rerouter(int pf) -{ - if (pf >= NPROTO) - return -EINVAL; - - write_lock_bh(&queue_handler_lock); - rcu_assign_pointer(queue_rerouter[pf], NULL); - write_unlock_bh(&queue_handler_lock); - synchronize_rcu(); - return 0; -} -EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); - void nf_unregister_queue_handlers(struct nf_queue_handler *qh) { int pf; @@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb, struct net_device *physindev = NULL; struct net_device *physoutdev = NULL; #endif - struct nf_queue_rerouter *rerouter; + struct nf_afinfo *afinfo; /* QUEUE == DROP if noone is waiting, to be safe. */ read_lock(&queue_handler_lock); @@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb, return 1; } - info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC); + afinfo = nf_get_afinfo(pf); + if (!afinfo) { + read_unlock(&queue_handler_lock); + kfree_skb(*skb); + return 1; + } + + info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC); if (!info) { if (net_ratelimit()) printk(KERN_ERR "OOM queueing packet %p\n", @@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb, if (physoutdev) dev_hold(physoutdev); } #endif - rerouter = rcu_dereference(queue_rerouter[pf]); - if (rerouter) - rerouter->save(*skb, info); - + afinfo->saveroute(*skb, info); status = queue_handler[pf]->outfn(*skb, info, queuenum, queue_handler[pf]->data); @@ -190,7 +167,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, { struct list_head *elem = &info->elem->list; struct list_head *i; - struct nf_queue_rerouter *rerouter; + struct nf_afinfo *afinfo; rcu_read_lock(); @@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, } if (verdict == NF_ACCEPT) { - rerouter = rcu_dereference(queue_rerouter[info->pf]); - if (rerouter && rerouter->reroute(&skb, info) < 0) + afinfo = nf_get_afinfo(info->pf); + if (!afinfo || afinfo->reroute(&skb, info) < 0) verdict = NF_DROP; } diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 3e3f5448bac..c60273cad77 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -1033,17 +1033,13 @@ static struct file_operations nful_file_ops = { #endif /* PROC_FS */ -static int -init_or_cleanup(int init) +static int __init nfnetlink_log_init(void) { int i, status = -ENOMEM; #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_nful; #endif - if (!init) - goto cleanup; - for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -1066,30 +1062,25 @@ init_or_cleanup(int init) goto cleanup_subsys; proc_nful->proc_fops = &nful_file_ops; #endif - return status; -cleanup: - nf_log_unregister_logger(&nfulnl_logger); #ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_log", proc_net_netfilter); cleanup_subsys: -#endif nfnetlink_subsys_unregister(&nfulnl_subsys); +#endif cleanup_netlink_notifier: netlink_unregister_notifier(&nfulnl_rtnl_notifier); return status; } -static int __init nfnetlink_log_init(void) -{ - - return init_or_cleanup(1); -} - static void __exit nfnetlink_log_fini(void) { - init_or_cleanup(0); + nf_log_unregister_logger(&nfulnl_logger); +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_log", proc_net_netfilter); +#endif + nfnetlink_subsys_unregister(&nfulnl_subsys); + netlink_unregister_notifier(&nfulnl_rtnl_notifier); } MODULE_DESCRIPTION("netfilter userspace logging"); diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index d0e62f68139..86a4ac33de3 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -1071,17 +1071,13 @@ static struct file_operations nfqnl_file_ops = { #endif /* PROC_FS */ -static int -init_or_cleanup(int init) +static int __init nfnetlink_queue_init(void) { int i, status = -ENOMEM; #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_nfqueue; #endif - if (!init) - goto cleanup; - for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -1101,31 +1097,26 @@ init_or_cleanup(int init) #endif register_netdevice_notifier(&nfqnl_dev_notifier); - return status; -cleanup: - nf_unregister_queue_handlers(&nfqh); - unregister_netdevice_notifier(&nfqnl_dev_notifier); #ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_queue", proc_net_netfilter); cleanup_subsys: -#endif nfnetlink_subsys_unregister(&nfqnl_subsys); +#endif cleanup_netlink_notifier: netlink_unregister_notifier(&nfqnl_rtnl_notifier); return status; } -static int __init nfnetlink_queue_init(void) -{ - - return init_or_cleanup(1); -} - static void __exit nfnetlink_queue_fini(void) { - init_or_cleanup(0); + nf_unregister_queue_handlers(&nfqh); + unregister_netdevice_notifier(&nfqnl_dev_notifier); +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_queue", proc_net_netfilter); +#endif + nfnetlink_subsys_unregister(&nfqnl_subsys); + netlink_unregister_notifier(&nfqnl_rtnl_notifier); } MODULE_DESCRIPTION("netfilter packet queue handler"); diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index a657ab5394c..17abf60f957 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -38,6 +38,7 @@ struct xt_af { struct list_head match; struct list_head target; struct list_head tables; + struct mutex compat_mutex; }; static struct xt_af *xt; @@ -272,6 +273,54 @@ int xt_check_match(const struct xt_match *match, unsigned short family, } EXPORT_SYMBOL_GPL(xt_check_match); +#ifdef CONFIG_COMPAT +int xt_compat_match(void *match, void **dstptr, int *size, int convert) +{ + struct xt_match *m; + struct compat_xt_entry_match *pcompat_m; + struct xt_entry_match *pm; + u_int16_t msize; + int off, ret; + + ret = 0; + m = ((struct xt_entry_match *)match)->u.kernel.match; + off = XT_ALIGN(m->matchsize) - COMPAT_XT_ALIGN(m->matchsize); + switch (convert) { + case COMPAT_TO_USER: + pm = (struct xt_entry_match *)match; + msize = pm->u.user.match_size; + if (__copy_to_user(*dstptr, pm, msize)) { + ret = -EFAULT; + break; + } + msize -= off; + if (put_user(msize, (u_int16_t *)*dstptr)) + ret = -EFAULT; + *size -= off; + *dstptr += msize; + break; + case COMPAT_FROM_USER: + pcompat_m = (struct compat_xt_entry_match *)match; + pm = (struct xt_entry_match *)*dstptr; + msize = pcompat_m->u.user.match_size; + memcpy(pm, pcompat_m, msize); + msize += off; + pm->u.user.match_size = msize; + *size += off; + *dstptr += msize; + break; + case COMPAT_CALC_SIZE: + *size += off; + break; + default: + ret = -ENOPROTOOPT; + break; + } + return ret; +} +EXPORT_SYMBOL_GPL(xt_compat_match); +#endif + int xt_check_target(const struct xt_target *target, unsigned short family, unsigned int size, const char *table, unsigned int hook_mask, unsigned short proto, int inv_proto) @@ -301,6 +350,54 @@ int xt_check_target(const struct xt_target *target, unsigned short family, } EXPORT_SYMBOL_GPL(xt_check_target); +#ifdef CONFIG_COMPAT +int xt_compat_target(void *target, void **dstptr, int *size, int convert) +{ + struct xt_target *t; + struct compat_xt_entry_target *pcompat; + struct xt_entry_target *pt; + u_int16_t tsize; + int off, ret; + + ret = 0; + t = ((struct xt_entry_target *)target)->u.kernel.target; + off = XT_ALIGN(t->targetsize) - COMPAT_XT_ALIGN(t->targetsize); + switch (convert) { + case COMPAT_TO_USER: + pt = (struct xt_entry_target *)target; + tsize = pt->u.user.target_size; + if (__copy_to_user(*dstptr, pt, tsize)) { + ret = -EFAULT; + break; + } + tsize -= off; + if (put_user(tsize, (u_int16_t *)*dstptr)) + ret = -EFAULT; + *size -= off; + *dstptr += tsize; + break; + case COMPAT_FROM_USER: + pcompat = (struct compat_xt_entry_target *)target; + pt = (struct xt_entry_target *)*dstptr; + tsize = pcompat->u.user.target_size; + memcpy(pt, pcompat, tsize); + tsize += off; + pt->u.user.target_size = tsize; + *size += off; + *dstptr += tsize; + break; + case COMPAT_CALC_SIZE: + *size += off; + break; + default: + ret = -ENOPROTOOPT; + break; + } + return ret; +} +EXPORT_SYMBOL_GPL(xt_compat_target); +#endif + struct xt_table_info *xt_alloc_table_info(unsigned int size) { struct xt_table_info *newinfo; @@ -316,7 +413,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size) newinfo->size = size; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { if (size <= PAGE_SIZE) newinfo->entries[cpu] = kmalloc_node(size, GFP_KERNEL, @@ -339,7 +436,7 @@ void xt_free_table_info(struct xt_table_info *info) { int cpu; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { if (info->size <= PAGE_SIZE) kfree(info->entries[cpu]); else @@ -371,6 +468,19 @@ void xt_table_unlock(struct xt_table *table) } EXPORT_SYMBOL_GPL(xt_table_unlock); +#ifdef CONFIG_COMPAT +void xt_compat_lock(int af) +{ + mutex_lock(&xt[af].compat_mutex); +} +EXPORT_SYMBOL_GPL(xt_compat_lock); + +void xt_compat_unlock(int af) +{ + mutex_unlock(&xt[af].compat_mutex); +} +EXPORT_SYMBOL_GPL(xt_compat_unlock); +#endif struct xt_table_info * xt_replace_table(struct xt_table *table, @@ -419,6 +529,7 @@ int xt_register_table(struct xt_table *table, /* Simplifies replace_table code. */ table->private = bootstrap; + rwlock_init(&table->lock); if (!xt_replace_table(table, 0, newinfo, &ret)) goto unlock; @@ -428,7 +539,6 @@ int xt_register_table(struct xt_table *table, /* save number of initial entries */ private->initial_entries = private->number; - rwlock_init(&table->lock); list_prepend(&xt[table->af].tables, table); ret = 0; @@ -671,6 +781,9 @@ static int __init xt_init(void) for (i = 0; i < NPROTO; i++) { mutex_init(&xt[i].mutex); +#ifdef CONFIG_COMPAT + mutex_init(&xt[i].compat_mutex); +#endif INIT_LIST_HEAD(&xt[i].target); INIT_LIST_HEAD(&xt[i].match); INIT_LIST_HEAD(&xt[i].tables); diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/netfilter/xt_esp.c index 3840b417a3c..9dad6281e0c 100644 --- a/net/ipv4/netfilter/ipt_esp.c +++ b/net/netfilter/xt_esp.c @@ -9,16 +9,22 @@ #include <linux/module.h> #include <linux/skbuff.h> +#include <linux/in.h> #include <linux/ip.h> -#include <linux/netfilter_ipv4/ipt_esp.h> +#include <linux/netfilter/xt_esp.h> +#include <linux/netfilter/x_tables.h> + #include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv6/ip6_tables.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>"); -MODULE_DESCRIPTION("iptables ESP SPI match module"); +MODULE_DESCRIPTION("x_tables ESP SPI match module"); +MODULE_ALIAS("ipt_esp"); +MODULE_ALIAS("ip6t_esp"); -#ifdef DEBUG_CONNTRACK +#if 0 #define duprintf(format, args...) printk(format , ## args) #else #define duprintf(format, args...) @@ -28,11 +34,11 @@ MODULE_DESCRIPTION("iptables ESP SPI match module"); static inline int spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) { - int r=0; - duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', - min,spi,max); - r=(spi >= min && spi <= max) ^ invert; - duprintf(" result %s\n",r? "PASS" : "FAILED"); + int r = 0; + duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', + min, spi, max); + r = (spi >= min && spi <= max) ^ invert; + duprintf(" result %s\n", r ? "PASS" : "FAILED"); return r; } @@ -47,14 +53,13 @@ match(const struct sk_buff *skb, int *hotdrop) { struct ip_esp_hdr _esp, *eh; - const struct ipt_esp *espinfo = matchinfo; + const struct xt_esp *espinfo = matchinfo; /* Must not be a fragment. */ if (offset) return 0; - eh = skb_header_pointer(skb, protoff, - sizeof(_esp), &_esp); + eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp); if (eh == NULL) { /* We've been asked to examine this packet, and we * can't. Hence, no choice but to drop. @@ -64,9 +69,8 @@ match(const struct sk_buff *skb, return 0; } - return spi_match(espinfo->spis[0], espinfo->spis[1], - ntohl(eh->spi), - !!(espinfo->invflags & IPT_ESP_INV_SPI)); + return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi), + !!(espinfo->invflags & XT_ESP_INV_SPI)); } /* Called when user tries to insert an entry of this type. */ @@ -78,34 +82,55 @@ checkentry(const char *tablename, unsigned int matchinfosize, unsigned int hook_mask) { - const struct ipt_esp *espinfo = matchinfo; + const struct xt_esp *espinfo = matchinfo; - /* Must specify no unknown invflags */ - if (espinfo->invflags & ~IPT_ESP_INV_MASK) { - duprintf("ipt_esp: unknown flags %X\n", espinfo->invflags); + if (espinfo->invflags & ~XT_ESP_INV_MASK) { + duprintf("xt_esp: unknown flags %X\n", espinfo->invflags); return 0; } + return 1; } -static struct ipt_match esp_match = { +static struct xt_match esp_match = { .name = "esp", - .match = match, - .matchsize = sizeof(struct ipt_esp), + .family = AF_INET, .proto = IPPROTO_ESP, - .checkentry = checkentry, + .match = &match, + .matchsize = sizeof(struct xt_esp), + .checkentry = &checkentry, .me = THIS_MODULE, }; -static int __init ipt_esp_init(void) +static struct xt_match esp6_match = { + .name = "esp", + .family = AF_INET6, + .proto = IPPROTO_ESP, + .match = &match, + .matchsize = sizeof(struct xt_esp), + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + +static int __init xt_esp_init(void) { - return ipt_register_match(&esp_match); + int ret; + ret = xt_register_match(&esp_match); + if (ret) + return ret; + + ret = xt_register_match(&esp6_match); + if (ret) + xt_unregister_match(&esp_match); + + return ret; } -static void __exit ipt_esp_fini(void) +static void __exit xt_esp_cleanup(void) { - ipt_unregister_match(&esp_match); + xt_unregister_match(&esp_match); + xt_unregister_match(&esp6_match); } -module_init(ipt_esp_init); -module_exit(ipt_esp_fini); +module_init(xt_esp_init); +module_exit(xt_esp_cleanup); diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c new file mode 100644 index 00000000000..b56cd2baaac --- /dev/null +++ b/net/netfilter/xt_multiport.c @@ -0,0 +1,314 @@ +/* Kernel module to match one of a list of TCP/UDP ports: ports are in + the same place so we can treat them as equal. */ + +/* (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/udp.h> +#include <linux/skbuff.h> +#include <linux/in.h> + +#include <linux/netfilter/xt_multiport.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv6/ip6_tables.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); +MODULE_DESCRIPTION("x_tables multiple port match module"); +MODULE_ALIAS("ipt_multiport"); +MODULE_ALIAS("ip6t_multiport"); + +#if 0 +#define duprintf(format, args...) printk(format , ## args) +#else +#define duprintf(format, args...) +#endif + +/* Returns 1 if the port is matched by the test, 0 otherwise. */ +static inline int +ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags, + u_int8_t count, u_int16_t src, u_int16_t dst) +{ + unsigned int i; + for (i = 0; i < count; i++) { + if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src) + return 1; + + if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst) + return 1; + } + + return 0; +} + +/* Returns 1 if the port is matched by the test, 0 otherwise. */ +static inline int +ports_match_v1(const struct xt_multiport_v1 *minfo, + u_int16_t src, u_int16_t dst) +{ + unsigned int i; + u_int16_t s, e; + + for (i = 0; i < minfo->count; i++) { + s = minfo->ports[i]; + + if (minfo->pflags[i]) { + /* range port matching */ + e = minfo->ports[++i]; + duprintf("src or dst matches with %d-%d?\n", s, e); + + if (minfo->flags == XT_MULTIPORT_SOURCE + && src >= s && src <= e) + return 1 ^ minfo->invert; + if (minfo->flags == XT_MULTIPORT_DESTINATION + && dst >= s && dst <= e) + return 1 ^ minfo->invert; + if (minfo->flags == XT_MULTIPORT_EITHER + && ((dst >= s && dst <= e) + || (src >= s && src <= e))) + return 1 ^ minfo->invert; + } else { + /* exact port matching */ + duprintf("src or dst matches with %d?\n", s); + + if (minfo->flags == XT_MULTIPORT_SOURCE + && src == s) + return 1 ^ minfo->invert; + if (minfo->flags == XT_MULTIPORT_DESTINATION + && dst == s) + return 1 ^ minfo->invert; + if (minfo->flags == XT_MULTIPORT_EITHER + && (src == s || dst == s)) + return 1 ^ minfo->invert; + } + } + + return minfo->invert; +} + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + u16 _ports[2], *pptr; + const struct xt_multiport *multiinfo = matchinfo; + + if (offset) + return 0; + + pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); + if (pptr == NULL) { + /* We've been asked to examine this packet, and we + * can't. Hence, no choice but to drop. + */ + duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); + *hotdrop = 1; + return 0; + } + + return ports_match(multiinfo->ports, + multiinfo->flags, multiinfo->count, + ntohs(pptr[0]), ntohs(pptr[1])); +} + +static int +match_v1(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + u16 _ports[2], *pptr; + const struct xt_multiport_v1 *multiinfo = matchinfo; + + if (offset) + return 0; + + pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports); + if (pptr == NULL) { + /* We've been asked to examine this packet, and we + * can't. Hence, no choice but to drop. + */ + duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n"); + *hotdrop = 1; + return 0; + } + + return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); +} + +static inline int +check(u_int16_t proto, + u_int8_t ip_invflags, + u_int8_t match_flags, + u_int8_t count) +{ + /* Must specify proto == TCP/UDP, no unknown flags or bad count */ + return (proto == IPPROTO_TCP || proto == IPPROTO_UDP) + && !(ip_invflags & XT_INV_PROTO) + && (match_flags == XT_MULTIPORT_SOURCE + || match_flags == XT_MULTIPORT_DESTINATION + || match_flags == XT_MULTIPORT_EITHER) + && count <= XT_MULTI_PORTS; +} + +/* Called when user tries to insert an entry of this type. */ +static int +checkentry(const char *tablename, + const void *info, + const struct xt_match *match, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ipt_ip *ip = info; + const struct xt_multiport *multiinfo = matchinfo; + + return check(ip->proto, ip->invflags, multiinfo->flags, + multiinfo->count); +} + +static int +checkentry_v1(const char *tablename, + const void *info, + const struct xt_match *match, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ipt_ip *ip = info; + const struct xt_multiport_v1 *multiinfo = matchinfo; + + return check(ip->proto, ip->invflags, multiinfo->flags, + multiinfo->count); +} + +static int +checkentry6(const char *tablename, + const void *info, + const struct xt_match *match, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ip = info; + const struct xt_multiport *multiinfo = matchinfo; + + return check(ip->proto, ip->invflags, multiinfo->flags, + multiinfo->count); +} + +static int +checkentry6_v1(const char *tablename, + const void *info, + const struct xt_match *match, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_ip6 *ip = info; + const struct xt_multiport_v1 *multiinfo = matchinfo; + + return check(ip->proto, ip->invflags, multiinfo->flags, + multiinfo->count); +} + +static struct xt_match multiport_match = { + .name = "multiport", + .revision = 0, + .matchsize = sizeof(struct xt_multiport), + .match = &match, + .checkentry = &checkentry, + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match multiport_match_v1 = { + .name = "multiport", + .revision = 1, + .matchsize = sizeof(struct xt_multiport_v1), + .match = &match_v1, + .checkentry = &checkentry_v1, + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match multiport6_match = { + .name = "multiport", + .revision = 0, + .matchsize = sizeof(struct xt_multiport), + .match = &match, + .checkentry = &checkentry6, + .family = AF_INET6, + .me = THIS_MODULE, +}; + +static struct xt_match multiport6_match_v1 = { + .name = "multiport", + .revision = 1, + .matchsize = sizeof(struct xt_multiport_v1), + .match = &match_v1, + .checkentry = &checkentry6_v1, + .family = AF_INET6, + .me = THIS_MODULE, +}; + +static int __init xt_multiport_init(void) +{ + int ret; + + ret = xt_register_match(&multiport_match); + if (ret) + goto out; + + ret = xt_register_match(&multiport_match_v1); + if (ret) + goto out_unreg_multi_v0; + + ret = xt_register_match(&multiport6_match); + if (ret) + goto out_unreg_multi_v1; + + ret = xt_register_match(&multiport6_match_v1); + if (ret) + goto out_unreg_multi6_v0; + + return ret; + +out_unreg_multi6_v0: + xt_unregister_match(&multiport6_match); +out_unreg_multi_v1: + xt_unregister_match(&multiport_match_v1); +out_unreg_multi_v0: + xt_unregister_match(&multiport_match); +out: + return ret; +} + +static void __exit xt_multiport_fini(void) +{ + xt_unregister_match(&multiport_match); + xt_unregister_match(&multiport_match_v1); + xt_unregister_match(&multiport6_match); + xt_unregister_match(&multiport6_match_v1); +} + +module_init(xt_multiport_init); +module_exit(xt_multiport_fini); diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c index 1099cb005fc..a3aa62fbda6 100644 --- a/net/netfilter/xt_policy.c +++ b/net/netfilter/xt_policy.c @@ -71,7 +71,7 @@ match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info, return 0; e = &info->pol[pos]; - if (match_xfrm_state(sp->x[i].xvec, e, family)) { + if (match_xfrm_state(sp->xvec[i], e, family)) { if (!strict) return 1; } else if (strict) diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 6056d20ef42..37640c6fc01 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -69,6 +69,11 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) DPRINTK("ipt_init_target: found %s\n", target->name); t->u.kernel.target = target; + ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), + table, hook, 0, 0); + if (ret) + return ret; + if (t->u.kernel.target->checkentry && !t->u.kernel.target->checkentry(table, NULL, t->u.kernel.target, t->data, diff --git a/net/sched/act_police.c b/net/sched/act_police.c index fa877f8f652..24c348fa892 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -66,7 +66,7 @@ static __inline__ struct tcf_police * tcf_police_lookup(u32 index) } #ifdef CONFIG_NET_CLS_ACT -static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, +static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, int type, struct tc_action *a) { struct tcf_police *p; @@ -113,7 +113,7 @@ rtattr_failure: } static inline int -tcf_hash_search(struct tc_action *a, u32 index) +tcf_act_police_hash_search(struct tc_action *a, u32 index) { struct tcf_police *p = tcf_police_lookup(index); @@ -387,9 +387,9 @@ static struct tc_action_ops act_police_ops = { .act = tcf_act_police, .dump = tcf_act_police_dump, .cleanup = tcf_act_police_cleanup, - .lookup = tcf_hash_search, + .lookup = tcf_act_police_hash_search, .init = tcf_act_police_locate, - .walk = tcf_generic_walker + .walk = tcf_act_police_walker }; static int __init diff --git a/net/sctp/proc.c b/net/sctp/proc.c index d47a52c303a..5b3b0e0ae7e 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -69,7 +69,7 @@ fold_field(void *mib[], int nr) unsigned long res = 0; int i; - for_each_cpu(i) { + for_each_possible_cpu(i) { res += *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) + sizeof (unsigned long) * nr)); diff --git a/net/socket.c b/net/socket.c index b13042f68c0..0ce12dfc7a7 100644 --- a/net/socket.c +++ b/net/socket.c @@ -119,10 +119,6 @@ static ssize_t sock_writev(struct file *file, const struct iovec *vector, static ssize_t sock_sendpage(struct file *file, struct page *page, int offset, size_t size, loff_t *ppos, int more); -extern ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, - size_t len, unsigned int flags); - - /* * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear * in the operation structures but are done directly via the socketcall() multiplexor. @@ -494,6 +490,7 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) struct file *file; struct socket *sock; + *err = -EBADF; file = fget_light(fd, fput_needed); if (file) { sock = sock_from_file(file, err); @@ -1418,7 +1415,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _ newfd = sock_alloc_fd(&newfile); if (unlikely(newfd < 0)) { err = newfd; - goto out_release; + sock_release(newsock); + goto out_put; } err = sock_attach_fd(newsock, newfile); @@ -1455,10 +1453,8 @@ out_put: out: return err; out_fd: - put_filp(newfile); + fput(newfile); put_unused_fd(newfd); -out_release: - sock_release(newsock); goto out_put; } @@ -2137,7 +2133,7 @@ void socket_seq_show(struct seq_file *seq) int cpu; int counter = 0; - for_each_cpu(cpu) + for_each_possible_cpu(cpu) counter += per_cpu(sockets_in_use, cpu); /* It can be negative, by the way. 8) */ diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 900ef31f5a0..519ebc17c02 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -794,7 +794,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) out_err: dprintk("RPC: gss_create_cred failed with error %d\n", err); - if (cred) gss_destroy_cred(&cred->gc_base); return ERR_PTR(err); } diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 97c981fa6b8..76b969e6904 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -212,7 +212,6 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, char *cksumname; struct crypto_tfm *tfm = NULL; /* XXX add to ctx? */ struct scatterlist sg[1]; - u32 code = GSS_S_FAILURE; switch (cksumtype) { case CKSUMTYPE_RSA_MD5: @@ -221,13 +220,11 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, default: dprintk("RPC: krb5_make_checksum:" " unsupported checksum %d", cksumtype); - goto out; + return GSS_S_FAILURE; } if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP))) - goto out; + return GSS_S_FAILURE; cksum->len = crypto_tfm_alg_digestsize(tfm); - if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL) - goto out; crypto_digest_init(tfm); sg_set_buf(sg, header, hdrlen); @@ -235,10 +232,8 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, process_xdr_buf(body, body_offset, body->len - body_offset, checksummer, tfm); crypto_digest_final(tfm, cksum->data); - code = 0; -out: crypto_free_tfm(tfm); - return code; + return 0; } EXPORT_SYMBOL(make_checksum); diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 4d7eb9e704d..d51e316c582 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1122,18 +1122,20 @@ svcauth_gss_release(struct svc_rqst *rqstp) integ_len)) BUG(); if (resbuf->page_len == 0 - && resbuf->tail[0].iov_len + RPC_MAX_AUTH_SIZE + && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE < PAGE_SIZE) { BUG_ON(resbuf->tail[0].iov_len); /* Use head for everything */ resv = &resbuf->head[0]; } else if (resbuf->tail[0].iov_base == NULL) { - /* copied from nfsd4_encode_read */ - svc_take_page(rqstp); - resbuf->tail[0].iov_base = page_address(rqstp - ->rq_respages[rqstp->rq_resused-1]); - rqstp->rq_restailpage = rqstp->rq_resused-1; + if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE + > PAGE_SIZE) + goto out_err; + resbuf->tail[0].iov_base = + resbuf->head[0].iov_base + + resbuf->head[0].iov_len; resbuf->tail[0].iov_len = 0; + rqstp->rq_restailpage = 0; resv = &resbuf->tail[0]; } else { resv = &resbuf->tail[0]; diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index dea529666d6..15c2db26767 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c @@ -176,7 +176,8 @@ void rpc_count_iostats(struct rpc_task *task) op_metrics->om_execute += execute; } -void _print_name(struct seq_file *seq, unsigned int op, struct rpc_procinfo *procs) +static void _print_name(struct seq_file *seq, unsigned int op, + struct rpc_procinfo *procs) { if (procs[op].p_name) seq_printf(seq, "\t%12s: ", procs[op].p_name); diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 953307a9df1..a3bbc891f95 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -229,8 +229,7 @@ static void node_is_down(struct publication *publ) publ->node, publ->ref, publ->key); assert(p == publ); write_unlock_bh(&tipc_nametbl_lock); - if (publ) - kfree(publ); + kfree(publ); } /** 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_input.c b/net/xfrm/xfrm_input.c index 2407a707232..b54971059f1 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -18,7 +18,7 @@ void __secpath_destroy(struct sec_path *sp) { int i; for (i = 0; i < sp->len; i++) - xfrm_state_put(sp->x[i].xvec); + xfrm_state_put(sp->xvec[i]); kmem_cache_free(secpath_cachep, sp); } EXPORT_SYMBOL(__secpath_destroy); @@ -37,7 +37,7 @@ struct sec_path *secpath_dup(struct sec_path *src) memcpy(sp, src, sizeof(*sp)); for (i = 0; i < sp->len; i++) - xfrm_state_hold(sp->x[i].xvec); + xfrm_state_hold(sp->xvec[i]); } atomic_set(&sp->refcnt, 1); return sp; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index f5eae9febd2..c3725fe2a8f 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -943,9 +943,9 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start, } else start = -1; for (; idx < sp->len; idx++) { - if (xfrm_state_ok(tmpl, sp->x[idx].xvec, family)) + if (xfrm_state_ok(tmpl, sp->xvec[idx], family)) return ++idx; - if (sp->x[idx].xvec->props.mode) + if (sp->xvec[idx]->props.mode) break; } return start; @@ -968,7 +968,7 @@ EXPORT_SYMBOL(xfrm_decode_session); static inline int secpath_has_tunnel(struct sec_path *sp, int k) { for (; k < sp->len; k++) { - if (sp->x[k].xvec->props.mode) + if (sp->xvec[k]->props.mode) return 1; } @@ -994,8 +994,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, int i; for (i=skb->sp->len-1; i>=0; i--) { - struct sec_decap_state *xvec = &(skb->sp->x[i]); - if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family)) + struct xfrm_state *x = skb->sp->xvec[i]; + if (!xfrm_selector_match(&x->sel, &fl, family)) return 0; } } 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) |