aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/atm/clip.c460
-rw-r--r--net/bluetooth/sco.c2
-rw-r--r--net/bridge/br_forward.c8
-rw-r--r--net/bridge/br_input.c3
-rw-r--r--net/bridge/br_netfilter.c13
-rw-r--r--net/bridge/netfilter/ebtables.c38
-rw-r--r--net/compat.c3
-rw-r--r--net/core/dev.c10
-rw-r--r--net/core/dv.c5
-rw-r--r--net/core/filter.c5
-rw-r--r--net/core/flow.c8
-rw-r--r--net/core/gen_estimator.c3
-rw-r--r--net/core/neighbour.c16
-rw-r--r--net/core/net-sysfs.c2
-rw-r--r--net/core/request_sock.c4
-rw-r--r--net/core/skbuff.c8
-rw-r--r--net/core/stream.c1
-rw-r--r--net/core/utils.c4
-rw-r--r--net/core/wireless.c8
-rw-r--r--net/dccp/ipv4.c2
-rw-r--r--net/ieee80211/softmac/Kconfig1
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c25
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_event.c40
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c18
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c2
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_scan.c2
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c37
-rw-r--r--net/ipv4/ah4.c2
-rw-r--r--net/ipv4/arp.c4
-rw-r--r--net/ipv4/devinet.c1
-rw-r--r--net/ipv4/esp4.c5
-rw-r--r--net/ipv4/fib_frontend.c1
-rw-r--r--net/ipv4/fib_trie.c14
-rw-r--r--net/ipv4/icmp.c2
-rw-r--r--net/ipv4/inet_hashtables.c4
-rw-r--r--net/ipv4/ip_fragment.c15
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_output.c8
-rw-r--r--net/ipv4/ipcomp.c16
-rw-r--r--net/ipv4/ipip.c4
-rw-r--r--net/ipv4/netfilter.c50
-rw-r--r--net/ipv4/netfilter/Kconfig21
-rw-r--r--net/ipv4/netfilter/Makefile3
-rw-r--r--net/ipv4/netfilter/arp_tables.c4
-rw-r--r--net/ipv4/netfilter/arptable_filter.c19
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c66
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h98
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_types.h938
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c23
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c268
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c71
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c159
-rw-r--r--net/ipv4/netfilter/ip_queue.c31
-rw-r--r--net/ipv4/netfilter/ip_tables.c1142
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c40
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c9
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c195
-rw-r--r--net/ipv4/netfilter/iptable_filter.c21
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c33
-rw-r--r--net/ipv4/netfilter/iptable_raw.c35
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c223
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c20
-rw-r--r--net/ipv4/proc.c4
-rw-r--r--net/ipv4/route.c7
-rw-r--r--net/ipv4/tcp_input.c1
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv4/tcp_output.c11
-rw-r--r--net/ipv4/tunnel4.c8
-rw-r--r--net/ipv4/xfrm4_input.c17
-rw-r--r--net/ipv4/xfrm4_tunnel.c2
-rw-r--r--net/ipv6/ah6.c2
-rw-r--r--net/ipv6/esp6.c2
-rw-r--r--net/ipv6/exthdrs.c16
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/inet6_hashtables.c80
-rw-r--r--net/ipv6/ip6_input.c3
-rw-r--r--net/ipv6/ip6_tunnel.c12
-rw-r--r--net/ipv6/ipcomp6.c10
-rw-r--r--net/ipv6/netfilter.c52
-rw-r--r--net/ipv6/netfilter/Kconfig16
-rw-r--r--net/ipv6/netfilter/Makefile3
-rw-r--r--net/ipv6/netfilter/ip6_queue.c31
-rw-r--r--net/ipv6/netfilter/ip6_tables.c17
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c115
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c125
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c21
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c33
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c15
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c179
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c12
-rw-r--r--net/ipv6/proc.c4
-rw-r--r--net/ipv6/reassembly.c18
-rw-r--r--net/ipv6/sit.c2
-rw-r--r--net/ipv6/tunnel6.c8
-rw-r--r--net/ipv6/xfrm6_input.c11
-rw-r--r--net/ipv6/xfrm6_policy.c8
-rw-r--r--net/ipv6/xfrm6_tunnel.c2
-rw-r--r--net/llc/llc_input.c3
-rw-r--r--net/netfilter/Kconfig19
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/core.c51
-rw-r--r--net/netfilter/nf_conntrack_core.c17
-rw-r--r--net/netfilter/nf_conntrack_l3proto_generic.c1
-rw-r--r--net/netfilter/nf_conntrack_netlink.c6
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c50
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c50
-rw-r--r--net/netfilter/nf_conntrack_standalone.c115
-rw-r--r--net/netfilter/nf_queue.c49
-rw-r--r--net/netfilter/nfnetlink_log.c25
-rw-r--r--net/netfilter/nfnetlink_queue.c27
-rw-r--r--net/netfilter/x_tables.c119
-rw-r--r--net/netfilter/xt_esp.c (renamed from net/ipv4/netfilter/ipt_esp.c)81
-rw-r--r--net/netfilter/xt_multiport.c314
-rw-r--r--net/netfilter/xt_policy.c2
-rw-r--r--net/sched/act_ipt.c5
-rw-r--r--net/sched/act_police.c8
-rw-r--r--net/sctp/proc.c2
-rw-r--r--net/socket.c14
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c1
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_crypto.c11
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c14
-rw-r--r--net/sunrpc/stats.c3
-rw-r--r--net/tipc/name_distr.c3
-rw-r--r--net/wanrouter/af_wanpipe.c2
-rw-r--r--net/xfrm/xfrm_input.c4
-rw-r--r--net/xfrm/xfrm_policy.c10
-rw-r--r--net/xfrm/xfrm_state.c25
133 files changed, 2848 insertions, 3334 deletions
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 3ab4e7947bab..1a786bfaa416 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -2,7 +2,6 @@
2 2
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ 3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4 4
5
6#include <linux/config.h> 5#include <linux/config.h>
7#include <linux/string.h> 6#include <linux/string.h>
8#include <linux/errno.h> 7#include <linux/errno.h>
@@ -54,24 +53,24 @@ static struct net_device *clip_devs;
54static struct atm_vcc *atmarpd; 53static struct atm_vcc *atmarpd;
55static struct neigh_table clip_tbl; 54static struct neigh_table clip_tbl;
56static struct timer_list idle_timer; 55static struct timer_list idle_timer;
57static int start_timer = 1;
58
59 56
60static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip) 57static int to_atmarpd(enum atmarp_ctrl_type type, int itf, unsigned long ip)
61{ 58{
62 struct sock *sk; 59 struct sock *sk;
63 struct atmarp_ctrl *ctrl; 60 struct atmarp_ctrl *ctrl;
64 struct sk_buff *skb; 61 struct sk_buff *skb;
65 62
66 DPRINTK("to_atmarpd(%d)\n",type); 63 DPRINTK("to_atmarpd(%d)\n", type);
67 if (!atmarpd) return -EUNATCH; 64 if (!atmarpd)
65 return -EUNATCH;
68 skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC); 66 skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC);
69 if (!skb) return -ENOMEM; 67 if (!skb)
68 return -ENOMEM;
70 ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl)); 69 ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl));
71 ctrl->type = type; 70 ctrl->type = type;
72 ctrl->itf_num = itf; 71 ctrl->itf_num = itf;
73 ctrl->ip = ip; 72 ctrl->ip = ip;
74 atm_force_charge(atmarpd,skb->truesize); 73 atm_force_charge(atmarpd, skb->truesize);
75 74
76 sk = sk_atm(atmarpd); 75 sk = sk_atm(atmarpd);
77 skb_queue_tail(&sk->sk_receive_queue, skb); 76 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)
79 return 0; 78 return 0;
80} 79}
81 80
82 81static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry)
83static void link_vcc(struct clip_vcc *clip_vcc,struct atmarp_entry *entry)
84{ 82{
85 DPRINTK("link_vcc %p to entry %p (neigh %p)\n",clip_vcc,entry, 83 DPRINTK("link_vcc %p to entry %p (neigh %p)\n", clip_vcc, entry,
86 entry->neigh); 84 entry->neigh);
87 clip_vcc->entry = entry; 85 clip_vcc->entry = entry;
88 clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */ 86 clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */
89 clip_vcc->next = entry->vccs; 87 clip_vcc->next = entry->vccs;
90 entry->vccs = clip_vcc; 88 entry->vccs = clip_vcc;
91 entry->neigh->used = jiffies; 89 entry->neigh->used = jiffies;
92} 90}
93 91
94
95static void unlink_clip_vcc(struct clip_vcc *clip_vcc) 92static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
96{ 93{
97 struct atmarp_entry *entry = clip_vcc->entry; 94 struct atmarp_entry *entry = clip_vcc->entry;
98 struct clip_vcc **walk; 95 struct clip_vcc **walk;
99 96
100 if (!entry) { 97 if (!entry) {
101 printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc); 98 printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
102 return; 99 return;
103 } 100 }
104 spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block clip_start_xmit() */ 101 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)
107 if (*walk == clip_vcc) { 104 if (*walk == clip_vcc) {
108 int error; 105 int error;
109 106
110 *walk = clip_vcc->next; /* atomic */ 107 *walk = clip_vcc->next; /* atomic */
111 clip_vcc->entry = NULL; 108 clip_vcc->entry = NULL;
112 if (clip_vcc->xoff) 109 if (clip_vcc->xoff)
113 netif_wake_queue(entry->neigh->dev); 110 netif_wake_queue(entry->neigh->dev);
114 if (entry->vccs) 111 if (entry->vccs)
115 goto out; 112 goto out;
116 entry->expires = jiffies-1; 113 entry->expires = jiffies - 1;
117 /* force resolution or expiration */ 114 /* force resolution or expiration */
118 error = neigh_update(entry->neigh, NULL, NUD_NONE, 115 error = neigh_update(entry->neigh, NULL, NUD_NONE,
119 NEIGH_UPDATE_F_ADMIN); 116 NEIGH_UPDATE_F_ADMIN);
120 if (error) 117 if (error)
121 printk(KERN_CRIT "unlink_clip_vcc: " 118 printk(KERN_CRIT "unlink_clip_vcc: "
122 "neigh_update failed with %d\n",error); 119 "neigh_update failed with %d\n", error);
123 goto out; 120 goto out;
124 } 121 }
125 printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc " 122 printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
126 "0x%p)\n",entry,clip_vcc); 123 "0x%p)\n", entry, clip_vcc);
127out: 124 out:
128 spin_unlock_bh(&entry->neigh->dev->xmit_lock); 125 spin_unlock_bh(&entry->neigh->dev->xmit_lock);
129} 126}
130 127
@@ -153,13 +150,13 @@ static int neigh_check_cb(struct neighbour *n)
153 DPRINTK("destruction postponed with ref %d\n", 150 DPRINTK("destruction postponed with ref %d\n",
154 atomic_read(&n->refcnt)); 151 atomic_read(&n->refcnt));
155 152
156 while ((skb = skb_dequeue(&n->arp_queue)) != NULL) 153 while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
157 dev_kfree_skb(skb); 154 dev_kfree_skb(skb);
158 155
159 return 0; 156 return 0;
160 } 157 }
161 158
162 DPRINTK("expired neigh %p\n",n); 159 DPRINTK("expired neigh %p\n", n);
163 return 1; 160 return 1;
164} 161}
165 162
@@ -167,7 +164,7 @@ static void idle_timer_check(unsigned long dummy)
167{ 164{
168 write_lock(&clip_tbl.lock); 165 write_lock(&clip_tbl.lock);
169 __neigh_for_each_release(&clip_tbl, neigh_check_cb); 166 __neigh_for_each_release(&clip_tbl, neigh_check_cb);
170 mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ); 167 mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
171 write_unlock(&clip_tbl.lock); 168 write_unlock(&clip_tbl.lock);
172} 169}
173 170
@@ -177,13 +174,13 @@ static int clip_arp_rcv(struct sk_buff *skb)
177 174
178 DPRINTK("clip_arp_rcv\n"); 175 DPRINTK("clip_arp_rcv\n");
179 vcc = ATM_SKB(skb)->vcc; 176 vcc = ATM_SKB(skb)->vcc;
180 if (!vcc || !atm_charge(vcc,skb->truesize)) { 177 if (!vcc || !atm_charge(vcc, skb->truesize)) {
181 dev_kfree_skb_any(skb); 178 dev_kfree_skb_any(skb);
182 return 0; 179 return 0;
183 } 180 }
184 DPRINTK("pushing to %p\n",vcc); 181 DPRINTK("pushing to %p\n", vcc);
185 DPRINTK("using %p\n",CLIP_VCC(vcc)->old_push); 182 DPRINTK("using %p\n", CLIP_VCC(vcc)->old_push);
186 CLIP_VCC(vcc)->old_push(vcc,skb); 183 CLIP_VCC(vcc)->old_push(vcc, skb);
187 return 0; 184 return 0;
188} 185}
189 186
@@ -193,34 +190,38 @@ static const unsigned char llc_oui[] = {
193 0x03, /* Ctrl: Unnumbered Information Command PDU */ 190 0x03, /* Ctrl: Unnumbered Information Command PDU */
194 0x00, /* OUI: EtherType */ 191 0x00, /* OUI: EtherType */
195 0x00, 192 0x00,
196 0x00 }; 193 0x00
194};
197 195
198static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) 196static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
199{ 197{
200 struct clip_vcc *clip_vcc = CLIP_VCC(vcc); 198 struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
201 199
202 DPRINTK("clip push\n"); 200 DPRINTK("clip push\n");
203 if (!skb) { 201 if (!skb) {
204 DPRINTK("removing VCC %p\n",clip_vcc); 202 DPRINTK("removing VCC %p\n", clip_vcc);
205 if (clip_vcc->entry) unlink_clip_vcc(clip_vcc); 203 if (clip_vcc->entry)
206 clip_vcc->old_push(vcc,NULL); /* pass on the bad news */ 204 unlink_clip_vcc(clip_vcc);
205 clip_vcc->old_push(vcc, NULL); /* pass on the bad news */
207 kfree(clip_vcc); 206 kfree(clip_vcc);
208 return; 207 return;
209 } 208 }
210 atm_return(vcc,skb->truesize); 209 atm_return(vcc, skb->truesize);
211 skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs; 210 skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
212 /* clip_vcc->entry == NULL if we don't have an IP address yet */ 211 /* clip_vcc->entry == NULL if we don't have an IP address yet */
213 if (!skb->dev) { 212 if (!skb->dev) {
214 dev_kfree_skb_any(skb); 213 dev_kfree_skb_any(skb);
215 return; 214 return;
216 } 215 }
217 ATM_SKB(skb)->vcc = vcc; 216 ATM_SKB(skb)->vcc = vcc;
218 skb->mac.raw = skb->data; 217 skb->mac.raw = skb->data;
219 if (!clip_vcc->encap || skb->len < RFC1483LLC_LEN || memcmp(skb->data, 218 if (!clip_vcc->encap
220 llc_oui,sizeof(llc_oui))) skb->protocol = htons(ETH_P_IP); 219 || skb->len < RFC1483LLC_LEN
220 || memcmp(skb->data, llc_oui, sizeof (llc_oui)))
221 skb->protocol = htons(ETH_P_IP);
221 else { 222 else {
222 skb->protocol = ((u16 *) skb->data)[3]; 223 skb->protocol = ((u16 *) skb->data)[3];
223 skb_pull(skb,RFC1483LLC_LEN); 224 skb_pull(skb, RFC1483LLC_LEN);
224 if (skb->protocol == htons(ETH_P_ARP)) { 225 if (skb->protocol == htons(ETH_P_ARP)) {
225 PRIV(skb->dev)->stats.rx_packets++; 226 PRIV(skb->dev)->stats.rx_packets++;
226 PRIV(skb->dev)->stats.rx_bytes += skb->len; 227 PRIV(skb->dev)->stats.rx_bytes += skb->len;
@@ -235,58 +236,54 @@ static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
235 netif_rx(skb); 236 netif_rx(skb);
236} 237}
237 238
238
239/* 239/*
240 * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that 240 * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that
241 * clip_pop is atomic with respect to the critical section in clip_start_xmit. 241 * clip_pop is atomic with respect to the critical section in clip_start_xmit.
242 */ 242 */
243 243
244 244static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
245static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
246{ 245{
247 struct clip_vcc *clip_vcc = CLIP_VCC(vcc); 246 struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
248 struct net_device *dev = skb->dev; 247 struct net_device *dev = skb->dev;
249 int old; 248 int old;
250 unsigned long flags; 249 unsigned long flags;
251 250
252 DPRINTK("clip_pop(vcc %p)\n",vcc); 251 DPRINTK("clip_pop(vcc %p)\n", vcc);
253 clip_vcc->old_pop(vcc,skb); 252 clip_vcc->old_pop(vcc, skb);
254 /* skb->dev == NULL in outbound ARP packets */ 253 /* skb->dev == NULL in outbound ARP packets */
255 if (!dev) return; 254 if (!dev)
256 spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags); 255 return;
257 if (atm_may_send(vcc,0)) { 256 spin_lock_irqsave(&PRIV(dev)->xoff_lock, flags);
258 old = xchg(&clip_vcc->xoff,0); 257 if (atm_may_send(vcc, 0)) {
259 if (old) netif_wake_queue(dev); 258 old = xchg(&clip_vcc->xoff, 0);
259 if (old)
260 netif_wake_queue(dev);
260 } 261 }
261 spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags); 262 spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
262} 263}
263 264
264
265static void clip_neigh_destroy(struct neighbour *neigh) 265static void clip_neigh_destroy(struct neighbour *neigh)
266{ 266{
267 DPRINTK("clip_neigh_destroy (neigh %p)\n",neigh); 267 DPRINTK("clip_neigh_destroy (neigh %p)\n", neigh);
268 if (NEIGH2ENTRY(neigh)->vccs) 268 if (NEIGH2ENTRY(neigh)->vccs)
269 printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n"); 269 printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n");
270 NEIGH2ENTRY(neigh)->vccs = (void *) 0xdeadbeef; 270 NEIGH2ENTRY(neigh)->vccs = (void *) 0xdeadbeef;
271} 271}
272 272
273 273static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
274static void clip_neigh_solicit(struct neighbour *neigh,struct sk_buff *skb)
275{ 274{
276 DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n",neigh,skb); 275 DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb);
277 to_atmarpd(act_need,PRIV(neigh->dev)->number,NEIGH2ENTRY(neigh)->ip); 276 to_atmarpd(act_need, PRIV(neigh->dev)->number, NEIGH2ENTRY(neigh)->ip);
278} 277}
279 278
280 279static void clip_neigh_error(struct neighbour *neigh, struct sk_buff *skb)
281static void clip_neigh_error(struct neighbour *neigh,struct sk_buff *skb)
282{ 280{
283#ifndef CONFIG_ATM_CLIP_NO_ICMP 281#ifndef CONFIG_ATM_CLIP_NO_ICMP
284 icmp_send(skb,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,0); 282 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
285#endif 283#endif
286 kfree_skb(skb); 284 kfree_skb(skb);
287} 285}
288 286
289
290static struct neigh_ops clip_neigh_ops = { 287static struct neigh_ops clip_neigh_ops = {
291 .family = AF_INET, 288 .family = AF_INET,
292 .solicit = clip_neigh_solicit, 289 .solicit = clip_neigh_solicit,
@@ -297,7 +294,6 @@ static struct neigh_ops clip_neigh_ops = {
297 .queue_xmit = dev_queue_xmit, 294 .queue_xmit = dev_queue_xmit,
298}; 295};
299 296
300
301static int clip_constructor(struct neighbour *neigh) 297static int clip_constructor(struct neighbour *neigh)
302{ 298{
303 struct atmarp_entry *entry = NEIGH2ENTRY(neigh); 299 struct atmarp_entry *entry = NEIGH2ENTRY(neigh);
@@ -305,9 +301,10 @@ static int clip_constructor(struct neighbour *neigh)
305 struct in_device *in_dev; 301 struct in_device *in_dev;
306 struct neigh_parms *parms; 302 struct neigh_parms *parms;
307 303
308 DPRINTK("clip_constructor (neigh %p, entry %p)\n",neigh,entry); 304 DPRINTK("clip_constructor (neigh %p, entry %p)\n", neigh, entry);
309 neigh->type = inet_addr_type(entry->ip); 305 neigh->type = inet_addr_type(entry->ip);
310 if (neigh->type != RTN_UNICAST) return -EINVAL; 306 if (neigh->type != RTN_UNICAST)
307 return -EINVAL;
311 308
312 rcu_read_lock(); 309 rcu_read_lock();
313 in_dev = __in_dev_get_rcu(dev); 310 in_dev = __in_dev_get_rcu(dev);
@@ -326,13 +323,13 @@ static int clip_constructor(struct neighbour *neigh)
326 neigh->ops->connected_output : neigh->ops->output; 323 neigh->ops->connected_output : neigh->ops->output;
327 entry->neigh = neigh; 324 entry->neigh = neigh;
328 entry->vccs = NULL; 325 entry->vccs = NULL;
329 entry->expires = jiffies-1; 326 entry->expires = jiffies - 1;
330 return 0; 327 return 0;
331} 328}
332 329
333static u32 clip_hash(const void *pkey, const struct net_device *dev) 330static u32 clip_hash(const void *pkey, const struct net_device *dev)
334{ 331{
335 return jhash_2words(*(u32 *)pkey, dev->ifindex, clip_tbl.hash_rnd); 332 return jhash_2words(*(u32 *) pkey, dev->ifindex, clip_tbl.hash_rnd);
336} 333}
337 334
338static struct neigh_table clip_tbl = { 335static struct neigh_table clip_tbl = {
@@ -366,7 +363,6 @@ static struct neigh_table clip_tbl = {
366 .gc_thresh3 = 1024, 363 .gc_thresh3 = 1024,
367}; 364};
368 365
369
370/* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */ 366/* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */
371 367
372/* 368/*
@@ -376,15 +372,13 @@ static struct neigh_table clip_tbl = {
376 * clip_setentry. 372 * clip_setentry.
377 */ 373 */
378 374
379 375static int clip_encap(struct atm_vcc *vcc, int mode)
380static int clip_encap(struct atm_vcc *vcc,int mode)
381{ 376{
382 CLIP_VCC(vcc)->encap = mode; 377 CLIP_VCC(vcc)->encap = mode;
383 return 0; 378 return 0;
384} 379}
385 380
386 381static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
387static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
388{ 382{
389 struct clip_priv *clip_priv = PRIV(dev); 383 struct clip_priv *clip_priv = PRIV(dev);
390 struct atmarp_entry *entry; 384 struct atmarp_entry *entry;
@@ -392,7 +386,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
392 int old; 386 int old;
393 unsigned long flags; 387 unsigned long flags;
394 388
395 DPRINTK("clip_start_xmit (skb %p)\n",skb); 389 DPRINTK("clip_start_xmit (skb %p)\n", skb);
396 if (!skb->dst) { 390 if (!skb->dst) {
397 printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n"); 391 printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n");
398 dev_kfree_skb(skb); 392 dev_kfree_skb(skb);
@@ -401,9 +395,9 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
401 } 395 }
402 if (!skb->dst->neighbour) { 396 if (!skb->dst->neighbour) {
403#if 0 397#if 0
404 skb->dst->neighbour = clip_find_neighbour(skb->dst,1); 398 skb->dst->neighbour = clip_find_neighbour(skb->dst, 1);
405 if (!skb->dst->neighbour) { 399 if (!skb->dst->neighbour) {
406 dev_kfree_skb(skb); /* lost that one */ 400 dev_kfree_skb(skb); /* lost that one */
407 clip_priv->stats.tx_dropped++; 401 clip_priv->stats.tx_dropped++;
408 return 0; 402 return 0;
409 } 403 }
@@ -417,73 +411,73 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
417 if (!entry->vccs) { 411 if (!entry->vccs) {
418 if (time_after(jiffies, entry->expires)) { 412 if (time_after(jiffies, entry->expires)) {
419 /* should be resolved */ 413 /* should be resolved */
420 entry->expires = jiffies+ATMARP_RETRY_DELAY*HZ; 414 entry->expires = jiffies + ATMARP_RETRY_DELAY * HZ;
421 to_atmarpd(act_need,PRIV(dev)->number,entry->ip); 415 to_atmarpd(act_need, PRIV(dev)->number, entry->ip);
422 } 416 }
423 if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS) 417 if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS)
424 skb_queue_tail(&entry->neigh->arp_queue,skb); 418 skb_queue_tail(&entry->neigh->arp_queue, skb);
425 else { 419 else {
426 dev_kfree_skb(skb); 420 dev_kfree_skb(skb);
427 clip_priv->stats.tx_dropped++; 421 clip_priv->stats.tx_dropped++;
428 } 422 }
429 return 0; 423 return 0;
430 } 424 }
431 DPRINTK("neigh %p, vccs %p\n",entry,entry->vccs); 425 DPRINTK("neigh %p, vccs %p\n", entry, entry->vccs);
432 ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc; 426 ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
433 DPRINTK("using neighbour %p, vcc %p\n",skb->dst->neighbour,vcc); 427 DPRINTK("using neighbour %p, vcc %p\n", skb->dst->neighbour, vcc);
434 if (entry->vccs->encap) { 428 if (entry->vccs->encap) {
435 void *here; 429 void *here;
436 430
437 here = skb_push(skb,RFC1483LLC_LEN); 431 here = skb_push(skb, RFC1483LLC_LEN);
438 memcpy(here,llc_oui,sizeof(llc_oui)); 432 memcpy(here, llc_oui, sizeof(llc_oui));
439 ((u16 *) here)[3] = skb->protocol; 433 ((u16 *) here)[3] = skb->protocol;
440 } 434 }
441 atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); 435 atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
442 ATM_SKB(skb)->atm_options = vcc->atm_options; 436 ATM_SKB(skb)->atm_options = vcc->atm_options;
443 entry->vccs->last_use = jiffies; 437 entry->vccs->last_use = jiffies;
444 DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev); 438 DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
445 old = xchg(&entry->vccs->xoff,1); /* assume XOFF ... */ 439 old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */
446 if (old) { 440 if (old) {
447 printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n"); 441 printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n");
448 return 0; 442 return 0;
449 } 443 }
450 clip_priv->stats.tx_packets++; 444 clip_priv->stats.tx_packets++;
451 clip_priv->stats.tx_bytes += skb->len; 445 clip_priv->stats.tx_bytes += skb->len;
452 (void) vcc->send(vcc,skb); 446 vcc->send(vcc, skb);
453 if (atm_may_send(vcc,0)) { 447 if (atm_may_send(vcc, 0)) {
454 entry->vccs->xoff = 0; 448 entry->vccs->xoff = 0;
455 return 0; 449 return 0;
456 } 450 }
457 spin_lock_irqsave(&clip_priv->xoff_lock,flags); 451 spin_lock_irqsave(&clip_priv->xoff_lock, flags);
458 netif_stop_queue(dev); /* XOFF -> throttle immediately */ 452 netif_stop_queue(dev); /* XOFF -> throttle immediately */
459 barrier(); 453 barrier();
460 if (!entry->vccs->xoff) 454 if (!entry->vccs->xoff)
461 netif_start_queue(dev); 455 netif_start_queue(dev);
462 /* Oh, we just raced with clip_pop. netif_start_queue should be 456 /* Oh, we just raced with clip_pop. netif_start_queue should be
463 good enough, because nothing should really be asleep because 457 good enough, because nothing should really be asleep because
464 of the brief netif_stop_queue. If this isn't true or if it 458 of the brief netif_stop_queue. If this isn't true or if it
465 changes, use netif_wake_queue instead. */ 459 changes, use netif_wake_queue instead. */
466 spin_unlock_irqrestore(&clip_priv->xoff_lock,flags); 460 spin_unlock_irqrestore(&clip_priv->xoff_lock, flags);
467 return 0; 461 return 0;
468} 462}
469 463
470
471static struct net_device_stats *clip_get_stats(struct net_device *dev) 464static struct net_device_stats *clip_get_stats(struct net_device *dev)
472{ 465{
473 return &PRIV(dev)->stats; 466 return &PRIV(dev)->stats;
474} 467}
475 468
476 469static int clip_mkip(struct atm_vcc *vcc, int timeout)
477static int clip_mkip(struct atm_vcc *vcc,int timeout)
478{ 470{
479 struct clip_vcc *clip_vcc; 471 struct clip_vcc *clip_vcc;
480 struct sk_buff_head copy; 472 struct sk_buff_head copy;
481 struct sk_buff *skb; 473 struct sk_buff *skb;
482 474
483 if (!vcc->push) return -EBADFD; 475 if (!vcc->push)
484 clip_vcc = kmalloc(sizeof(struct clip_vcc),GFP_KERNEL); 476 return -EBADFD;
485 if (!clip_vcc) return -ENOMEM; 477 clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL);
486 DPRINTK("mkip clip_vcc %p vcc %p\n",clip_vcc,vcc); 478 if (!clip_vcc)
479 return -ENOMEM;
480 DPRINTK("mkip clip_vcc %p vcc %p\n", clip_vcc, vcc);
487 clip_vcc->vcc = vcc; 481 clip_vcc->vcc = vcc;
488 vcc->user_back = clip_vcc; 482 vcc->user_back = clip_vcc;
489 set_bit(ATM_VF_IS_CLIP, &vcc->flags); 483 set_bit(ATM_VF_IS_CLIP, &vcc->flags);
@@ -491,7 +485,7 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout)
491 clip_vcc->xoff = 0; 485 clip_vcc->xoff = 0;
492 clip_vcc->encap = 1; 486 clip_vcc->encap = 1;
493 clip_vcc->last_use = jiffies; 487 clip_vcc->last_use = jiffies;
494 clip_vcc->idle_timeout = timeout*HZ; 488 clip_vcc->idle_timeout = timeout * HZ;
495 clip_vcc->old_push = vcc->push; 489 clip_vcc->old_push = vcc->push;
496 clip_vcc->old_pop = vcc->pop; 490 clip_vcc->old_pop = vcc->pop;
497 vcc->push = clip_push; 491 vcc->push = clip_push;
@@ -501,27 +495,25 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout)
501 /* re-process everything received between connection setup and MKIP */ 495 /* re-process everything received between connection setup and MKIP */
502 while ((skb = skb_dequeue(&copy)) != NULL) 496 while ((skb = skb_dequeue(&copy)) != NULL)
503 if (!clip_devs) { 497 if (!clip_devs) {
504 atm_return(vcc,skb->truesize); 498 atm_return(vcc, skb->truesize);
505 kfree_skb(skb); 499 kfree_skb(skb);
506 } 500 } else {
507 else {
508 unsigned int len = skb->len; 501 unsigned int len = skb->len;
509 502
510 clip_push(vcc,skb); 503 clip_push(vcc, skb);
511 PRIV(skb->dev)->stats.rx_packets--; 504 PRIV(skb->dev)->stats.rx_packets--;
512 PRIV(skb->dev)->stats.rx_bytes -= len; 505 PRIV(skb->dev)->stats.rx_bytes -= len;
513 } 506 }
514 return 0; 507 return 0;
515} 508}
516 509
517 510static int clip_setentry(struct atm_vcc *vcc, u32 ip)
518static int clip_setentry(struct atm_vcc *vcc,u32 ip)
519{ 511{
520 struct neighbour *neigh; 512 struct neighbour *neigh;
521 struct atmarp_entry *entry; 513 struct atmarp_entry *entry;
522 int error; 514 int error;
523 struct clip_vcc *clip_vcc; 515 struct clip_vcc *clip_vcc;
524 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } }; 516 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} };
525 struct rtable *rt; 517 struct rtable *rt;
526 518
527 if (vcc->push != clip_push) { 519 if (vcc->push != clip_push) {
@@ -538,28 +530,29 @@ static int clip_setentry(struct atm_vcc *vcc,u32 ip)
538 unlink_clip_vcc(clip_vcc); 530 unlink_clip_vcc(clip_vcc);
539 return 0; 531 return 0;
540 } 532 }
541 error = ip_route_output_key(&rt,&fl); 533 error = ip_route_output_key(&rt, &fl);
542 if (error) return error; 534 if (error)
543 neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1); 535 return error;
536 neigh = __neigh_lookup(&clip_tbl, &ip, rt->u.dst.dev, 1);
544 ip_rt_put(rt); 537 ip_rt_put(rt);
545 if (!neigh) 538 if (!neigh)
546 return -ENOMEM; 539 return -ENOMEM;
547 entry = NEIGH2ENTRY(neigh); 540 entry = NEIGH2ENTRY(neigh);
548 if (entry != clip_vcc->entry) { 541 if (entry != clip_vcc->entry) {
549 if (!clip_vcc->entry) DPRINTK("setentry: add\n"); 542 if (!clip_vcc->entry)
543 DPRINTK("setentry: add\n");
550 else { 544 else {
551 DPRINTK("setentry: update\n"); 545 DPRINTK("setentry: update\n");
552 unlink_clip_vcc(clip_vcc); 546 unlink_clip_vcc(clip_vcc);
553 } 547 }
554 link_vcc(clip_vcc,entry); 548 link_vcc(clip_vcc, entry);
555 } 549 }
556 error = neigh_update(neigh, llc_oui, NUD_PERMANENT, 550 error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
557 NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN); 551 NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);
558 neigh_release(neigh); 552 neigh_release(neigh);
559 return error; 553 return error;
560} 554}
561 555
562
563static void clip_setup(struct net_device *dev) 556static void clip_setup(struct net_device *dev)
564{ 557{
565 dev->hard_start_xmit = clip_start_xmit; 558 dev->hard_start_xmit = clip_start_xmit;
@@ -568,15 +561,14 @@ static void clip_setup(struct net_device *dev)
568 dev->type = ARPHRD_ATM; 561 dev->type = ARPHRD_ATM;
569 dev->hard_header_len = RFC1483LLC_LEN; 562 dev->hard_header_len = RFC1483LLC_LEN;
570 dev->mtu = RFC1626_MTU; 563 dev->mtu = RFC1626_MTU;
571 dev->tx_queue_len = 100; /* "normal" queue (packets) */ 564 dev->tx_queue_len = 100; /* "normal" queue (packets) */
572 /* When using a "real" qdisc, the qdisc determines the queue */ 565 /* When using a "real" qdisc, the qdisc determines the queue */
573 /* length. tx_queue_len is only used for the default case, */ 566 /* length. tx_queue_len is only used for the default case, */
574 /* without any more elaborate queuing. 100 is a reasonable */ 567 /* without any more elaborate queuing. 100 is a reasonable */
575 /* compromise between decent burst-tolerance and protection */ 568 /* compromise between decent burst-tolerance and protection */
576 /* against memory hogs. */ 569 /* against memory hogs. */
577} 570}
578 571
579
580static int clip_create(int number) 572static int clip_create(int number)
581{ 573{
582 struct net_device *dev; 574 struct net_device *dev;
@@ -585,19 +577,19 @@ static int clip_create(int number)
585 577
586 if (number != -1) { 578 if (number != -1) {
587 for (dev = clip_devs; dev; dev = PRIV(dev)->next) 579 for (dev = clip_devs; dev; dev = PRIV(dev)->next)
588 if (PRIV(dev)->number == number) return -EEXIST; 580 if (PRIV(dev)->number == number)
589 } 581 return -EEXIST;
590 else { 582 } else {
591 number = 0; 583 number = 0;
592 for (dev = clip_devs; dev; dev = PRIV(dev)->next) 584 for (dev = clip_devs; dev; dev = PRIV(dev)->next)
593 if (PRIV(dev)->number >= number) 585 if (PRIV(dev)->number >= number)
594 number = PRIV(dev)->number+1; 586 number = PRIV(dev)->number + 1;
595 } 587 }
596 dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup); 588 dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup);
597 if (!dev) 589 if (!dev)
598 return -ENOMEM; 590 return -ENOMEM;
599 clip_priv = PRIV(dev); 591 clip_priv = PRIV(dev);
600 sprintf(dev->name,"atm%d",number); 592 sprintf(dev->name, "atm%d", number);
601 spin_lock_init(&clip_priv->xoff_lock); 593 spin_lock_init(&clip_priv->xoff_lock);
602 clip_priv->number = number; 594 clip_priv->number = number;
603 error = register_netdev(dev); 595 error = register_netdev(dev);
@@ -607,53 +599,48 @@ static int clip_create(int number)
607 } 599 }
608 clip_priv->next = clip_devs; 600 clip_priv->next = clip_devs;
609 clip_devs = dev; 601 clip_devs = dev;
610 DPRINTK("registered (net:%s)\n",dev->name); 602 DPRINTK("registered (net:%s)\n", dev->name);
611 return number; 603 return number;
612} 604}
613 605
614 606static int clip_device_event(struct notifier_block *this, unsigned long event,
615static int clip_device_event(struct notifier_block *this,unsigned long event, 607 void *arg)
616 void *dev)
617{ 608{
609 struct net_device *dev = arg;
610
611 if (event == NETDEV_UNREGISTER) {
612 neigh_ifdown(&clip_tbl, dev);
613 return NOTIFY_DONE;
614 }
615
618 /* ignore non-CLIP devices */ 616 /* ignore non-CLIP devices */
619 if (((struct net_device *) dev)->type != ARPHRD_ATM || 617 if (dev->type != ARPHRD_ATM || dev->hard_start_xmit != clip_start_xmit)
620 ((struct net_device *) dev)->hard_start_xmit != clip_start_xmit)
621 return NOTIFY_DONE; 618 return NOTIFY_DONE;
619
622 switch (event) { 620 switch (event) {
623 case NETDEV_UP: 621 case NETDEV_UP:
624 DPRINTK("clip_device_event NETDEV_UP\n"); 622 DPRINTK("clip_device_event NETDEV_UP\n");
625 (void) to_atmarpd(act_up,PRIV(dev)->number,0); 623 to_atmarpd(act_up, PRIV(dev)->number, 0);
626 break; 624 break;
627 case NETDEV_GOING_DOWN: 625 case NETDEV_GOING_DOWN:
628 DPRINTK("clip_device_event NETDEV_DOWN\n"); 626 DPRINTK("clip_device_event NETDEV_DOWN\n");
629 (void) to_atmarpd(act_down,PRIV(dev)->number,0); 627 to_atmarpd(act_down, PRIV(dev)->number, 0);
630 break; 628 break;
631 case NETDEV_CHANGE: 629 case NETDEV_CHANGE:
632 case NETDEV_CHANGEMTU: 630 case NETDEV_CHANGEMTU:
633 DPRINTK("clip_device_event NETDEV_CHANGE*\n"); 631 DPRINTK("clip_device_event NETDEV_CHANGE*\n");
634 (void) to_atmarpd(act_change,PRIV(dev)->number,0); 632 to_atmarpd(act_change, PRIV(dev)->number, 0);
635 break; 633 break;
636 case NETDEV_REBOOT:
637 case NETDEV_REGISTER:
638 case NETDEV_DOWN:
639 DPRINTK("clip_device_event %ld\n",event);
640 /* ignore */
641 break;
642 default:
643 printk(KERN_WARNING "clip_device_event: unknown event "
644 "%ld\n",event);
645 break;
646 } 634 }
647 return NOTIFY_DONE; 635 return NOTIFY_DONE;
648} 636}
649 637
650 638static int clip_inet_event(struct notifier_block *this, unsigned long event,
651static int clip_inet_event(struct notifier_block *this,unsigned long event, 639 void *ifa)
652 void *ifa)
653{ 640{
654 struct in_device *in_dev; 641 struct in_device *in_dev;
655 642
656 in_dev = ((struct in_ifaddr *) ifa)->ifa_dev; 643 in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
657 if (!in_dev || !in_dev->dev) { 644 if (!in_dev || !in_dev->dev) {
658 printk(KERN_WARNING "clip_inet_event: no device\n"); 645 printk(KERN_WARNING "clip_inet_event: no device\n");
659 return NOTIFY_DONE; 646 return NOTIFY_DONE;
@@ -662,23 +649,20 @@ static int clip_inet_event(struct notifier_block *this,unsigned long event,
662 * Transitions are of the down-change-up type, so it's sufficient to 649 * Transitions are of the down-change-up type, so it's sufficient to
663 * handle the change on up. 650 * handle the change on up.
664 */ 651 */
665 if (event != NETDEV_UP) return NOTIFY_DONE; 652 if (event != NETDEV_UP)
666 return clip_device_event(this,NETDEV_CHANGE,in_dev->dev); 653 return NOTIFY_DONE;
654 return clip_device_event(this, NETDEV_CHANGE, in_dev->dev);
667} 655}
668 656
669 657
670static struct notifier_block clip_dev_notifier = { 658static struct notifier_block clip_dev_notifier = {
671 clip_device_event, 659 .notifier_call = clip_device_event,
672 NULL,
673 0
674}; 660};
675 661
676 662
677 663
678static struct notifier_block clip_inet_notifier = { 664static struct notifier_block clip_inet_notifier = {
679 clip_inet_event, 665 .notifier_call = clip_inet_event,
680 NULL,
681 0
682}; 666};
683 667
684 668
@@ -686,14 +670,12 @@ static struct notifier_block clip_inet_notifier = {
686static void atmarpd_close(struct atm_vcc *vcc) 670static void atmarpd_close(struct atm_vcc *vcc)
687{ 671{
688 DPRINTK("atmarpd_close\n"); 672 DPRINTK("atmarpd_close\n");
689 atmarpd = NULL; /* assumed to be atomic */ 673
690 barrier(); 674 rtnl_lock();
691 unregister_inetaddr_notifier(&clip_inet_notifier); 675 atmarpd = NULL;
692 unregister_netdevice_notifier(&clip_dev_notifier);
693 if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
694 printk(KERN_ERR "atmarpd_close: closing with requests "
695 "pending\n");
696 skb_queue_purge(&sk_atm(vcc)->sk_receive_queue); 676 skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
677 rtnl_unlock();
678
697 DPRINTK("(done)\n"); 679 DPRINTK("(done)\n");
698 module_put(THIS_MODULE); 680 module_put(THIS_MODULE);
699} 681}
@@ -714,14 +696,14 @@ static struct atm_dev atmarpd_dev = {
714 696
715static int atm_init_atmarp(struct atm_vcc *vcc) 697static int atm_init_atmarp(struct atm_vcc *vcc)
716{ 698{
717 if (atmarpd) return -EADDRINUSE; 699 rtnl_lock();
718 if (start_timer) { 700 if (atmarpd) {
719 start_timer = 0; 701 rtnl_unlock();
720 init_timer(&idle_timer); 702 return -EADDRINUSE;
721 idle_timer.expires = jiffies+CLIP_CHECK_INTERVAL*HZ;
722 idle_timer.function = idle_timer_check;
723 add_timer(&idle_timer);
724 } 703 }
704
705 mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
706
725 atmarpd = vcc; 707 atmarpd = vcc;
726 set_bit(ATM_VF_META,&vcc->flags); 708 set_bit(ATM_VF_META,&vcc->flags);
727 set_bit(ATM_VF_READY,&vcc->flags); 709 set_bit(ATM_VF_READY,&vcc->flags);
@@ -731,10 +713,7 @@ static int atm_init_atmarp(struct atm_vcc *vcc)
731 vcc->push = NULL; 713 vcc->push = NULL;
732 vcc->pop = NULL; /* crash */ 714 vcc->pop = NULL; /* crash */
733 vcc->push_oam = NULL; /* crash */ 715 vcc->push_oam = NULL; /* crash */
734 if (register_netdevice_notifier(&clip_dev_notifier)) 716 rtnl_unlock();
735 printk(KERN_ERR "register_netdevice_notifier failed\n");
736 if (register_inetaddr_notifier(&clip_inet_notifier))
737 printk(KERN_ERR "register_inetaddr_notifier failed\n");
738 return 0; 717 return 0;
739} 718}
740 719
@@ -744,53 +723,53 @@ static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
744 int err = 0; 723 int err = 0;
745 724
746 switch (cmd) { 725 switch (cmd) {
747 case SIOCMKCLIP: 726 case SIOCMKCLIP:
748 case ATMARPD_CTRL: 727 case ATMARPD_CTRL:
749 case ATMARP_MKIP: 728 case ATMARP_MKIP:
750 case ATMARP_SETENTRY: 729 case ATMARP_SETENTRY:
751 case ATMARP_ENCAP: 730 case ATMARP_ENCAP:
752 if (!capable(CAP_NET_ADMIN)) 731 if (!capable(CAP_NET_ADMIN))
753 return -EPERM; 732 return -EPERM;
754 break; 733 break;
755 default: 734 default:
756 return -ENOIOCTLCMD; 735 return -ENOIOCTLCMD;
757 } 736 }
758 737
759 switch (cmd) { 738 switch (cmd) {
760 case SIOCMKCLIP: 739 case SIOCMKCLIP:
761 err = clip_create(arg); 740 err = clip_create(arg);
762 break; 741 break;
763 case ATMARPD_CTRL: 742 case ATMARPD_CTRL:
764 err = atm_init_atmarp(vcc); 743 err = atm_init_atmarp(vcc);
765 if (!err) { 744 if (!err) {
766 sock->state = SS_CONNECTED; 745 sock->state = SS_CONNECTED;
767 __module_get(THIS_MODULE); 746 __module_get(THIS_MODULE);
768 } 747 }
769 break; 748 break;
770 case ATMARP_MKIP: 749 case ATMARP_MKIP:
771 err = clip_mkip(vcc ,arg); 750 err = clip_mkip(vcc, arg);
772 break; 751 break;
773 case ATMARP_SETENTRY: 752 case ATMARP_SETENTRY:
774 err = clip_setentry(vcc, arg); 753 err = clip_setentry(vcc, arg);
775 break; 754 break;
776 case ATMARP_ENCAP: 755 case ATMARP_ENCAP:
777 err = clip_encap(vcc, arg); 756 err = clip_encap(vcc, arg);
778 break; 757 break;
779 } 758 }
780 return err; 759 return err;
781} 760}
782 761
783static struct atm_ioctl clip_ioctl_ops = { 762static struct atm_ioctl clip_ioctl_ops = {
784 .owner = THIS_MODULE, 763 .owner = THIS_MODULE,
785 .ioctl = clip_ioctl, 764 .ioctl = clip_ioctl,
786}; 765};
787 766
788#ifdef CONFIG_PROC_FS 767#ifdef CONFIG_PROC_FS
789 768
790static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr) 769static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
791{ 770{
792 static int code[] = { 1,2,10,6,1,0 }; 771 static int code[] = { 1, 2, 10, 6, 1, 0 };
793 static int e164[] = { 1,8,4,6,1,0 }; 772 static int e164[] = { 1, 8, 4, 6, 1, 0 };
794 773
795 if (*addr->sas_addr.pub) { 774 if (*addr->sas_addr.pub) {
796 seq_printf(seq, "%s", addr->sas_addr.pub); 775 seq_printf(seq, "%s", addr->sas_addr.pub);
@@ -809,7 +788,7 @@ static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
809 for (i = 0; fields[i]; i++) { 788 for (i = 0; fields[i]; i++) {
810 for (j = fields[i]; j; j--) 789 for (j = fields[i]; j; j--)
811 seq_printf(seq, "%02X", *prv++); 790 seq_printf(seq, "%02X", *prv++);
812 if (fields[i+1]) 791 if (fields[i + 1])
813 seq_putc(seq, '.'); 792 seq_putc(seq, '.');
814 } 793 }
815 } 794 }
@@ -828,8 +807,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
828 svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || 807 svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
829 (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC)); 808 (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
830 809
831 llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || 810 llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || clip_vcc->encap);
832 clip_vcc->encap);
833 811
834 if (clip_vcc == SEQ_NO_VCC_TOKEN) 812 if (clip_vcc == SEQ_NO_VCC_TOKEN)
835 exp = entry->neigh->used; 813 exp = entry->neigh->used;
@@ -839,10 +817,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
839 exp = (jiffies - exp) / HZ; 817 exp = (jiffies - exp) / HZ;
840 818
841 seq_printf(seq, "%-6s%-4s%-4s%5ld ", 819 seq_printf(seq, "%-6s%-4s%-4s%5ld ",
842 dev->name, 820 dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
843 svc ? "SVC" : "PVC",
844 llc ? "LLC" : "NULL",
845 exp);
846 821
847 off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d", 822 off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
848 NIPQUAD(entry->ip)); 823 NIPQUAD(entry->ip));
@@ -860,8 +835,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
860 } else if (!svc) { 835 } else if (!svc) {
861 seq_printf(seq, "%d.%d.%d\n", 836 seq_printf(seq, "%d.%d.%d\n",
862 clip_vcc->vcc->dev->number, 837 clip_vcc->vcc->dev->number,
863 clip_vcc->vcc->vpi, 838 clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
864 clip_vcc->vcc->vci);
865 } else { 839 } else {
866 svc_addr(seq, &clip_vcc->vcc->remote); 840 svc_addr(seq, &clip_vcc->vcc->remote);
867 seq_putc(seq, '\n'); 841 seq_putc(seq, '\n');
@@ -894,7 +868,7 @@ static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
894} 868}
895 869
896static void *clip_seq_vcc_walk(struct clip_seq_state *state, 870static void *clip_seq_vcc_walk(struct clip_seq_state *state,
897 struct atmarp_entry *e, loff_t *pos) 871 struct atmarp_entry *e, loff_t * pos)
898{ 872{
899 struct clip_vcc *vcc = state->vcc; 873 struct clip_vcc *vcc = state->vcc;
900 874
@@ -911,24 +885,24 @@ static void *clip_seq_vcc_walk(struct clip_seq_state *state,
911 885
912 return vcc; 886 return vcc;
913} 887}
914 888
915static void *clip_seq_sub_iter(struct neigh_seq_state *_state, 889static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
916 struct neighbour *n, loff_t *pos) 890 struct neighbour *n, loff_t * pos)
917{ 891{
918 struct clip_seq_state *state = (struct clip_seq_state *) _state; 892 struct clip_seq_state *state = (struct clip_seq_state *)_state;
919 893
920 return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos); 894 return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos);
921} 895}
922 896
923static void *clip_seq_start(struct seq_file *seq, loff_t *pos) 897static void *clip_seq_start(struct seq_file *seq, loff_t * pos)
924{ 898{
925 return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY); 899 return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY);
926} 900}
927 901
928static int clip_seq_show(struct seq_file *seq, void *v) 902static int clip_seq_show(struct seq_file *seq, void *v)
929{ 903{
930 static char atm_arp_banner[] = 904 static char atm_arp_banner[] =
931 "IPitf TypeEncp Idle IP address ATM address\n"; 905 "IPitf TypeEncp Idle IP address ATM address\n";
932 906
933 if (v == SEQ_START_TOKEN) { 907 if (v == SEQ_START_TOKEN) {
934 seq_puts(seq, atm_arp_banner); 908 seq_puts(seq, atm_arp_banner);
@@ -939,7 +913,7 @@ static int clip_seq_show(struct seq_file *seq, void *v)
939 913
940 atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc); 914 atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
941 } 915 }
942 return 0; 916 return 0;
943} 917}
944 918
945static struct seq_operations arp_seq_ops = { 919static struct seq_operations arp_seq_ops = {
@@ -988,20 +962,19 @@ static struct file_operations arp_seq_fops = {
988 962
989static int __init atm_clip_init(void) 963static int __init atm_clip_init(void)
990{ 964{
965 struct proc_dir_entry *p;
991 neigh_table_init(&clip_tbl); 966 neigh_table_init(&clip_tbl);
992 967
993 clip_tbl_hook = &clip_tbl; 968 clip_tbl_hook = &clip_tbl;
994 register_atm_ioctl(&clip_ioctl_ops); 969 register_atm_ioctl(&clip_ioctl_ops);
970 register_netdevice_notifier(&clip_dev_notifier);
971 register_inetaddr_notifier(&clip_inet_notifier);
995 972
996#ifdef CONFIG_PROC_FS 973 setup_timer(&idle_timer, idle_timer_check, 0);
997{
998 struct proc_dir_entry *p;
999 974
1000 p = create_proc_entry("arp", S_IRUGO, atm_proc_root); 975 p = create_proc_entry("arp", S_IRUGO, atm_proc_root);
1001 if (p) 976 if (p)
1002 p->proc_fops = &arp_seq_fops; 977 p->proc_fops = &arp_seq_fops;
1003}
1004#endif
1005 978
1006 return 0; 979 return 0;
1007} 980}
@@ -1012,13 +985,15 @@ static void __exit atm_clip_exit(void)
1012 985
1013 remove_proc_entry("arp", atm_proc_root); 986 remove_proc_entry("arp", atm_proc_root);
1014 987
988 unregister_inetaddr_notifier(&clip_inet_notifier);
989 unregister_netdevice_notifier(&clip_dev_notifier);
990
1015 deregister_atm_ioctl(&clip_ioctl_ops); 991 deregister_atm_ioctl(&clip_ioctl_ops);
1016 992
1017 /* First, stop the idle timer, so it stops banging 993 /* First, stop the idle timer, so it stops banging
1018 * on the table. 994 * on the table.
1019 */ 995 */
1020 if (start_timer == 0) 996 del_timer_sync(&idle_timer);
1021 del_timer(&idle_timer);
1022 997
1023 /* Next, purge the table, so that the device 998 /* Next, purge the table, so that the device
1024 * unregister loop below does not hang due to 999 * unregister loop below does not hang due to
@@ -1042,5 +1017,6 @@ static void __exit atm_clip_exit(void)
1042 1017
1043module_init(atm_clip_init); 1018module_init(atm_clip_init);
1044module_exit(atm_clip_exit); 1019module_exit(atm_clip_exit);
1045 1020MODULE_AUTHOR("Werner Almesberger");
1021MODULE_DESCRIPTION("Classical/IP over ATM interface");
1046MODULE_LICENSE("GPL"); 1022MODULE_LICENSE("GPL");
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 6b61323ce23c..0c2d13ad69bb 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)
255 } 255 }
256 256
257 if ((err = hci_send_sco(conn->hcon, skb)) < 0) 257 if ((err = hci_send_sco(conn->hcon, skb)) < 0)
258 goto fail; 258 return err;
259 259
260 return count; 260 return count;
261 261
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 2d24fb400e0c..56f3aa47e758 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -16,6 +16,7 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/netdevice.h> 17#include <linux/netdevice.h>
18#include <linux/skbuff.h> 18#include <linux/skbuff.h>
19#include <linux/if_vlan.h>
19#include <linux/netfilter_bridge.h> 20#include <linux/netfilter_bridge.h>
20#include "br_private.h" 21#include "br_private.h"
21 22
@@ -29,10 +30,15 @@ static inline int should_deliver(const struct net_bridge_port *p,
29 return 1; 30 return 1;
30} 31}
31 32
33static inline unsigned packet_length(const struct sk_buff *skb)
34{
35 return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0);
36}
37
32int br_dev_queue_push_xmit(struct sk_buff *skb) 38int br_dev_queue_push_xmit(struct sk_buff *skb)
33{ 39{
34 /* drop mtu oversized packets except tso */ 40 /* drop mtu oversized packets except tso */
35 if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size) 41 if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
36 kfree_skb(skb); 42 kfree_skb(skb);
37 else { 43 else {
38#ifdef CONFIG_BRIDGE_NETFILTER 44#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index b7766562d72c..b0b7f55c1edd 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)
125 struct sk_buff *skb = *pskb; 125 struct sk_buff *skb = *pskb;
126 const unsigned char *dest = eth_hdr(skb)->h_dest; 126 const unsigned char *dest = eth_hdr(skb)->h_dest;
127 127
128 if (p->state == BR_STATE_DISABLED)
129 goto err;
130
131 if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) 128 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
132 goto err; 129 goto err;
133 130
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index f29450b788be..3da9264449f7 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -765,6 +765,15 @@ out:
765 return NF_STOLEN; 765 return NF_STOLEN;
766} 766}
767 767
768static int br_nf_dev_queue_xmit(struct sk_buff *skb)
769{
770 if (skb->protocol == htons(ETH_P_IP) &&
771 skb->len > skb->dev->mtu &&
772 !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
773 return ip_fragment(skb, br_dev_queue_push_xmit);
774 else
775 return br_dev_queue_push_xmit(skb);
776}
768 777
769/* PF_BRIDGE/POST_ROUTING ********************************************/ 778/* PF_BRIDGE/POST_ROUTING ********************************************/
770static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, 779static 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,
824 realoutdev = nf_bridge->netoutdev; 833 realoutdev = nf_bridge->netoutdev;
825#endif 834#endif
826 NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, 835 NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
827 br_dev_queue_push_xmit); 836 br_nf_dev_queue_xmit);
828 837
829 return NF_STOLEN; 838 return NF_STOLEN;
830 839
@@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
869 878
870 if ((out->hard_start_xmit == br_dev_xmit && 879 if ((out->hard_start_xmit == br_dev_xmit &&
871 okfn != br_nf_forward_finish && 880 okfn != br_nf_forward_finish &&
872 okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit) 881 okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
873#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) 882#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
874 || ((out->priv_flags & IFF_802_1Q_VLAN) && 883 || ((out->priv_flags & IFF_802_1Q_VLAN) &&
875 VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) 884 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 01eae97c53d9..3a13ed643459 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,
824 if (udc_cnt) { 824 if (udc_cnt) {
825 /* this will get free'd in do_replace()/ebt_register_table() 825 /* this will get free'd in do_replace()/ebt_register_table()
826 if an error occurs */ 826 if an error occurs */
827 newinfo->chainstack = (struct ebt_chainstack **) 827 newinfo->chainstack =
828 vmalloc((highest_possible_processor_id()+1) 828 vmalloc((highest_possible_processor_id()+1)
829 * sizeof(struct ebt_chainstack)); 829 * sizeof(*(newinfo->chainstack)));
830 if (!newinfo->chainstack) 830 if (!newinfo->chainstack)
831 return -ENOMEM; 831 return -ENOMEM;
832 for_each_cpu(i) { 832 for_each_possible_cpu(i) {
833 newinfo->chainstack[i] = 833 newinfo->chainstack[i] =
834 vmalloc(udc_cnt * sizeof(struct ebt_chainstack)); 834 vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
835 if (!newinfo->chainstack[i]) { 835 if (!newinfo->chainstack[i]) {
836 while (i) 836 while (i)
837 vfree(newinfo->chainstack[--i]); 837 vfree(newinfo->chainstack[--i]);
@@ -841,8 +841,7 @@ static int translate_table(struct ebt_replace *repl,
841 } 841 }
842 } 842 }
843 843
844 cl_s = (struct ebt_cl_stack *) 844 cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
845 vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
846 if (!cl_s) 845 if (!cl_s)
847 return -ENOMEM; 846 return -ENOMEM;
848 i = 0; /* the i'th udc */ 847 i = 0; /* the i'th udc */
@@ -901,7 +900,7 @@ static void get_counters(struct ebt_counter *oldcounters,
901 sizeof(struct ebt_counter) * nentries); 900 sizeof(struct ebt_counter) * nentries);
902 901
903 /* add other counters to those of cpu 0 */ 902 /* add other counters to those of cpu 0 */
904 for_each_cpu(cpu) { 903 for_each_possible_cpu(cpu) {
905 if (cpu == 0) 904 if (cpu == 0)
906 continue; 905 continue;
907 counter_base = COUNTER_BASE(oldcounters, nentries, cpu); 906 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
@@ -944,8 +943,7 @@ static int do_replace(void __user *user, unsigned int len)
944 943
945 countersize = COUNTER_OFFSET(tmp.nentries) * 944 countersize = COUNTER_OFFSET(tmp.nentries) *
946 (highest_possible_processor_id()+1); 945 (highest_possible_processor_id()+1);
947 newinfo = (struct ebt_table_info *) 946 newinfo = vmalloc(sizeof(*newinfo) + countersize);
948 vmalloc(sizeof(struct ebt_table_info) + countersize);
949 if (!newinfo) 947 if (!newinfo)
950 return -ENOMEM; 948 return -ENOMEM;
951 949
@@ -967,8 +965,7 @@ static int do_replace(void __user *user, unsigned int len)
967 /* the user wants counters back 965 /* the user wants counters back
968 the check on the size is done later, when we have the lock */ 966 the check on the size is done later, when we have the lock */
969 if (tmp.num_counters) { 967 if (tmp.num_counters) {
970 counterstmp = (struct ebt_counter *) 968 counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
971 vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
972 if (!counterstmp) { 969 if (!counterstmp) {
973 ret = -ENOMEM; 970 ret = -ENOMEM;
974 goto free_entries; 971 goto free_entries;
@@ -1036,7 +1033,7 @@ static int do_replace(void __user *user, unsigned int len)
1036 1033
1037 vfree(table->entries); 1034 vfree(table->entries);
1038 if (table->chainstack) { 1035 if (table->chainstack) {
1039 for_each_cpu(i) 1036 for_each_possible_cpu(i)
1040 vfree(table->chainstack[i]); 1037 vfree(table->chainstack[i]);
1041 vfree(table->chainstack); 1038 vfree(table->chainstack);
1042 } 1039 }
@@ -1054,7 +1051,7 @@ free_counterstmp:
1054 vfree(counterstmp); 1051 vfree(counterstmp);
1055 /* can be initialized in translate_table() */ 1052 /* can be initialized in translate_table() */
1056 if (newinfo->chainstack) { 1053 if (newinfo->chainstack) {
1057 for_each_cpu(i) 1054 for_each_possible_cpu(i)
1058 vfree(newinfo->chainstack[i]); 1055 vfree(newinfo->chainstack[i]);
1059 vfree(newinfo->chainstack); 1056 vfree(newinfo->chainstack);
1060 } 1057 }
@@ -1148,8 +1145,7 @@ int ebt_register_table(struct ebt_table *table)
1148 1145
1149 countersize = COUNTER_OFFSET(table->table->nentries) * 1146 countersize = COUNTER_OFFSET(table->table->nentries) *
1150 (highest_possible_processor_id()+1); 1147 (highest_possible_processor_id()+1);
1151 newinfo = (struct ebt_table_info *) 1148 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1152 vmalloc(sizeof(struct ebt_table_info) + countersize);
1153 ret = -ENOMEM; 1149 ret = -ENOMEM;
1154 if (!newinfo) 1150 if (!newinfo)
1155 return -ENOMEM; 1151 return -ENOMEM;
@@ -1201,7 +1197,7 @@ free_unlock:
1201 mutex_unlock(&ebt_mutex); 1197 mutex_unlock(&ebt_mutex);
1202free_chainstack: 1198free_chainstack:
1203 if (newinfo->chainstack) { 1199 if (newinfo->chainstack) {
1204 for_each_cpu(i) 1200 for_each_possible_cpu(i)
1205 vfree(newinfo->chainstack[i]); 1201 vfree(newinfo->chainstack[i]);
1206 vfree(newinfo->chainstack); 1202 vfree(newinfo->chainstack);
1207 } 1203 }
@@ -1224,7 +1220,7 @@ void ebt_unregister_table(struct ebt_table *table)
1224 mutex_unlock(&ebt_mutex); 1220 mutex_unlock(&ebt_mutex);
1225 vfree(table->private->entries); 1221 vfree(table->private->entries);
1226 if (table->private->chainstack) { 1222 if (table->private->chainstack) {
1227 for_each_cpu(i) 1223 for_each_possible_cpu(i)
1228 vfree(table->private->chainstack[i]); 1224 vfree(table->private->chainstack[i]);
1229 vfree(table->private->chainstack); 1225 vfree(table->private->chainstack);
1230 } 1226 }
@@ -1247,8 +1243,7 @@ static int update_counters(void __user *user, unsigned int len)
1247 if (hlp.num_counters == 0) 1243 if (hlp.num_counters == 0)
1248 return -EINVAL; 1244 return -EINVAL;
1249 1245
1250 if ( !(tmp = (struct ebt_counter *) 1246 if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
1251 vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){
1252 MEMPRINT("Update_counters && nomemory\n"); 1247 MEMPRINT("Update_counters && nomemory\n");
1253 return -ENOMEM; 1248 return -ENOMEM;
1254 } 1249 }
@@ -1377,8 +1372,7 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1377 BUGPRINT("Num_counters wrong\n"); 1372 BUGPRINT("Num_counters wrong\n");
1378 return -EINVAL; 1373 return -EINVAL;
1379 } 1374 }
1380 counterstmp = (struct ebt_counter *) 1375 counterstmp = vmalloc(nentries * sizeof(*counterstmp));
1381 vmalloc(nentries * sizeof(struct ebt_counter));
1382 if (!counterstmp) { 1376 if (!counterstmp) {
1383 MEMPRINT("Couldn't copy counters, out of memory\n"); 1377 MEMPRINT("Couldn't copy counters, out of memory\n");
1384 return -ENOMEM; 1378 return -ENOMEM;
diff --git a/net/compat.c b/net/compat.c
index 8fd37cd7b501..d5d69fa15d07 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -476,8 +476,7 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
476 int err; 476 int err;
477 struct socket *sock; 477 struct socket *sock;
478 478
479 /* SO_SET_REPLACE seems to be the same in all levels */ 479 if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE)
480 if (optname == IPT_SO_SET_REPLACE)
481 return do_netfilter_replace(fd, level, optname, 480 return do_netfilter_replace(fd, level, optname,
482 optval, optlen); 481 optval, optlen);
483 482
diff --git a/net/core/dev.c b/net/core/dev.c
index 434220d093aa..3bad1afc89fa 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2698,7 +2698,8 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
2698 /* If command is `set a parameter', or 2698 /* If command is `set a parameter', or
2699 * `get the encoding parameters', check if 2699 * `get the encoding parameters', check if
2700 * the user has the right to do it */ 2700 * the user has the right to do it */
2701 if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE) { 2701 if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE
2702 || cmd == SIOCGIWENCODEEXT) {
2702 if (!capable(CAP_NET_ADMIN)) 2703 if (!capable(CAP_NET_ADMIN))
2703 return -EPERM; 2704 return -EPERM;
2704 } 2705 }
@@ -3042,11 +3043,11 @@ void netdev_run_todo(void)
3042 3043
3043 switch(dev->reg_state) { 3044 switch(dev->reg_state) {
3044 case NETREG_REGISTERING: 3045 case NETREG_REGISTERING:
3046 dev->reg_state = NETREG_REGISTERED;
3045 err = netdev_register_sysfs(dev); 3047 err = netdev_register_sysfs(dev);
3046 if (err) 3048 if (err)
3047 printk(KERN_ERR "%s: failed sysfs registration (%d)\n", 3049 printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
3048 dev->name, err); 3050 dev->name, err);
3049 dev->reg_state = NETREG_REGISTERED;
3050 break; 3051 break;
3051 3052
3052 case NETREG_UNREGISTERING: 3053 case NETREG_UNREGISTERING:
@@ -3100,12 +3101,11 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name,
3100 alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; 3101 alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
3101 alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; 3102 alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
3102 3103
3103 p = kmalloc(alloc_size, GFP_KERNEL); 3104 p = kzalloc(alloc_size, GFP_KERNEL);
3104 if (!p) { 3105 if (!p) {
3105 printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); 3106 printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
3106 return NULL; 3107 return NULL;
3107 } 3108 }
3108 memset(p, 0, alloc_size);
3109 3109
3110 dev = (struct net_device *) 3110 dev = (struct net_device *)
3111 (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); 3111 (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
@@ -3347,7 +3347,7 @@ static int __init net_dev_init(void)
3347 * Initialise the packet receive queues. 3347 * Initialise the packet receive queues.
3348 */ 3348 */
3349 3349
3350 for_each_cpu(i) { 3350 for_each_possible_cpu(i) {
3351 struct softnet_data *queue; 3351 struct softnet_data *queue;
3352 3352
3353 queue = &per_cpu(softnet_data, i); 3353 queue = &per_cpu(softnet_data, i);
diff --git a/net/core/dv.c b/net/core/dv.c
index cf581407538c..29ee77f15932 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -55,15 +55,12 @@ int alloc_divert_blk(struct net_device *dev)
55 55
56 dev->divert = NULL; 56 dev->divert = NULL;
57 if (dev->type == ARPHRD_ETHER) { 57 if (dev->type == ARPHRD_ETHER) {
58 dev->divert = (struct divert_blk *) 58 dev->divert = kzalloc(alloc_size, GFP_KERNEL);
59 kmalloc(alloc_size, GFP_KERNEL);
60 if (dev->divert == NULL) { 59 if (dev->divert == NULL) {
61 printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n", 60 printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n",
62 dev->name); 61 dev->name);
63 return -ENOMEM; 62 return -ENOMEM;
64 } 63 }
65
66 memset(dev->divert, 0, sizeof(struct divert_blk));
67 dev_hold(dev); 64 dev_hold(dev);
68 } 65 }
69 66
diff --git a/net/core/filter.c b/net/core/filter.c
index 93fbd01d2259..5b4486a60cf6 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -34,6 +34,7 @@
34#include <linux/timer.h> 34#include <linux/timer.h>
35#include <asm/system.h> 35#include <asm/system.h>
36#include <asm/uaccess.h> 36#include <asm/uaccess.h>
37#include <asm/unaligned.h>
37#include <linux/filter.h> 38#include <linux/filter.h>
38 39
39/* No hurry in this branch */ 40/* No hurry in this branch */
@@ -177,7 +178,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
177load_w: 178load_w:
178 ptr = load_pointer(skb, k, 4, &tmp); 179 ptr = load_pointer(skb, k, 4, &tmp);
179 if (ptr != NULL) { 180 if (ptr != NULL) {
180 A = ntohl(*(u32 *)ptr); 181 A = ntohl(get_unaligned((u32 *)ptr));
181 continue; 182 continue;
182 } 183 }
183 break; 184 break;
@@ -186,7 +187,7 @@ load_w:
186load_h: 187load_h:
187 ptr = load_pointer(skb, k, 2, &tmp); 188 ptr = load_pointer(skb, k, 2, &tmp);
188 if (ptr != NULL) { 189 if (ptr != NULL) {
189 A = ntohs(*(u16 *)ptr); 190 A = ntohs(get_unaligned((u16 *)ptr));
190 continue; 191 continue;
191 } 192 }
192 break; 193 break;
diff --git a/net/core/flow.c b/net/core/flow.c
index 55789f832eda..2191af5f26ac 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -79,7 +79,7 @@ static void flow_cache_new_hashrnd(unsigned long arg)
79{ 79{
80 int i; 80 int i;
81 81
82 for_each_cpu(i) 82 for_each_possible_cpu(i)
83 flow_hash_rnd_recalc(i) = 1; 83 flow_hash_rnd_recalc(i) = 1;
84 84
85 flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; 85 flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
@@ -318,12 +318,10 @@ static void __devinit flow_cache_cpu_prepare(int cpu)
318 /* NOTHING */; 318 /* NOTHING */;
319 319
320 flow_table(cpu) = (struct flow_cache_entry **) 320 flow_table(cpu) = (struct flow_cache_entry **)
321 __get_free_pages(GFP_KERNEL, order); 321 __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
322 if (!flow_table(cpu)) 322 if (!flow_table(cpu))
323 panic("NET: failed to allocate flow cache order %lu\n", order); 323 panic("NET: failed to allocate flow cache order %lu\n", order);
324 324
325 memset(flow_table(cpu), 0, PAGE_SIZE << order);
326
327 flow_hash_rnd_recalc(cpu) = 1; 325 flow_hash_rnd_recalc(cpu) = 1;
328 flow_count(cpu) = 0; 326 flow_count(cpu) = 0;
329 327
@@ -363,7 +361,7 @@ static int __init flow_cache_init(void)
363 flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; 361 flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
364 add_timer(&flow_hash_rnd_timer); 362 add_timer(&flow_hash_rnd_timer);
365 363
366 for_each_cpu(i) 364 for_each_possible_cpu(i)
367 flow_cache_cpu_prepare(i); 365 flow_cache_cpu_prepare(i);
368 366
369 hotcpu_notifier(flow_cache_cpu, 0); 367 hotcpu_notifier(flow_cache_cpu, 0);
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index b07c029e8219..3cad026764f0 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,
159 if (parm->interval < -2 || parm->interval > 3) 159 if (parm->interval < -2 || parm->interval > 3)
160 return -EINVAL; 160 return -EINVAL;
161 161
162 est = kmalloc(sizeof(*est), GFP_KERNEL); 162 est = kzalloc(sizeof(*est), GFP_KERNEL);
163 if (est == NULL) 163 if (est == NULL)
164 return -ENOBUFS; 164 return -ENOBUFS;
165 165
166 memset(est, 0, sizeof(*est));
167 est->interval = parm->interval + 2; 166 est->interval = parm->interval + 2;
168 est->bstats = bstats; 167 est->bstats = bstats;
169 est->rate_est = rate_est; 168 est->rate_est = rate_est;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0c8666872d10..4cf878efdb49 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -284,14 +284,11 @@ static struct neighbour **neigh_hash_alloc(unsigned int entries)
284 struct neighbour **ret; 284 struct neighbour **ret;
285 285
286 if (size <= PAGE_SIZE) { 286 if (size <= PAGE_SIZE) {
287 ret = kmalloc(size, GFP_ATOMIC); 287 ret = kzalloc(size, GFP_ATOMIC);
288 } else { 288 } else {
289 ret = (struct neighbour **) 289 ret = (struct neighbour **)
290 __get_free_pages(GFP_ATOMIC, get_order(size)); 290 __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size));
291 } 291 }
292 if (ret)
293 memset(ret, 0, size);
294
295 return ret; 292 return ret;
296} 293}
297 294
@@ -1089,8 +1086,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
1089 if (hh->hh_type == protocol) 1086 if (hh->hh_type == protocol)
1090 break; 1087 break;
1091 1088
1092 if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { 1089 if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
1093 memset(hh, 0, sizeof(struct hh_cache));
1094 rwlock_init(&hh->hh_lock); 1090 rwlock_init(&hh->hh_lock);
1095 hh->hh_type = protocol; 1091 hh->hh_type = protocol;
1096 atomic_set(&hh->hh_refcnt, 0); 1092 atomic_set(&hh->hh_refcnt, 0);
@@ -1366,13 +1362,11 @@ void neigh_table_init(struct neigh_table *tbl)
1366 tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1); 1362 tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
1367 1363
1368 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); 1364 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
1369 tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL); 1365 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
1370 1366
1371 if (!tbl->hash_buckets || !tbl->phash_buckets) 1367 if (!tbl->hash_buckets || !tbl->phash_buckets)
1372 panic("cannot allocate neighbour cache hashes"); 1368 panic("cannot allocate neighbour cache hashes");
1373 1369
1374 memset(tbl->phash_buckets, 0, phsize);
1375
1376 get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); 1370 get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
1377 1371
1378 rwlock_init(&tbl->lock); 1372 rwlock_init(&tbl->lock);
@@ -1633,7 +1627,7 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
1633 1627
1634 memset(&ndst, 0, sizeof(ndst)); 1628 memset(&ndst, 0, sizeof(ndst));
1635 1629
1636 for_each_cpu(cpu) { 1630 for_each_possible_cpu(cpu) {
1637 struct neigh_statistics *st; 1631 struct neigh_statistics *st;
1638 1632
1639 st = per_cpu_ptr(tbl->stats, cpu); 1633 st = per_cpu_ptr(tbl->stats, cpu);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 21b68464cabb..c12990c9c603 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)
165 operstate = IF_OPER_DOWN; 165 operstate = IF_OPER_DOWN;
166 read_unlock(&dev_base_lock); 166 read_unlock(&dev_base_lock);
167 167
168 if (operstate >= sizeof(operstates)) 168 if (operstate >= ARRAY_SIZE(operstates))
169 return -EINVAL; /* should not happen */ 169 return -EINVAL; /* should not happen */
170 170
171 return sprintf(buf, "%s\n", operstates[operstate]); 171 return sprintf(buf, "%s\n", operstates[operstate]);
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 1e44eda1fda9..79ebd75fbe4d 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,
38{ 38{
39 const int lopt_size = sizeof(struct listen_sock) + 39 const int lopt_size = sizeof(struct listen_sock) +
40 nr_table_entries * sizeof(struct request_sock *); 40 nr_table_entries * sizeof(struct request_sock *);
41 struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL); 41 struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL);
42 42
43 if (lopt == NULL) 43 if (lopt == NULL)
44 return -ENOMEM; 44 return -ENOMEM;
45 45
46 memset(lopt, 0, lopt_size);
47
48 for (lopt->max_qlen_log = 6; 46 for (lopt->max_qlen_log = 6;
49 (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog; 47 (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
50 lopt->max_qlen_log++); 48 lopt->max_qlen_log++);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 09464fa8d72f..fb3770f9c094 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)
112 BUG(); 112 BUG();
113} 113}
114 114
115void skb_truesize_bug(struct sk_buff *skb)
116{
117 printk(KERN_ERR "SKB BUG: Invalid truesize (%u) "
118 "len=%u, sizeof(sk_buff)=%Zd\n",
119 skb->truesize, skb->len, sizeof(struct sk_buff));
120}
121EXPORT_SYMBOL(skb_truesize_bug);
122
115/* Allocate a new skbuff. We do this ourselves so we can fill in a few 123/* Allocate a new skbuff. We do this ourselves so we can fill in a few
116 * 'private' fields and also do memory statistics to find all the 124 * 'private' fields and also do memory statistics to find all the
117 * [BEEP] leaks. 125 * [BEEP] leaks.
diff --git a/net/core/stream.c b/net/core/stream.c
index 35e25259fd95..e9489696f694 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -176,6 +176,7 @@ void sk_stream_rfree(struct sk_buff *skb)
176{ 176{
177 struct sock *sk = skb->sk; 177 struct sock *sk = skb->sk;
178 178
179 skb_truesize_check(skb);
179 atomic_sub(skb->truesize, &sk->sk_rmem_alloc); 180 atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
180 sk->sk_forward_alloc += skb->truesize; 181 sk->sk_forward_alloc += skb->truesize;
181} 182}
diff --git a/net/core/utils.c b/net/core/utils.c
index fdc4f38bc46c..4f96f389243d 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -121,7 +121,7 @@ void __init net_random_init(void)
121{ 121{
122 int i; 122 int i;
123 123
124 for_each_cpu(i) { 124 for_each_possible_cpu(i) {
125 struct nrnd_state *state = &per_cpu(net_rand_state,i); 125 struct nrnd_state *state = &per_cpu(net_rand_state,i);
126 __net_srandom(state, i+jiffies); 126 __net_srandom(state, i+jiffies);
127 } 127 }
@@ -133,7 +133,7 @@ static int net_random_reseed(void)
133 unsigned long seed[NR_CPUS]; 133 unsigned long seed[NR_CPUS];
134 134
135 get_random_bytes(seed, sizeof(seed)); 135 get_random_bytes(seed, sizeof(seed));
136 for_each_cpu(i) { 136 for_each_possible_cpu(i) {
137 struct nrnd_state *state = &per_cpu(net_rand_state,i); 137 struct nrnd_state *state = &per_cpu(net_rand_state,i);
138 __net_srandom(state, seed[i]); 138 __net_srandom(state, seed[i]);
139 } 139 }
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 81d6995fcfdb..d2bc72d318f7 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -1726,6 +1726,14 @@ int wireless_rtnetlink_get(struct net_device * dev,
1726 if(!IW_IS_GET(request->cmd)) 1726 if(!IW_IS_GET(request->cmd))
1727 return -EOPNOTSUPP; 1727 return -EOPNOTSUPP;
1728 1728
1729 /* If command is `get the encoding parameters', check if
1730 * the user has the right to do it */
1731 if (request->cmd == SIOCGIWENCODE ||
1732 request->cmd == SIOCGIWENCODEEXT) {
1733 if (!capable(CAP_NET_ADMIN))
1734 return -EPERM;
1735 }
1736
1729 /* Special cases */ 1737 /* Special cases */
1730 if(request->cmd == SIOCGIWSTATS) 1738 if(request->cmd == SIOCGIWSTATS)
1731 /* Get Wireless Stats */ 1739 /* Get Wireless Stats */
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 29047995c695..f2c011fd2ba1 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)
498 goto drop; 498 goto drop;
499 499
500 if (dccp_parse_options(sk, skb)) 500 if (dccp_parse_options(sk, skb))
501 goto drop; 501 goto drop_and_free;
502 502
503 dccp_openreq_init(req, &dp, skb); 503 dccp_openreq_init(req, &dp, skb);
504 504
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index 6cd9f3427be6..f2a27cc6ecb1 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -1,6 +1,7 @@
1config IEEE80211_SOFTMAC 1config IEEE80211_SOFTMAC
2 tristate "Software MAC add-on to the IEEE 802.11 networking stack" 2 tristate "Software MAC add-on to the IEEE 802.11 networking stack"
3 depends on IEEE80211 && EXPERIMENTAL 3 depends on IEEE80211 && EXPERIMENTAL
4 select WIRELESS_EXT
4 ---help--- 5 ---help---
5 This option enables the hardware independent software MAC addon 6 This option enables the hardware independent software MAC addon
6 for the IEEE 802.11 networking stack. 7 for the IEEE 802.11 networking stack.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index be61de78dfa4..fb79ce7d6439 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)
101 /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */ 101 /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
102 mac->associated = 0; 102 mac->associated = 0;
103 mac->associnfo.associating = 0; 103 mac->associnfo.associating = 0;
104 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
104 spin_unlock_irqrestore(&mac->lock, flags); 105 spin_unlock_irqrestore(&mac->lock, flags);
105} 106}
106 107
@@ -143,6 +144,12 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
143 if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) 144 if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
144 return 0; 145 return 0;
145 146
147 /* assume that users know what they're doing ...
148 * (note we don't let them select a net we're incompatible with) */
149 if (mac->associnfo.bssfixed) {
150 return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN);
151 }
152
146 /* if 'ANY' network requested, take any that doesn't have privacy enabled */ 153 /* if 'ANY' network requested, take any that doesn't have privacy enabled */
147 if (mac->associnfo.req_essid.len == 0 154 if (mac->associnfo.req_essid.len == 0
148 && !(net->capability & WLAN_CAPABILITY_PRIVACY)) 155 && !(net->capability & WLAN_CAPABILITY_PRIVACY))
@@ -175,7 +182,7 @@ ieee80211softmac_assoc_work(void *d)
175 ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); 182 ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
176 183
177 /* try to find the requested network in our list, if we found one already */ 184 /* try to find the requested network in our list, if we found one already */
178 if (mac->associnfo.bssvalid) 185 if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
179 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); 186 found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
180 187
181 /* Search the ieee80211 networks for this network if we didn't find it by bssid, 188 /* Search the ieee80211 networks for this network if we didn't find it by bssid,
@@ -240,19 +247,25 @@ ieee80211softmac_assoc_work(void *d)
240 if (ieee80211softmac_start_scan(mac)) 247 if (ieee80211softmac_start_scan(mac))
241 dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); 248 dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
242 return; 249 return;
243 } 250 } else {
244 else {
245 spin_lock_irqsave(&mac->lock, flags); 251 spin_lock_irqsave(&mac->lock, flags);
246 mac->associnfo.associating = 0; 252 mac->associnfo.associating = 0;
247 mac->associated = 0; 253 mac->associated = 0;
248 spin_unlock_irqrestore(&mac->lock, flags); 254 spin_unlock_irqrestore(&mac->lock, flags);
249 255
250 dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); 256 dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
257 /* reset the retry counter for the next user request since we
258 * break out and don't reschedule ourselves after this point. */
259 mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
251 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); 260 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
252 return; 261 return;
253 } 262 }
254 } 263 }
255 264
265 /* reset the retry counter for the next user request since we
266 * now found a net and will try to associate to it, but not
267 * schedule this function again. */
268 mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
256 mac->associnfo.bssvalid = 1; 269 mac->associnfo.bssvalid = 1;
257 memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); 270 memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
258 /* copy the ESSID for displaying it */ 271 /* copy the ESSID for displaying it */
@@ -373,6 +386,7 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
373 spin_lock_irqsave(&mac->lock, flags); 386 spin_lock_irqsave(&mac->lock, flags);
374 mac->associnfo.bssvalid = 0; 387 mac->associnfo.bssvalid = 0;
375 mac->associated = 0; 388 mac->associated = 0;
389 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
376 schedule_work(&mac->associnfo.work); 390 schedule_work(&mac->associnfo.work);
377 spin_unlock_irqrestore(&mac->lock, flags); 391 spin_unlock_irqrestore(&mac->lock, flags);
378 392
@@ -391,6 +405,7 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
391 dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); 405 dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
392 return 0; 406 return 0;
393 } 407 }
394 ieee80211softmac_assoc(mac, network); 408 schedule_work(&mac->associnfo.work);
409
395 return 0; 410 return 0;
396} 411}
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 0a52bbda1e4c..8cc8f3f0f8e7 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] = {
67 "authenticating failed", 67 "authenticating failed",
68 "authenticating timed out", 68 "authenticating timed out",
69 "associating failed because no suitable network was found", 69 "associating failed because no suitable network was found",
70 "disassociated",
70}; 71};
71 72
72 73
@@ -128,13 +129,42 @@ void
128ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx) 129ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
129{ 130{
130 struct ieee80211softmac_event *eventptr, *tmp; 131 struct ieee80211softmac_event *eventptr, *tmp;
131 union iwreq_data wrqu; 132 struct ieee80211softmac_network *network;
132 char *msg;
133 133
134 if (event >= 0) { 134 if (event >= 0) {
135 msg = event_descriptions[event]; 135 union iwreq_data wrqu;
136 wrqu.data.length = strlen(msg); 136 int we_event;
137 wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg); 137 char *msg = NULL;
138
139 switch(event) {
140 case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
141 network = (struct ieee80211softmac_network *)event_ctx;
142 wrqu.data.length = 0;
143 wrqu.data.flags = 0;
144 memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
145 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
146 we_event = SIOCGIWAP;
147 break;
148 case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
149 wrqu.data.length = 0;
150 wrqu.data.flags = 0;
151 memset(&wrqu, '\0', sizeof (union iwreq_data));
152 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
153 we_event = SIOCGIWAP;
154 break;
155 case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
156 wrqu.data.length = 0;
157 wrqu.data.flags = 0;
158 memset(&wrqu, '\0', sizeof (union iwreq_data));
159 we_event = SIOCGIWSCAN;
160 break;
161 default:
162 msg = event_descriptions[event];
163 wrqu.data.length = strlen(msg);
164 we_event = IWEVCUSTOM;
165 break;
166 }
167 wireless_send_event(mac->dev, we_event, &wrqu, msg);
138 } 168 }
139 169
140 if (!list_empty(&mac->events)) 170 if (!list_empty(&mac->events))
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index febc51dbb412..cc6cd56c85b1 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,
180 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); 180 ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
181 181
182 /* Fill in capability Info */ 182 /* Fill in capability Info */
183 (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ? 183 switch (mac->ieee->iw_mode) {
184 cpu_to_le16(WLAN_CAPABILITY_ESS) : 184 case IW_MODE_INFRA:
185 cpu_to_le16(WLAN_CAPABILITY_IBSS); 185 (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
186 break;
187 case IW_MODE_ADHOC:
188 (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
189 break;
190 case IW_MODE_AUTO:
191 (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
192 break;
193 default:
194 /* bleh. we don't ever go to these modes */
195 printk(KERN_ERR PFX "invalid iw_mode!\n");
196 break;
197 }
186 /* Need to add this 198 /* Need to add this
187 (*pkt)->capability |= mac->ieee->short_slot ? 199 (*pkt)->capability |= mac->ieee->short_slot ?
188 cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; 200 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 60f06a31f0d1..be83bdc1644a 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)
45 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; 45 softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
46 softmac->scaninfo = NULL; 46 softmac->scaninfo = NULL;
47 47
48 softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
49
48 /* TODO: initialise all the other callbacks in the ieee struct 50 /* TODO: initialise all the other callbacks in the ieee struct
49 * (once they're written) 51 * (once they're written)
50 */ 52 */
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index bb9ab8b45d09..2b9e7edfa3ce 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)
47 sm->scanning = 1; 47 sm->scanning = 1;
48 spin_unlock_irqrestore(&sm->lock, flags); 48 spin_unlock_irqrestore(&sm->lock, flags);
49 49
50 netif_tx_disable(sm->ieee->dev);
50 ret = sm->start_scan(sm->dev); 51 ret = sm->start_scan(sm->dev);
51 if (ret) { 52 if (ret) {
52 spin_lock_irqsave(&sm->lock, flags); 53 spin_lock_irqsave(&sm->lock, flags);
@@ -239,6 +240,7 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
239 if (net) 240 if (net)
240 sm->set_channel(sm->dev, net->channel); 241 sm->set_channel(sm->dev, net->channel);
241 } 242 }
243 netif_wake_queue(sm->ieee->dev);
242 ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); 244 ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
243} 245}
244EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); 246EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index b559aa9b5507..27edb2b5581a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -27,7 +27,8 @@
27#include "ieee80211softmac_priv.h" 27#include "ieee80211softmac_priv.h"
28 28
29#include <net/iw_handler.h> 29#include <net/iw_handler.h>
30 30/* for is_broadcast_ether_addr and is_zero_ether_addr */
31#include <linux/etherdevice.h>
31 32
32int 33int
33ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, 34ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
@@ -41,13 +42,23 @@ ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
41EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan); 42EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
42 43
43 44
45/* if we're still scanning, return -EAGAIN so that userspace tools
46 * can get the complete scan results, otherwise return 0. */
44int 47int
45ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, 48ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
46 struct iw_request_info *info, 49 struct iw_request_info *info,
47 union iwreq_data *data, 50 union iwreq_data *data,
48 char *extra) 51 char *extra)
49{ 52{
53 unsigned long flags;
50 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); 54 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
55
56 spin_lock_irqsave(&sm->lock, flags);
57 if (sm->scanning) {
58 spin_unlock_irqrestore(&sm->lock, flags);
59 return -EAGAIN;
60 }
61 spin_unlock_irqrestore(&sm->lock, flags);
51 return ieee80211_wx_get_scan(sm->ieee, info, data, extra); 62 return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
52} 63}
53EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results); 64EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
@@ -73,7 +84,6 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
73 sm->associnfo.static_essid = 1; 84 sm->associnfo.static_essid = 1;
74 } 85 }
75 } 86 }
76 sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
77 87
78 /* set our requested ESSID length. 88 /* set our requested ESSID length.
79 * If applicable, we have already copied the data in */ 89 * If applicable, we have already copied the data in */
@@ -300,8 +310,6 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
300 char *extra) 310 char *extra)
301{ 311{
302 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); 312 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
303 static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
304 static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
305 unsigned long flags; 313 unsigned long flags;
306 314
307 /* sanity check */ 315 /* sanity check */
@@ -310,10 +318,17 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
310 } 318 }
311 319
312 spin_lock_irqsave(&mac->lock, flags); 320 spin_lock_irqsave(&mac->lock, flags);
313 if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || 321 if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
314 !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { 322 /* the bssid we have is not to be fixed any longer,
315 schedule_work(&mac->associnfo.work); 323 * and we should reassociate to the best AP. */
316 goto out; 324 mac->associnfo.bssfixed = 0;
325 /* force reassociation */
326 mac->associnfo.bssvalid = 0;
327 if (mac->associated)
328 schedule_work(&mac->associnfo.work);
329 } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
330 /* the bssid we have is no longer fixed */
331 mac->associnfo.bssfixed = 0;
317 } else { 332 } else {
318 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { 333 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
319 if (mac->associnfo.associating || mac->associated) { 334 if (mac->associnfo.associating || mac->associated) {
@@ -323,12 +338,14 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev,
323 } else { 338 } else {
324 /* copy new value in data->ap_addr.sa_data to bssid */ 339 /* copy new value in data->ap_addr.sa_data to bssid */
325 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); 340 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
326 } 341 }
342 /* tell the other code that this bssid should be used no matter what */
343 mac->associnfo.bssfixed = 1;
327 /* queue associate if new bssid or (old one again and not associated) */ 344 /* queue associate if new bssid or (old one again and not associated) */
328 schedule_work(&mac->associnfo.work); 345 schedule_work(&mac->associnfo.work);
329 } 346 }
330 347
331out: 348 out:
332 spin_unlock_irqrestore(&mac->lock, flags); 349 spin_unlock_irqrestore(&mac->lock, flags);
333 return 0; 350 return 0;
334} 351}
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index e16d8b42b953..e2e4771fa4c6 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -116,7 +116,7 @@ error:
116 return err; 116 return err;
117} 117}
118 118
119static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 119static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
120{ 120{
121 int ah_hlen; 121 int ah_hlen;
122 struct iphdr *iph; 122 struct iphdr *iph;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 041dadde31af..4749d504c629 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -928,7 +928,8 @@ static void parp_redo(struct sk_buff *skb)
928 * Receive an arp request from the device layer. 928 * Receive an arp request from the device layer.
929 */ 929 */
930 930
931int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) 931static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
932 struct packet_type *pt, struct net_device *orig_dev)
932{ 933{
933 struct arphdr *arp; 934 struct arphdr *arp;
934 935
@@ -1417,7 +1418,6 @@ static int __init arp_proc_init(void)
1417 1418
1418EXPORT_SYMBOL(arp_broken_ops); 1419EXPORT_SYMBOL(arp_broken_ops);
1419EXPORT_SYMBOL(arp_find); 1420EXPORT_SYMBOL(arp_find);
1420EXPORT_SYMBOL(arp_rcv);
1421EXPORT_SYMBOL(arp_create); 1421EXPORT_SYMBOL(arp_create);
1422EXPORT_SYMBOL(arp_xmit); 1422EXPORT_SYMBOL(arp_xmit);
1423EXPORT_SYMBOL(arp_send); 1423EXPORT_SYMBOL(arp_send);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 81c2f7885292..54419b27686f 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1556,7 +1556,6 @@ void __init devinet_init(void)
1556#endif 1556#endif
1557} 1557}
1558 1558
1559EXPORT_SYMBOL(devinet_ioctl);
1560EXPORT_SYMBOL(in_dev_finish_destroy); 1559EXPORT_SYMBOL(in_dev_finish_destroy);
1561EXPORT_SYMBOL(inet_select_addr); 1560EXPORT_SYMBOL(inet_select_addr);
1562EXPORT_SYMBOL(inetdev_by_index); 1561EXPORT_SYMBOL(inetdev_by_index);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index bf88c620a954..9d1881c07a32 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -133,7 +133,7 @@ error:
133 * expensive, so we only support truncated data, which is the recommended 133 * expensive, so we only support truncated data, which is the recommended
134 * and common case. 134 * and common case.
135 */ 135 */
136static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 136static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
137{ 137{
138 struct iphdr *iph; 138 struct iphdr *iph;
139 struct ip_esp_hdr *esph; 139 struct ip_esp_hdr *esph;
@@ -208,9 +208,6 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
208 struct xfrm_encap_tmpl *encap = x->encap; 208 struct xfrm_encap_tmpl *encap = x->encap;
209 struct udphdr *uh; 209 struct udphdr *uh;
210 210
211 if (encap->encap_type != decap->decap_type)
212 goto out;
213
214 uh = (struct udphdr *)(iph + 1); 211 uh = (struct udphdr *)(iph + 1);
215 encap_len = (void*)esph - (void*)uh; 212 encap_len = (void*)esph - (void*)uh;
216 213
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 4e3d3811dea2..cdde96390960 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -666,4 +666,3 @@ void __init ip_fib_init(void)
666} 666}
667 667
668EXPORT_SYMBOL(inet_addr_type); 668EXPORT_SYMBOL(inet_addr_type);
669EXPORT_SYMBOL(ip_rt_ioctl);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index ccd3efc6a173..95a639f2e3db 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -50,7 +50,7 @@
50 * Patrick McHardy <kaber@trash.net> 50 * Patrick McHardy <kaber@trash.net>
51 */ 51 */
52 52
53#define VERSION "0.406" 53#define VERSION "0.407"
54 54
55#include <linux/config.h> 55#include <linux/config.h>
56#include <asm/uaccess.h> 56#include <asm/uaccess.h>
@@ -314,11 +314,6 @@ static void __leaf_free_rcu(struct rcu_head *head)
314 kfree(container_of(head, struct leaf, rcu)); 314 kfree(container_of(head, struct leaf, rcu));
315} 315}
316 316
317static inline void free_leaf(struct leaf *leaf)
318{
319 call_rcu(&leaf->rcu, __leaf_free_rcu);
320}
321
322static void __leaf_info_free_rcu(struct rcu_head *head) 317static void __leaf_info_free_rcu(struct rcu_head *head)
323{ 318{
324 kfree(container_of(head, struct leaf_info, rcu)); 319 kfree(container_of(head, struct leaf_info, rcu));
@@ -357,7 +352,12 @@ static void __tnode_free_rcu(struct rcu_head *head)
357 352
358static inline void tnode_free(struct tnode *tn) 353static inline void tnode_free(struct tnode *tn)
359{ 354{
360 call_rcu(&tn->rcu, __tnode_free_rcu); 355 if(IS_LEAF(tn)) {
356 struct leaf *l = (struct leaf *) tn;
357 call_rcu_bh(&l->rcu, __leaf_free_rcu);
358 }
359 else
360 call_rcu(&tn->rcu, __tnode_free_rcu);
361} 361}
362 362
363static struct leaf *leaf_new(void) 363static struct leaf *leaf_new(void)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 9831fd2c73a0..2a0455911ee0 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1107,7 +1107,7 @@ void __init icmp_init(struct net_proto_family *ops)
1107 struct inet_sock *inet; 1107 struct inet_sock *inet;
1108 int i; 1108 int i;
1109 1109
1110 for_each_cpu(i) { 1110 for_each_possible_cpu(i) {
1111 int err; 1111 int err;
1112 1112
1113 err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, 1113 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 ef7366fc132f..ee9b5515b9ae 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,
43 return tb; 43 return tb;
44} 44}
45 45
46EXPORT_SYMBOL(inet_bind_bucket_create);
47
48/* 46/*
49 * Caller must hold hashbucket lock for this tb with local BH disabled 47 * Caller must hold hashbucket lock for this tb with local BH disabled
50 */ 48 */
@@ -64,8 +62,6 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
64 inet_csk(sk)->icsk_bind_hash = tb; 62 inet_csk(sk)->icsk_bind_hash = tb;
65} 63}
66 64
67EXPORT_SYMBOL(inet_bind_hash);
68
69/* 65/*
70 * Get rid of any references to a local port held by the given sock. 66 * Get rid of any references to a local port held by the given sock.
71 */ 67 */
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 2a8adda15e11..da734c439179 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -304,13 +304,17 @@ out:
304 304
305/* Creation primitives. */ 305/* Creation primitives. */
306 306
307static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) 307static struct ipq *ip_frag_intern(struct ipq *qp_in)
308{ 308{
309 struct ipq *qp; 309 struct ipq *qp;
310#ifdef CONFIG_SMP 310#ifdef CONFIG_SMP
311 struct hlist_node *n; 311 struct hlist_node *n;
312#endif 312#endif
313 unsigned int hash;
314
313 write_lock(&ipfrag_lock); 315 write_lock(&ipfrag_lock);
316 hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
317 qp_in->protocol);
314#ifdef CONFIG_SMP 318#ifdef CONFIG_SMP
315 /* With SMP race we have to recheck hash table, because 319 /* With SMP race we have to recheck hash table, because
316 * such entry could be created on other cpu, while we 320 * 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)
345} 349}
346 350
347/* Add an entry to the 'ipq' queue for a newly received IP datagram. */ 351/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
348static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) 352static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
349{ 353{
350 struct ipq *qp; 354 struct ipq *qp;
351 355
@@ -371,7 +375,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
371 spin_lock_init(&qp->lock); 375 spin_lock_init(&qp->lock);
372 atomic_set(&qp->refcnt, 1); 376 atomic_set(&qp->refcnt, 1);
373 377
374 return ip_frag_intern(hash, qp); 378 return ip_frag_intern(qp);
375 379
376out_nomem: 380out_nomem:
377 LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n"); 381 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)
387 __u32 saddr = iph->saddr; 391 __u32 saddr = iph->saddr;
388 __u32 daddr = iph->daddr; 392 __u32 daddr = iph->daddr;
389 __u8 protocol = iph->protocol; 393 __u8 protocol = iph->protocol;
390 unsigned int hash = ipqhashfn(id, saddr, daddr, protocol); 394 unsigned int hash;
391 struct ipq *qp; 395 struct ipq *qp;
392 struct hlist_node *n; 396 struct hlist_node *n;
393 397
394 read_lock(&ipfrag_lock); 398 read_lock(&ipfrag_lock);
399 hash = ipqhashfn(id, saddr, daddr, protocol);
395 hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { 400 hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
396 if(qp->id == id && 401 if(qp->id == id &&
397 qp->saddr == saddr && 402 qp->saddr == saddr &&
@@ -405,7 +410,7 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
405 } 410 }
406 read_unlock(&ipfrag_lock); 411 read_unlock(&ipfrag_lock);
407 412
408 return ip_frag_create(hash, iph, user); 413 return ip_frag_create(iph, user);
409} 414}
410 415
411/* Is the fragment too far ahead to be part of ipq? */ 416/* 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 9981dcd68f11..ab99bebdcdc8 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)
656 read_unlock(&ipgre_lock); 656 read_unlock(&ipgre_lock);
657 return(0); 657 return(0);
658 } 658 }
659 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); 659 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
660 660
661drop: 661drop:
662 read_unlock(&ipgre_lock); 662 read_unlock(&ipgre_lock);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index f75ff1d96551..cff9c3a72daf 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -86,8 +86,6 @@
86 86
87int sysctl_ip_default_ttl = IPDEFTTL; 87int sysctl_ip_default_ttl = IPDEFTTL;
88 88
89static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
90
91/* Generate a checksum for an outgoing IP datagram. */ 89/* Generate a checksum for an outgoing IP datagram. */
92__inline__ void ip_send_check(struct iphdr *iph) 90__inline__ void ip_send_check(struct iphdr *iph)
93{ 91{
@@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
421 * single device frame, and queue such a frame for sending. 419 * single device frame, and queue such a frame for sending.
422 */ 420 */
423 421
424static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) 422int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
425{ 423{
426 struct iphdr *iph; 424 struct iphdr *iph;
427 int raw = 0; 425 int raw = 0;
@@ -673,6 +671,8 @@ fail:
673 return err; 671 return err;
674} 672}
675 673
674EXPORT_SYMBOL(ip_fragment);
675
676int 676int
677ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) 677ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
678{ 678{
@@ -904,7 +904,7 @@ alloc_new_skb:
904 * because we have no idea what fragment will be 904 * because we have no idea what fragment will be
905 * the last. 905 * the last.
906 */ 906 */
907 if (datalen == length) 907 if (datalen == length + fraggap)
908 alloclen += rt->u.dst.trailer_len; 908 alloclen += rt->u.dst.trailer_len;
909 909
910 if (transhdrlen) { 910 if (transhdrlen) {
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index c95020f7c81e..cd810f41af1a 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -81,8 +81,7 @@ out:
81 return err; 81 return err;
82} 82}
83 83
84static int ipcomp_input(struct xfrm_state *x, 84static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
85 struct xfrm_decap_state *decap, struct sk_buff *skb)
86{ 85{
87 u8 nexthdr; 86 u8 nexthdr;
88 int err = 0; 87 int err = 0;
@@ -291,11 +290,8 @@ static void ipcomp_free_scratches(void)
291 if (!scratches) 290 if (!scratches)
292 return; 291 return;
293 292
294 for_each_cpu(i) { 293 for_each_possible_cpu(i)
295 void *scratch = *per_cpu_ptr(scratches, i); 294 vfree(*per_cpu_ptr(scratches, i));
296 if (scratch)
297 vfree(scratch);
298 }
299 295
300 free_percpu(scratches); 296 free_percpu(scratches);
301} 297}
@@ -314,7 +310,7 @@ static void **ipcomp_alloc_scratches(void)
314 310
315 ipcomp_scratches = scratches; 311 ipcomp_scratches = scratches;
316 312
317 for_each_cpu(i) { 313 for_each_possible_cpu(i) {
318 void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE); 314 void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
319 if (!scratch) 315 if (!scratch)
320 return NULL; 316 return NULL;
@@ -345,7 +341,7 @@ static void ipcomp_free_tfms(struct crypto_tfm **tfms)
345 if (!tfms) 341 if (!tfms)
346 return; 342 return;
347 343
348 for_each_cpu(cpu) { 344 for_each_possible_cpu(cpu) {
349 struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu); 345 struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
350 crypto_free_tfm(tfm); 346 crypto_free_tfm(tfm);
351 } 347 }
@@ -385,7 +381,7 @@ static struct crypto_tfm **ipcomp_alloc_tfms(const char *alg_name)
385 if (!tfms) 381 if (!tfms)
386 goto error; 382 goto error;
387 383
388 for_each_cpu(cpu) { 384 for_each_possible_cpu(cpu) {
389 struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0); 385 struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
390 if (!tfm) 386 if (!tfm)
391 goto error; 387 goto error;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index eef07b0916a3..ea398ee43f28 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -474,9 +474,6 @@ static int ipip_rcv(struct sk_buff *skb)
474 struct iphdr *iph; 474 struct iphdr *iph;
475 struct ip_tunnel *tunnel; 475 struct ip_tunnel *tunnel;
476 476
477 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
478 goto out;
479
480 iph = skb->nh.iph; 477 iph = skb->nh.iph;
481 478
482 read_lock(&ipip_lock); 479 read_lock(&ipip_lock);
@@ -508,7 +505,6 @@ static int ipip_rcv(struct sk_buff *skb)
508 } 505 }
509 read_unlock(&ipip_lock); 506 read_unlock(&ipip_lock);
510 507
511out:
512 return -1; 508 return -1;
513} 509}
514 510
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b5ad9ac2fbcc..6a9e34b794bc 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -133,7 +133,7 @@ struct ip_rt_info {
133 u_int8_t tos; 133 u_int8_t tos;
134}; 134};
135 135
136static void queue_save(const struct sk_buff *skb, struct nf_info *info) 136static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
137{ 137{
138 struct ip_rt_info *rt_info = nf_info_reroute(info); 138 struct ip_rt_info *rt_info = nf_info_reroute(info);
139 139
@@ -146,7 +146,7 @@ static void queue_save(const struct sk_buff *skb, struct nf_info *info)
146 } 146 }
147} 147}
148 148
149static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) 149static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
150{ 150{
151 const struct ip_rt_info *rt_info = nf_info_reroute(info); 151 const struct ip_rt_info *rt_info = nf_info_reroute(info);
152 152
@@ -161,20 +161,54 @@ static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
161 return 0; 161 return 0;
162} 162}
163 163
164static struct nf_queue_rerouter ip_reroute = { 164unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
165 .rer_size = sizeof(struct ip_rt_info), 165 unsigned int dataoff, u_int8_t protocol)
166 .save = queue_save, 166{
167 .reroute = queue_reroute, 167 struct iphdr *iph = skb->nh.iph;
168 unsigned int csum = 0;
169
170 switch (skb->ip_summed) {
171 case CHECKSUM_HW:
172 if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
173 break;
174 if ((protocol == 0 && !(u16)csum_fold(skb->csum)) ||
175 !csum_tcpudp_magic(iph->saddr, iph->daddr,
176 skb->len - dataoff, protocol,
177 skb->csum)) {
178 skb->ip_summed = CHECKSUM_UNNECESSARY;
179 break;
180 }
181 /* fall through */
182 case CHECKSUM_NONE:
183 if (protocol == 0)
184 skb->csum = 0;
185 else
186 skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
187 skb->len - dataoff,
188 protocol, 0);
189 csum = __skb_checksum_complete(skb);
190 }
191 return csum;
192}
193
194EXPORT_SYMBOL(nf_ip_checksum);
195
196static struct nf_afinfo nf_ip_afinfo = {
197 .family = AF_INET,
198 .checksum = nf_ip_checksum,
199 .saveroute = nf_ip_saveroute,
200 .reroute = nf_ip_reroute,
201 .route_key_size = sizeof(struct ip_rt_info),
168}; 202};
169 203
170static int ipv4_netfilter_init(void) 204static int ipv4_netfilter_init(void)
171{ 205{
172 return nf_register_queue_rerouter(PF_INET, &ip_reroute); 206 return nf_register_afinfo(&nf_ip_afinfo);
173} 207}
174 208
175static void ipv4_netfilter_fini(void) 209static void ipv4_netfilter_fini(void)
176{ 210{
177 nf_unregister_queue_rerouter(PF_INET); 211 nf_unregister_afinfo(&nf_ip_afinfo);
178} 212}
179 213
180module_init(ipv4_netfilter_init); 214module_init(ipv4_netfilter_init);
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 882b842c25d4..3d560dec63ab 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -69,6 +69,7 @@ config IP_NF_CONNTRACK_NETLINK
69 tristate 'Connection tracking netlink interface (EXPERIMENTAL)' 69 tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
70 depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK 70 depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK
71 depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m 71 depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
72 depends on IP_NF_NAT=n || IP_NF_NAT
72 help 73 help
73 This option enables support for a netlink-based userspace interface 74 This option enables support for a netlink-based userspace interface
74 75
@@ -221,16 +222,6 @@ config IP_NF_MATCH_IPRANGE
221 222
222 To compile it as a module, choose M here. If unsure, say N. 223 To compile it as a module, choose M here. If unsure, say N.
223 224
224config IP_NF_MATCH_MULTIPORT
225 tristate "Multiple port match support"
226 depends on IP_NF_IPTABLES
227 help
228 Multiport matching allows you to match TCP or UDP packets based on
229 a series of source or destination ports: normally a rule can only
230 match a single range of ports.
231
232 To compile it as a module, choose M here. If unsure, say N.
233
234config IP_NF_MATCH_TOS 225config IP_NF_MATCH_TOS
235 tristate "TOS match support" 226 tristate "TOS match support"
236 depends on IP_NF_IPTABLES 227 depends on IP_NF_IPTABLES
@@ -272,12 +263,12 @@ config IP_NF_MATCH_DSCP
272 263
273 To compile it as a module, choose M here. If unsure, say N. 264 To compile it as a module, choose M here. If unsure, say N.
274 265
275config IP_NF_MATCH_AH_ESP 266config IP_NF_MATCH_AH
276 tristate "AH/ESP match support" 267 tristate "AH match support"
277 depends on IP_NF_IPTABLES 268 depends on IP_NF_IPTABLES
278 help 269 help
279 These two match extensions (`ah' and `esp') allow you to match a 270 This match extension allows you to match a range of SPIs
280 range of SPIs inside AH or ESP headers of IPSec packets. 271 inside AH header of IPSec packets.
281 272
282 To compile it as a module, choose M here. If unsure, say N. 273 To compile it as a module, choose M here. If unsure, say N.
283 274
@@ -354,7 +345,7 @@ config IP_NF_TARGET_LOG
354 To compile it as a module, choose M here. If unsure, say N. 345 To compile it as a module, choose M here. If unsure, say N.
355 346
356config IP_NF_TARGET_ULOG 347config IP_NF_TARGET_ULOG
357 tristate "ULOG target support (OBSOLETE)" 348 tristate "ULOG target support"
358 depends on IP_NF_IPTABLES 349 depends on IP_NF_IPTABLES
359 ---help--- 350 ---help---
360 351
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index f2cd9a6c5b91..461cb1eb5de7 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -53,13 +53,12 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
53# matches 53# matches
54obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o 54obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
55obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o 55obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
56obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
57obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o 56obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
58obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o 57obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
59obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o 58obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
60obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o 59obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
61obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o 60obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
62obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o 61obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
63obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o 62obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
64obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o 63obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
65 64
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index a44a5d73457d..c2d92f99a2b8 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,
646 } 646 }
647 647
648 /* And one copy for every other CPU */ 648 /* And one copy for every other CPU */
649 for_each_cpu(i) { 649 for_each_possible_cpu(i) {
650 if (newinfo->entries[i] && newinfo->entries[i] != entry0) 650 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
651 memcpy(newinfo->entries[i], entry0, newinfo->size); 651 memcpy(newinfo->entries[i], entry0, newinfo->size);
652 } 652 }
@@ -696,7 +696,7 @@ static void get_counters(const struct xt_table_info *t,
696 counters, 696 counters,
697 &i); 697 &i);
698 698
699 for_each_cpu(cpu) { 699 for_each_possible_cpu(cpu) {
700 if (cpu == curcpu) 700 if (cpu == curcpu)
701 continue; 701 continue;
702 i = 0; 702 i = 0;
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index d0d379c7df9a..d7c472faa53b 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[] = {
181 181
182static int __init arptable_filter_init(void) 182static int __init arptable_filter_init(void)
183{ 183{
184 int ret, i; 184 int ret;
185 185
186 /* Register table */ 186 /* Register table */
187 ret = arpt_register_table(&packet_filter, &initial_table.repl); 187 ret = arpt_register_table(&packet_filter, &initial_table.repl);
188 if (ret < 0) 188 if (ret < 0)
189 return ret; 189 return ret;
190 190
191 for (i = 0; i < ARRAY_SIZE(arpt_ops); i++) 191 ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
192 if ((ret = nf_register_hook(&arpt_ops[i])) < 0) 192 if (ret < 0)
193 goto cleanup_hooks; 193 goto cleanup_table;
194 return ret; 194 return ret;
195 195
196cleanup_hooks: 196cleanup_table:
197 while (--i >= 0)
198 nf_unregister_hook(&arpt_ops[i]);
199
200 arpt_unregister_table(&packet_filter); 197 arpt_unregister_table(&packet_filter);
201 return ret; 198 return ret;
202} 199}
203 200
204static void __exit arptable_filter_fini(void) 201static void __exit arptable_filter_fini(void)
205{ 202{
206 unsigned int i; 203 nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
207
208 for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
209 nf_unregister_hook(&arpt_ops[i]);
210
211 arpt_unregister_table(&packet_filter); 204 arpt_unregister_table(&packet_filter);
212} 205}
213 206
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index ceaabc18202b..979a2eac6f00 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)
133 struct ip_conntrack_ecache *ecache; 133 struct ip_conntrack_ecache *ecache;
134 int cpu; 134 int cpu;
135 135
136 for_each_cpu(cpu) { 136 for_each_possible_cpu(cpu) {
137 ecache = &per_cpu(ip_conntrack_ecache, cpu); 137 ecache = &per_cpu(ip_conntrack_ecache, cpu);
138 if (ecache->ct) 138 if (ecache->ct)
139 ip_conntrack_put(ecache->ct); 139 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 daeb1395faa4..2c2fb700d835 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -9,37 +9,6 @@
9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10 * 10 *
11 * For more information, please see http://nath323.sourceforge.net/ 11 * For more information, please see http://nath323.sourceforge.net/
12 *
13 * Changes:
14 * 2006-02-01 - initial version 0.1
15 *
16 * 2006-02-20 - version 0.2
17 * 1. Changed source format to follow kernel conventions
18 * 2. Deleted some unnecessary structures
19 * 3. Minor fixes
20 *
21 * 2006-03-10 - version 0.3
22 * 1. Added support for multiple TPKTs in one packet (suggested by
23 * Patrick McHardy)
24 * 2. Avoid excessive stack usage (based on Patrick McHardy's patch)
25 * 3. Added support for non-linear skb (based on Patrick McHardy's patch)
26 * 4. Fixed missing H.245 module owner (Patrick McHardy)
27 * 5. Avoid long RAS expectation chains (Patrick McHardy)
28 * 6. Fixed incorrect __exit attribute (Patrick McHardy)
29 * 7. Eliminated unnecessary return code
30 * 8. Fixed incorrect use of NAT data from conntrack code (suggested by
31 * Patrick McHardy)
32 * 9. Fixed TTL calculation error in RCF
33 * 10. Added TTL support in RRQ
34 * 11. Better support for separate TPKT header and data
35 *
36 * 2006-03-15 - version 0.4
37 * 1. Added support for T.120 channels
38 * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
39 * 3. Splitted ASN.1 code and data (suggested by Patrick McHardy)
40 * 4. Sort ASN.1 data to avoid forwarding declarations (suggested by
41 * Patrick McHardy)
42 * 5. Reset next TPKT data length in get_tpkt_data()
43 */ 12 */
44 13
45#include <linux/config.h> 14#include <linux/config.h>
@@ -54,8 +23,6 @@
54#include <linux/netfilter_ipv4/ip_conntrack_h323.h> 23#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
55#include <linux/moduleparam.h> 24#include <linux/moduleparam.h>
56 25
57#include "ip_conntrack_helper_h323_asn1.h"
58
59#if 0 26#if 0
60#define DEBUGP printk 27#define DEBUGP printk
61#else 28#else
@@ -63,6 +30,10 @@
63#endif 30#endif
64 31
65/* Parameters */ 32/* Parameters */
33static unsigned int default_rrq_ttl = 300;
34module_param(default_rrq_ttl, uint, 0600);
35MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
36
66static int gkrouted_only = 1; 37static int gkrouted_only = 1;
67module_param(gkrouted_only, int, 0600); 38module_param(gkrouted_only, int, 0600);
68MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); 39MODULE_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,
222} 193}
223 194
224/****************************************************************************/ 195/****************************************************************************/
225int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, 196static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
226 u_int32_t * ip, u_int16_t * port) 197 u_int32_t * ip, u_int16_t * port)
227{ 198{
228 unsigned char *p; 199 unsigned char *p;
229 200
@@ -1302,7 +1273,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1302 DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); 1273 DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
1303 info->timeout = rrq->timeToLive; 1274 info->timeout = rrq->timeToLive;
1304 } else 1275 } else
1305 info->timeout = 0; 1276 info->timeout = default_rrq_ttl;
1306 1277
1307 return 0; 1278 return 0;
1308} 1279}
@@ -1713,18 +1684,17 @@ static int __init init(void)
1713module_init(init); 1684module_init(init);
1714module_exit(fini); 1685module_exit(fini);
1715 1686
1716EXPORT_SYMBOL(get_h245_addr); 1687EXPORT_SYMBOL_GPL(get_h225_addr);
1717EXPORT_SYMBOL(get_h225_addr); 1688EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
1718EXPORT_SYMBOL(ip_conntrack_h245_expect); 1689EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect);
1719EXPORT_SYMBOL(ip_conntrack_q931_expect); 1690EXPORT_SYMBOL_GPL(set_h245_addr_hook);
1720EXPORT_SYMBOL(set_h245_addr_hook); 1691EXPORT_SYMBOL_GPL(set_h225_addr_hook);
1721EXPORT_SYMBOL(set_h225_addr_hook); 1692EXPORT_SYMBOL_GPL(set_sig_addr_hook);
1722EXPORT_SYMBOL(set_sig_addr_hook); 1693EXPORT_SYMBOL_GPL(set_ras_addr_hook);
1723EXPORT_SYMBOL(set_ras_addr_hook); 1694EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
1724EXPORT_SYMBOL(nat_rtp_rtcp_hook); 1695EXPORT_SYMBOL_GPL(nat_t120_hook);
1725EXPORT_SYMBOL(nat_t120_hook); 1696EXPORT_SYMBOL_GPL(nat_h245_hook);
1726EXPORT_SYMBOL(nat_h245_hook); 1697EXPORT_SYMBOL_GPL(nat_q931_hook);
1727EXPORT_SYMBOL(nat_q931_hook);
1728 1698
1729MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); 1699MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
1730MODULE_DESCRIPTION("H.323 connection tracking helper"); 1700MODULE_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 afa525129b51..48078002e450 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 @@
15#else 15#else
16#include <stdio.h> 16#include <stdio.h>
17#endif 17#endif
18#include "ip_conntrack_helper_h323_asn1.h" 18#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
19 19
20/* Trace Flag */ 20/* Trace Flag */
21#ifndef H323_TRACE 21#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 0bd828081c0c..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
+++ /dev/null
@@ -1,98 +0,0 @@
1/****************************************************************************
2 * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
3 * conntrack/NAT module.
4 *
5 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
6 *
7 * This source code is licensed under General Public License version 2.
8 *
9 *
10 * This library is based on H.225 version 4, H.235 version 2 and H.245
11 * version 7. It is extremely optimized to decode only the absolutely
12 * necessary objects in a signal for Linux kernel NAT module use, so don't
13 * expect it to be a full ASN.1 library.
14 *
15 * Features:
16 *
17 * 1. Small. The total size of code plus data is less than 20 KB (IA32).
18 * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866
19 * takes only 3.9 seconds.
20 * 3. No memory allocation. It uses a static object. No need to initialize or
21 * cleanup.
22 * 4. Thread safe.
23 * 5. Support embedded architectures that has no misaligned memory access
24 * support.
25 *
26 * Limitations:
27 *
28 * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU.
29 * If a Setup signal contains more than 30 faststart, the packet size will
30 * very likely exceed the MTU size, then the TPKT will be fragmented. I
31 * don't know how to handle this in a Netfilter module. Anybody can help?
32 * Although I think 30 is enough for most of the cases.
33 * 2. IPv4 addresses only.
34 *
35 ****************************************************************************/
36
37#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_
38#define _IP_CONNTRACK_HELPER_H323_ASN1_H_
39
40/*****************************************************************************
41 * H.323 Types
42 ****************************************************************************/
43#include "ip_conntrack_helper_h323_types.h"
44
45typedef struct {
46 enum {
47 Q931_NationalEscape = 0x00,
48 Q931_Alerting = 0x01,
49 Q931_CallProceeding = 0x02,
50 Q931_Connect = 0x07,
51 Q931_ConnectAck = 0x0F,
52 Q931_Progress = 0x03,
53 Q931_Setup = 0x05,
54 Q931_SetupAck = 0x0D,
55 Q931_Resume = 0x26,
56 Q931_ResumeAck = 0x2E,
57 Q931_ResumeReject = 0x22,
58 Q931_Suspend = 0x25,
59 Q931_SuspendAck = 0x2D,
60 Q931_SuspendReject = 0x21,
61 Q931_UserInformation = 0x20,
62 Q931_Disconnect = 0x45,
63 Q931_Release = 0x4D,
64 Q931_ReleaseComplete = 0x5A,
65 Q931_Restart = 0x46,
66 Q931_RestartAck = 0x4E,
67 Q931_Segment = 0x60,
68 Q931_CongestionCtrl = 0x79,
69 Q931_Information = 0x7B,
70 Q931_Notify = 0x6E,
71 Q931_Status = 0x7D,
72 Q931_StatusEnquiry = 0x75,
73 Q931_Facility = 0x62
74 } MessageType;
75 H323_UserInformation UUIE;
76} Q931;
77
78/*****************************************************************************
79 * Decode Functions Return Codes
80 ****************************************************************************/
81
82#define H323_ERROR_NONE 0 /* Decoded successfully */
83#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */
84#define H323_ERROR_BOUND -1
85#define H323_ERROR_RANGE -2
86
87
88/*****************************************************************************
89 * Decode Functions
90 ****************************************************************************/
91
92int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras);
93int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931);
94int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
95 MultimediaSystemControlMessage *
96 mscm);
97
98#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 cc98f7aa5abe..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
+++ /dev/null
@@ -1,938 +0,0 @@
1/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
2 *
3 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
4 *
5 * This source code is licensed under General Public License version 2.
6 */
7
8typedef struct TransportAddress_ipAddress { /* SEQUENCE */
9 int options; /* No use */
10 unsigned ip;
11} TransportAddress_ipAddress;
12
13typedef struct TransportAddress { /* CHOICE */
14 enum {
15 eTransportAddress_ipAddress,
16 eTransportAddress_ipSourceRoute,
17 eTransportAddress_ipxAddress,
18 eTransportAddress_ip6Address,
19 eTransportAddress_netBios,
20 eTransportAddress_nsap,
21 eTransportAddress_nonStandardAddress,
22 } choice;
23 union {
24 TransportAddress_ipAddress ipAddress;
25 };
26} TransportAddress;
27
28typedef struct DataProtocolCapability { /* CHOICE */
29 enum {
30 eDataProtocolCapability_nonStandard,
31 eDataProtocolCapability_v14buffered,
32 eDataProtocolCapability_v42lapm,
33 eDataProtocolCapability_hdlcFrameTunnelling,
34 eDataProtocolCapability_h310SeparateVCStack,
35 eDataProtocolCapability_h310SingleVCStack,
36 eDataProtocolCapability_transparent,
37 eDataProtocolCapability_segmentationAndReassembly,
38 eDataProtocolCapability_hdlcFrameTunnelingwSAR,
39 eDataProtocolCapability_v120,
40 eDataProtocolCapability_separateLANStack,
41 eDataProtocolCapability_v76wCompression,
42 eDataProtocolCapability_tcp,
43 eDataProtocolCapability_udp,
44 } choice;
45} DataProtocolCapability;
46
47typedef struct DataApplicationCapability_application { /* CHOICE */
48 enum {
49 eDataApplicationCapability_application_nonStandard,
50 eDataApplicationCapability_application_t120,
51 eDataApplicationCapability_application_dsm_cc,
52 eDataApplicationCapability_application_userData,
53 eDataApplicationCapability_application_t84,
54 eDataApplicationCapability_application_t434,
55 eDataApplicationCapability_application_h224,
56 eDataApplicationCapability_application_nlpid,
57 eDataApplicationCapability_application_dsvdControl,
58 eDataApplicationCapability_application_h222DataPartitioning,
59 eDataApplicationCapability_application_t30fax,
60 eDataApplicationCapability_application_t140,
61 eDataApplicationCapability_application_t38fax,
62 eDataApplicationCapability_application_genericDataCapability,
63 } choice;
64 union {
65 DataProtocolCapability t120;
66 };
67} DataApplicationCapability_application;
68
69typedef struct DataApplicationCapability { /* SEQUENCE */
70 int options; /* No use */
71 DataApplicationCapability_application application;
72} DataApplicationCapability;
73
74typedef struct DataType { /* CHOICE */
75 enum {
76 eDataType_nonStandard,
77 eDataType_nullData,
78 eDataType_videoData,
79 eDataType_audioData,
80 eDataType_data,
81 eDataType_encryptionData,
82 eDataType_h235Control,
83 eDataType_h235Media,
84 eDataType_multiplexedStream,
85 } choice;
86 union {
87 DataApplicationCapability data;
88 };
89} DataType;
90
91typedef struct UnicastAddress_iPAddress { /* SEQUENCE */
92 int options; /* No use */
93 unsigned network;
94} UnicastAddress_iPAddress;
95
96typedef struct UnicastAddress { /* CHOICE */
97 enum {
98 eUnicastAddress_iPAddress,
99 eUnicastAddress_iPXAddress,
100 eUnicastAddress_iP6Address,
101 eUnicastAddress_netBios,
102 eUnicastAddress_iPSourceRouteAddress,
103 eUnicastAddress_nsap,
104 eUnicastAddress_nonStandardAddress,
105 } choice;
106 union {
107 UnicastAddress_iPAddress iPAddress;
108 };
109} UnicastAddress;
110
111typedef struct H245_TransportAddress { /* CHOICE */
112 enum {
113 eH245_TransportAddress_unicastAddress,
114 eH245_TransportAddress_multicastAddress,
115 } choice;
116 union {
117 UnicastAddress unicastAddress;
118 };
119} H245_TransportAddress;
120
121typedef struct H2250LogicalChannelParameters { /* SEQUENCE */
122 enum {
123 eH2250LogicalChannelParameters_nonStandard = (1 << 31),
124 eH2250LogicalChannelParameters_associatedSessionID =
125 (1 << 30),
126 eH2250LogicalChannelParameters_mediaChannel = (1 << 29),
127 eH2250LogicalChannelParameters_mediaGuaranteedDelivery =
128 (1 << 28),
129 eH2250LogicalChannelParameters_mediaControlChannel =
130 (1 << 27),
131 eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery
132 = (1 << 26),
133 eH2250LogicalChannelParameters_silenceSuppression = (1 << 25),
134 eH2250LogicalChannelParameters_destination = (1 << 24),
135 eH2250LogicalChannelParameters_dynamicRTPPayloadType =
136 (1 << 23),
137 eH2250LogicalChannelParameters_mediaPacketization = (1 << 22),
138 eH2250LogicalChannelParameters_transportCapability =
139 (1 << 21),
140 eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20),
141 eH2250LogicalChannelParameters_source = (1 << 19),
142 } options;
143 H245_TransportAddress mediaChannel;
144 H245_TransportAddress mediaControlChannel;
145} H2250LogicalChannelParameters;
146
147typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */
148 enum {
149 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
150 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
151 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
152 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
153 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none,
154 } choice;
155 union {
156 H2250LogicalChannelParameters h2250LogicalChannelParameters;
157 };
158} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters;
159
160typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */
161 enum {
162 eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber
163 = (1 << 31),
164 eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency
165 = (1 << 30),
166 eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor
167 = (1 << 29),
168 } options;
169 DataType dataType;
170 OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
171 multiplexParameters;
172} OpenLogicalChannel_forwardLogicalChannelParameters;
173
174typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
175 enum {
176 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
177 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
178 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
179 } choice;
180 union {
181 H2250LogicalChannelParameters h2250LogicalChannelParameters;
182 };
183} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters;
184
185typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */
186 enum {
187 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
188 = (1 << 31),
189 eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency
190 = (1 << 30),
191 eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor
192 = (1 << 29),
193 } options;
194 OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
195 multiplexParameters;
196} OpenLogicalChannel_reverseLogicalChannelParameters;
197
198typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */
199 enum {
200 eNetworkAccessParameters_networkAddress_q2931Address,
201 eNetworkAccessParameters_networkAddress_e164Address,
202 eNetworkAccessParameters_networkAddress_localAreaAddress,
203 } choice;
204 union {
205 H245_TransportAddress localAreaAddress;
206 };
207} NetworkAccessParameters_networkAddress;
208
209typedef struct NetworkAccessParameters { /* SEQUENCE */
210 enum {
211 eNetworkAccessParameters_distribution = (1 << 31),
212 eNetworkAccessParameters_externalReference = (1 << 30),
213 eNetworkAccessParameters_t120SetupProcedure = (1 << 29),
214 } options;
215 NetworkAccessParameters_networkAddress networkAddress;
216} NetworkAccessParameters;
217
218typedef struct OpenLogicalChannel { /* SEQUENCE */
219 enum {
220 eOpenLogicalChannel_reverseLogicalChannelParameters =
221 (1 << 31),
222 eOpenLogicalChannel_separateStack = (1 << 30),
223 eOpenLogicalChannel_encryptionSync = (1 << 29),
224 } options;
225 OpenLogicalChannel_forwardLogicalChannelParameters
226 forwardLogicalChannelParameters;
227 OpenLogicalChannel_reverseLogicalChannelParameters
228 reverseLogicalChannelParameters;
229 NetworkAccessParameters separateStack;
230} OpenLogicalChannel;
231
232typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */
233 int count;
234 OpenLogicalChannel item[30];
235} Setup_UUIE_fastStart;
236
237typedef struct Setup_UUIE { /* SEQUENCE */
238 enum {
239 eSetup_UUIE_h245Address = (1 << 31),
240 eSetup_UUIE_sourceAddress = (1 << 30),
241 eSetup_UUIE_destinationAddress = (1 << 29),
242 eSetup_UUIE_destCallSignalAddress = (1 << 28),
243 eSetup_UUIE_destExtraCallInfo = (1 << 27),
244 eSetup_UUIE_destExtraCRV = (1 << 26),
245 eSetup_UUIE_callServices = (1 << 25),
246 eSetup_UUIE_sourceCallSignalAddress = (1 << 24),
247 eSetup_UUIE_remoteExtensionAddress = (1 << 23),
248 eSetup_UUIE_callIdentifier = (1 << 22),
249 eSetup_UUIE_h245SecurityCapability = (1 << 21),
250 eSetup_UUIE_tokens = (1 << 20),
251 eSetup_UUIE_cryptoTokens = (1 << 19),
252 eSetup_UUIE_fastStart = (1 << 18),
253 eSetup_UUIE_mediaWaitForConnect = (1 << 17),
254 eSetup_UUIE_canOverlapSend = (1 << 16),
255 eSetup_UUIE_endpointIdentifier = (1 << 15),
256 eSetup_UUIE_multipleCalls = (1 << 14),
257 eSetup_UUIE_maintainConnection = (1 << 13),
258 eSetup_UUIE_connectionParameters = (1 << 12),
259 eSetup_UUIE_language = (1 << 11),
260 eSetup_UUIE_presentationIndicator = (1 << 10),
261 eSetup_UUIE_screeningIndicator = (1 << 9),
262 eSetup_UUIE_serviceControl = (1 << 8),
263 eSetup_UUIE_symmetricOperationRequired = (1 << 7),
264 eSetup_UUIE_capacity = (1 << 6),
265 eSetup_UUIE_circuitInfo = (1 << 5),
266 eSetup_UUIE_desiredProtocols = (1 << 4),
267 eSetup_UUIE_neededFeatures = (1 << 3),
268 eSetup_UUIE_desiredFeatures = (1 << 2),
269 eSetup_UUIE_supportedFeatures = (1 << 1),
270 eSetup_UUIE_parallelH245Control = (1 << 0),
271 } options;
272 TransportAddress h245Address;
273 TransportAddress destCallSignalAddress;
274 TransportAddress sourceCallSignalAddress;
275 Setup_UUIE_fastStart fastStart;
276} Setup_UUIE;
277
278typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */
279 int count;
280 OpenLogicalChannel item[30];
281} CallProceeding_UUIE_fastStart;
282
283typedef struct CallProceeding_UUIE { /* SEQUENCE */
284 enum {
285 eCallProceeding_UUIE_h245Address = (1 << 31),
286 eCallProceeding_UUIE_callIdentifier = (1 << 30),
287 eCallProceeding_UUIE_h245SecurityMode = (1 << 29),
288 eCallProceeding_UUIE_tokens = (1 << 28),
289 eCallProceeding_UUIE_cryptoTokens = (1 << 27),
290 eCallProceeding_UUIE_fastStart = (1 << 26),
291 eCallProceeding_UUIE_multipleCalls = (1 << 25),
292 eCallProceeding_UUIE_maintainConnection = (1 << 24),
293 eCallProceeding_UUIE_fastConnectRefused = (1 << 23),
294 eCallProceeding_UUIE_featureSet = (1 << 22),
295 } options;
296 TransportAddress h245Address;
297 CallProceeding_UUIE_fastStart fastStart;
298} CallProceeding_UUIE;
299
300typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */
301 int count;
302 OpenLogicalChannel item[30];
303} Connect_UUIE_fastStart;
304
305typedef struct Connect_UUIE { /* SEQUENCE */
306 enum {
307 eConnect_UUIE_h245Address = (1 << 31),
308 eConnect_UUIE_callIdentifier = (1 << 30),
309 eConnect_UUIE_h245SecurityMode = (1 << 29),
310 eConnect_UUIE_tokens = (1 << 28),
311 eConnect_UUIE_cryptoTokens = (1 << 27),
312 eConnect_UUIE_fastStart = (1 << 26),
313 eConnect_UUIE_multipleCalls = (1 << 25),
314 eConnect_UUIE_maintainConnection = (1 << 24),
315 eConnect_UUIE_language = (1 << 23),
316 eConnect_UUIE_connectedAddress = (1 << 22),
317 eConnect_UUIE_presentationIndicator = (1 << 21),
318 eConnect_UUIE_screeningIndicator = (1 << 20),
319 eConnect_UUIE_fastConnectRefused = (1 << 19),
320 eConnect_UUIE_serviceControl = (1 << 18),
321 eConnect_UUIE_capacity = (1 << 17),
322 eConnect_UUIE_featureSet = (1 << 16),
323 } options;
324 TransportAddress h245Address;
325 Connect_UUIE_fastStart fastStart;
326} Connect_UUIE;
327
328typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */
329 int count;
330 OpenLogicalChannel item[30];
331} Alerting_UUIE_fastStart;
332
333typedef struct Alerting_UUIE { /* SEQUENCE */
334 enum {
335 eAlerting_UUIE_h245Address = (1 << 31),
336 eAlerting_UUIE_callIdentifier = (1 << 30),
337 eAlerting_UUIE_h245SecurityMode = (1 << 29),
338 eAlerting_UUIE_tokens = (1 << 28),
339 eAlerting_UUIE_cryptoTokens = (1 << 27),
340 eAlerting_UUIE_fastStart = (1 << 26),
341 eAlerting_UUIE_multipleCalls = (1 << 25),
342 eAlerting_UUIE_maintainConnection = (1 << 24),
343 eAlerting_UUIE_alertingAddress = (1 << 23),
344 eAlerting_UUIE_presentationIndicator = (1 << 22),
345 eAlerting_UUIE_screeningIndicator = (1 << 21),
346 eAlerting_UUIE_fastConnectRefused = (1 << 20),
347 eAlerting_UUIE_serviceControl = (1 << 19),
348 eAlerting_UUIE_capacity = (1 << 18),
349 eAlerting_UUIE_featureSet = (1 << 17),
350 } options;
351 TransportAddress h245Address;
352 Alerting_UUIE_fastStart fastStart;
353} Alerting_UUIE;
354
355typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */
356 int count;
357 OpenLogicalChannel item[30];
358} Information_UUIE_fastStart;
359
360typedef struct Information_UUIE { /* SEQUENCE */
361 enum {
362 eInformation_UUIE_callIdentifier = (1 << 31),
363 eInformation_UUIE_tokens = (1 << 30),
364 eInformation_UUIE_cryptoTokens = (1 << 29),
365 eInformation_UUIE_fastStart = (1 << 28),
366 eInformation_UUIE_fastConnectRefused = (1 << 27),
367 eInformation_UUIE_circuitInfo = (1 << 26),
368 } options;
369 Information_UUIE_fastStart fastStart;
370} Information_UUIE;
371
372typedef struct FacilityReason { /* CHOICE */
373 enum {
374 eFacilityReason_routeCallToGatekeeper,
375 eFacilityReason_callForwarded,
376 eFacilityReason_routeCallToMC,
377 eFacilityReason_undefinedReason,
378 eFacilityReason_conferenceListChoice,
379 eFacilityReason_startH245,
380 eFacilityReason_noH245,
381 eFacilityReason_newTokens,
382 eFacilityReason_featureSetUpdate,
383 eFacilityReason_forwardedElements,
384 eFacilityReason_transportedInformation,
385 } choice;
386} FacilityReason;
387
388typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */
389 int count;
390 OpenLogicalChannel item[30];
391} Facility_UUIE_fastStart;
392
393typedef struct Facility_UUIE { /* SEQUENCE */
394 enum {
395 eFacility_UUIE_alternativeAddress = (1 << 31),
396 eFacility_UUIE_alternativeAliasAddress = (1 << 30),
397 eFacility_UUIE_conferenceID = (1 << 29),
398 eFacility_UUIE_callIdentifier = (1 << 28),
399 eFacility_UUIE_destExtraCallInfo = (1 << 27),
400 eFacility_UUIE_remoteExtensionAddress = (1 << 26),
401 eFacility_UUIE_tokens = (1 << 25),
402 eFacility_UUIE_cryptoTokens = (1 << 24),
403 eFacility_UUIE_conferences = (1 << 23),
404 eFacility_UUIE_h245Address = (1 << 22),
405 eFacility_UUIE_fastStart = (1 << 21),
406 eFacility_UUIE_multipleCalls = (1 << 20),
407 eFacility_UUIE_maintainConnection = (1 << 19),
408 eFacility_UUIE_fastConnectRefused = (1 << 18),
409 eFacility_UUIE_serviceControl = (1 << 17),
410 eFacility_UUIE_circuitInfo = (1 << 16),
411 eFacility_UUIE_featureSet = (1 << 15),
412 eFacility_UUIE_destinationInfo = (1 << 14),
413 eFacility_UUIE_h245SecurityMode = (1 << 13),
414 } options;
415 FacilityReason reason;
416 TransportAddress h245Address;
417 Facility_UUIE_fastStart fastStart;
418} Facility_UUIE;
419
420typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */
421 int count;
422 OpenLogicalChannel item[30];
423} Progress_UUIE_fastStart;
424
425typedef struct Progress_UUIE { /* SEQUENCE */
426 enum {
427 eProgress_UUIE_h245Address = (1 << 31),
428 eProgress_UUIE_h245SecurityMode = (1 << 30),
429 eProgress_UUIE_tokens = (1 << 29),
430 eProgress_UUIE_cryptoTokens = (1 << 28),
431 eProgress_UUIE_fastStart = (1 << 27),
432 eProgress_UUIE_multipleCalls = (1 << 26),
433 eProgress_UUIE_maintainConnection = (1 << 25),
434 eProgress_UUIE_fastConnectRefused = (1 << 24),
435 } options;
436 TransportAddress h245Address;
437 Progress_UUIE_fastStart fastStart;
438} Progress_UUIE;
439
440typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */
441 enum {
442 eH323_UU_PDU_h323_message_body_setup,
443 eH323_UU_PDU_h323_message_body_callProceeding,
444 eH323_UU_PDU_h323_message_body_connect,
445 eH323_UU_PDU_h323_message_body_alerting,
446 eH323_UU_PDU_h323_message_body_information,
447 eH323_UU_PDU_h323_message_body_releaseComplete,
448 eH323_UU_PDU_h323_message_body_facility,
449 eH323_UU_PDU_h323_message_body_progress,
450 eH323_UU_PDU_h323_message_body_empty,
451 eH323_UU_PDU_h323_message_body_status,
452 eH323_UU_PDU_h323_message_body_statusInquiry,
453 eH323_UU_PDU_h323_message_body_setupAcknowledge,
454 eH323_UU_PDU_h323_message_body_notify,
455 } choice;
456 union {
457 Setup_UUIE setup;
458 CallProceeding_UUIE callProceeding;
459 Connect_UUIE connect;
460 Alerting_UUIE alerting;
461 Information_UUIE information;
462 Facility_UUIE facility;
463 Progress_UUIE progress;
464 };
465} H323_UU_PDU_h323_message_body;
466
467typedef struct RequestMessage { /* CHOICE */
468 enum {
469 eRequestMessage_nonStandard,
470 eRequestMessage_masterSlaveDetermination,
471 eRequestMessage_terminalCapabilitySet,
472 eRequestMessage_openLogicalChannel,
473 eRequestMessage_closeLogicalChannel,
474 eRequestMessage_requestChannelClose,
475 eRequestMessage_multiplexEntrySend,
476 eRequestMessage_requestMultiplexEntry,
477 eRequestMessage_requestMode,
478 eRequestMessage_roundTripDelayRequest,
479 eRequestMessage_maintenanceLoopRequest,
480 eRequestMessage_communicationModeRequest,
481 eRequestMessage_conferenceRequest,
482 eRequestMessage_multilinkRequest,
483 eRequestMessage_logicalChannelRateRequest,
484 } choice;
485 union {
486 OpenLogicalChannel openLogicalChannel;
487 };
488} RequestMessage;
489
490typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
491 enum {
492 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
493 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
494 } choice;
495 union {
496 H2250LogicalChannelParameters h2250LogicalChannelParameters;
497 };
498} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters;
499
500typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */
501 enum {
502 eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber
503 = (1 << 31),
504 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
505 = (1 << 30),
506 eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor
507 = (1 << 29),
508 } options;
509 OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
510 multiplexParameters;
511} OpenLogicalChannelAck_reverseLogicalChannelParameters;
512
513typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */
514 enum {
515 eH2250LogicalChannelAckParameters_nonStandard = (1 << 31),
516 eH2250LogicalChannelAckParameters_sessionID = (1 << 30),
517 eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29),
518 eH2250LogicalChannelAckParameters_mediaControlChannel =
519 (1 << 28),
520 eH2250LogicalChannelAckParameters_dynamicRTPPayloadType =
521 (1 << 27),
522 eH2250LogicalChannelAckParameters_flowControlToZero =
523 (1 << 26),
524 eH2250LogicalChannelAckParameters_portNumber = (1 << 25),
525 } options;
526 H245_TransportAddress mediaChannel;
527 H245_TransportAddress mediaControlChannel;
528} H2250LogicalChannelAckParameters;
529
530typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */
531 enum {
532 eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters,
533 } choice;
534 union {
535 H2250LogicalChannelAckParameters
536 h2250LogicalChannelAckParameters;
537 };
538} OpenLogicalChannelAck_forwardMultiplexAckParameters;
539
540typedef struct OpenLogicalChannelAck { /* SEQUENCE */
541 enum {
542 eOpenLogicalChannelAck_reverseLogicalChannelParameters =
543 (1 << 31),
544 eOpenLogicalChannelAck_separateStack = (1 << 30),
545 eOpenLogicalChannelAck_forwardMultiplexAckParameters =
546 (1 << 29),
547 eOpenLogicalChannelAck_encryptionSync = (1 << 28),
548 } options;
549 OpenLogicalChannelAck_reverseLogicalChannelParameters
550 reverseLogicalChannelParameters;
551 OpenLogicalChannelAck_forwardMultiplexAckParameters
552 forwardMultiplexAckParameters;
553} OpenLogicalChannelAck;
554
555typedef struct ResponseMessage { /* CHOICE */
556 enum {
557 eResponseMessage_nonStandard,
558 eResponseMessage_masterSlaveDeterminationAck,
559 eResponseMessage_masterSlaveDeterminationReject,
560 eResponseMessage_terminalCapabilitySetAck,
561 eResponseMessage_terminalCapabilitySetReject,
562 eResponseMessage_openLogicalChannelAck,
563 eResponseMessage_openLogicalChannelReject,
564 eResponseMessage_closeLogicalChannelAck,
565 eResponseMessage_requestChannelCloseAck,
566 eResponseMessage_requestChannelCloseReject,
567 eResponseMessage_multiplexEntrySendAck,
568 eResponseMessage_multiplexEntrySendReject,
569 eResponseMessage_requestMultiplexEntryAck,
570 eResponseMessage_requestMultiplexEntryReject,
571 eResponseMessage_requestModeAck,
572 eResponseMessage_requestModeReject,
573 eResponseMessage_roundTripDelayResponse,
574 eResponseMessage_maintenanceLoopAck,
575 eResponseMessage_maintenanceLoopReject,
576 eResponseMessage_communicationModeResponse,
577 eResponseMessage_conferenceResponse,
578 eResponseMessage_multilinkResponse,
579 eResponseMessage_logicalChannelRateAcknowledge,
580 eResponseMessage_logicalChannelRateReject,
581 } choice;
582 union {
583 OpenLogicalChannelAck openLogicalChannelAck;
584 };
585} ResponseMessage;
586
587typedef struct MultimediaSystemControlMessage { /* CHOICE */
588 enum {
589 eMultimediaSystemControlMessage_request,
590 eMultimediaSystemControlMessage_response,
591 eMultimediaSystemControlMessage_command,
592 eMultimediaSystemControlMessage_indication,
593 } choice;
594 union {
595 RequestMessage request;
596 ResponseMessage response;
597 };
598} MultimediaSystemControlMessage;
599
600typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */
601 int count;
602 MultimediaSystemControlMessage item[4];
603} H323_UU_PDU_h245Control;
604
605typedef struct H323_UU_PDU { /* SEQUENCE */
606 enum {
607 eH323_UU_PDU_nonStandardData = (1 << 31),
608 eH323_UU_PDU_h4501SupplementaryService = (1 << 30),
609 eH323_UU_PDU_h245Tunneling = (1 << 29),
610 eH323_UU_PDU_h245Control = (1 << 28),
611 eH323_UU_PDU_nonStandardControl = (1 << 27),
612 eH323_UU_PDU_callLinkage = (1 << 26),
613 eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25),
614 eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24),
615 eH323_UU_PDU_stimulusControl = (1 << 23),
616 eH323_UU_PDU_genericData = (1 << 22),
617 } options;
618 H323_UU_PDU_h323_message_body h323_message_body;
619 H323_UU_PDU_h245Control h245Control;
620} H323_UU_PDU;
621
622typedef struct H323_UserInformation { /* SEQUENCE */
623 enum {
624 eH323_UserInformation_user_data = (1 << 31),
625 } options;
626 H323_UU_PDU h323_uu_pdu;
627} H323_UserInformation;
628
629typedef struct GatekeeperRequest { /* SEQUENCE */
630 enum {
631 eGatekeeperRequest_nonStandardData = (1 << 31),
632 eGatekeeperRequest_gatekeeperIdentifier = (1 << 30),
633 eGatekeeperRequest_callServices = (1 << 29),
634 eGatekeeperRequest_endpointAlias = (1 << 28),
635 eGatekeeperRequest_alternateEndpoints = (1 << 27),
636 eGatekeeperRequest_tokens = (1 << 26),
637 eGatekeeperRequest_cryptoTokens = (1 << 25),
638 eGatekeeperRequest_authenticationCapability = (1 << 24),
639 eGatekeeperRequest_algorithmOIDs = (1 << 23),
640 eGatekeeperRequest_integrity = (1 << 22),
641 eGatekeeperRequest_integrityCheckValue = (1 << 21),
642 eGatekeeperRequest_supportsAltGK = (1 << 20),
643 eGatekeeperRequest_featureSet = (1 << 19),
644 eGatekeeperRequest_genericData = (1 << 18),
645 } options;
646 TransportAddress rasAddress;
647} GatekeeperRequest;
648
649typedef struct GatekeeperConfirm { /* SEQUENCE */
650 enum {
651 eGatekeeperConfirm_nonStandardData = (1 << 31),
652 eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30),
653 eGatekeeperConfirm_alternateGatekeeper = (1 << 29),
654 eGatekeeperConfirm_authenticationMode = (1 << 28),
655 eGatekeeperConfirm_tokens = (1 << 27),
656 eGatekeeperConfirm_cryptoTokens = (1 << 26),
657 eGatekeeperConfirm_algorithmOID = (1 << 25),
658 eGatekeeperConfirm_integrity = (1 << 24),
659 eGatekeeperConfirm_integrityCheckValue = (1 << 23),
660 eGatekeeperConfirm_featureSet = (1 << 22),
661 eGatekeeperConfirm_genericData = (1 << 21),
662 } options;
663 TransportAddress rasAddress;
664} GatekeeperConfirm;
665
666typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */
667 int count;
668 TransportAddress item[10];
669} RegistrationRequest_callSignalAddress;
670
671typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */
672 int count;
673 TransportAddress item[10];
674} RegistrationRequest_rasAddress;
675
676typedef struct RegistrationRequest { /* SEQUENCE */
677 enum {
678 eRegistrationRequest_nonStandardData = (1 << 31),
679 eRegistrationRequest_terminalAlias = (1 << 30),
680 eRegistrationRequest_gatekeeperIdentifier = (1 << 29),
681 eRegistrationRequest_alternateEndpoints = (1 << 28),
682 eRegistrationRequest_timeToLive = (1 << 27),
683 eRegistrationRequest_tokens = (1 << 26),
684 eRegistrationRequest_cryptoTokens = (1 << 25),
685 eRegistrationRequest_integrityCheckValue = (1 << 24),
686 eRegistrationRequest_keepAlive = (1 << 23),
687 eRegistrationRequest_endpointIdentifier = (1 << 22),
688 eRegistrationRequest_willSupplyUUIEs = (1 << 21),
689 eRegistrationRequest_maintainConnection = (1 << 20),
690 eRegistrationRequest_alternateTransportAddresses = (1 << 19),
691 eRegistrationRequest_additiveRegistration = (1 << 18),
692 eRegistrationRequest_terminalAliasPattern = (1 << 17),
693 eRegistrationRequest_supportsAltGK = (1 << 16),
694 eRegistrationRequest_usageReportingCapability = (1 << 15),
695 eRegistrationRequest_multipleCalls = (1 << 14),
696 eRegistrationRequest_supportedH248Packages = (1 << 13),
697 eRegistrationRequest_callCreditCapability = (1 << 12),
698 eRegistrationRequest_capacityReportingCapability = (1 << 11),
699 eRegistrationRequest_capacity = (1 << 10),
700 eRegistrationRequest_featureSet = (1 << 9),
701 eRegistrationRequest_genericData = (1 << 8),
702 } options;
703 RegistrationRequest_callSignalAddress callSignalAddress;
704 RegistrationRequest_rasAddress rasAddress;
705 unsigned timeToLive;
706} RegistrationRequest;
707
708typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */
709 int count;
710 TransportAddress item[10];
711} RegistrationConfirm_callSignalAddress;
712
713typedef struct RegistrationConfirm { /* SEQUENCE */
714 enum {
715 eRegistrationConfirm_nonStandardData = (1 << 31),
716 eRegistrationConfirm_terminalAlias = (1 << 30),
717 eRegistrationConfirm_gatekeeperIdentifier = (1 << 29),
718 eRegistrationConfirm_alternateGatekeeper = (1 << 28),
719 eRegistrationConfirm_timeToLive = (1 << 27),
720 eRegistrationConfirm_tokens = (1 << 26),
721 eRegistrationConfirm_cryptoTokens = (1 << 25),
722 eRegistrationConfirm_integrityCheckValue = (1 << 24),
723 eRegistrationConfirm_willRespondToIRR = (1 << 23),
724 eRegistrationConfirm_preGrantedARQ = (1 << 22),
725 eRegistrationConfirm_maintainConnection = (1 << 21),
726 eRegistrationConfirm_serviceControl = (1 << 20),
727 eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19),
728 eRegistrationConfirm_terminalAliasPattern = (1 << 18),
729 eRegistrationConfirm_supportedPrefixes = (1 << 17),
730 eRegistrationConfirm_usageSpec = (1 << 16),
731 eRegistrationConfirm_featureServerAlias = (1 << 15),
732 eRegistrationConfirm_capacityReportingSpec = (1 << 14),
733 eRegistrationConfirm_featureSet = (1 << 13),
734 eRegistrationConfirm_genericData = (1 << 12),
735 } options;
736 RegistrationConfirm_callSignalAddress callSignalAddress;
737 unsigned timeToLive;
738} RegistrationConfirm;
739
740typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */
741 int count;
742 TransportAddress item[10];
743} UnregistrationRequest_callSignalAddress;
744
745typedef struct UnregistrationRequest { /* SEQUENCE */
746 enum {
747 eUnregistrationRequest_endpointAlias = (1 << 31),
748 eUnregistrationRequest_nonStandardData = (1 << 30),
749 eUnregistrationRequest_endpointIdentifier = (1 << 29),
750 eUnregistrationRequest_alternateEndpoints = (1 << 28),
751 eUnregistrationRequest_gatekeeperIdentifier = (1 << 27),
752 eUnregistrationRequest_tokens = (1 << 26),
753 eUnregistrationRequest_cryptoTokens = (1 << 25),
754 eUnregistrationRequest_integrityCheckValue = (1 << 24),
755 eUnregistrationRequest_reason = (1 << 23),
756 eUnregistrationRequest_endpointAliasPattern = (1 << 22),
757 eUnregistrationRequest_supportedPrefixes = (1 << 21),
758 eUnregistrationRequest_alternateGatekeeper = (1 << 20),
759 eUnregistrationRequest_genericData = (1 << 19),
760 } options;
761 UnregistrationRequest_callSignalAddress callSignalAddress;
762} UnregistrationRequest;
763
764typedef struct AdmissionRequest { /* SEQUENCE */
765 enum {
766 eAdmissionRequest_callModel = (1 << 31),
767 eAdmissionRequest_destinationInfo = (1 << 30),
768 eAdmissionRequest_destCallSignalAddress = (1 << 29),
769 eAdmissionRequest_destExtraCallInfo = (1 << 28),
770 eAdmissionRequest_srcCallSignalAddress = (1 << 27),
771 eAdmissionRequest_nonStandardData = (1 << 26),
772 eAdmissionRequest_callServices = (1 << 25),
773 eAdmissionRequest_canMapAlias = (1 << 24),
774 eAdmissionRequest_callIdentifier = (1 << 23),
775 eAdmissionRequest_srcAlternatives = (1 << 22),
776 eAdmissionRequest_destAlternatives = (1 << 21),
777 eAdmissionRequest_gatekeeperIdentifier = (1 << 20),
778 eAdmissionRequest_tokens = (1 << 19),
779 eAdmissionRequest_cryptoTokens = (1 << 18),
780 eAdmissionRequest_integrityCheckValue = (1 << 17),
781 eAdmissionRequest_transportQOS = (1 << 16),
782 eAdmissionRequest_willSupplyUUIEs = (1 << 15),
783 eAdmissionRequest_callLinkage = (1 << 14),
784 eAdmissionRequest_gatewayDataRate = (1 << 13),
785 eAdmissionRequest_capacity = (1 << 12),
786 eAdmissionRequest_circuitInfo = (1 << 11),
787 eAdmissionRequest_desiredProtocols = (1 << 10),
788 eAdmissionRequest_desiredTunnelledProtocol = (1 << 9),
789 eAdmissionRequest_featureSet = (1 << 8),
790 eAdmissionRequest_genericData = (1 << 7),
791 } options;
792 TransportAddress destCallSignalAddress;
793 TransportAddress srcCallSignalAddress;
794} AdmissionRequest;
795
796typedef struct AdmissionConfirm { /* SEQUENCE */
797 enum {
798 eAdmissionConfirm_irrFrequency = (1 << 31),
799 eAdmissionConfirm_nonStandardData = (1 << 30),
800 eAdmissionConfirm_destinationInfo = (1 << 29),
801 eAdmissionConfirm_destExtraCallInfo = (1 << 28),
802 eAdmissionConfirm_destinationType = (1 << 27),
803 eAdmissionConfirm_remoteExtensionAddress = (1 << 26),
804 eAdmissionConfirm_alternateEndpoints = (1 << 25),
805 eAdmissionConfirm_tokens = (1 << 24),
806 eAdmissionConfirm_cryptoTokens = (1 << 23),
807 eAdmissionConfirm_integrityCheckValue = (1 << 22),
808 eAdmissionConfirm_transportQOS = (1 << 21),
809 eAdmissionConfirm_willRespondToIRR = (1 << 20),
810 eAdmissionConfirm_uuiesRequested = (1 << 19),
811 eAdmissionConfirm_language = (1 << 18),
812 eAdmissionConfirm_alternateTransportAddresses = (1 << 17),
813 eAdmissionConfirm_useSpecifiedTransport = (1 << 16),
814 eAdmissionConfirm_circuitInfo = (1 << 15),
815 eAdmissionConfirm_usageSpec = (1 << 14),
816 eAdmissionConfirm_supportedProtocols = (1 << 13),
817 eAdmissionConfirm_serviceControl = (1 << 12),
818 eAdmissionConfirm_multipleCalls = (1 << 11),
819 eAdmissionConfirm_featureSet = (1 << 10),
820 eAdmissionConfirm_genericData = (1 << 9),
821 } options;
822 TransportAddress destCallSignalAddress;
823} AdmissionConfirm;
824
825typedef struct LocationRequest { /* SEQUENCE */
826 enum {
827 eLocationRequest_endpointIdentifier = (1 << 31),
828 eLocationRequest_nonStandardData = (1 << 30),
829 eLocationRequest_sourceInfo = (1 << 29),
830 eLocationRequest_canMapAlias = (1 << 28),
831 eLocationRequest_gatekeeperIdentifier = (1 << 27),
832 eLocationRequest_tokens = (1 << 26),
833 eLocationRequest_cryptoTokens = (1 << 25),
834 eLocationRequest_integrityCheckValue = (1 << 24),
835 eLocationRequest_desiredProtocols = (1 << 23),
836 eLocationRequest_desiredTunnelledProtocol = (1 << 22),
837 eLocationRequest_featureSet = (1 << 21),
838 eLocationRequest_genericData = (1 << 20),
839 eLocationRequest_hopCount = (1 << 19),
840 eLocationRequest_circuitInfo = (1 << 18),
841 } options;
842 TransportAddress replyAddress;
843} LocationRequest;
844
845typedef struct LocationConfirm { /* SEQUENCE */
846 enum {
847 eLocationConfirm_nonStandardData = (1 << 31),
848 eLocationConfirm_destinationInfo = (1 << 30),
849 eLocationConfirm_destExtraCallInfo = (1 << 29),
850 eLocationConfirm_destinationType = (1 << 28),
851 eLocationConfirm_remoteExtensionAddress = (1 << 27),
852 eLocationConfirm_alternateEndpoints = (1 << 26),
853 eLocationConfirm_tokens = (1 << 25),
854 eLocationConfirm_cryptoTokens = (1 << 24),
855 eLocationConfirm_integrityCheckValue = (1 << 23),
856 eLocationConfirm_alternateTransportAddresses = (1 << 22),
857 eLocationConfirm_supportedProtocols = (1 << 21),
858 eLocationConfirm_multipleCalls = (1 << 20),
859 eLocationConfirm_featureSet = (1 << 19),
860 eLocationConfirm_genericData = (1 << 18),
861 eLocationConfirm_circuitInfo = (1 << 17),
862 eLocationConfirm_serviceControl = (1 << 16),
863 } options;
864 TransportAddress callSignalAddress;
865 TransportAddress rasAddress;
866} LocationConfirm;
867
868typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */
869 int count;
870 TransportAddress item[10];
871} InfoRequestResponse_callSignalAddress;
872
873typedef struct InfoRequestResponse { /* SEQUENCE */
874 enum {
875 eInfoRequestResponse_nonStandardData = (1 << 31),
876 eInfoRequestResponse_endpointAlias = (1 << 30),
877 eInfoRequestResponse_perCallInfo = (1 << 29),
878 eInfoRequestResponse_tokens = (1 << 28),
879 eInfoRequestResponse_cryptoTokens = (1 << 27),
880 eInfoRequestResponse_integrityCheckValue = (1 << 26),
881 eInfoRequestResponse_needResponse = (1 << 25),
882 eInfoRequestResponse_capacity = (1 << 24),
883 eInfoRequestResponse_irrStatus = (1 << 23),
884 eInfoRequestResponse_unsolicited = (1 << 22),
885 eInfoRequestResponse_genericData = (1 << 21),
886 } options;
887 TransportAddress rasAddress;
888 InfoRequestResponse_callSignalAddress callSignalAddress;
889} InfoRequestResponse;
890
891typedef struct RasMessage { /* CHOICE */
892 enum {
893 eRasMessage_gatekeeperRequest,
894 eRasMessage_gatekeeperConfirm,
895 eRasMessage_gatekeeperReject,
896 eRasMessage_registrationRequest,
897 eRasMessage_registrationConfirm,
898 eRasMessage_registrationReject,
899 eRasMessage_unregistrationRequest,
900 eRasMessage_unregistrationConfirm,
901 eRasMessage_unregistrationReject,
902 eRasMessage_admissionRequest,
903 eRasMessage_admissionConfirm,
904 eRasMessage_admissionReject,
905 eRasMessage_bandwidthRequest,
906 eRasMessage_bandwidthConfirm,
907 eRasMessage_bandwidthReject,
908 eRasMessage_disengageRequest,
909 eRasMessage_disengageConfirm,
910 eRasMessage_disengageReject,
911 eRasMessage_locationRequest,
912 eRasMessage_locationConfirm,
913 eRasMessage_locationReject,
914 eRasMessage_infoRequest,
915 eRasMessage_infoRequestResponse,
916 eRasMessage_nonStandardMessage,
917 eRasMessage_unknownMessageResponse,
918 eRasMessage_requestInProgress,
919 eRasMessage_resourcesAvailableIndicate,
920 eRasMessage_resourcesAvailableConfirm,
921 eRasMessage_infoRequestAck,
922 eRasMessage_infoRequestNak,
923 eRasMessage_serviceControlIndication,
924 eRasMessage_serviceControlResponse,
925 } choice;
926 union {
927 GatekeeperRequest gatekeeperRequest;
928 GatekeeperConfirm gatekeeperConfirm;
929 RegistrationRequest registrationRequest;
930 RegistrationConfirm registrationConfirm;
931 UnregistrationRequest unregistrationRequest;
932 AdmissionRequest admissionRequest;
933 AdmissionConfirm admissionConfirm;
934 LocationRequest locationRequest;
935 LocationConfirm locationConfirm;
936 InfoRequestResponse infoRequestResponse;
937 };
938} RasMessage;
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 9b6e19bae90f..01bd7cab9367 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)
1658 printk("ctnetlink: unregistering from nfnetlink.\n"); 1658 printk("ctnetlink: unregistering from nfnetlink.\n");
1659 1659
1660#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS 1660#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
1661 ip_conntrack_unregister_notifier(&ctnl_notifier_exp); 1661 ip_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
1662 ip_conntrack_unregister_notifier(&ctnl_notifier); 1662 ip_conntrack_unregister_notifier(&ctnl_notifier);
1663#endif 1663#endif
1664 1664
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 3021af0910f1..d8b14a9010a6 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,
224 } 224 }
225 225
226 /* See ip_conntrack_proto_tcp.c */ 226 /* See ip_conntrack_proto_tcp.c */
227 if (hooknum != NF_IP_PRE_ROUTING) 227 if (hooknum == NF_IP_PRE_ROUTING &&
228 goto checksum_skipped; 228 nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
229 229 if (LOG_INVALID(IPPROTO_ICMP))
230 switch (skb->ip_summed) { 230 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
231 case CHECKSUM_HW: 231 "ip_ct_icmp: bad ICMP checksum ");
232 if (!(u16)csum_fold(skb->csum)) 232 return -NF_ACCEPT;
233 break;
234 /* fall through */
235 case CHECKSUM_NONE:
236 skb->csum = 0;
237 if (__skb_checksum_complete(skb)) {
238 if (LOG_INVALID(IPPROTO_ICMP))
239 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
240 "ip_ct_icmp: bad ICMP checksum ");
241 return -NF_ACCEPT;
242 }
243 } 233 }
244 234
245checksum_skipped:
246 /* 235 /*
247 * 18 is the highest 'known' ICMP type. Anything else is a mystery 236 * 18 is the highest 'known' ICMP type. Anything else is a mystery
248 * 237 *
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index e0dc37063545..062b252b58ad 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,
870 * and moreover root might send raw packets. 870 * and moreover root might send raw packets.
871 */ 871 */
872 /* FIXME: Source route IP option packets --RR */ 872 /* FIXME: Source route IP option packets --RR */
873 if (hooknum == NF_IP_PRE_ROUTING 873 if (hooknum == NF_IP_PRE_ROUTING &&
874 && skb->ip_summed != CHECKSUM_UNNECESSARY 874 nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
875 && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
876 skb->ip_summed == CHECKSUM_HW ? skb->csum
877 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
878 if (LOG_INVALID(IPPROTO_TCP)) 875 if (LOG_INVALID(IPPROTO_TCP))
879 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 876 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
880 "ip_ct_tcp: bad TCP checksum "); 877 "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 55b7d3210adf..70899868783b 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,
120 * because the semantic of CHECKSUM_HW is different there 120 * because the semantic of CHECKSUM_HW is different there
121 * and moreover root might send raw packets. 121 * and moreover root might send raw packets.
122 * FIXME: Source route IP option packets --RR */ 122 * FIXME: Source route IP option packets --RR */
123 if (hooknum == NF_IP_PRE_ROUTING 123 if (hooknum == NF_IP_PRE_ROUTING &&
124 && skb->ip_summed != CHECKSUM_UNNECESSARY 124 nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
125 && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
126 skb->ip_summed == CHECKSUM_HW ? skb->csum
127 : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
128 if (LOG_INVALID(IPPROTO_UDP)) 125 if (LOG_INVALID(IPPROTO_UDP))
129 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 126 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
130 "ip_ct_udp: bad UDP checksum "); 127 "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 52076026db36..929d61f7be91 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,
469 469
470/* Connection tracking may drop packets, but never alters them, so 470/* Connection tracking may drop packets, but never alters them, so
471 make it the first hook. */ 471 make it the first hook. */
472static struct nf_hook_ops ip_conntrack_defrag_ops = { 472static struct nf_hook_ops ip_conntrack_ops[] = {
473 .hook = ip_conntrack_defrag, 473 {
474 .owner = THIS_MODULE, 474 .hook = ip_conntrack_defrag,
475 .pf = PF_INET, 475 .owner = THIS_MODULE,
476 .hooknum = NF_IP_PRE_ROUTING, 476 .pf = PF_INET,
477 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 477 .hooknum = NF_IP_PRE_ROUTING,
478}; 478 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
479 479 },
480static struct nf_hook_ops ip_conntrack_in_ops = { 480 {
481 .hook = ip_conntrack_in, 481 .hook = ip_conntrack_in,
482 .owner = THIS_MODULE, 482 .owner = THIS_MODULE,
483 .pf = PF_INET, 483 .pf = PF_INET,
484 .hooknum = NF_IP_PRE_ROUTING, 484 .hooknum = NF_IP_PRE_ROUTING,
485 .priority = NF_IP_PRI_CONNTRACK, 485 .priority = NF_IP_PRI_CONNTRACK,
486}; 486 },
487 487 {
488static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = { 488 .hook = ip_conntrack_defrag,
489 .hook = ip_conntrack_defrag, 489 .owner = THIS_MODULE,
490 .owner = THIS_MODULE, 490 .pf = PF_INET,
491 .pf = PF_INET, 491 .hooknum = NF_IP_LOCAL_OUT,
492 .hooknum = NF_IP_LOCAL_OUT, 492 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
493 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 493 },
494}; 494 {
495 495 .hook = ip_conntrack_local,
496static struct nf_hook_ops ip_conntrack_local_out_ops = { 496 .owner = THIS_MODULE,
497 .hook = ip_conntrack_local, 497 .pf = PF_INET,
498 .owner = THIS_MODULE, 498 .hooknum = NF_IP_LOCAL_OUT,
499 .pf = PF_INET, 499 .priority = NF_IP_PRI_CONNTRACK,
500 .hooknum = NF_IP_LOCAL_OUT, 500 },
501 .priority = NF_IP_PRI_CONNTRACK, 501 {
502}; 502 .hook = ip_conntrack_help,
503 503 .owner = THIS_MODULE,
504/* helpers */ 504 .pf = PF_INET,
505static struct nf_hook_ops ip_conntrack_helper_out_ops = { 505 .hooknum = NF_IP_POST_ROUTING,
506 .hook = ip_conntrack_help, 506 .priority = NF_IP_PRI_CONNTRACK_HELPER,
507 .owner = THIS_MODULE, 507 },
508 .pf = PF_INET, 508 {
509 .hooknum = NF_IP_POST_ROUTING, 509 .hook = ip_conntrack_help,
510 .priority = NF_IP_PRI_CONNTRACK_HELPER, 510 .owner = THIS_MODULE,
511}; 511 .pf = PF_INET,
512 512 .hooknum = NF_IP_LOCAL_IN,
513static struct nf_hook_ops ip_conntrack_helper_in_ops = { 513 .priority = NF_IP_PRI_CONNTRACK_HELPER,
514 .hook = ip_conntrack_help, 514 },
515 .owner = THIS_MODULE, 515 {
516 .pf = PF_INET, 516 .hook = ip_confirm,
517 .hooknum = NF_IP_LOCAL_IN, 517 .owner = THIS_MODULE,
518 .priority = NF_IP_PRI_CONNTRACK_HELPER, 518 .pf = PF_INET,
519}; 519 .hooknum = NF_IP_POST_ROUTING,
520 520 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
521/* Refragmenter; last chance. */ 521 },
522static struct nf_hook_ops ip_conntrack_out_ops = { 522 {
523 .hook = ip_confirm, 523 .hook = ip_confirm,
524 .owner = THIS_MODULE, 524 .owner = THIS_MODULE,
525 .pf = PF_INET, 525 .pf = PF_INET,
526 .hooknum = NF_IP_POST_ROUTING, 526 .hooknum = NF_IP_LOCAL_IN,
527 .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 527 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
528}; 528 },
529
530static struct nf_hook_ops ip_conntrack_local_in_ops = {
531 .hook = ip_confirm,
532 .owner = THIS_MODULE,
533 .pf = PF_INET,
534 .hooknum = NF_IP_LOCAL_IN,
535 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
536}; 529};
537 530
538/* Sysctl support */ 531/* Sysctl support */
@@ -783,18 +776,46 @@ static ctl_table ip_ct_net_table[] = {
783EXPORT_SYMBOL(ip_ct_log_invalid); 776EXPORT_SYMBOL(ip_ct_log_invalid);
784#endif /* CONFIG_SYSCTL */ 777#endif /* CONFIG_SYSCTL */
785 778
786static int init_or_cleanup(int init) 779/* FIXME: Allow NULL functions and sub in pointers to generic for
780 them. --RR */
781int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
782{
783 int ret = 0;
784
785 write_lock_bh(&ip_conntrack_lock);
786 if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
787 ret = -EBUSY;
788 goto out;
789 }
790 ip_ct_protos[proto->proto] = proto;
791 out:
792 write_unlock_bh(&ip_conntrack_lock);
793 return ret;
794}
795
796void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
797{
798 write_lock_bh(&ip_conntrack_lock);
799 ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
800 write_unlock_bh(&ip_conntrack_lock);
801
802 /* Somebody could be still looking at the proto in bh. */
803 synchronize_net();
804
805 /* Remove all contrack entries for this protocol */
806 ip_ct_iterate_cleanup(kill_proto, &proto->proto);
807}
808
809static int __init ip_conntrack_standalone_init(void)
787{ 810{
788#ifdef CONFIG_PROC_FS 811#ifdef CONFIG_PROC_FS
789 struct proc_dir_entry *proc, *proc_exp, *proc_stat; 812 struct proc_dir_entry *proc, *proc_exp, *proc_stat;
790#endif 813#endif
791 int ret = 0; 814 int ret = 0;
792 815
793 if (!init) goto cleanup;
794
795 ret = ip_conntrack_init(); 816 ret = ip_conntrack_init();
796 if (ret < 0) 817 if (ret < 0)
797 goto cleanup_nothing; 818 return ret;
798 819
799#ifdef CONFIG_PROC_FS 820#ifdef CONFIG_PROC_FS
800 ret = -ENOMEM; 821 ret = -ENOMEM;
@@ -813,78 +834,25 @@ static int init_or_cleanup(int init)
813 proc_stat->owner = THIS_MODULE; 834 proc_stat->owner = THIS_MODULE;
814#endif 835#endif
815 836
816 ret = nf_register_hook(&ip_conntrack_defrag_ops); 837 ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
817 if (ret < 0) { 838 if (ret < 0) {
818 printk("ip_conntrack: can't register pre-routing defrag hook.\n"); 839 printk("ip_conntrack: can't register hooks.\n");
819 goto cleanup_proc_stat; 840 goto cleanup_proc_stat;
820 } 841 }
821 ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
822 if (ret < 0) {
823 printk("ip_conntrack: can't register local_out defrag hook.\n");
824 goto cleanup_defragops;
825 }
826 ret = nf_register_hook(&ip_conntrack_in_ops);
827 if (ret < 0) {
828 printk("ip_conntrack: can't register pre-routing hook.\n");
829 goto cleanup_defraglocalops;
830 }
831 ret = nf_register_hook(&ip_conntrack_local_out_ops);
832 if (ret < 0) {
833 printk("ip_conntrack: can't register local out hook.\n");
834 goto cleanup_inops;
835 }
836 ret = nf_register_hook(&ip_conntrack_helper_in_ops);
837 if (ret < 0) {
838 printk("ip_conntrack: can't register local in helper hook.\n");
839 goto cleanup_inandlocalops;
840 }
841 ret = nf_register_hook(&ip_conntrack_helper_out_ops);
842 if (ret < 0) {
843 printk("ip_conntrack: can't register postrouting helper hook.\n");
844 goto cleanup_helperinops;
845 }
846 ret = nf_register_hook(&ip_conntrack_out_ops);
847 if (ret < 0) {
848 printk("ip_conntrack: can't register post-routing hook.\n");
849 goto cleanup_helperoutops;
850 }
851 ret = nf_register_hook(&ip_conntrack_local_in_ops);
852 if (ret < 0) {
853 printk("ip_conntrack: can't register local in hook.\n");
854 goto cleanup_inoutandlocalops;
855 }
856#ifdef CONFIG_SYSCTL 842#ifdef CONFIG_SYSCTL
857 ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0); 843 ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
858 if (ip_ct_sysctl_header == NULL) { 844 if (ip_ct_sysctl_header == NULL) {
859 printk("ip_conntrack: can't register to sysctl.\n"); 845 printk("ip_conntrack: can't register to sysctl.\n");
860 ret = -ENOMEM; 846 ret = -ENOMEM;
861 goto cleanup_localinops; 847 goto cleanup_hooks;
862 } 848 }
863#endif 849#endif
864
865 return ret; 850 return ret;
866 851
867 cleanup:
868 synchronize_net();
869#ifdef CONFIG_SYSCTL 852#ifdef CONFIG_SYSCTL
870 unregister_sysctl_table(ip_ct_sysctl_header); 853 cleanup_hooks:
871 cleanup_localinops: 854 nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
872#endif 855#endif
873 nf_unregister_hook(&ip_conntrack_local_in_ops);
874 cleanup_inoutandlocalops:
875 nf_unregister_hook(&ip_conntrack_out_ops);
876 cleanup_helperoutops:
877 nf_unregister_hook(&ip_conntrack_helper_out_ops);
878 cleanup_helperinops:
879 nf_unregister_hook(&ip_conntrack_helper_in_ops);
880 cleanup_inandlocalops:
881 nf_unregister_hook(&ip_conntrack_local_out_ops);
882 cleanup_inops:
883 nf_unregister_hook(&ip_conntrack_in_ops);
884 cleanup_defraglocalops:
885 nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
886 cleanup_defragops:
887 nf_unregister_hook(&ip_conntrack_defrag_ops);
888 cleanup_proc_stat: 856 cleanup_proc_stat:
889#ifdef CONFIG_PROC_FS 857#ifdef CONFIG_PROC_FS
890 remove_proc_entry("ip_conntrack", proc_net_stat); 858 remove_proc_entry("ip_conntrack", proc_net_stat);
@@ -895,48 +863,22 @@ static int init_or_cleanup(int init)
895 cleanup_init: 863 cleanup_init:
896#endif /* CONFIG_PROC_FS */ 864#endif /* CONFIG_PROC_FS */
897 ip_conntrack_cleanup(); 865 ip_conntrack_cleanup();
898 cleanup_nothing:
899 return ret;
900}
901
902/* FIXME: Allow NULL functions and sub in pointers to generic for
903 them. --RR */
904int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
905{
906 int ret = 0;
907
908 write_lock_bh(&ip_conntrack_lock);
909 if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
910 ret = -EBUSY;
911 goto out;
912 }
913 ip_ct_protos[proto->proto] = proto;
914 out:
915 write_unlock_bh(&ip_conntrack_lock);
916 return ret; 866 return ret;
917} 867}
918 868
919void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
920{
921 write_lock_bh(&ip_conntrack_lock);
922 ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
923 write_unlock_bh(&ip_conntrack_lock);
924
925 /* Somebody could be still looking at the proto in bh. */
926 synchronize_net();
927
928 /* Remove all contrack entries for this protocol */
929 ip_ct_iterate_cleanup(kill_proto, &proto->proto);
930}
931
932static int __init ip_conntrack_standalone_init(void)
933{
934 return init_or_cleanup(1);
935}
936
937static void __exit ip_conntrack_standalone_fini(void) 869static void __exit ip_conntrack_standalone_fini(void)
938{ 870{
939 init_or_cleanup(0); 871 synchronize_net();
872#ifdef CONFIG_SYSCTL
873 unregister_sysctl_table(ip_ct_sysctl_header);
874#endif
875 nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
876#ifdef CONFIG_PROC_FS
877 remove_proc_entry("ip_conntrack", proc_net_stat);
878 proc_net_remove("ip_conntrack_expect");
879 proc_net_remove("ip_conntrack");
880#endif /* CONFIG_PROC_FS */
881 ip_conntrack_cleanup();
940} 882}
941 883
942module_init(ip_conntrack_standalone_init); 884module_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 a0bc883928c0..d45663d137a7 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -7,24 +7,6 @@
7 * 7 *
8 * Based on the 'brute force' H.323 NAT module by 8 * Based on the 'brute force' H.323 NAT module by
9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10 *
11 * Changes:
12 * 2006-02-01 - initial version 0.1
13 *
14 * 2006-02-20 - version 0.2
15 * 1. Changed source format to follow kernel conventions
16 * 2. Deleted some unnecessary structures
17 * 3. Minor fixes
18 *
19 * 2006-03-10 - version 0.3
20 * 1. Added support for multiple TPKTs in one packet (suggested by
21 * Patrick McHardy)
22 * 2. Added support for non-linear skb (based on Patrick McHardy's patch)
23 * 3. Eliminated unnecessary return code
24 *
25 * 2006-03-15 - version 0.4
26 * 1. Added support for T.120 channels
27 * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
28 */ 10 */
29 11
30#include <linux/module.h> 12#include <linux/module.h>
@@ -41,65 +23,12 @@
41#include <linux/netfilter_ipv4/ip_conntrack_h323.h> 23#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
42#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 24#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
43 25
44#include "ip_conntrack_helper_h323_asn1.h"
45
46#if 0 26#if 0
47#define DEBUGP printk 27#define DEBUGP printk
48#else 28#else
49#define DEBUGP(format, args...) 29#define DEBUGP(format, args...)
50#endif 30#endif
51 31
52extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
53 u_int32_t * ip, u_int16_t * port);
54extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
55 u_int32_t * ip, u_int16_t * port);
56extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
57 struct ip_conntrack_expect *this);
58extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
59 struct ip_conntrack_expect *this);
60extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
61 unsigned char **data, int dataoff,
62 H245_TransportAddress * addr,
63 u_int32_t ip, u_int16_t port);
64extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
65 unsigned char **data, int dataoff,
66 TransportAddress * addr,
67 u_int32_t ip, u_int16_t port);
68extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
69 struct ip_conntrack * ct,
70 enum ip_conntrack_info ctinfo,
71 unsigned char **data,
72 TransportAddress * addr, int count);
73extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
74 struct ip_conntrack * ct,
75 enum ip_conntrack_info ctinfo,
76 unsigned char **data,
77 TransportAddress * addr, int count);
78extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
79 struct ip_conntrack * ct,
80 enum ip_conntrack_info ctinfo,
81 unsigned char **data, int dataoff,
82 H245_TransportAddress * addr,
83 u_int16_t port, u_int16_t rtp_port,
84 struct ip_conntrack_expect * rtp_exp,
85 struct ip_conntrack_expect * rtcp_exp);
86extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
87 enum ip_conntrack_info ctinfo,
88 unsigned char **data, int dataoff,
89 H245_TransportAddress * addr, u_int16_t port,
90 struct ip_conntrack_expect * exp);
91extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
92 enum ip_conntrack_info ctinfo,
93 unsigned char **data, int dataoff,
94 TransportAddress * addr, u_int16_t port,
95 struct ip_conntrack_expect * exp);
96extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
97 enum ip_conntrack_info ctinfo,
98 unsigned char **data, TransportAddress * addr,
99 int idx, u_int16_t port,
100 struct ip_conntrack_expect * exp);
101
102
103/****************************************************************************/ 32/****************************************************************************/
104static int set_addr(struct sk_buff **pskb, 33static int set_addr(struct sk_buff **pskb,
105 unsigned char **data, int dataoff, 34 unsigned char **data, int dataoff,
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index efba8c4e42e0..1aba926c1cb0 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 = {
279 .target = ipt_dnat_target, 279 .target = ipt_dnat_target,
280 .targetsize = sizeof(struct ip_nat_multi_range_compat), 280 .targetsize = sizeof(struct ip_nat_multi_range_compat),
281 .table = "nat", 281 .table = "nat",
282 .hooks = 1 << NF_IP_PRE_ROUTING, 282 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
283 .checkentry = ipt_dnat_checkentry, 283 .checkentry = ipt_dnat_checkentry,
284}; 284};
285 285
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 3505b0de2e04..8f760b28617e 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,
299 299
300/* We must be after connection tracking and before packet filtering. */ 300/* We must be after connection tracking and before packet filtering. */
301 301
302/* Before packet filtering, change destination */ 302static struct nf_hook_ops ip_nat_ops[] = {
303static struct nf_hook_ops ip_nat_in_ops = { 303 /* Before packet filtering, change destination */
304 .hook = ip_nat_in, 304 {
305 .owner = THIS_MODULE, 305 .hook = ip_nat_in,
306 .pf = PF_INET, 306 .owner = THIS_MODULE,
307 .hooknum = NF_IP_PRE_ROUTING, 307 .pf = PF_INET,
308 .priority = NF_IP_PRI_NAT_DST, 308 .hooknum = NF_IP_PRE_ROUTING,
309 .priority = NF_IP_PRI_NAT_DST,
310 },
311 /* After packet filtering, change source */
312 {
313 .hook = ip_nat_out,
314 .owner = THIS_MODULE,
315 .pf = PF_INET,
316 .hooknum = NF_IP_POST_ROUTING,
317 .priority = NF_IP_PRI_NAT_SRC,
318 },
319 /* After conntrack, adjust sequence number */
320 {
321 .hook = ip_nat_adjust,
322 .owner = THIS_MODULE,
323 .pf = PF_INET,
324 .hooknum = NF_IP_POST_ROUTING,
325 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
326 },
327 /* Before packet filtering, change destination */
328 {
329 .hook = ip_nat_local_fn,
330 .owner = THIS_MODULE,
331 .pf = PF_INET,
332 .hooknum = NF_IP_LOCAL_OUT,
333 .priority = NF_IP_PRI_NAT_DST,
334 },
335 /* After packet filtering, change source */
336 {
337 .hook = ip_nat_fn,
338 .owner = THIS_MODULE,
339 .pf = PF_INET,
340 .hooknum = NF_IP_LOCAL_IN,
341 .priority = NF_IP_PRI_NAT_SRC,
342 },
343 /* After conntrack, adjust sequence number */
344 {
345 .hook = ip_nat_adjust,
346 .owner = THIS_MODULE,
347 .pf = PF_INET,
348 .hooknum = NF_IP_LOCAL_IN,
349 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
350 },
309}; 351};
310 352
311/* After packet filtering, change source */ 353static int __init ip_nat_standalone_init(void)
312static struct nf_hook_ops ip_nat_out_ops = {
313 .hook = ip_nat_out,
314 .owner = THIS_MODULE,
315 .pf = PF_INET,
316 .hooknum = NF_IP_POST_ROUTING,
317 .priority = NF_IP_PRI_NAT_SRC,
318};
319
320/* After conntrack, adjust sequence number */
321static struct nf_hook_ops ip_nat_adjust_out_ops = {
322 .hook = ip_nat_adjust,
323 .owner = THIS_MODULE,
324 .pf = PF_INET,
325 .hooknum = NF_IP_POST_ROUTING,
326 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
327};
328
329/* Before packet filtering, change destination */
330static struct nf_hook_ops ip_nat_local_out_ops = {
331 .hook = ip_nat_local_fn,
332 .owner = THIS_MODULE,
333 .pf = PF_INET,
334 .hooknum = NF_IP_LOCAL_OUT,
335 .priority = NF_IP_PRI_NAT_DST,
336};
337
338/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */
339static struct nf_hook_ops ip_nat_local_in_ops = {
340 .hook = ip_nat_fn,
341 .owner = THIS_MODULE,
342 .pf = PF_INET,
343 .hooknum = NF_IP_LOCAL_IN,
344 .priority = NF_IP_PRI_NAT_SRC,
345};
346
347/* After conntrack, adjust sequence number */
348static struct nf_hook_ops ip_nat_adjust_in_ops = {
349 .hook = ip_nat_adjust,
350 .owner = THIS_MODULE,
351 .pf = PF_INET,
352 .hooknum = NF_IP_LOCAL_IN,
353 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
354};
355
356
357static int init_or_cleanup(int init)
358{ 354{
359 int ret = 0; 355 int ret = 0;
360 356
361 need_conntrack(); 357 need_conntrack();
362 358
363 if (!init) goto cleanup;
364
365#ifdef CONFIG_XFRM 359#ifdef CONFIG_XFRM
366 BUG_ON(ip_nat_decode_session != NULL); 360 BUG_ON(ip_nat_decode_session != NULL);
367 ip_nat_decode_session = nat_decode_session; 361 ip_nat_decode_session = nat_decode_session;
@@ -371,50 +365,13 @@ static int init_or_cleanup(int init)
371 printk("ip_nat_init: can't setup rules.\n"); 365 printk("ip_nat_init: can't setup rules.\n");
372 goto cleanup_decode_session; 366 goto cleanup_decode_session;
373 } 367 }
374 ret = nf_register_hook(&ip_nat_in_ops); 368 ret = nf_register_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
375 if (ret < 0) { 369 if (ret < 0) {
376 printk("ip_nat_init: can't register in hook.\n"); 370 printk("ip_nat_init: can't register hooks.\n");
377 goto cleanup_rule_init; 371 goto cleanup_rule_init;
378 } 372 }
379 ret = nf_register_hook(&ip_nat_out_ops);
380 if (ret < 0) {
381 printk("ip_nat_init: can't register out hook.\n");
382 goto cleanup_inops;
383 }
384 ret = nf_register_hook(&ip_nat_adjust_in_ops);
385 if (ret < 0) {
386 printk("ip_nat_init: can't register adjust in hook.\n");
387 goto cleanup_outops;
388 }
389 ret = nf_register_hook(&ip_nat_adjust_out_ops);
390 if (ret < 0) {
391 printk("ip_nat_init: can't register adjust out hook.\n");
392 goto cleanup_adjustin_ops;
393 }
394 ret = nf_register_hook(&ip_nat_local_out_ops);
395 if (ret < 0) {
396 printk("ip_nat_init: can't register local out hook.\n");
397 goto cleanup_adjustout_ops;
398 }
399 ret = nf_register_hook(&ip_nat_local_in_ops);
400 if (ret < 0) {
401 printk("ip_nat_init: can't register local in hook.\n");
402 goto cleanup_localoutops;
403 }
404 return ret; 373 return ret;
405 374
406 cleanup:
407 nf_unregister_hook(&ip_nat_local_in_ops);
408 cleanup_localoutops:
409 nf_unregister_hook(&ip_nat_local_out_ops);
410 cleanup_adjustout_ops:
411 nf_unregister_hook(&ip_nat_adjust_out_ops);
412 cleanup_adjustin_ops:
413 nf_unregister_hook(&ip_nat_adjust_in_ops);
414 cleanup_outops:
415 nf_unregister_hook(&ip_nat_out_ops);
416 cleanup_inops:
417 nf_unregister_hook(&ip_nat_in_ops);
418 cleanup_rule_init: 375 cleanup_rule_init:
419 ip_nat_rule_cleanup(); 376 ip_nat_rule_cleanup();
420 cleanup_decode_session: 377 cleanup_decode_session:
@@ -425,14 +382,14 @@ static int init_or_cleanup(int init)
425 return ret; 382 return ret;
426} 383}
427 384
428static int __init ip_nat_standalone_init(void)
429{
430 return init_or_cleanup(1);
431}
432
433static void __exit ip_nat_standalone_fini(void) 385static void __exit ip_nat_standalone_fini(void)
434{ 386{
435 init_or_cleanup(0); 387 nf_unregister_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
388 ip_nat_rule_cleanup();
389#ifdef CONFIG_XFRM
390 ip_nat_decode_session = NULL;
391 synchronize_net();
392#endif
436} 393}
437 394
438module_init(ip_nat_standalone_init); 395module_init(ip_nat_standalone_init);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 896a244f8f91..b93f0494362f 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 = {
662 .outfn = &ipq_enqueue_packet, 662 .outfn = &ipq_enqueue_packet,
663}; 663};
664 664
665static int 665static int __init ip_queue_init(void)
666init_or_cleanup(int init)
667{ 666{
668 int status = -ENOMEM; 667 int status = -ENOMEM;
669 struct proc_dir_entry *proc; 668 struct proc_dir_entry *proc;
670 669
671 if (!init)
672 goto cleanup;
673
674 netlink_register_notifier(&ipq_nl_notifier); 670 netlink_register_notifier(&ipq_nl_notifier);
675 ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk, 671 ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
676 THIS_MODULE); 672 THIS_MODULE);
@@ -697,11 +693,6 @@ init_or_cleanup(int init)
697 } 693 }
698 return status; 694 return status;
699 695
700cleanup:
701 nf_unregister_queue_handlers(&nfqh);
702 synchronize_net();
703 ipq_flush(NF_DROP);
704
705cleanup_sysctl: 696cleanup_sysctl:
706 unregister_sysctl_table(ipq_sysctl_header); 697 unregister_sysctl_table(ipq_sysctl_header);
707 unregister_netdevice_notifier(&ipq_dev_notifier); 698 unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -717,15 +708,21 @@ cleanup_netlink_notifier:
717 return status; 708 return status;
718} 709}
719 710
720static int __init ip_queue_init(void)
721{
722
723 return init_or_cleanup(1);
724}
725
726static void __exit ip_queue_fini(void) 711static void __exit ip_queue_fini(void)
727{ 712{
728 init_or_cleanup(0); 713 nf_unregister_queue_handlers(&nfqh);
714 synchronize_net();
715 ipq_flush(NF_DROP);
716
717 unregister_sysctl_table(ipq_sysctl_header);
718 unregister_netdevice_notifier(&ipq_dev_notifier);
719 proc_net_remove(IPQ_PROC_FS_NAME);
720
721 sock_release(ipqnl->sk_socket);
722 mutex_lock(&ipqnl_mutex);
723 mutex_unlock(&ipqnl_mutex);
724
725 netlink_unregister_notifier(&ipq_nl_notifier);
729} 726}
730 727
731MODULE_DESCRIPTION("IPv4 packet queue handler"); 728MODULE_DESCRIPTION("IPv4 packet queue handler");
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 460fd905fad0..d25ac8ba6eba 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -24,6 +24,7 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/icmp.h> 25#include <linux/icmp.h>
26#include <net/ip.h> 26#include <net/ip.h>
27#include <net/compat.h>
27#include <asm/uaccess.h> 28#include <asm/uaccess.h>
28#include <linux/mutex.h> 29#include <linux/mutex.h>
29#include <linux/proc_fs.h> 30#include <linux/proc_fs.h>
@@ -734,7 +735,7 @@ translate_table(const char *name,
734 } 735 }
735 736
736 /* And one copy for every other CPU */ 737 /* And one copy for every other CPU */
737 for_each_cpu(i) { 738 for_each_possible_cpu(i) {
738 if (newinfo->entries[i] && newinfo->entries[i] != entry0) 739 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
739 memcpy(newinfo->entries[i], entry0, newinfo->size); 740 memcpy(newinfo->entries[i], entry0, newinfo->size);
740 } 741 }
@@ -787,7 +788,7 @@ get_counters(const struct xt_table_info *t,
787 counters, 788 counters,
788 &i); 789 &i);
789 790
790 for_each_cpu(cpu) { 791 for_each_possible_cpu(cpu) {
791 if (cpu == curcpu) 792 if (cpu == curcpu)
792 continue; 793 continue;
793 i = 0; 794 i = 0;
@@ -799,17 +800,11 @@ get_counters(const struct xt_table_info *t,
799 } 800 }
800} 801}
801 802
802static int 803static inline struct xt_counters * alloc_counters(struct ipt_table *table)
803copy_entries_to_user(unsigned int total_size,
804 struct ipt_table *table,
805 void __user *userptr)
806{ 804{
807 unsigned int off, num, countersize; 805 unsigned int countersize;
808 struct ipt_entry *e;
809 struct xt_counters *counters; 806 struct xt_counters *counters;
810 struct xt_table_info *private = table->private; 807 struct xt_table_info *private = table->private;
811 int ret = 0;
812 void *loc_cpu_entry;
813 808
814 /* We need atomic snapshot of counters: rest doesn't change 809 /* We need atomic snapshot of counters: rest doesn't change
815 (other than comefrom, which userspace doesn't care 810 (other than comefrom, which userspace doesn't care
@@ -818,13 +813,32 @@ copy_entries_to_user(unsigned int total_size,
818 counters = vmalloc_node(countersize, numa_node_id()); 813 counters = vmalloc_node(countersize, numa_node_id());
819 814
820 if (counters == NULL) 815 if (counters == NULL)
821 return -ENOMEM; 816 return ERR_PTR(-ENOMEM);
822 817
823 /* First, sum counters... */ 818 /* First, sum counters... */
824 write_lock_bh(&table->lock); 819 write_lock_bh(&table->lock);
825 get_counters(private, counters); 820 get_counters(private, counters);
826 write_unlock_bh(&table->lock); 821 write_unlock_bh(&table->lock);
827 822
823 return counters;
824}
825
826static int
827copy_entries_to_user(unsigned int total_size,
828 struct ipt_table *table,
829 void __user *userptr)
830{
831 unsigned int off, num;
832 struct ipt_entry *e;
833 struct xt_counters *counters;
834 struct xt_table_info *private = table->private;
835 int ret = 0;
836 void *loc_cpu_entry;
837
838 counters = alloc_counters(table);
839 if (IS_ERR(counters))
840 return PTR_ERR(counters);
841
828 /* choose the copy that is on our node/cpu, ... 842 /* choose the copy that is on our node/cpu, ...
829 * This choice is lazy (because current thread is 843 * This choice is lazy (because current thread is
830 * allowed to migrate to another cpu) 844 * allowed to migrate to another cpu)
@@ -884,25 +898,278 @@ copy_entries_to_user(unsigned int total_size,
884 return ret; 898 return ret;
885} 899}
886 900
901#ifdef CONFIG_COMPAT
902struct compat_delta {
903 struct compat_delta *next;
904 u_int16_t offset;
905 short delta;
906};
907
908static struct compat_delta *compat_offsets = NULL;
909
910static int compat_add_offset(u_int16_t offset, short delta)
911{
912 struct compat_delta *tmp;
913
914 tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
915 if (!tmp)
916 return -ENOMEM;
917 tmp->offset = offset;
918 tmp->delta = delta;
919 if (compat_offsets) {
920 tmp->next = compat_offsets->next;
921 compat_offsets->next = tmp;
922 } else {
923 compat_offsets = tmp;
924 tmp->next = NULL;
925 }
926 return 0;
927}
928
929static void compat_flush_offsets(void)
930{
931 struct compat_delta *tmp, *next;
932
933 if (compat_offsets) {
934 for(tmp = compat_offsets; tmp; tmp = next) {
935 next = tmp->next;
936 kfree(tmp);
937 }
938 compat_offsets = NULL;
939 }
940}
941
942static short compat_calc_jump(u_int16_t offset)
943{
944 struct compat_delta *tmp;
945 short delta;
946
947 for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
948 if (tmp->offset < offset)
949 delta += tmp->delta;
950 return delta;
951}
952
953struct compat_ipt_standard_target
954{
955 struct compat_xt_entry_target target;
956 compat_int_t verdict;
957};
958
959#define IPT_ST_OFFSET (sizeof(struct ipt_standard_target) - \
960 sizeof(struct compat_ipt_standard_target))
961
962struct compat_ipt_standard
963{
964 struct compat_ipt_entry entry;
965 struct compat_ipt_standard_target target;
966};
967
968static int compat_ipt_standard_fn(void *target,
969 void **dstptr, int *size, int convert)
970{
971 struct compat_ipt_standard_target compat_st, *pcompat_st;
972 struct ipt_standard_target st, *pst;
973 int ret;
974
975 ret = 0;
976 switch (convert) {
977 case COMPAT_TO_USER:
978 pst = (struct ipt_standard_target *)target;
979 memcpy(&compat_st.target, &pst->target,
980 sizeof(struct ipt_entry_target));
981 compat_st.verdict = pst->verdict;
982 if (compat_st.verdict > 0)
983 compat_st.verdict -=
984 compat_calc_jump(compat_st.verdict);
985 compat_st.target.u.user.target_size =
986 sizeof(struct compat_ipt_standard_target);
987 if (__copy_to_user(*dstptr, &compat_st,
988 sizeof(struct compat_ipt_standard_target)))
989 ret = -EFAULT;
990 *size -= IPT_ST_OFFSET;
991 *dstptr += sizeof(struct compat_ipt_standard_target);
992 break;
993 case COMPAT_FROM_USER:
994 pcompat_st =
995 (struct compat_ipt_standard_target *)target;
996 memcpy(&st.target, &pcompat_st->target,
997 sizeof(struct ipt_entry_target));
998 st.verdict = pcompat_st->verdict;
999 if (st.verdict > 0)
1000 st.verdict += compat_calc_jump(st.verdict);
1001 st.target.u.user.target_size =
1002 sizeof(struct ipt_standard_target);
1003 memcpy(*dstptr, &st,
1004 sizeof(struct ipt_standard_target));
1005 *size += IPT_ST_OFFSET;
1006 *dstptr += sizeof(struct ipt_standard_target);
1007 break;
1008 case COMPAT_CALC_SIZE:
1009 *size += IPT_ST_OFFSET;
1010 break;
1011 default:
1012 ret = -ENOPROTOOPT;
1013 break;
1014 }
1015 return ret;
1016}
1017
1018static inline int
1019compat_calc_match(struct ipt_entry_match *m, int * size)
1020{
1021 if (m->u.kernel.match->compat)
1022 m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
1023 else
1024 xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
1025 return 0;
1026}
1027
1028static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
1029 void *base, struct xt_table_info *newinfo)
1030{
1031 struct ipt_entry_target *t;
1032 u_int16_t entry_offset;
1033 int off, i, ret;
1034
1035 off = 0;
1036 entry_offset = (void *)e - base;
1037 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1038 t = ipt_get_target(e);
1039 if (t->u.kernel.target->compat)
1040 t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
1041 else
1042 xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
1043 newinfo->size -= off;
1044 ret = compat_add_offset(entry_offset, off);
1045 if (ret)
1046 return ret;
1047
1048 for (i = 0; i< NF_IP_NUMHOOKS; i++) {
1049 if (info->hook_entry[i] && (e < (struct ipt_entry *)
1050 (base + info->hook_entry[i])))
1051 newinfo->hook_entry[i] -= off;
1052 if (info->underflow[i] && (e < (struct ipt_entry *)
1053 (base + info->underflow[i])))
1054 newinfo->underflow[i] -= off;
1055 }
1056 return 0;
1057}
1058
1059static int compat_table_info(struct xt_table_info *info,
1060 struct xt_table_info *newinfo)
1061{
1062 void *loc_cpu_entry;
1063 int i;
1064
1065 if (!newinfo || !info)
1066 return -EINVAL;
1067
1068 memset(newinfo, 0, sizeof(struct xt_table_info));
1069 newinfo->size = info->size;
1070 newinfo->number = info->number;
1071 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1072 newinfo->hook_entry[i] = info->hook_entry[i];
1073 newinfo->underflow[i] = info->underflow[i];
1074 }
1075 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1076 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1077 compat_calc_entry, info, loc_cpu_entry, newinfo);
1078}
1079#endif
1080
1081static int get_info(void __user *user, int *len, int compat)
1082{
1083 char name[IPT_TABLE_MAXNAMELEN];
1084 struct ipt_table *t;
1085 int ret;
1086
1087 if (*len != sizeof(struct ipt_getinfo)) {
1088 duprintf("length %u != %u\n", *len,
1089 (unsigned int)sizeof(struct ipt_getinfo));
1090 return -EINVAL;
1091 }
1092
1093 if (copy_from_user(name, user, sizeof(name)) != 0)
1094 return -EFAULT;
1095
1096 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1097#ifdef CONFIG_COMPAT
1098 if (compat)
1099 xt_compat_lock(AF_INET);
1100#endif
1101 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1102 "iptable_%s", name);
1103 if (t && !IS_ERR(t)) {
1104 struct ipt_getinfo info;
1105 struct xt_table_info *private = t->private;
1106
1107#ifdef CONFIG_COMPAT
1108 if (compat) {
1109 struct xt_table_info tmp;
1110 ret = compat_table_info(private, &tmp);
1111 compat_flush_offsets();
1112 private = &tmp;
1113 }
1114#endif
1115 info.valid_hooks = t->valid_hooks;
1116 memcpy(info.hook_entry, private->hook_entry,
1117 sizeof(info.hook_entry));
1118 memcpy(info.underflow, private->underflow,
1119 sizeof(info.underflow));
1120 info.num_entries = private->number;
1121 info.size = private->size;
1122 strcpy(info.name, name);
1123
1124 if (copy_to_user(user, &info, *len) != 0)
1125 ret = -EFAULT;
1126 else
1127 ret = 0;
1128
1129 xt_table_unlock(t);
1130 module_put(t->me);
1131 } else
1132 ret = t ? PTR_ERR(t) : -ENOENT;
1133#ifdef CONFIG_COMPAT
1134 if (compat)
1135 xt_compat_unlock(AF_INET);
1136#endif
1137 return ret;
1138}
1139
887static int 1140static int
888get_entries(const struct ipt_get_entries *entries, 1141get_entries(struct ipt_get_entries __user *uptr, int *len)
889 struct ipt_get_entries __user *uptr)
890{ 1142{
891 int ret; 1143 int ret;
1144 struct ipt_get_entries get;
892 struct ipt_table *t; 1145 struct ipt_table *t;
893 1146
894 t = xt_find_table_lock(AF_INET, entries->name); 1147 if (*len < sizeof(get)) {
1148 duprintf("get_entries: %u < %d\n", *len,
1149 (unsigned int)sizeof(get));
1150 return -EINVAL;
1151 }
1152 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1153 return -EFAULT;
1154 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1155 duprintf("get_entries: %u != %u\n", *len,
1156 (unsigned int)(sizeof(struct ipt_get_entries) +
1157 get.size));
1158 return -EINVAL;
1159 }
1160
1161 t = xt_find_table_lock(AF_INET, get.name);
895 if (t && !IS_ERR(t)) { 1162 if (t && !IS_ERR(t)) {
896 struct xt_table_info *private = t->private; 1163 struct xt_table_info *private = t->private;
897 duprintf("t->private->number = %u\n", 1164 duprintf("t->private->number = %u\n",
898 private->number); 1165 private->number);
899 if (entries->size == private->size) 1166 if (get.size == private->size)
900 ret = copy_entries_to_user(private->size, 1167 ret = copy_entries_to_user(private->size,
901 t, uptr->entrytable); 1168 t, uptr->entrytable);
902 else { 1169 else {
903 duprintf("get_entries: I've got %u not %u!\n", 1170 duprintf("get_entries: I've got %u not %u!\n",
904 private->size, 1171 private->size,
905 entries->size); 1172 get.size);
906 ret = -EINVAL; 1173 ret = -EINVAL;
907 } 1174 }
908 module_put(t->me); 1175 module_put(t->me);
@@ -914,79 +1181,47 @@ get_entries(const struct ipt_get_entries *entries,
914} 1181}
915 1182
916static int 1183static int
917do_replace(void __user *user, unsigned int len) 1184__do_replace(const char *name, unsigned int valid_hooks,
1185 struct xt_table_info *newinfo, unsigned int num_counters,
1186 void __user *counters_ptr)
918{ 1187{
919 int ret; 1188 int ret;
920 struct ipt_replace tmp;
921 struct ipt_table *t; 1189 struct ipt_table *t;
922 struct xt_table_info *newinfo, *oldinfo; 1190 struct xt_table_info *oldinfo;
923 struct xt_counters *counters; 1191 struct xt_counters *counters;
924 void *loc_cpu_entry, *loc_cpu_old_entry; 1192 void *loc_cpu_old_entry;
925 1193
926 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1194 ret = 0;
927 return -EFAULT; 1195 counters = vmalloc(num_counters * sizeof(struct xt_counters));
928
929 /* Hack: Causes ipchains to give correct error msg --RR */
930 if (len != sizeof(tmp) + tmp.size)
931 return -ENOPROTOOPT;
932
933 /* overflow check */
934 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
935 SMP_CACHE_BYTES)
936 return -ENOMEM;
937 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
938 return -ENOMEM;
939
940 newinfo = xt_alloc_table_info(tmp.size);
941 if (!newinfo)
942 return -ENOMEM;
943
944 /* choose the copy that is our node/cpu */
945 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
946 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
947 tmp.size) != 0) {
948 ret = -EFAULT;
949 goto free_newinfo;
950 }
951
952 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
953 if (!counters) { 1196 if (!counters) {
954 ret = -ENOMEM; 1197 ret = -ENOMEM;
955 goto free_newinfo; 1198 goto out;
956 } 1199 }
957 1200
958 ret = translate_table(tmp.name, tmp.valid_hooks, 1201 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
959 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, 1202 "iptable_%s", name);
960 tmp.hook_entry, tmp.underflow);
961 if (ret != 0)
962 goto free_newinfo_counters;
963
964 duprintf("ip_tables: Translated table\n");
965
966 t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name),
967 "iptable_%s", tmp.name);
968 if (!t || IS_ERR(t)) { 1203 if (!t || IS_ERR(t)) {
969 ret = t ? PTR_ERR(t) : -ENOENT; 1204 ret = t ? PTR_ERR(t) : -ENOENT;
970 goto free_newinfo_counters_untrans; 1205 goto free_newinfo_counters_untrans;
971 } 1206 }
972 1207
973 /* You lied! */ 1208 /* You lied! */
974 if (tmp.valid_hooks != t->valid_hooks) { 1209 if (valid_hooks != t->valid_hooks) {
975 duprintf("Valid hook crap: %08X vs %08X\n", 1210 duprintf("Valid hook crap: %08X vs %08X\n",
976 tmp.valid_hooks, t->valid_hooks); 1211 valid_hooks, t->valid_hooks);
977 ret = -EINVAL; 1212 ret = -EINVAL;
978 goto put_module; 1213 goto put_module;
979 } 1214 }
980 1215
981 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); 1216 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
982 if (!oldinfo) 1217 if (!oldinfo)
983 goto put_module; 1218 goto put_module;
984 1219
985 /* Update module usage count based on number of rules */ 1220 /* Update module usage count based on number of rules */
986 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", 1221 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
987 oldinfo->number, oldinfo->initial_entries, newinfo->number); 1222 oldinfo->number, oldinfo->initial_entries, newinfo->number);
988 if ((oldinfo->number > oldinfo->initial_entries) || 1223 if ((oldinfo->number > oldinfo->initial_entries) ||
989 (newinfo->number <= oldinfo->initial_entries)) 1224 (newinfo->number <= oldinfo->initial_entries))
990 module_put(t->me); 1225 module_put(t->me);
991 if ((oldinfo->number > oldinfo->initial_entries) && 1226 if ((oldinfo->number > oldinfo->initial_entries) &&
992 (newinfo->number <= oldinfo->initial_entries)) 1227 (newinfo->number <= oldinfo->initial_entries))
@@ -998,8 +1233,8 @@ do_replace(void __user *user, unsigned int len)
998 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1233 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
999 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); 1234 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1000 xt_free_table_info(oldinfo); 1235 xt_free_table_info(oldinfo);
1001 if (copy_to_user(tmp.counters, counters, 1236 if (copy_to_user(counters_ptr, counters,
1002 sizeof(struct xt_counters) * tmp.num_counters) != 0) 1237 sizeof(struct xt_counters) * num_counters) != 0)
1003 ret = -EFAULT; 1238 ret = -EFAULT;
1004 vfree(counters); 1239 vfree(counters);
1005 xt_table_unlock(t); 1240 xt_table_unlock(t);
@@ -1009,9 +1244,62 @@ do_replace(void __user *user, unsigned int len)
1009 module_put(t->me); 1244 module_put(t->me);
1010 xt_table_unlock(t); 1245 xt_table_unlock(t);
1011 free_newinfo_counters_untrans: 1246 free_newinfo_counters_untrans:
1012 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1013 free_newinfo_counters:
1014 vfree(counters); 1247 vfree(counters);
1248 out:
1249 return ret;
1250}
1251
1252static int
1253do_replace(void __user *user, unsigned int len)
1254{
1255 int ret;
1256 struct ipt_replace tmp;
1257 struct xt_table_info *newinfo;
1258 void *loc_cpu_entry;
1259
1260 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1261 return -EFAULT;
1262
1263 /* Hack: Causes ipchains to give correct error msg --RR */
1264 if (len != sizeof(tmp) + tmp.size)
1265 return -ENOPROTOOPT;
1266
1267 /* overflow check */
1268 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1269 SMP_CACHE_BYTES)
1270 return -ENOMEM;
1271 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1272 return -ENOMEM;
1273
1274 newinfo = xt_alloc_table_info(tmp.size);
1275 if (!newinfo)
1276 return -ENOMEM;
1277
1278 /* choose the copy that is our node/cpu */
1279 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1280 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1281 tmp.size) != 0) {
1282 ret = -EFAULT;
1283 goto free_newinfo;
1284 }
1285
1286 ret = translate_table(tmp.name, tmp.valid_hooks,
1287 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1288 tmp.hook_entry, tmp.underflow);
1289 if (ret != 0)
1290 goto free_newinfo;
1291
1292 duprintf("ip_tables: Translated table\n");
1293
1294 ret = __do_replace(tmp.name, tmp.valid_hooks,
1295 newinfo, tmp.num_counters,
1296 tmp.counters);
1297 if (ret)
1298 goto free_newinfo_untrans;
1299 return 0;
1300
1301 free_newinfo_untrans:
1302 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1015 free_newinfo: 1303 free_newinfo:
1016 xt_free_table_info(newinfo); 1304 xt_free_table_info(newinfo);
1017 return ret; 1305 return ret;
@@ -1040,31 +1328,59 @@ add_counter_to_entry(struct ipt_entry *e,
1040} 1328}
1041 1329
1042static int 1330static int
1043do_add_counters(void __user *user, unsigned int len) 1331do_add_counters(void __user *user, unsigned int len, int compat)
1044{ 1332{
1045 unsigned int i; 1333 unsigned int i;
1046 struct xt_counters_info tmp, *paddc; 1334 struct xt_counters_info tmp;
1335 struct xt_counters *paddc;
1336 unsigned int num_counters;
1337 char *name;
1338 int size;
1339 void *ptmp;
1047 struct ipt_table *t; 1340 struct ipt_table *t;
1048 struct xt_table_info *private; 1341 struct xt_table_info *private;
1049 int ret = 0; 1342 int ret = 0;
1050 void *loc_cpu_entry; 1343 void *loc_cpu_entry;
1344#ifdef CONFIG_COMPAT
1345 struct compat_xt_counters_info compat_tmp;
1051 1346
1052 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1347 if (compat) {
1348 ptmp = &compat_tmp;
1349 size = sizeof(struct compat_xt_counters_info);
1350 } else
1351#endif
1352 {
1353 ptmp = &tmp;
1354 size = sizeof(struct xt_counters_info);
1355 }
1356
1357 if (copy_from_user(ptmp, user, size) != 0)
1053 return -EFAULT; 1358 return -EFAULT;
1054 1359
1055 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) 1360#ifdef CONFIG_COMPAT
1361 if (compat) {
1362 num_counters = compat_tmp.num_counters;
1363 name = compat_tmp.name;
1364 } else
1365#endif
1366 {
1367 num_counters = tmp.num_counters;
1368 name = tmp.name;
1369 }
1370
1371 if (len != size + num_counters * sizeof(struct xt_counters))
1056 return -EINVAL; 1372 return -EINVAL;
1057 1373
1058 paddc = vmalloc_node(len, numa_node_id()); 1374 paddc = vmalloc_node(len - size, numa_node_id());
1059 if (!paddc) 1375 if (!paddc)
1060 return -ENOMEM; 1376 return -ENOMEM;
1061 1377
1062 if (copy_from_user(paddc, user, len) != 0) { 1378 if (copy_from_user(paddc, user + size, len - size) != 0) {
1063 ret = -EFAULT; 1379 ret = -EFAULT;
1064 goto free; 1380 goto free;
1065 } 1381 }
1066 1382
1067 t = xt_find_table_lock(AF_INET, tmp.name); 1383 t = xt_find_table_lock(AF_INET, name);
1068 if (!t || IS_ERR(t)) { 1384 if (!t || IS_ERR(t)) {
1069 ret = t ? PTR_ERR(t) : -ENOENT; 1385 ret = t ? PTR_ERR(t) : -ENOENT;
1070 goto free; 1386 goto free;
@@ -1072,7 +1388,7 @@ do_add_counters(void __user *user, unsigned int len)
1072 1388
1073 write_lock_bh(&t->lock); 1389 write_lock_bh(&t->lock);
1074 private = t->private; 1390 private = t->private;
1075 if (private->number != paddc->num_counters) { 1391 if (private->number != num_counters) {
1076 ret = -EINVAL; 1392 ret = -EINVAL;
1077 goto unlock_up_free; 1393 goto unlock_up_free;
1078 } 1394 }
@@ -1083,7 +1399,7 @@ do_add_counters(void __user *user, unsigned int len)
1083 IPT_ENTRY_ITERATE(loc_cpu_entry, 1399 IPT_ENTRY_ITERATE(loc_cpu_entry,
1084 private->size, 1400 private->size,
1085 add_counter_to_entry, 1401 add_counter_to_entry,
1086 paddc->counters, 1402 paddc,
1087 &i); 1403 &i);
1088 unlock_up_free: 1404 unlock_up_free:
1089 write_unlock_bh(&t->lock); 1405 write_unlock_bh(&t->lock);
@@ -1095,8 +1411,438 @@ do_add_counters(void __user *user, unsigned int len)
1095 return ret; 1411 return ret;
1096} 1412}
1097 1413
1414#ifdef CONFIG_COMPAT
1415struct compat_ipt_replace {
1416 char name[IPT_TABLE_MAXNAMELEN];
1417 u32 valid_hooks;
1418 u32 num_entries;
1419 u32 size;
1420 u32 hook_entry[NF_IP_NUMHOOKS];
1421 u32 underflow[NF_IP_NUMHOOKS];
1422 u32 num_counters;
1423 compat_uptr_t counters; /* struct ipt_counters * */
1424 struct compat_ipt_entry entries[0];
1425};
1426
1427static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
1428 void __user **dstptr, compat_uint_t *size)
1429{
1430 if (m->u.kernel.match->compat)
1431 return m->u.kernel.match->compat(m, dstptr, size,
1432 COMPAT_TO_USER);
1433 else
1434 return xt_compat_match(m, dstptr, size, COMPAT_TO_USER);
1435}
1436
1437static int compat_copy_entry_to_user(struct ipt_entry *e,
1438 void __user **dstptr, compat_uint_t *size)
1439{
1440 struct ipt_entry_target __user *t;
1441 struct compat_ipt_entry __user *ce;
1442 u_int16_t target_offset, next_offset;
1443 compat_uint_t origsize;
1444 int ret;
1445
1446 ret = -EFAULT;
1447 origsize = *size;
1448 ce = (struct compat_ipt_entry __user *)*dstptr;
1449 if (__copy_to_user(ce, e, sizeof(struct ipt_entry)))
1450 goto out;
1451
1452 *dstptr += sizeof(struct compat_ipt_entry);
1453 ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
1454 target_offset = e->target_offset - (origsize - *size);
1455 if (ret)
1456 goto out;
1457 t = ipt_get_target(e);
1458 if (t->u.kernel.target->compat)
1459 ret = t->u.kernel.target->compat(t, dstptr, size,
1460 COMPAT_TO_USER);
1461 else
1462 ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER);
1463 if (ret)
1464 goto out;
1465 ret = -EFAULT;
1466 next_offset = e->next_offset - (origsize - *size);
1467 if (__put_user(target_offset, &ce->target_offset))
1468 goto out;
1469 if (__put_user(next_offset, &ce->next_offset))
1470 goto out;
1471 return 0;
1472out:
1473 return ret;
1474}
1475
1476static inline int
1477compat_check_calc_match(struct ipt_entry_match *m,
1478 const char *name,
1479 const struct ipt_ip *ip,
1480 unsigned int hookmask,
1481 int *size, int *i)
1482{
1483 struct ipt_match *match;
1484
1485 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1486 m->u.user.revision),
1487 "ipt_%s", m->u.user.name);
1488 if (IS_ERR(match) || !match) {
1489 duprintf("compat_check_calc_match: `%s' not found\n",
1490 m->u.user.name);
1491 return match ? PTR_ERR(match) : -ENOENT;
1492 }
1493 m->u.kernel.match = match;
1494
1495 if (m->u.kernel.match->compat)
1496 m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
1497 else
1498 xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
1499
1500 (*i)++;
1501 return 0;
1502}
1503
1504static inline int
1505check_compat_entry_size_and_hooks(struct ipt_entry *e,
1506 struct xt_table_info *newinfo,
1507 unsigned int *size,
1508 unsigned char *base,
1509 unsigned char *limit,
1510 unsigned int *hook_entries,
1511 unsigned int *underflows,
1512 unsigned int *i,
1513 const char *name)
1514{
1515 struct ipt_entry_target *t;
1516 struct ipt_target *target;
1517 u_int16_t entry_offset;
1518 int ret, off, h, j;
1519
1520 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1521 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1522 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1523 duprintf("Bad offset %p, limit = %p\n", e, limit);
1524 return -EINVAL;
1525 }
1526
1527 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1528 sizeof(struct compat_xt_entry_target)) {
1529 duprintf("checking: element %p size %u\n",
1530 e, e->next_offset);
1531 return -EINVAL;
1532 }
1533
1534 if (!ip_checkentry(&e->ip)) {
1535 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
1536 return -EINVAL;
1537 }
1538
1539 off = 0;
1540 entry_offset = (void *)e - (void *)base;
1541 j = 0;
1542 ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
1543 e->comefrom, &off, &j);
1544 if (ret != 0)
1545 goto out;
1546
1547 t = ipt_get_target(e);
1548 target = try_then_request_module(xt_find_target(AF_INET,
1549 t->u.user.name,
1550 t->u.user.revision),
1551 "ipt_%s", t->u.user.name);
1552 if (IS_ERR(target) || !target) {
1553 duprintf("check_entry: `%s' not found\n", t->u.user.name);
1554 ret = target ? PTR_ERR(target) : -ENOENT;
1555 goto out;
1556 }
1557 t->u.kernel.target = target;
1558
1559 if (t->u.kernel.target->compat)
1560 t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
1561 else
1562 xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
1563 *size += off;
1564 ret = compat_add_offset(entry_offset, off);
1565 if (ret)
1566 goto out;
1567
1568 /* Check hooks & underflows */
1569 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
1570 if ((unsigned char *)e - base == hook_entries[h])
1571 newinfo->hook_entry[h] = hook_entries[h];
1572 if ((unsigned char *)e - base == underflows[h])
1573 newinfo->underflow[h] = underflows[h];
1574 }
1575
1576 /* Clear counters and comefrom */
1577 e->counters = ((struct ipt_counters) { 0, 0 });
1578 e->comefrom = 0;
1579
1580 (*i)++;
1581 return 0;
1582out:
1583 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1584 return ret;
1585}
1586
1587static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
1588 void **dstptr, compat_uint_t *size, const char *name,
1589 const struct ipt_ip *ip, unsigned int hookmask)
1590{
1591 struct ipt_entry_match *dm;
1592 struct ipt_match *match;
1593 int ret;
1594
1595 dm = (struct ipt_entry_match *)*dstptr;
1596 match = m->u.kernel.match;
1597 if (match->compat)
1598 match->compat(m, dstptr, size, COMPAT_FROM_USER);
1599 else
1600 xt_compat_match(m, dstptr, size, COMPAT_FROM_USER);
1601
1602 ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
1603 name, hookmask, ip->proto,
1604 ip->invflags & IPT_INV_PROTO);
1605 if (ret)
1606 return ret;
1607
1608 if (m->u.kernel.match->checkentry
1609 && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
1610 dm->u.match_size - sizeof(*dm),
1611 hookmask)) {
1612 duprintf("ip_tables: check failed for `%s'.\n",
1613 m->u.kernel.match->name);
1614 return -EINVAL;
1615 }
1616 return 0;
1617}
1618
1619static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1620 unsigned int *size, const char *name,
1621 struct xt_table_info *newinfo, unsigned char *base)
1622{
1623 struct ipt_entry_target *t;
1624 struct ipt_target *target;
1625 struct ipt_entry *de;
1626 unsigned int origsize;
1627 int ret, h;
1628
1629 ret = 0;
1630 origsize = *size;
1631 de = (struct ipt_entry *)*dstptr;
1632 memcpy(de, e, sizeof(struct ipt_entry));
1633
1634 *dstptr += sizeof(struct compat_ipt_entry);
1635 ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
1636 name, &de->ip, de->comefrom);
1637 if (ret)
1638 goto out;
1639 de->target_offset = e->target_offset - (origsize - *size);
1640 t = ipt_get_target(e);
1641 target = t->u.kernel.target;
1642 if (target->compat)
1643 target->compat(t, dstptr, size, COMPAT_FROM_USER);
1644 else
1645 xt_compat_target(t, dstptr, size, COMPAT_FROM_USER);
1646
1647 de->next_offset = e->next_offset - (origsize - *size);
1648 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
1649 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1650 newinfo->hook_entry[h] -= origsize - *size;
1651 if ((unsigned char *)de - base < newinfo->underflow[h])
1652 newinfo->underflow[h] -= origsize - *size;
1653 }
1654
1655 t = ipt_get_target(de);
1656 target = t->u.kernel.target;
1657 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
1658 name, e->comefrom, e->ip.proto,
1659 e->ip.invflags & IPT_INV_PROTO);
1660 if (ret)
1661 goto out;
1662
1663 ret = -EINVAL;
1664 if (t->u.kernel.target == &ipt_standard_target) {
1665 if (!standard_check(t, *size))
1666 goto out;
1667 } else if (t->u.kernel.target->checkentry
1668 && !t->u.kernel.target->checkentry(name, de, target,
1669 t->data, t->u.target_size - sizeof(*t),
1670 de->comefrom)) {
1671 duprintf("ip_tables: compat: check failed for `%s'.\n",
1672 t->u.kernel.target->name);
1673 goto out;
1674 }
1675 ret = 0;
1676out:
1677 return ret;
1678}
1679
1098static int 1680static int
1099do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) 1681translate_compat_table(const char *name,
1682 unsigned int valid_hooks,
1683 struct xt_table_info **pinfo,
1684 void **pentry0,
1685 unsigned int total_size,
1686 unsigned int number,
1687 unsigned int *hook_entries,
1688 unsigned int *underflows)
1689{
1690 unsigned int i;
1691 struct xt_table_info *newinfo, *info;
1692 void *pos, *entry0, *entry1;
1693 unsigned int size;
1694 int ret;
1695
1696 info = *pinfo;
1697 entry0 = *pentry0;
1698 size = total_size;
1699 info->number = number;
1700
1701 /* Init all hooks to impossible value. */
1702 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1703 info->hook_entry[i] = 0xFFFFFFFF;
1704 info->underflow[i] = 0xFFFFFFFF;
1705 }
1706
1707 duprintf("translate_compat_table: size %u\n", info->size);
1708 i = 0;
1709 xt_compat_lock(AF_INET);
1710 /* Walk through entries, checking offsets. */
1711 ret = IPT_ENTRY_ITERATE(entry0, total_size,
1712 check_compat_entry_size_and_hooks,
1713 info, &size, entry0,
1714 entry0 + total_size,
1715 hook_entries, underflows, &i, name);
1716 if (ret != 0)
1717 goto out_unlock;
1718
1719 ret = -EINVAL;
1720 if (i != number) {
1721 duprintf("translate_compat_table: %u not %u entries\n",
1722 i, number);
1723 goto out_unlock;
1724 }
1725
1726 /* Check hooks all assigned */
1727 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1728 /* Only hooks which are valid */
1729 if (!(valid_hooks & (1 << i)))
1730 continue;
1731 if (info->hook_entry[i] == 0xFFFFFFFF) {
1732 duprintf("Invalid hook entry %u %u\n",
1733 i, hook_entries[i]);
1734 goto out_unlock;
1735 }
1736 if (info->underflow[i] == 0xFFFFFFFF) {
1737 duprintf("Invalid underflow %u %u\n",
1738 i, underflows[i]);
1739 goto out_unlock;
1740 }
1741 }
1742
1743 ret = -ENOMEM;
1744 newinfo = xt_alloc_table_info(size);
1745 if (!newinfo)
1746 goto out_unlock;
1747
1748 newinfo->number = number;
1749 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1750 newinfo->hook_entry[i] = info->hook_entry[i];
1751 newinfo->underflow[i] = info->underflow[i];
1752 }
1753 entry1 = newinfo->entries[raw_smp_processor_id()];
1754 pos = entry1;
1755 size = total_size;
1756 ret = IPT_ENTRY_ITERATE(entry0, total_size,
1757 compat_copy_entry_from_user, &pos, &size,
1758 name, newinfo, entry1);
1759 compat_flush_offsets();
1760 xt_compat_unlock(AF_INET);
1761 if (ret)
1762 goto free_newinfo;
1763
1764 ret = -ELOOP;
1765 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1766 goto free_newinfo;
1767
1768 /* And one copy for every other CPU */
1769 for_each_cpu(i)
1770 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1771 memcpy(newinfo->entries[i], entry1, newinfo->size);
1772
1773 *pinfo = newinfo;
1774 *pentry0 = entry1;
1775 xt_free_table_info(info);
1776 return 0;
1777
1778free_newinfo:
1779 xt_free_table_info(newinfo);
1780out:
1781 return ret;
1782out_unlock:
1783 xt_compat_unlock(AF_INET);
1784 goto out;
1785}
1786
1787static int
1788compat_do_replace(void __user *user, unsigned int len)
1789{
1790 int ret;
1791 struct compat_ipt_replace tmp;
1792 struct xt_table_info *newinfo;
1793 void *loc_cpu_entry;
1794
1795 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1796 return -EFAULT;
1797
1798 /* Hack: Causes ipchains to give correct error msg --RR */
1799 if (len != sizeof(tmp) + tmp.size)
1800 return -ENOPROTOOPT;
1801
1802 /* overflow check */
1803 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1804 SMP_CACHE_BYTES)
1805 return -ENOMEM;
1806 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1807 return -ENOMEM;
1808
1809 newinfo = xt_alloc_table_info(tmp.size);
1810 if (!newinfo)
1811 return -ENOMEM;
1812
1813 /* choose the copy that is our node/cpu */
1814 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1815 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1816 tmp.size) != 0) {
1817 ret = -EFAULT;
1818 goto free_newinfo;
1819 }
1820
1821 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1822 &newinfo, &loc_cpu_entry, tmp.size,
1823 tmp.num_entries, tmp.hook_entry, tmp.underflow);
1824 if (ret != 0)
1825 goto free_newinfo;
1826
1827 duprintf("compat_do_replace: Translated table\n");
1828
1829 ret = __do_replace(tmp.name, tmp.valid_hooks,
1830 newinfo, tmp.num_counters,
1831 compat_ptr(tmp.counters));
1832 if (ret)
1833 goto free_newinfo_untrans;
1834 return 0;
1835
1836 free_newinfo_untrans:
1837 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1838 free_newinfo:
1839 xt_free_table_info(newinfo);
1840 return ret;
1841}
1842
1843static int
1844compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1845 unsigned int len)
1100{ 1846{
1101 int ret; 1847 int ret;
1102 1848
@@ -1105,11 +1851,11 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1105 1851
1106 switch (cmd) { 1852 switch (cmd) {
1107 case IPT_SO_SET_REPLACE: 1853 case IPT_SO_SET_REPLACE:
1108 ret = do_replace(user, len); 1854 ret = compat_do_replace(user, len);
1109 break; 1855 break;
1110 1856
1111 case IPT_SO_SET_ADD_COUNTERS: 1857 case IPT_SO_SET_ADD_COUNTERS:
1112 ret = do_add_counters(user, len); 1858 ret = do_add_counters(user, len, 1);
1113 break; 1859 break;
1114 1860
1115 default: 1861 default:
@@ -1120,75 +1866,196 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1120 return ret; 1866 return ret;
1121} 1867}
1122 1868
1869struct compat_ipt_get_entries
1870{
1871 char name[IPT_TABLE_MAXNAMELEN];
1872 compat_uint_t size;
1873 struct compat_ipt_entry entrytable[0];
1874};
1875
1876static int compat_copy_entries_to_user(unsigned int total_size,
1877 struct ipt_table *table, void __user *userptr)
1878{
1879 unsigned int off, num;
1880 struct compat_ipt_entry e;
1881 struct xt_counters *counters;
1882 struct xt_table_info *private = table->private;
1883 void __user *pos;
1884 unsigned int size;
1885 int ret = 0;
1886 void *loc_cpu_entry;
1887
1888 counters = alloc_counters(table);
1889 if (IS_ERR(counters))
1890 return PTR_ERR(counters);
1891
1892 /* choose the copy that is on our node/cpu, ...
1893 * This choice is lazy (because current thread is
1894 * allowed to migrate to another cpu)
1895 */
1896 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1897 pos = userptr;
1898 size = total_size;
1899 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1900 compat_copy_entry_to_user, &pos, &size);
1901 if (ret)
1902 goto free_counters;
1903
1904 /* ... then go back and fix counters and names */
1905 for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
1906 unsigned int i;
1907 struct ipt_entry_match m;
1908 struct ipt_entry_target t;
1909
1910 ret = -EFAULT;
1911 if (copy_from_user(&e, userptr + off,
1912 sizeof(struct compat_ipt_entry)))
1913 goto free_counters;
1914 if (copy_to_user(userptr + off +
1915 offsetof(struct compat_ipt_entry, counters),
1916 &counters[num], sizeof(counters[num])))
1917 goto free_counters;
1918
1919 for (i = sizeof(struct compat_ipt_entry);
1920 i < e.target_offset; i += m.u.match_size) {
1921 if (copy_from_user(&m, userptr + off + i,
1922 sizeof(struct ipt_entry_match)))
1923 goto free_counters;
1924 if (copy_to_user(userptr + off + i +
1925 offsetof(struct ipt_entry_match, u.user.name),
1926 m.u.kernel.match->name,
1927 strlen(m.u.kernel.match->name) + 1))
1928 goto free_counters;
1929 }
1930
1931 if (copy_from_user(&t, userptr + off + e.target_offset,
1932 sizeof(struct ipt_entry_target)))
1933 goto free_counters;
1934 if (copy_to_user(userptr + off + e.target_offset +
1935 offsetof(struct ipt_entry_target, u.user.name),
1936 t.u.kernel.target->name,
1937 strlen(t.u.kernel.target->name) + 1))
1938 goto free_counters;
1939 }
1940 ret = 0;
1941free_counters:
1942 vfree(counters);
1943 return ret;
1944}
1945
1123static int 1946static int
1124do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) 1947compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
1125{ 1948{
1126 int ret; 1949 int ret;
1950 struct compat_ipt_get_entries get;
1951 struct ipt_table *t;
1127 1952
1128 if (!capable(CAP_NET_ADMIN))
1129 return -EPERM;
1130 1953
1131 switch (cmd) { 1954 if (*len < sizeof(get)) {
1132 case IPT_SO_GET_INFO: { 1955 duprintf("compat_get_entries: %u < %u\n",
1133 char name[IPT_TABLE_MAXNAMELEN]; 1956 *len, (unsigned int)sizeof(get));
1134 struct ipt_table *t; 1957 return -EINVAL;
1958 }
1959
1960 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1961 return -EFAULT;
1962
1963 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1964 duprintf("compat_get_entries: %u != %u\n", *len,
1965 (unsigned int)(sizeof(struct compat_ipt_get_entries) +
1966 get.size));
1967 return -EINVAL;
1968 }
1135 1969
1136 if (*len != sizeof(struct ipt_getinfo)) { 1970 xt_compat_lock(AF_INET);
1137 duprintf("length %u != %u\n", *len, 1971 t = xt_find_table_lock(AF_INET, get.name);
1138 sizeof(struct ipt_getinfo)); 1972 if (t && !IS_ERR(t)) {
1973 struct xt_table_info *private = t->private;
1974 struct xt_table_info info;
1975 duprintf("t->private->number = %u\n",
1976 private->number);
1977 ret = compat_table_info(private, &info);
1978 if (!ret && get.size == info.size) {
1979 ret = compat_copy_entries_to_user(private->size,
1980 t, uptr->entrytable);
1981 } else if (!ret) {
1982 duprintf("compat_get_entries: I've got %u not %u!\n",
1983 private->size,
1984 get.size);
1139 ret = -EINVAL; 1985 ret = -EINVAL;
1140 break;
1141 } 1986 }
1987 compat_flush_offsets();
1988 module_put(t->me);
1989 xt_table_unlock(t);
1990 } else
1991 ret = t ? PTR_ERR(t) : -ENOENT;
1142 1992
1143 if (copy_from_user(name, user, sizeof(name)) != 0) { 1993 xt_compat_unlock(AF_INET);
1144 ret = -EFAULT; 1994 return ret;
1145 break; 1995}
1146 } 1996
1147 name[IPT_TABLE_MAXNAMELEN-1] = '\0'; 1997static int
1148 1998compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1149 t = try_then_request_module(xt_find_table_lock(AF_INET, name), 1999{
1150 "iptable_%s", name); 2000 int ret;
1151 if (t && !IS_ERR(t)) { 2001
1152 struct ipt_getinfo info; 2002 switch (cmd) {
1153 struct xt_table_info *private = t->private; 2003 case IPT_SO_GET_INFO:
1154 2004 ret = get_info(user, len, 1);
1155 info.valid_hooks = t->valid_hooks; 2005 break;
1156 memcpy(info.hook_entry, private->hook_entry, 2006 case IPT_SO_GET_ENTRIES:
1157 sizeof(info.hook_entry)); 2007 ret = compat_get_entries(user, len);
1158 memcpy(info.underflow, private->underflow, 2008 break;
1159 sizeof(info.underflow)); 2009 default:
1160 info.num_entries = private->number; 2010 duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd);
1161 info.size = private->size; 2011 ret = -EINVAL;
1162 memcpy(info.name, name, sizeof(info.name));
1163
1164 if (copy_to_user(user, &info, *len) != 0)
1165 ret = -EFAULT;
1166 else
1167 ret = 0;
1168 xt_table_unlock(t);
1169 module_put(t->me);
1170 } else
1171 ret = t ? PTR_ERR(t) : -ENOENT;
1172 } 2012 }
1173 break; 2013 return ret;
2014}
2015#endif
1174 2016
1175 case IPT_SO_GET_ENTRIES: { 2017static int
1176 struct ipt_get_entries get; 2018do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2019{
2020 int ret;
1177 2021
1178 if (*len < sizeof(get)) { 2022 if (!capable(CAP_NET_ADMIN))
1179 duprintf("get_entries: %u < %u\n", *len, sizeof(get)); 2023 return -EPERM;
1180 ret = -EINVAL; 2024
1181 } else if (copy_from_user(&get, user, sizeof(get)) != 0) { 2025 switch (cmd) {
1182 ret = -EFAULT; 2026 case IPT_SO_SET_REPLACE:
1183 } else if (*len != sizeof(struct ipt_get_entries) + get.size) { 2027 ret = do_replace(user, len);
1184 duprintf("get_entries: %u != %u\n", *len,
1185 sizeof(struct ipt_get_entries) + get.size);
1186 ret = -EINVAL;
1187 } else
1188 ret = get_entries(&get, user);
1189 break; 2028 break;
2029
2030 case IPT_SO_SET_ADD_COUNTERS:
2031 ret = do_add_counters(user, len, 0);
2032 break;
2033
2034 default:
2035 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2036 ret = -EINVAL;
1190 } 2037 }
1191 2038
2039 return ret;
2040}
2041
2042static int
2043do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2044{
2045 int ret;
2046
2047 if (!capable(CAP_NET_ADMIN))
2048 return -EPERM;
2049
2050 switch (cmd) {
2051 case IPT_SO_GET_INFO:
2052 ret = get_info(user, len, 0);
2053 break;
2054
2055 case IPT_SO_GET_ENTRIES:
2056 ret = get_entries(user, len);
2057 break;
2058
1192 case IPT_SO_GET_REVISION_MATCH: 2059 case IPT_SO_GET_REVISION_MATCH:
1193 case IPT_SO_GET_REVISION_TARGET: { 2060 case IPT_SO_GET_REVISION_TARGET: {
1194 struct ipt_get_revision rev; 2061 struct ipt_get_revision rev;
@@ -1336,6 +2203,9 @@ static struct ipt_target ipt_standard_target = {
1336 .name = IPT_STANDARD_TARGET, 2203 .name = IPT_STANDARD_TARGET,
1337 .targetsize = sizeof(int), 2204 .targetsize = sizeof(int),
1338 .family = AF_INET, 2205 .family = AF_INET,
2206#ifdef CONFIG_COMPAT
2207 .compat = &compat_ipt_standard_fn,
2208#endif
1339}; 2209};
1340 2210
1341static struct ipt_target ipt_error_target = { 2211static struct ipt_target ipt_error_target = {
@@ -1350,9 +2220,15 @@ static struct nf_sockopt_ops ipt_sockopts = {
1350 .set_optmin = IPT_BASE_CTL, 2220 .set_optmin = IPT_BASE_CTL,
1351 .set_optmax = IPT_SO_SET_MAX+1, 2221 .set_optmax = IPT_SO_SET_MAX+1,
1352 .set = do_ipt_set_ctl, 2222 .set = do_ipt_set_ctl,
2223#ifdef CONFIG_COMPAT
2224 .compat_set = compat_do_ipt_set_ctl,
2225#endif
1353 .get_optmin = IPT_BASE_CTL, 2226 .get_optmin = IPT_BASE_CTL,
1354 .get_optmax = IPT_SO_GET_MAX+1, 2227 .get_optmax = IPT_SO_GET_MAX+1,
1355 .get = do_ipt_get_ctl, 2228 .get = do_ipt_get_ctl,
2229#ifdef CONFIG_COMPAT
2230 .compat_get = compat_do_ipt_get_ctl,
2231#endif
1356}; 2232};
1357 2233
1358static struct ipt_match icmp_matchstruct = { 2234static struct ipt_match icmp_matchstruct = {
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index e4768a31718b..aad9d28c8d71 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 = {
725 725
726#endif /* CONFIG_PROC_FS */ 726#endif /* CONFIG_PROC_FS */
727 727
728static int init_or_cleanup(int fini) 728static int __init ipt_clusterip_init(void)
729{ 729{
730 int ret; 730 int ret;
731 731
732 if (fini) 732 ret = ipt_register_target(&clusterip_tgt);
733 goto cleanup; 733 if (ret < 0)
734 734 return ret;
735 if (ipt_register_target(&clusterip_tgt)) {
736 ret = -EINVAL;
737 goto cleanup_none;
738 }
739 735
740 if (nf_register_hook(&cip_arp_ops) < 0) { 736 ret = nf_register_hook(&cip_arp_ops);
741 ret = -EINVAL; 737 if (ret < 0)
742 goto cleanup_target; 738 goto cleanup_target;
743 }
744 739
745#ifdef CONFIG_PROC_FS 740#ifdef CONFIG_PROC_FS
746 clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net); 741 clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
@@ -753,31 +748,24 @@ static int init_or_cleanup(int fini)
753 748
754 printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n", 749 printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n",
755 CLUSTERIP_VERSION); 750 CLUSTERIP_VERSION);
756
757 return 0; 751 return 0;
758 752
759cleanup:
760 printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
761 CLUSTERIP_VERSION);
762#ifdef CONFIG_PROC_FS
763 remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
764#endif
765cleanup_hook: 753cleanup_hook:
766 nf_unregister_hook(&cip_arp_ops); 754 nf_unregister_hook(&cip_arp_ops);
767cleanup_target: 755cleanup_target:
768 ipt_unregister_target(&clusterip_tgt); 756 ipt_unregister_target(&clusterip_tgt);
769cleanup_none: 757 return ret;
770 return -EINVAL;
771}
772
773static int __init ipt_clusterip_init(void)
774{
775 return init_or_cleanup(0);
776} 758}
777 759
778static void __exit ipt_clusterip_fini(void) 760static void __exit ipt_clusterip_fini(void)
779{ 761{
780 init_or_cleanup(1); 762 printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
763 CLUSTERIP_VERSION);
764#ifdef CONFIG_PROC_FS
765 remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
766#endif
767 nf_unregister_hook(&cip_arp_ops);
768 ipt_unregister_target(&clusterip_tgt);
781} 769}
782 770
783module_init(ipt_clusterip_init); 771module_init(ipt_clusterip_init);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 4269a5440d43..0bba3c2bb786 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)
106 struct rtable *rt; 106 struct rtable *rt;
107 u_int16_t tmp_port; 107 u_int16_t tmp_port;
108 u_int32_t tmp_addr; 108 u_int32_t tmp_addr;
109 unsigned int tcplen;
110 int needs_ack; 109 int needs_ack;
111 int hh_len; 110 int hh_len;
112 111
@@ -124,13 +123,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
124 return; 123 return;
125 124
126 /* Check checksum */ 125 /* Check checksum */
127 tcplen = oldskb->len - iph->ihl * 4; 126 if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
128 if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
129 (hook == NF_IP_LOCAL_IN &&
130 oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
131 csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
132 oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
133 skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
134 return; 127 return;
135 128
136 if ((rt = route_reverse(oldskb, oth, hook)) == NULL) 129 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 ac95d8390bcc..000000000000
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ /dev/null
@@ -1,195 +0,0 @@
1/* Kernel module to match one of a list of TCP/UDP ports: ports are in
2 the same place so we can treat them as equal. */
3
4/* (C) 1999-2001 Paul `Rusty' Russell
5 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/types.h>
14#include <linux/udp.h>
15#include <linux/skbuff.h>
16
17#include <linux/netfilter_ipv4/ipt_multiport.h>
18#include <linux/netfilter_ipv4/ip_tables.h>
19
20MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
22MODULE_DESCRIPTION("iptables multiple port match module");
23
24#if 0
25#define duprintf(format, args...) printk(format , ## args)
26#else
27#define duprintf(format, args...)
28#endif
29
30/* Returns 1 if the port is matched by the test, 0 otherwise. */
31static inline int
32ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags,
33 u_int8_t count, u_int16_t src, u_int16_t dst)
34{
35 unsigned int i;
36 for (i=0; i<count; i++) {
37 if (flags != IPT_MULTIPORT_DESTINATION
38 && portlist[i] == src)
39 return 1;
40
41 if (flags != IPT_MULTIPORT_SOURCE
42 && portlist[i] == dst)
43 return 1;
44 }
45
46 return 0;
47}
48
49/* Returns 1 if the port is matched by the test, 0 otherwise. */
50static inline int
51ports_match_v1(const struct ipt_multiport_v1 *minfo,
52 u_int16_t src, u_int16_t dst)
53{
54 unsigned int i;
55 u_int16_t s, e;
56
57 for (i=0; i < minfo->count; i++) {
58 s = minfo->ports[i];
59
60 if (minfo->pflags[i]) {
61 /* range port matching */
62 e = minfo->ports[++i];
63 duprintf("src or dst matches with %d-%d?\n", s, e);
64
65 if (minfo->flags == IPT_MULTIPORT_SOURCE
66 && src >= s && src <= e)
67 return 1 ^ minfo->invert;
68 if (minfo->flags == IPT_MULTIPORT_DESTINATION
69 && dst >= s && dst <= e)
70 return 1 ^ minfo->invert;
71 if (minfo->flags == IPT_MULTIPORT_EITHER
72 && ((dst >= s && dst <= e)
73 || (src >= s && src <= e)))
74 return 1 ^ minfo->invert;
75 } else {
76 /* exact port matching */
77 duprintf("src or dst matches with %d?\n", s);
78
79 if (minfo->flags == IPT_MULTIPORT_SOURCE
80 && src == s)
81 return 1 ^ minfo->invert;
82 if (minfo->flags == IPT_MULTIPORT_DESTINATION
83 && dst == s)
84 return 1 ^ minfo->invert;
85 if (minfo->flags == IPT_MULTIPORT_EITHER
86 && (src == s || dst == s))
87 return 1 ^ minfo->invert;
88 }
89 }
90
91 return minfo->invert;
92}
93
94static int
95match(const struct sk_buff *skb,
96 const struct net_device *in,
97 const struct net_device *out,
98 const struct xt_match *match,
99 const void *matchinfo,
100 int offset,
101 unsigned int protoff,
102 int *hotdrop)
103{
104 u16 _ports[2], *pptr;
105 const struct ipt_multiport *multiinfo = matchinfo;
106
107 if (offset)
108 return 0;
109
110 pptr = skb_header_pointer(skb, protoff,
111 sizeof(_ports), _ports);
112 if (pptr == NULL) {
113 /* We've been asked to examine this packet, and we
114 * can't. Hence, no choice but to drop.
115 */
116 duprintf("ipt_multiport:"
117 " Dropping evil offset=0 tinygram.\n");
118 *hotdrop = 1;
119 return 0;
120 }
121
122 return ports_match(multiinfo->ports,
123 multiinfo->flags, multiinfo->count,
124 ntohs(pptr[0]), ntohs(pptr[1]));
125}
126
127static int
128match_v1(const struct sk_buff *skb,
129 const struct net_device *in,
130 const struct net_device *out,
131 const struct xt_match *match,
132 const void *matchinfo,
133 int offset,
134 unsigned int protoff,
135 int *hotdrop)
136{
137 u16 _ports[2], *pptr;
138 const struct ipt_multiport_v1 *multiinfo = matchinfo;
139
140 if (offset)
141 return 0;
142
143 pptr = skb_header_pointer(skb, protoff,
144 sizeof(_ports), _ports);
145 if (pptr == NULL) {
146 /* We've been asked to examine this packet, and we
147 * can't. Hence, no choice but to drop.
148 */
149 duprintf("ipt_multiport:"
150 " Dropping evil offset=0 tinygram.\n");
151 *hotdrop = 1;
152 return 0;
153 }
154
155 return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
156}
157
158static struct ipt_match multiport_match = {
159 .name = "multiport",
160 .revision = 0,
161 .match = match,
162 .matchsize = sizeof(struct ipt_multiport),
163 .me = THIS_MODULE,
164};
165
166static struct ipt_match multiport_match_v1 = {
167 .name = "multiport",
168 .revision = 1,
169 .match = match_v1,
170 .matchsize = sizeof(struct ipt_multiport_v1),
171 .me = THIS_MODULE,
172};
173
174static int __init ipt_multiport_init(void)
175{
176 int err;
177
178 err = ipt_register_match(&multiport_match);
179 if (!err) {
180 err = ipt_register_match(&multiport_match_v1);
181 if (err)
182 ipt_unregister_match(&multiport_match);
183 }
184
185 return err;
186}
187
188static void __exit ipt_multiport_fini(void)
189{
190 ipt_unregister_match(&multiport_match);
191 ipt_unregister_match(&multiport_match_v1);
192}
193
194module_init(ipt_multiport_init);
195module_exit(ipt_multiport_fini);
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 3d80aefe9cfa..7f417484bfbf 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)
157 return ret; 157 return ret;
158 158
159 /* Register hooks */ 159 /* Register hooks */
160 ret = nf_register_hook(&ipt_ops[0]); 160 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
161 if (ret < 0) 161 if (ret < 0)
162 goto cleanup_table; 162 goto cleanup_table;
163 163
164 ret = nf_register_hook(&ipt_ops[1]);
165 if (ret < 0)
166 goto cleanup_hook0;
167
168 ret = nf_register_hook(&ipt_ops[2]);
169 if (ret < 0)
170 goto cleanup_hook1;
171
172 return ret; 164 return ret;
173 165
174 cleanup_hook1:
175 nf_unregister_hook(&ipt_ops[1]);
176 cleanup_hook0:
177 nf_unregister_hook(&ipt_ops[0]);
178 cleanup_table: 166 cleanup_table:
179 ipt_unregister_table(&packet_filter); 167 ipt_unregister_table(&packet_filter);
180
181 return ret; 168 return ret;
182} 169}
183 170
184static void __exit iptable_filter_fini(void) 171static void __exit iptable_filter_fini(void)
185{ 172{
186 unsigned int i; 173 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
187
188 for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
189 nf_unregister_hook(&ipt_ops[i]);
190
191 ipt_unregister_table(&packet_filter); 174 ipt_unregister_table(&packet_filter);
192} 175}
193 176
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 412fc96cc896..397b95cc026b 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)
211 return ret; 211 return ret;
212 212
213 /* Register hooks */ 213 /* Register hooks */
214 ret = nf_register_hook(&ipt_ops[0]); 214 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
215 if (ret < 0) 215 if (ret < 0)
216 goto cleanup_table; 216 goto cleanup_table;
217 217
218 ret = nf_register_hook(&ipt_ops[1]);
219 if (ret < 0)
220 goto cleanup_hook0;
221
222 ret = nf_register_hook(&ipt_ops[2]);
223 if (ret < 0)
224 goto cleanup_hook1;
225
226 ret = nf_register_hook(&ipt_ops[3]);
227 if (ret < 0)
228 goto cleanup_hook2;
229
230 ret = nf_register_hook(&ipt_ops[4]);
231 if (ret < 0)
232 goto cleanup_hook3;
233
234 return ret; 218 return ret;
235 219
236 cleanup_hook3:
237 nf_unregister_hook(&ipt_ops[3]);
238 cleanup_hook2:
239 nf_unregister_hook(&ipt_ops[2]);
240 cleanup_hook1:
241 nf_unregister_hook(&ipt_ops[1]);
242 cleanup_hook0:
243 nf_unregister_hook(&ipt_ops[0]);
244 cleanup_table: 220 cleanup_table:
245 ipt_unregister_table(&packet_mangler); 221 ipt_unregister_table(&packet_mangler);
246
247 return ret; 222 return ret;
248} 223}
249 224
250static void __exit iptable_mangle_fini(void) 225static void __exit iptable_mangle_fini(void)
251{ 226{
252 unsigned int i; 227 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
253
254 for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
255 nf_unregister_hook(&ipt_ops[i]);
256
257 ipt_unregister_table(&packet_mangler); 228 ipt_unregister_table(&packet_mangler);
258} 229}
259 230
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 03cc79a6160a..7912cce1e1b8 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -101,18 +101,18 @@ ipt_hook(unsigned int hook,
101/* 'raw' is the very first table. */ 101/* 'raw' is the very first table. */
102static struct nf_hook_ops ipt_ops[] = { 102static struct nf_hook_ops ipt_ops[] = {
103 { 103 {
104 .hook = ipt_hook, 104 .hook = ipt_hook,
105 .pf = PF_INET, 105 .pf = PF_INET,
106 .hooknum = NF_IP_PRE_ROUTING, 106 .hooknum = NF_IP_PRE_ROUTING,
107 .priority = NF_IP_PRI_RAW, 107 .priority = NF_IP_PRI_RAW,
108 .owner = THIS_MODULE, 108 .owner = THIS_MODULE,
109 }, 109 },
110 { 110 {
111 .hook = ipt_hook, 111 .hook = ipt_hook,
112 .pf = PF_INET, 112 .pf = PF_INET,
113 .hooknum = NF_IP_LOCAL_OUT, 113 .hooknum = NF_IP_LOCAL_OUT,
114 .priority = NF_IP_PRI_RAW, 114 .priority = NF_IP_PRI_RAW,
115 .owner = THIS_MODULE, 115 .owner = THIS_MODULE,
116 }, 116 },
117}; 117};
118 118
@@ -126,31 +126,20 @@ static int __init iptable_raw_init(void)
126 return ret; 126 return ret;
127 127
128 /* Register hooks */ 128 /* Register hooks */
129 ret = nf_register_hook(&ipt_ops[0]); 129 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
130 if (ret < 0) 130 if (ret < 0)
131 goto cleanup_table; 131 goto cleanup_table;
132 132
133 ret = nf_register_hook(&ipt_ops[1]);
134 if (ret < 0)
135 goto cleanup_hook0;
136
137 return ret; 133 return ret;
138 134
139 cleanup_hook0:
140 nf_unregister_hook(&ipt_ops[0]);
141 cleanup_table: 135 cleanup_table:
142 ipt_unregister_table(&packet_raw); 136 ipt_unregister_table(&packet_raw);
143
144 return ret; 137 return ret;
145} 138}
146 139
147static void __exit iptable_raw_fini(void) 140static void __exit iptable_raw_fini(void)
148{ 141{
149 unsigned int i; 142 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
150
151 for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
152 nf_unregister_hook(&ipt_ops[i]);
153
154 ipt_unregister_table(&packet_raw); 143 ipt_unregister_table(&packet_raw);
155} 144}
156 145
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 4afbc699d3ba..5bc9f64d7b5b 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,
210 210
211/* Connection tracking may drop packets, but never alters them, so 211/* Connection tracking may drop packets, but never alters them, so
212 make it the first hook. */ 212 make it the first hook. */
213static struct nf_hook_ops ipv4_conntrack_defrag_ops = { 213static struct nf_hook_ops ipv4_conntrack_ops[] = {
214 .hook = ipv4_conntrack_defrag, 214 {
215 .owner = THIS_MODULE, 215 .hook = ipv4_conntrack_defrag,
216 .pf = PF_INET, 216 .owner = THIS_MODULE,
217 .hooknum = NF_IP_PRE_ROUTING, 217 .pf = PF_INET,
218 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 218 .hooknum = NF_IP_PRE_ROUTING,
219}; 219 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
220 220 },
221static struct nf_hook_ops ipv4_conntrack_in_ops = { 221 {
222 .hook = ipv4_conntrack_in, 222 .hook = ipv4_conntrack_in,
223 .owner = THIS_MODULE, 223 .owner = THIS_MODULE,
224 .pf = PF_INET, 224 .pf = PF_INET,
225 .hooknum = NF_IP_PRE_ROUTING, 225 .hooknum = NF_IP_PRE_ROUTING,
226 .priority = NF_IP_PRI_CONNTRACK, 226 .priority = NF_IP_PRI_CONNTRACK,
227}; 227 },
228 228 {
229static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = { 229 .hook = ipv4_conntrack_defrag,
230 .hook = ipv4_conntrack_defrag, 230 .owner = THIS_MODULE,
231 .owner = THIS_MODULE, 231 .pf = PF_INET,
232 .pf = PF_INET, 232 .hooknum = NF_IP_LOCAL_OUT,
233 .hooknum = NF_IP_LOCAL_OUT, 233 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
234 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 234 },
235}; 235 {
236 236 .hook = ipv4_conntrack_local,
237static struct nf_hook_ops ipv4_conntrack_local_out_ops = { 237 .owner = THIS_MODULE,
238 .hook = ipv4_conntrack_local, 238 .pf = PF_INET,
239 .owner = THIS_MODULE, 239 .hooknum = NF_IP_LOCAL_OUT,
240 .pf = PF_INET, 240 .priority = NF_IP_PRI_CONNTRACK,
241 .hooknum = NF_IP_LOCAL_OUT, 241 },
242 .priority = NF_IP_PRI_CONNTRACK, 242 {
243}; 243 .hook = ipv4_conntrack_help,
244 244 .owner = THIS_MODULE,
245/* helpers */ 245 .pf = PF_INET,
246static struct nf_hook_ops ipv4_conntrack_helper_out_ops = { 246 .hooknum = NF_IP_POST_ROUTING,
247 .hook = ipv4_conntrack_help, 247 .priority = NF_IP_PRI_CONNTRACK_HELPER,
248 .owner = THIS_MODULE, 248 },
249 .pf = PF_INET, 249 {
250 .hooknum = NF_IP_POST_ROUTING, 250 .hook = ipv4_conntrack_help,
251 .priority = NF_IP_PRI_CONNTRACK_HELPER, 251 .owner = THIS_MODULE,
252}; 252 .pf = PF_INET,
253 253 .hooknum = NF_IP_LOCAL_IN,
254static struct nf_hook_ops ipv4_conntrack_helper_in_ops = { 254 .priority = NF_IP_PRI_CONNTRACK_HELPER,
255 .hook = ipv4_conntrack_help, 255 },
256 .owner = THIS_MODULE, 256 {
257 .pf = PF_INET, 257 .hook = ipv4_confirm,
258 .hooknum = NF_IP_LOCAL_IN, 258 .owner = THIS_MODULE,
259 .priority = NF_IP_PRI_CONNTRACK_HELPER, 259 .pf = PF_INET,
260}; 260 .hooknum = NF_IP_POST_ROUTING,
261 261 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
262 262 },
263/* Refragmenter; last chance. */ 263 {
264static struct nf_hook_ops ipv4_conntrack_out_ops = { 264 .hook = ipv4_confirm,
265 .hook = ipv4_confirm, 265 .owner = THIS_MODULE,
266 .owner = THIS_MODULE, 266 .pf = PF_INET,
267 .pf = PF_INET, 267 .hooknum = NF_IP_LOCAL_IN,
268 .hooknum = NF_IP_POST_ROUTING, 268 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
269 .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 269 },
270};
271
272static struct nf_hook_ops ipv4_conntrack_local_in_ops = {
273 .hook = ipv4_confirm,
274 .owner = THIS_MODULE,
275 .pf = PF_INET,
276 .hooknum = NF_IP_LOCAL_IN,
277 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
278}; 270};
279 271
280#ifdef CONFIG_SYSCTL 272#ifdef CONFIG_SYSCTL
@@ -440,16 +432,20 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
440extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4; 432extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;
441extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; 433extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
442extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp; 434extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
443static int init_or_cleanup(int init) 435
436MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
437MODULE_LICENSE("GPL");
438
439static int __init nf_conntrack_l3proto_ipv4_init(void)
444{ 440{
445 int ret = 0; 441 int ret = 0;
446 442
447 if (!init) goto cleanup; 443 need_conntrack();
448 444
449 ret = nf_register_sockopt(&so_getorigdst); 445 ret = nf_register_sockopt(&so_getorigdst);
450 if (ret < 0) { 446 if (ret < 0) {
451 printk(KERN_ERR "Unable to register netfilter socket option\n"); 447 printk(KERN_ERR "Unable to register netfilter socket option\n");
452 goto cleanup_nothing; 448 return ret;
453 } 449 }
454 450
455 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4); 451 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
@@ -476,84 +472,26 @@ static int init_or_cleanup(int init)
476 goto cleanup_icmp; 472 goto cleanup_icmp;
477 } 473 }
478 474
479 ret = nf_register_hook(&ipv4_conntrack_defrag_ops); 475 ret = nf_register_hooks(ipv4_conntrack_ops,
476 ARRAY_SIZE(ipv4_conntrack_ops));
480 if (ret < 0) { 477 if (ret < 0) {
481 printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n"); 478 printk("nf_conntrack_ipv4: can't register hooks.\n");
482 goto cleanup_ipv4; 479 goto cleanup_ipv4;
483 } 480 }
484 ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops);
485 if (ret < 0) {
486 printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n");
487 goto cleanup_defragops;
488 }
489
490 ret = nf_register_hook(&ipv4_conntrack_in_ops);
491 if (ret < 0) {
492 printk("nf_conntrack_ipv4: can't register pre-routing hook.\n");
493 goto cleanup_defraglocalops;
494 }
495
496 ret = nf_register_hook(&ipv4_conntrack_local_out_ops);
497 if (ret < 0) {
498 printk("nf_conntrack_ipv4: can't register local out hook.\n");
499 goto cleanup_inops;
500 }
501
502 ret = nf_register_hook(&ipv4_conntrack_helper_in_ops);
503 if (ret < 0) {
504 printk("nf_conntrack_ipv4: can't register local helper hook.\n");
505 goto cleanup_inandlocalops;
506 }
507
508 ret = nf_register_hook(&ipv4_conntrack_helper_out_ops);
509 if (ret < 0) {
510 printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n");
511 goto cleanup_helperinops;
512 }
513
514 ret = nf_register_hook(&ipv4_conntrack_out_ops);
515 if (ret < 0) {
516 printk("nf_conntrack_ipv4: can't register post-routing hook.\n");
517 goto cleanup_helperoutops;
518 }
519
520 ret = nf_register_hook(&ipv4_conntrack_local_in_ops);
521 if (ret < 0) {
522 printk("nf_conntrack_ipv4: can't register local in hook.\n");
523 goto cleanup_inoutandlocalops;
524 }
525
526#ifdef CONFIG_SYSCTL 481#ifdef CONFIG_SYSCTL
527 nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); 482 nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
528 if (nf_ct_ipv4_sysctl_header == NULL) { 483 if (nf_ct_ipv4_sysctl_header == NULL) {
529 printk("nf_conntrack: can't register to sysctl.\n"); 484 printk("nf_conntrack: can't register to sysctl.\n");
530 ret = -ENOMEM; 485 ret = -ENOMEM;
531 goto cleanup_localinops; 486 goto cleanup_hooks;
532 } 487 }
533#endif 488#endif
534 return ret; 489 return ret;
535 490
536 cleanup:
537 synchronize_net();
538#ifdef CONFIG_SYSCTL 491#ifdef CONFIG_SYSCTL
539 unregister_sysctl_table(nf_ct_ipv4_sysctl_header); 492 cleanup_hooks:
540 cleanup_localinops: 493 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
541#endif 494#endif
542 nf_unregister_hook(&ipv4_conntrack_local_in_ops);
543 cleanup_inoutandlocalops:
544 nf_unregister_hook(&ipv4_conntrack_out_ops);
545 cleanup_helperoutops:
546 nf_unregister_hook(&ipv4_conntrack_helper_out_ops);
547 cleanup_helperinops:
548 nf_unregister_hook(&ipv4_conntrack_helper_in_ops);
549 cleanup_inandlocalops:
550 nf_unregister_hook(&ipv4_conntrack_local_out_ops);
551 cleanup_inops:
552 nf_unregister_hook(&ipv4_conntrack_in_ops);
553 cleanup_defraglocalops:
554 nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops);
555 cleanup_defragops:
556 nf_unregister_hook(&ipv4_conntrack_defrag_ops);
557 cleanup_ipv4: 495 cleanup_ipv4:
558 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); 496 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
559 cleanup_icmp: 497 cleanup_icmp:
@@ -564,22 +502,21 @@ static int init_or_cleanup(int init)
564 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); 502 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
565 cleanup_sockopt: 503 cleanup_sockopt:
566 nf_unregister_sockopt(&so_getorigdst); 504 nf_unregister_sockopt(&so_getorigdst);
567 cleanup_nothing:
568 return ret; 505 return ret;
569} 506}
570 507
571MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
572MODULE_LICENSE("GPL");
573
574static int __init nf_conntrack_l3proto_ipv4_init(void)
575{
576 need_conntrack();
577 return init_or_cleanup(1);
578}
579
580static void __exit nf_conntrack_l3proto_ipv4_fini(void) 508static void __exit nf_conntrack_l3proto_ipv4_fini(void)
581{ 509{
582 init_or_cleanup(0); 510 synchronize_net();
511#ifdef CONFIG_SYSCTL
512 unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
513#endif
514 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
515 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
516 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
517 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
518 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
519 nf_unregister_sockopt(&so_getorigdst);
583} 520}
584 521
585module_init(nf_conntrack_l3proto_ipv4_init); 522module_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 52dc175be39a..4b0d361cc6e6 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,
235 } 235 }
236 236
237 /* See ip_conntrack_proto_tcp.c */ 237 /* See ip_conntrack_proto_tcp.c */
238 if (hooknum != NF_IP_PRE_ROUTING) 238 if (hooknum == NF_IP_PRE_ROUTING &&
239 goto checksum_skipped; 239 nf_ip_checksum(skb, hooknum, dataoff, 0)) {
240
241 switch (skb->ip_summed) {
242 case CHECKSUM_HW:
243 if (!(u16)csum_fold(skb->csum))
244 break;
245 if (LOG_INVALID(IPPROTO_ICMP)) 240 if (LOG_INVALID(IPPROTO_ICMP))
246 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 241 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
247 "nf_ct_icmp: bad HW ICMP checksum "); 242 "nf_ct_icmp: bad HW ICMP checksum ");
248 return -NF_ACCEPT; 243 return -NF_ACCEPT;
249 case CHECKSUM_NONE:
250 if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
251 if (LOG_INVALID(IPPROTO_ICMP))
252 nf_log_packet(PF_INET, 0, skb, NULL, NULL,
253 NULL,
254 "nf_ct_icmp: bad ICMP checksum ");
255 return -NF_ACCEPT;
256 }
257 default:
258 break;
259 } 244 }
260 245
261checksum_skipped:
262 /* 246 /*
263 * 18 is the highest 'known' ICMP type. Anything else is a mystery 247 * 18 is the highest 'known' ICMP type. Anything else is a mystery
264 * 248 *
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 1b167c4bb3be..d61e2a9d394d 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -49,7 +49,7 @@ static int fold_prot_inuse(struct proto *proto)
49 int res = 0; 49 int res = 0;
50 int cpu; 50 int cpu;
51 51
52 for_each_cpu(cpu) 52 for_each_possible_cpu(cpu)
53 res += proto->stats[cpu].inuse; 53 res += proto->stats[cpu].inuse;
54 54
55 return res; 55 return res;
@@ -91,7 +91,7 @@ fold_field(void *mib[], int offt)
91 unsigned long res = 0; 91 unsigned long res = 0;
92 int i; 92 int i;
93 93
94 for_each_cpu(i) { 94 for_each_possible_cpu(i) {
95 res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt); 95 res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
96 res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt); 96 res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
97 } 97 }
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 94fcbc5e5a1b..cc9423de7311 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)
2741 /* Reserve room for dummy headers, this skb can pass 2741 /* Reserve room for dummy headers, this skb can pass
2742 through good chunk of routing engine. 2742 through good chunk of routing engine.
2743 */ 2743 */
2744 skb->mac.raw = skb->data; 2744 skb->mac.raw = skb->nh.raw = skb->data;
2745
2746 /* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
2747 skb->nh.iph->protocol = IPPROTO_ICMP;
2745 skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr)); 2748 skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
2746 2749
2747 if (rta[RTA_SRC - 1]) 2750 if (rta[RTA_SRC - 1])
@@ -3083,7 +3086,7 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
3083 memcpy(dst, src, length); 3086 memcpy(dst, src, length);
3084 3087
3085 /* Add the other cpus in, one int at a time */ 3088 /* Add the other cpus in, one int at a time */
3086 for_each_cpu(i) { 3089 for_each_possible_cpu(i) {
3087 unsigned int j; 3090 unsigned int j;
3088 3091
3089 src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset; 3092 src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 195d83584558..9f0cca4c4fae 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4559,7 +4559,6 @@ discard:
4559 4559
4560EXPORT_SYMBOL(sysctl_tcp_ecn); 4560EXPORT_SYMBOL(sysctl_tcp_ecn);
4561EXPORT_SYMBOL(sysctl_tcp_reordering); 4561EXPORT_SYMBOL(sysctl_tcp_reordering);
4562EXPORT_SYMBOL(sysctl_tcp_abc);
4563EXPORT_SYMBOL(tcp_parse_options); 4562EXPORT_SYMBOL(tcp_parse_options);
4564EXPORT_SYMBOL(tcp_rcv_established); 4563EXPORT_SYMBOL(tcp_rcv_established);
4565EXPORT_SYMBOL(tcp_rcv_state_process); 4564EXPORT_SYMBOL(tcp_rcv_state_process);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 9e85c0416109..672950e54c49 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1859,5 +1859,4 @@ EXPORT_SYMBOL(tcp_proc_unregister);
1859#endif 1859#endif
1860EXPORT_SYMBOL(sysctl_local_port_range); 1860EXPORT_SYMBOL(sysctl_local_port_range);
1861EXPORT_SYMBOL(sysctl_tcp_low_latency); 1861EXPORT_SYMBOL(sysctl_tcp_low_latency);
1862EXPORT_SYMBOL(sysctl_tcp_tw_reuse);
1863 1862
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9d79546d384e..a28ae593b976 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -59,9 +59,6 @@ int sysctl_tcp_tso_win_divisor = 3;
59int sysctl_tcp_mtu_probing = 0; 59int sysctl_tcp_mtu_probing = 0;
60int sysctl_tcp_base_mss = 512; 60int sysctl_tcp_base_mss = 512;
61 61
62EXPORT_SYMBOL(sysctl_tcp_mtu_probing);
63EXPORT_SYMBOL(sysctl_tcp_base_mss);
64
65static void update_send_head(struct sock *sk, struct tcp_sock *tp, 62static void update_send_head(struct sock *sk, struct tcp_sock *tp,
66 struct sk_buff *skb) 63 struct sk_buff *skb)
67{ 64{
@@ -536,6 +533,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
536 struct tcp_sock *tp = tcp_sk(sk); 533 struct tcp_sock *tp = tcp_sk(sk);
537 struct sk_buff *buff; 534 struct sk_buff *buff;
538 int nsize, old_factor; 535 int nsize, old_factor;
536 int nlen;
539 u16 flags; 537 u16 flags;
540 538
541 BUG_ON(len > skb->len); 539 BUG_ON(len > skb->len);
@@ -554,7 +552,11 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
554 buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC); 552 buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC);
555 if (buff == NULL) 553 if (buff == NULL)
556 return -ENOMEM; /* We'll just try again later. */ 554 return -ENOMEM; /* We'll just try again later. */
555
557 sk_charge_skb(sk, buff); 556 sk_charge_skb(sk, buff);
557 nlen = skb->len - len - nsize;
558 buff->truesize += nlen;
559 skb->truesize -= nlen;
558 560
559 /* Correct the sequence numbers. */ 561 /* Correct the sequence numbers. */
560 TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len; 562 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,
1040 if (unlikely(buff == NULL)) 1042 if (unlikely(buff == NULL))
1041 return -ENOMEM; 1043 return -ENOMEM;
1042 1044
1043 buff->truesize = nlen; 1045 sk_charge_skb(sk, buff);
1046 buff->truesize += nlen;
1044 skb->truesize -= nlen; 1047 skb->truesize -= nlen;
1045 1048
1046 /* Correct the sequence numbers. */ 1049 /* Correct the sequence numbers. */
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index 0d7d386dac22..8d30c48f090e 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -8,6 +8,8 @@
8#include <linux/mutex.h> 8#include <linux/mutex.h>
9#include <linux/netdevice.h> 9#include <linux/netdevice.h>
10#include <linux/skbuff.h> 10#include <linux/skbuff.h>
11#include <net/icmp.h>
12#include <net/ip.h>
11#include <net/protocol.h> 13#include <net/protocol.h>
12#include <net/xfrm.h> 14#include <net/xfrm.h>
13 15
@@ -70,10 +72,16 @@ static int tunnel4_rcv(struct sk_buff *skb)
70{ 72{
71 struct xfrm_tunnel *handler; 73 struct xfrm_tunnel *handler;
72 74
75 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
76 goto drop;
77
73 for (handler = tunnel4_handlers; handler; handler = handler->next) 78 for (handler = tunnel4_handlers; handler; handler = handler->next)
74 if (!handler->handler(skb)) 79 if (!handler->handler(skb))
75 return 0; 80 return 0;
76 81
82 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
83
84drop:
77 kfree_skb(skb); 85 kfree_skb(skb);
78 return 0; 86 return 0;
79} 87}
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 850d919591d1..3e174c83bfe7 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)
37{ 37{
38 switch (nexthdr) { 38 switch (nexthdr) {
39 case IPPROTO_IPIP: 39 case IPPROTO_IPIP:
40 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
41 return -EINVAL;
42 *spi = skb->nh.iph->saddr; 40 *spi = skb->nh.iph->saddr;
43 *seq = 0; 41 *seq = 0;
44 return 0; 42 return 0;
@@ -68,7 +66,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
68{ 66{
69 int err; 67 int err;
70 u32 spi, seq; 68 u32 spi, seq;
71 struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH]; 69 struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
72 struct xfrm_state *x; 70 struct xfrm_state *x;
73 int xfrm_nr = 0; 71 int xfrm_nr = 0;
74 int decaps = 0; 72 int decaps = 0;
@@ -90,14 +88,16 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
90 if (unlikely(x->km.state != XFRM_STATE_VALID)) 88 if (unlikely(x->km.state != XFRM_STATE_VALID))
91 goto drop_unlock; 89 goto drop_unlock;
92 90
91 if ((x->encap ? x->encap->encap_type : 0) != encap_type)
92 goto drop_unlock;
93
93 if (x->props.replay_window && xfrm_replay_check(x, seq)) 94 if (x->props.replay_window && xfrm_replay_check(x, seq))
94 goto drop_unlock; 95 goto drop_unlock;
95 96
96 if (xfrm_state_check_expire(x)) 97 if (xfrm_state_check_expire(x))
97 goto drop_unlock; 98 goto drop_unlock;
98 99
99 xfrm_vec[xfrm_nr].decap.decap_type = encap_type; 100 if (x->type->input(x, skb))
100 if (x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb))
101 goto drop_unlock; 101 goto drop_unlock;
102 102
103 /* only the first xfrm gets the encap type */ 103 /* only the first xfrm gets the encap type */
@@ -111,7 +111,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
111 111
112 spin_unlock(&x->lock); 112 spin_unlock(&x->lock);
113 113
114 xfrm_vec[xfrm_nr++].xvec = x; 114 xfrm_vec[xfrm_nr++] = x;
115 115
116 iph = skb->nh.iph; 116 iph = skb->nh.iph;
117 117
@@ -153,7 +153,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
153 if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) 153 if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
154 goto drop; 154 goto drop;
155 155
156 memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); 156 memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
157 xfrm_nr * sizeof(xfrm_vec[0]));
157 skb->sp->len += xfrm_nr; 158 skb->sp->len += xfrm_nr;
158 159
159 nf_reset(skb); 160 nf_reset(skb);
@@ -184,7 +185,7 @@ drop_unlock:
184 xfrm_state_put(x); 185 xfrm_state_put(x);
185drop: 186drop:
186 while (--xfrm_nr >= 0) 187 while (--xfrm_nr >= 0)
187 xfrm_state_put(xfrm_vec[xfrm_nr].xvec); 188 xfrm_state_put(xfrm_vec[xfrm_nr]);
188 189
189 kfree_skb(skb); 190 kfree_skb(skb);
190 return 0; 191 return 0;
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 2d670935c2b5..f8ceaa127c83 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)
21 return 0; 21 return 0;
22} 22}
23 23
24static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 24static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
25{ 25{
26 return 0; 26 return 0;
27} 27}
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index cf58251df4b3..6778173a3dda 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -229,7 +229,7 @@ error:
229 return err; 229 return err;
230} 230}
231 231
232static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 232static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
233{ 233{
234 /* 234 /*
235 * Before process AH 235 * Before process AH
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 3dcaac7a0972..22f046079037 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -130,7 +130,7 @@ error:
130 return err; 130 return err;
131} 131}
132 132
133static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 133static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
134{ 134{
135 struct ipv6hdr *iph; 135 struct ipv6hdr *iph;
136 struct ipv6_esp_hdr *esph; 136 struct ipv6_esp_hdr *esph;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 2a1e7e45b890..a18d4256372c 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
485 { -1, } 485 { -1, }
486}; 486};
487 487
488int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) 488int ipv6_parse_hopopts(struct sk_buff *skb)
489{ 489{
490 struct inet6_skb_parm *opt = IP6CB(skb); 490 struct inet6_skb_parm *opt = IP6CB(skb);
491 491
492 /*
493 * skb->nh.raw is equal to skb->data, and
494 * skb->h.raw - skb->nh.raw is always equal to
495 * sizeof(struct ipv6hdr) by definition of
496 * hop-by-hop options.
497 */
498 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
499 !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
500 kfree_skb(skb);
501 return -1;
502 }
503
492 opt->hop = sizeof(struct ipv6hdr); 504 opt->hop = sizeof(struct ipv6hdr);
493 if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { 505 if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
494 skb->h.raw += (skb->h.raw[1]+1)<<3; 506 skb->h.raw += (skb->h.raw[1]+1)<<3;
495 opt->nhoff = sizeof(struct ipv6hdr); 507 opt->nhoff = sizeof(struct ipv6hdr);
496 return sizeof(struct ipv6hdr); 508 return 1;
497 } 509 }
498 return -1; 510 return -1;
499} 511}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 21eb725e885f..1044b6fce0d5 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -717,7 +717,7 @@ int __init icmpv6_init(struct net_proto_family *ops)
717 struct sock *sk; 717 struct sock *sk;
718 int err, i, j; 718 int err, i, j;
719 719
720 for_each_cpu(i) { 720 for_each_possible_cpu(i) {
721 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, 721 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
722 &per_cpu(__icmpv6_socket, i)); 722 &per_cpu(__icmpv6_socket, i));
723 if (err < 0) { 723 if (err < 0) {
@@ -763,7 +763,7 @@ void icmpv6_cleanup(void)
763{ 763{
764 int i; 764 int i;
765 765
766 for_each_cpu(i) { 766 for_each_possible_cpu(i) {
767 sock_release(per_cpu(__icmpv6_socket, i)); 767 sock_release(per_cpu(__icmpv6_socket, i));
768 } 768 }
769 inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); 769 inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index bb8ffb8a14c5..2ae84c961678 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -23,6 +23,86 @@
23#include <net/inet6_hashtables.h> 23#include <net/inet6_hashtables.h>
24#include <net/ip.h> 24#include <net/ip.h>
25 25
26void __inet6_hash(struct inet_hashinfo *hashinfo,
27 struct sock *sk)
28{
29 struct hlist_head *list;
30 rwlock_t *lock;
31
32 BUG_TRAP(sk_unhashed(sk));
33
34 if (sk->sk_state == TCP_LISTEN) {
35 list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
36 lock = &hashinfo->lhash_lock;
37 inet_listen_wlock(hashinfo);
38 } else {
39 unsigned int hash;
40 sk->sk_hash = hash = inet6_sk_ehashfn(sk);
41 hash &= (hashinfo->ehash_size - 1);
42 list = &hashinfo->ehash[hash].chain;
43 lock = &hashinfo->ehash[hash].lock;
44 write_lock(lock);
45 }
46
47 __sk_add_node(sk, list);
48 sock_prot_inc_use(sk->sk_prot);
49 write_unlock(lock);
50}
51EXPORT_SYMBOL(__inet6_hash);
52
53/*
54 * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
55 * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
56 *
57 * The sockhash lock must be held as a reader here.
58 */
59struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
60 const struct in6_addr *saddr,
61 const u16 sport,
62 const struct in6_addr *daddr,
63 const u16 hnum,
64 const int dif)
65{
66 struct sock *sk;
67 const struct hlist_node *node;
68 const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
69 /* Optimize here for direct hit, only listening connections can
70 * have wildcards anyways.
71 */
72 unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
73 struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
74
75 prefetch(head->chain.first);
76 read_lock(&head->lock);
77 sk_for_each(sk, node, &head->chain) {
78 /* For IPV6 do the cheaper port and family tests first. */
79 if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
80 goto hit; /* You sunk my battleship! */
81 }
82 /* Must check for a TIME_WAIT'er before going to listener hash. */
83 sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
84 const struct inet_timewait_sock *tw = inet_twsk(sk);
85
86 if(*((__u32 *)&(tw->tw_dport)) == ports &&
87 sk->sk_family == PF_INET6) {
88 const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
89
90 if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
91 ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
92 (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
93 goto hit;
94 }
95 }
96 read_unlock(&head->lock);
97 return NULL;
98
99hit:
100 sock_hold(sk);
101 read_unlock(&head->lock);
102 return sk;
103}
104EXPORT_SYMBOL(__inet6_lookup_established);
105
26struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, 106struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
27 const struct in6_addr *daddr, 107 const struct in6_addr *daddr,
28 const unsigned short hnum, const int dif) 108 const unsigned short hnum, const int dif)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 29f73592e68e..aceee252503d 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
114 } 114 }
115 115
116 if (hdr->nexthdr == NEXTHDR_HOP) { 116 if (hdr->nexthdr == NEXTHDR_HOP) {
117 if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) { 117 if (ipv6_parse_hopopts(skb) < 0) {
118 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 118 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
119 return 0; 119 return 0;
120 } 120 }
121 hdr = skb->nh.ipv6h;
122 } 121 }
123 122
124 return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); 123 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 ff9040c92556..a995796b5a57 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -519,9 +519,6 @@ ip6ip6_rcv(struct sk_buff *skb)
519 struct ipv6hdr *ipv6h; 519 struct ipv6hdr *ipv6h;
520 struct ip6_tnl *t; 520 struct ip6_tnl *t;
521 521
522 if (!pskb_may_pull(skb, sizeof (*ipv6h)))
523 goto discard;
524
525 ipv6h = skb->nh.ipv6h; 522 ipv6h = skb->nh.ipv6h;
526 523
527 read_lock(&ip6ip6_lock); 524 read_lock(&ip6ip6_lock);
@@ -529,8 +526,7 @@ ip6ip6_rcv(struct sk_buff *skb)
529 if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { 526 if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
530 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { 527 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
531 read_unlock(&ip6ip6_lock); 528 read_unlock(&ip6ip6_lock);
532 kfree_skb(skb); 529 goto discard;
533 return 0;
534 } 530 }
535 531
536 if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { 532 if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
@@ -557,9 +553,11 @@ ip6ip6_rcv(struct sk_buff *skb)
557 return 0; 553 return 0;
558 } 554 }
559 read_unlock(&ip6ip6_lock); 555 read_unlock(&ip6ip6_lock);
560 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
561discard:
562 return 1; 556 return 1;
557
558discard:
559 kfree_skb(skb);
560 return 0;
563} 561}
564 562
565static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) 563static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index d4cfec3f414e..05eb67def39f 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -63,7 +63,7 @@ static void **ipcomp6_scratches;
63static int ipcomp6_scratch_users; 63static int ipcomp6_scratch_users;
64static LIST_HEAD(ipcomp6_tfms_list); 64static LIST_HEAD(ipcomp6_tfms_list);
65 65
66static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 66static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
67{ 67{
68 int err = 0; 68 int err = 0;
69 u8 nexthdr = 0; 69 u8 nexthdr = 0;
@@ -290,7 +290,7 @@ static void ipcomp6_free_scratches(void)
290 if (!scratches) 290 if (!scratches)
291 return; 291 return;
292 292
293 for_each_cpu(i) { 293 for_each_possible_cpu(i) {
294 void *scratch = *per_cpu_ptr(scratches, i); 294 void *scratch = *per_cpu_ptr(scratches, i);
295 295
296 vfree(scratch); 296 vfree(scratch);
@@ -313,7 +313,7 @@ static void **ipcomp6_alloc_scratches(void)
313 313
314 ipcomp6_scratches = scratches; 314 ipcomp6_scratches = scratches;
315 315
316 for_each_cpu(i) { 316 for_each_possible_cpu(i) {
317 void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE); 317 void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
318 if (!scratch) 318 if (!scratch)
319 return NULL; 319 return NULL;
@@ -344,7 +344,7 @@ static void ipcomp6_free_tfms(struct crypto_tfm **tfms)
344 if (!tfms) 344 if (!tfms)
345 return; 345 return;
346 346
347 for_each_cpu(cpu) { 347 for_each_possible_cpu(cpu) {
348 struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu); 348 struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
349 crypto_free_tfm(tfm); 349 crypto_free_tfm(tfm);
350 } 350 }
@@ -384,7 +384,7 @@ static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name)
384 if (!tfms) 384 if (!tfms)
385 goto error; 385 goto error;
386 386
387 for_each_cpu(cpu) { 387 for_each_possible_cpu(cpu) {
388 struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0); 388 struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
389 if (!tfm) 389 if (!tfm)
390 goto error; 390 goto error;
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index d750cfc019dc..395a417ba955 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -7,6 +7,7 @@
7#include <net/ipv6.h> 7#include <net/ipv6.h>
8#include <net/ip6_route.h> 8#include <net/ip6_route.h>
9#include <net/xfrm.h> 9#include <net/xfrm.h>
10#include <net/ip6_checksum.h>
10 11
11int ip6_route_me_harder(struct sk_buff *skb) 12int ip6_route_me_harder(struct sk_buff *skb)
12{ 13{
@@ -54,7 +55,7 @@ struct ip6_rt_info {
54 struct in6_addr saddr; 55 struct in6_addr saddr;
55}; 56};
56 57
57static void save(const struct sk_buff *skb, struct nf_info *info) 58static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
58{ 59{
59 struct ip6_rt_info *rt_info = nf_info_reroute(info); 60 struct ip6_rt_info *rt_info = nf_info_reroute(info);
60 61
@@ -66,7 +67,7 @@ static void save(const struct sk_buff *skb, struct nf_info *info)
66 } 67 }
67} 68}
68 69
69static int reroute(struct sk_buff **pskb, const struct nf_info *info) 70static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
70{ 71{
71 struct ip6_rt_info *rt_info = nf_info_reroute(info); 72 struct ip6_rt_info *rt_info = nf_info_reroute(info);
72 73
@@ -79,15 +80,50 @@ static int reroute(struct sk_buff **pskb, const struct nf_info *info)
79 return 0; 80 return 0;
80} 81}
81 82
82static struct nf_queue_rerouter ip6_reroute = { 83unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
83 .rer_size = sizeof(struct ip6_rt_info), 84 unsigned int dataoff, u_int8_t protocol)
84 .save = &save, 85{
85 .reroute = &reroute, 86 struct ipv6hdr *ip6h = skb->nh.ipv6h;
87 unsigned int csum = 0;
88
89 switch (skb->ip_summed) {
90 case CHECKSUM_HW:
91 if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
92 break;
93 if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
94 skb->len - dataoff, protocol,
95 csum_sub(skb->csum,
96 skb_checksum(skb, 0,
97 dataoff, 0)))) {
98 skb->ip_summed = CHECKSUM_UNNECESSARY;
99 break;
100 }
101 /* fall through */
102 case CHECKSUM_NONE:
103 skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
104 skb->len - dataoff,
105 protocol,
106 csum_sub(0,
107 skb_checksum(skb, 0,
108 dataoff, 0)));
109 csum = __skb_checksum_complete(skb);
110 }
111 return csum;
112}
113
114EXPORT_SYMBOL(nf_ip6_checksum);
115
116static struct nf_afinfo nf_ip6_afinfo = {
117 .family = AF_INET6,
118 .checksum = nf_ip6_checksum,
119 .saveroute = nf_ip6_saveroute,
120 .reroute = nf_ip6_reroute,
121 .route_key_size = sizeof(struct ip6_rt_info),
86}; 122};
87 123
88int __init ipv6_netfilter_init(void) 124int __init ipv6_netfilter_init(void)
89{ 125{
90 return nf_register_queue_rerouter(PF_INET6, &ip6_reroute); 126 return nf_register_afinfo(&nf_ip6_afinfo);
91} 127}
92 128
93/* This can be called from inet6_init() on errors, so it cannot 129/* This can be called from inet6_init() on errors, so it cannot
@@ -95,5 +131,5 @@ int __init ipv6_netfilter_init(void)
95 */ 131 */
96void ipv6_netfilter_fini(void) 132void ipv6_netfilter_fini(void)
97{ 133{
98 nf_unregister_queue_rerouter(PF_INET6); 134 nf_unregister_afinfo(&nf_ip6_afinfo);
99} 135}
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 98f78759f1ab..4bc4e5b33794 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -87,16 +87,6 @@ config IP6_NF_MATCH_HL
87 87
88 To compile it as a module, choose M here. If unsure, say N. 88 To compile it as a module, choose M here. If unsure, say N.
89 89
90config IP6_NF_MATCH_MULTIPORT
91 tristate "Multiple port match support"
92 depends on IP6_NF_IPTABLES
93 help
94 Multiport matching allows you to match TCP or UDP packets based on
95 a series of source or destination ports: normally a rule can only
96 match a single range of ports.
97
98 To compile it as a module, choose M here. If unsure, say N.
99
100config IP6_NF_MATCH_OWNER 90config IP6_NF_MATCH_OWNER
101 tristate "Owner match support" 91 tristate "Owner match support"
102 depends on IP6_NF_IPTABLES 92 depends on IP6_NF_IPTABLES
@@ -115,11 +105,11 @@ config IP6_NF_MATCH_IPV6HEADER
115 105
116 To compile it as a module, choose M here. If unsure, say N. 106 To compile it as a module, choose M here. If unsure, say N.
117 107
118config IP6_NF_MATCH_AHESP 108config IP6_NF_MATCH_AH
119 tristate "AH/ESP match support" 109 tristate "AH match support"
120 depends on IP6_NF_IPTABLES 110 depends on IP6_NF_IPTABLES
121 help 111 help
122 This module allows one to match AH and ESP packets. 112 This module allows one to match AH packets.
123 113
124 To compile it as a module, choose M here. If unsure, say N. 114 To compile it as a module, choose M here. If unsure, say N.
125 115
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 8436a1a1731f..eeeb57d4c9c5 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -8,9 +8,8 @@ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
8obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o 8obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
9obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o 9obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
10obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o 10obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
11obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o 11obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
12obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o 12obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
13obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
14obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o 13obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
15obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 14obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
16obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 15obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index e81c6a9dab81..b4b7d441af25 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 = {
658 .outfn = &ipq_enqueue_packet, 658 .outfn = &ipq_enqueue_packet,
659}; 659};
660 660
661static int 661static int __init ip6_queue_init(void)
662init_or_cleanup(int init)
663{ 662{
664 int status = -ENOMEM; 663 int status = -ENOMEM;
665 struct proc_dir_entry *proc; 664 struct proc_dir_entry *proc;
666 665
667 if (!init)
668 goto cleanup;
669
670 netlink_register_notifier(&ipq_nl_notifier); 666 netlink_register_notifier(&ipq_nl_notifier);
671 ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, 667 ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
672 THIS_MODULE); 668 THIS_MODULE);
@@ -693,11 +689,6 @@ init_or_cleanup(int init)
693 } 689 }
694 return status; 690 return status;
695 691
696cleanup:
697 nf_unregister_queue_handlers(&nfqh);
698 synchronize_net();
699 ipq_flush(NF_DROP);
700
701cleanup_sysctl: 692cleanup_sysctl:
702 unregister_sysctl_table(ipq_sysctl_header); 693 unregister_sysctl_table(ipq_sysctl_header);
703 unregister_netdevice_notifier(&ipq_dev_notifier); 694 unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -713,15 +704,21 @@ cleanup_netlink_notifier:
713 return status; 704 return status;
714} 705}
715 706
716static int __init ip6_queue_init(void)
717{
718
719 return init_or_cleanup(1);
720}
721
722static void __exit ip6_queue_fini(void) 707static void __exit ip6_queue_fini(void)
723{ 708{
724 init_or_cleanup(0); 709 nf_unregister_queue_handlers(&nfqh);
710 synchronize_net();
711 ipq_flush(NF_DROP);
712
713 unregister_sysctl_table(ipq_sysctl_header);
714 unregister_netdevice_notifier(&ipq_dev_notifier);
715 proc_net_remove(IPQ_PROC_FS_NAME);
716
717 sock_release(ipqnl->sk_socket);
718 mutex_lock(&ipqnl_mutex);
719 mutex_unlock(&ipqnl_mutex);
720
721 netlink_unregister_notifier(&ipq_nl_notifier);
725} 722}
726 723
727MODULE_DESCRIPTION("IPv6 packet queue handler"); 724MODULE_DESCRIPTION("IPv6 packet queue handler");
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 3ecf2db841f8..0a673038344f 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,
288 table_base = (void *)private->entries[smp_processor_id()]; 288 table_base = (void *)private->entries[smp_processor_id()];
289 e = get_entry(table_base, private->hook_entry[hook]); 289 e = get_entry(table_base, private->hook_entry[hook]);
290 290
291#ifdef CONFIG_NETFILTER_DEBUG
292 /* Check noone else using our table */
293 if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac
294 && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) {
295 printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
296 smp_processor_id(),
297 table->name,
298 &((struct ip6t_entry *)table_base)->comefrom,
299 ((struct ip6t_entry *)table_base)->comefrom);
300 }
301 ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001;
302#endif
303
304 /* For return from builtin chain */ 291 /* For return from builtin chain */
305 back = get_entry(table_base, private->underflow[hook]); 292 back = get_entry(table_base, private->underflow[hook]);
306 293
@@ -788,7 +775,7 @@ translate_table(const char *name,
788 } 775 }
789 776
790 /* And one copy for every other CPU */ 777 /* And one copy for every other CPU */
791 for_each_cpu(i) { 778 for_each_possible_cpu(i) {
792 if (newinfo->entries[i] && newinfo->entries[i] != entry0) 779 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
793 memcpy(newinfo->entries[i], entry0, newinfo->size); 780 memcpy(newinfo->entries[i], entry0, newinfo->size);
794 } 781 }
@@ -841,7 +828,7 @@ get_counters(const struct xt_table_info *t,
841 counters, 828 counters,
842 &i); 829 &i);
843 830
844 for_each_cpu(cpu) { 831 for_each_possible_cpu(cpu) {
845 if (cpu == curcpu) 832 if (cpu == curcpu)
846 continue; 833 continue;
847 i = 0; 834 i = 0;
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
deleted file mode 100644
index 36bedad2c6f7..000000000000
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ /dev/null
@@ -1,115 +0,0 @@
1/* Kernel module to match ESP parameters. */
2/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9
10#include <linux/module.h>
11#include <linux/skbuff.h>
12#include <linux/ip.h>
13#include <linux/ipv6.h>
14#include <linux/types.h>
15#include <net/checksum.h>
16#include <net/ipv6.h>
17
18#include <linux/netfilter_ipv6/ip6_tables.h>
19#include <linux/netfilter_ipv6/ip6t_esp.h>
20
21MODULE_LICENSE("GPL");
22MODULE_DESCRIPTION("IPv6 ESP match");
23MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
24
25#if 0
26#define DEBUGP printk
27#else
28#define DEBUGP(format, args...)
29#endif
30
31/* Returns 1 if the spi is matched by the range, 0 otherwise */
32static inline int
33spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
34{
35 int r=0;
36 DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
37 min,spi,max);
38 r=(spi >= min && spi <= max) ^ invert;
39 DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
40 return r;
41}
42
43static int
44match(const struct sk_buff *skb,
45 const struct net_device *in,
46 const struct net_device *out,
47 const struct xt_match *match,
48 const void *matchinfo,
49 int offset,
50 unsigned int protoff,
51 int *hotdrop)
52{
53 struct ip_esp_hdr _esp, *eh;
54 const struct ip6t_esp *espinfo = matchinfo;
55 unsigned int ptr;
56
57 /* Make sure this isn't an evil packet */
58 /*DEBUGP("ipv6_esp entered \n");*/
59
60 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP, NULL) < 0)
61 return 0;
62
63 eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
64 if (eh == NULL) {
65 *hotdrop = 1;
66 return 0;
67 }
68
69 DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
70
71 return (eh != NULL)
72 && spi_match(espinfo->spis[0], espinfo->spis[1],
73 ntohl(eh->spi),
74 !!(espinfo->invflags & IP6T_ESP_INV_SPI));
75}
76
77/* Called when user tries to insert an entry of this type. */
78static int
79checkentry(const char *tablename,
80 const void *ip,
81 const struct xt_match *match,
82 void *matchinfo,
83 unsigned int matchinfosize,
84 unsigned int hook_mask)
85{
86 const struct ip6t_esp *espinfo = matchinfo;
87
88 if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
89 DEBUGP("ip6t_esp: unknown flags %X\n",
90 espinfo->invflags);
91 return 0;
92 }
93 return 1;
94}
95
96static struct ip6t_match esp_match = {
97 .name = "esp",
98 .match = match,
99 .matchsize = sizeof(struct ip6t_esp),
100 .checkentry = checkentry,
101 .me = THIS_MODULE,
102};
103
104static int __init ip6t_esp_init(void)
105{
106 return ip6t_register_match(&esp_match);
107}
108
109static void __exit ip6t_esp_fini(void)
110{
111 ip6t_unregister_match(&esp_match);
112}
113
114module_init(ip6t_esp_init);
115module_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 10c48ba596d6..000000000000
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ /dev/null
@@ -1,125 +0,0 @@
1/* Kernel module to match one of a list of TCP/UDP ports: ports are in
2 the same place so we can treat them as equal. */
3
4/* (C) 1999-2001 Paul `Rusty' Russell
5 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/types.h>
14#include <linux/udp.h>
15#include <linux/skbuff.h>
16#include <linux/in.h>
17
18#include <linux/netfilter_ipv6/ip6t_multiport.h>
19#include <linux/netfilter_ipv6/ip6_tables.h>
20
21MODULE_LICENSE("GPL");
22MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
23MODULE_DESCRIPTION("ip6tables match for multiple ports");
24
25#if 0
26#define duprintf(format, args...) printk(format , ## args)
27#else
28#define duprintf(format, args...)
29#endif
30
31/* Returns 1 if the port is matched by the test, 0 otherwise. */
32static inline int
33ports_match(const u_int16_t *portlist, enum ip6t_multiport_flags flags,
34 u_int8_t count, u_int16_t src, u_int16_t dst)
35{
36 unsigned int i;
37 for (i=0; i<count; i++) {
38 if (flags != IP6T_MULTIPORT_DESTINATION
39 && portlist[i] == src)
40 return 1;
41
42 if (flags != IP6T_MULTIPORT_SOURCE
43 && portlist[i] == dst)
44 return 1;
45 }
46
47 return 0;
48}
49
50static int
51match(const struct sk_buff *skb,
52 const struct net_device *in,
53 const struct net_device *out,
54 const struct xt_match *match,
55 const void *matchinfo,
56 int offset,
57 unsigned int protoff,
58 int *hotdrop)
59{
60 u16 _ports[2], *pptr;
61 const struct ip6t_multiport *multiinfo = matchinfo;
62
63 /* Must not be a fragment. */
64 if (offset)
65 return 0;
66
67 /* Must be big enough to read ports (both UDP and TCP have
68 them at the start). */
69 pptr = skb_header_pointer(skb, protoff, sizeof(_ports), &_ports[0]);
70 if (pptr == NULL) {
71 /* We've been asked to examine this packet, and we
72 * can't. Hence, no choice but to drop.
73 */
74 duprintf("ip6t_multiport:"
75 " Dropping evil offset=0 tinygram.\n");
76 *hotdrop = 1;
77 return 0;
78 }
79
80 return ports_match(multiinfo->ports,
81 multiinfo->flags, multiinfo->count,
82 ntohs(pptr[0]), ntohs(pptr[1]));
83}
84
85/* Called when user tries to insert an entry of this type. */
86static int
87checkentry(const char *tablename,
88 const void *info,
89 const struct xt_match *match,
90 void *matchinfo,
91 unsigned int matchsize,
92 unsigned int hook_mask)
93{
94 const struct ip6t_ip6 *ip = info;
95 const struct ip6t_multiport *multiinfo = matchinfo;
96
97 /* Must specify proto == TCP/UDP, no unknown flags or bad count */
98 return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
99 && !(ip->invflags & IP6T_INV_PROTO)
100 && (multiinfo->flags == IP6T_MULTIPORT_SOURCE
101 || multiinfo->flags == IP6T_MULTIPORT_DESTINATION
102 || multiinfo->flags == IP6T_MULTIPORT_EITHER)
103 && multiinfo->count <= IP6T_MULTI_PORTS;
104}
105
106static struct ip6t_match multiport_match = {
107 .name = "multiport",
108 .match = match,
109 .matchsize = sizeof(struct ip6t_multiport),
110 .checkentry = checkentry,
111 .me = THIS_MODULE,
112};
113
114static int __init ip6t_multiport_init(void)
115{
116 return ip6t_register_match(&multiport_match);
117}
118
119static void __exit ip6t_multiport_fini(void)
120{
121 ip6t_unregister_match(&multiport_match);
122}
123
124module_init(ip6t_multiport_init);
125module_exit(ip6t_multiport_fini);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index e5e724d9ee60..60976c0c58e8 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)
177 return ret; 177 return ret;
178 178
179 /* Register hooks */ 179 /* Register hooks */
180 ret = nf_register_hook(&ip6t_ops[0]); 180 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
181 if (ret < 0) 181 if (ret < 0)
182 goto cleanup_table; 182 goto cleanup_table;
183 183
184 ret = nf_register_hook(&ip6t_ops[1]);
185 if (ret < 0)
186 goto cleanup_hook0;
187
188 ret = nf_register_hook(&ip6t_ops[2]);
189 if (ret < 0)
190 goto cleanup_hook1;
191
192 return ret; 184 return ret;
193 185
194 cleanup_hook1:
195 nf_unregister_hook(&ip6t_ops[1]);
196 cleanup_hook0:
197 nf_unregister_hook(&ip6t_ops[0]);
198 cleanup_table: 186 cleanup_table:
199 ip6t_unregister_table(&packet_filter); 187 ip6t_unregister_table(&packet_filter);
200
201 return ret; 188 return ret;
202} 189}
203 190
204static void __exit ip6table_filter_fini(void) 191static void __exit ip6table_filter_fini(void)
205{ 192{
206 unsigned int i; 193 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
207
208 for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
209 nf_unregister_hook(&ip6t_ops[i]);
210
211 ip6t_unregister_table(&packet_filter); 194 ip6t_unregister_table(&packet_filter);
212} 195}
213 196
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index e1f0f6ae9841..03a13eab1dae 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)
238 return ret; 238 return ret;
239 239
240 /* Register hooks */ 240 /* Register hooks */
241 ret = nf_register_hook(&ip6t_ops[0]); 241 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
242 if (ret < 0) 242 if (ret < 0)
243 goto cleanup_table; 243 goto cleanup_table;
244 244
245 ret = nf_register_hook(&ip6t_ops[1]);
246 if (ret < 0)
247 goto cleanup_hook0;
248
249 ret = nf_register_hook(&ip6t_ops[2]);
250 if (ret < 0)
251 goto cleanup_hook1;
252
253 ret = nf_register_hook(&ip6t_ops[3]);
254 if (ret < 0)
255 goto cleanup_hook2;
256
257 ret = nf_register_hook(&ip6t_ops[4]);
258 if (ret < 0)
259 goto cleanup_hook3;
260
261 return ret; 245 return ret;
262 246
263 cleanup_hook3:
264 nf_unregister_hook(&ip6t_ops[3]);
265 cleanup_hook2:
266 nf_unregister_hook(&ip6t_ops[2]);
267 cleanup_hook1:
268 nf_unregister_hook(&ip6t_ops[1]);
269 cleanup_hook0:
270 nf_unregister_hook(&ip6t_ops[0]);
271 cleanup_table: 247 cleanup_table:
272 ip6t_unregister_table(&packet_mangler); 248 ip6t_unregister_table(&packet_mangler);
273
274 return ret; 249 return ret;
275} 250}
276 251
277static void __exit ip6table_mangle_fini(void) 252static void __exit ip6table_mangle_fini(void)
278{ 253{
279 unsigned int i; 254 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
280
281 for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
282 nf_unregister_hook(&ip6t_ops[i]);
283
284 ip6t_unregister_table(&packet_mangler); 255 ip6t_unregister_table(&packet_mangler);
285} 256}
286 257
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 54d1fffd62ba..61a7c58e99f8 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)
152 return ret; 152 return ret;
153 153
154 /* Register hooks */ 154 /* Register hooks */
155 ret = nf_register_hook(&ip6t_ops[0]); 155 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
156 if (ret < 0) 156 if (ret < 0)
157 goto cleanup_table; 157 goto cleanup_table;
158 158
159 ret = nf_register_hook(&ip6t_ops[1]);
160 if (ret < 0)
161 goto cleanup_hook0;
162
163 return ret; 159 return ret;
164 160
165 cleanup_hook0:
166 nf_unregister_hook(&ip6t_ops[0]);
167 cleanup_table: 161 cleanup_table:
168 ip6t_unregister_table(&packet_raw); 162 ip6t_unregister_table(&packet_raw);
169
170 return ret; 163 return ret;
171} 164}
172 165
173static void __exit ip6table_raw_fini(void) 166static void __exit ip6table_raw_fini(void)
174{ 167{
175 unsigned int i; 168 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
176
177 for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
178 nf_unregister_hook(&ip6t_ops[i]);
179
180 ip6t_unregister_table(&packet_raw); 169 ip6t_unregister_table(&packet_raw);
181} 170}
182 171
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index c8b5a96cbb0f..93bae36f2663 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,
286 return ipv6_conntrack_in(hooknum, pskb, in, out, okfn); 286 return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
287} 287}
288 288
289/* Connection tracking may drop packets, but never alters them, so 289static struct nf_hook_ops ipv6_conntrack_ops[] = {
290 make it the first hook. */ 290 {
291static struct nf_hook_ops ipv6_conntrack_defrag_ops = { 291 .hook = ipv6_defrag,
292 .hook = ipv6_defrag, 292 .owner = THIS_MODULE,
293 .owner = THIS_MODULE, 293 .pf = PF_INET6,
294 .pf = PF_INET6, 294 .hooknum = NF_IP6_PRE_ROUTING,
295 .hooknum = NF_IP6_PRE_ROUTING, 295 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
296 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, 296 },
297}; 297 {
298 298 .hook = ipv6_conntrack_in,
299static struct nf_hook_ops ipv6_conntrack_in_ops = { 299 .owner = THIS_MODULE,
300 .hook = ipv6_conntrack_in, 300 .pf = PF_INET6,
301 .owner = THIS_MODULE, 301 .hooknum = NF_IP6_PRE_ROUTING,
302 .pf = PF_INET6, 302 .priority = NF_IP6_PRI_CONNTRACK,
303 .hooknum = NF_IP6_PRE_ROUTING, 303 },
304 .priority = NF_IP6_PRI_CONNTRACK, 304 {
305}; 305 .hook = ipv6_conntrack_local,
306 306 .owner = THIS_MODULE,
307static struct nf_hook_ops ipv6_conntrack_local_out_ops = { 307 .pf = PF_INET6,
308 .hook = ipv6_conntrack_local, 308 .hooknum = NF_IP6_LOCAL_OUT,
309 .owner = THIS_MODULE, 309 .priority = NF_IP6_PRI_CONNTRACK,
310 .pf = PF_INET6, 310 },
311 .hooknum = NF_IP6_LOCAL_OUT, 311 {
312 .priority = NF_IP6_PRI_CONNTRACK, 312 .hook = ipv6_defrag,
313}; 313 .owner = THIS_MODULE,
314 314 .pf = PF_INET6,
315static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = { 315 .hooknum = NF_IP6_LOCAL_OUT,
316 .hook = ipv6_defrag, 316 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG,
317 .owner = THIS_MODULE, 317 },
318 .pf = PF_INET6, 318 {
319 .hooknum = NF_IP6_LOCAL_OUT, 319 .hook = ipv6_confirm,
320 .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, 320 .owner = THIS_MODULE,
321}; 321 .pf = PF_INET6,
322 322 .hooknum = NF_IP6_POST_ROUTING,
323/* Refragmenter; last chance. */ 323 .priority = NF_IP6_PRI_LAST,
324static struct nf_hook_ops ipv6_conntrack_out_ops = { 324 },
325 .hook = ipv6_confirm, 325 {
326 .owner = THIS_MODULE, 326 .hook = ipv6_confirm,
327 .pf = PF_INET6, 327 .owner = THIS_MODULE,
328 .hooknum = NF_IP6_POST_ROUTING, 328 .pf = PF_INET6,
329 .priority = NF_IP6_PRI_LAST, 329 .hooknum = NF_IP6_LOCAL_IN,
330}; 330 .priority = NF_IP6_PRI_LAST-1,
331 331 },
332static struct nf_hook_ops ipv6_conntrack_local_in_ops = {
333 .hook = ipv6_confirm,
334 .owner = THIS_MODULE,
335 .pf = PF_INET6,
336 .hooknum = NF_IP6_LOCAL_IN,
337 .priority = NF_IP6_PRI_LAST-1,
338}; 332};
339 333
340#ifdef CONFIG_SYSCTL 334#ifdef CONFIG_SYSCTL
@@ -470,16 +464,21 @@ extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
470extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6; 464extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6;
471extern int nf_ct_frag6_init(void); 465extern int nf_ct_frag6_init(void);
472extern void nf_ct_frag6_cleanup(void); 466extern void nf_ct_frag6_cleanup(void);
473static int init_or_cleanup(int init) 467
468MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
469MODULE_LICENSE("GPL");
470MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
471
472static int __init nf_conntrack_l3proto_ipv6_init(void)
474{ 473{
475 int ret = 0; 474 int ret = 0;
476 475
477 if (!init) goto cleanup; 476 need_conntrack();
478 477
479 ret = nf_ct_frag6_init(); 478 ret = nf_ct_frag6_init();
480 if (ret < 0) { 479 if (ret < 0) {
481 printk("nf_conntrack_ipv6: can't initialize frag6.\n"); 480 printk("nf_conntrack_ipv6: can't initialize frag6.\n");
482 goto cleanup_nothing; 481 return ret;
483 } 482 }
484 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6); 483 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
485 if (ret < 0) { 484 if (ret < 0) {
@@ -505,71 +504,27 @@ static int init_or_cleanup(int init)
505 goto cleanup_icmpv6; 504 goto cleanup_icmpv6;
506 } 505 }
507 506
508 ret = nf_register_hook(&ipv6_conntrack_defrag_ops); 507 ret = nf_register_hooks(ipv6_conntrack_ops,
508 ARRAY_SIZE(ipv6_conntrack_ops));
509 if (ret < 0) { 509 if (ret < 0) {
510 printk("nf_conntrack_ipv6: can't register pre-routing defrag " 510 printk("nf_conntrack_ipv6: can't register pre-routing defrag "
511 "hook.\n"); 511 "hook.\n");
512 goto cleanup_ipv6; 512 goto cleanup_ipv6;
513 } 513 }
514
515 ret = nf_register_hook(&ipv6_conntrack_defrag_local_out_ops);
516 if (ret < 0) {
517 printk("nf_conntrack_ipv6: can't register local_out defrag "
518 "hook.\n");
519 goto cleanup_defragops;
520 }
521
522 ret = nf_register_hook(&ipv6_conntrack_in_ops);
523 if (ret < 0) {
524 printk("nf_conntrack_ipv6: can't register pre-routing hook.\n");
525 goto cleanup_defraglocalops;
526 }
527
528 ret = nf_register_hook(&ipv6_conntrack_local_out_ops);
529 if (ret < 0) {
530 printk("nf_conntrack_ipv6: can't register local out hook.\n");
531 goto cleanup_inops;
532 }
533
534 ret = nf_register_hook(&ipv6_conntrack_out_ops);
535 if (ret < 0) {
536 printk("nf_conntrack_ipv6: can't register post-routing hook.\n");
537 goto cleanup_inandlocalops;
538 }
539
540 ret = nf_register_hook(&ipv6_conntrack_local_in_ops);
541 if (ret < 0) {
542 printk("nf_conntrack_ipv6: can't register local in hook.\n");
543 goto cleanup_inoutandlocalops;
544 }
545
546#ifdef CONFIG_SYSCTL 514#ifdef CONFIG_SYSCTL
547 nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); 515 nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
548 if (nf_ct_ipv6_sysctl_header == NULL) { 516 if (nf_ct_ipv6_sysctl_header == NULL) {
549 printk("nf_conntrack: can't register to sysctl.\n"); 517 printk("nf_conntrack: can't register to sysctl.\n");
550 ret = -ENOMEM; 518 ret = -ENOMEM;
551 goto cleanup_localinops; 519 goto cleanup_hooks;
552 } 520 }
553#endif 521#endif
554 return ret; 522 return ret;
555 523
556 cleanup:
557 synchronize_net();
558#ifdef CONFIG_SYSCTL 524#ifdef CONFIG_SYSCTL
559 unregister_sysctl_table(nf_ct_ipv6_sysctl_header); 525 cleanup_hooks:
560 cleanup_localinops: 526 nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
561#endif 527#endif
562 nf_unregister_hook(&ipv6_conntrack_local_in_ops);
563 cleanup_inoutandlocalops:
564 nf_unregister_hook(&ipv6_conntrack_out_ops);
565 cleanup_inandlocalops:
566 nf_unregister_hook(&ipv6_conntrack_local_out_ops);
567 cleanup_inops:
568 nf_unregister_hook(&ipv6_conntrack_in_ops);
569 cleanup_defraglocalops:
570 nf_unregister_hook(&ipv6_conntrack_defrag_local_out_ops);
571 cleanup_defragops:
572 nf_unregister_hook(&ipv6_conntrack_defrag_ops);
573 cleanup_ipv6: 528 cleanup_ipv6:
574 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); 529 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
575 cleanup_icmpv6: 530 cleanup_icmpv6:
@@ -580,23 +535,21 @@ static int init_or_cleanup(int init)
580 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); 535 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
581 cleanup_frag6: 536 cleanup_frag6:
582 nf_ct_frag6_cleanup(); 537 nf_ct_frag6_cleanup();
583 cleanup_nothing:
584 return ret; 538 return ret;
585} 539}
586 540
587MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
588MODULE_LICENSE("GPL");
589MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
590
591static int __init nf_conntrack_l3proto_ipv6_init(void)
592{
593 need_conntrack();
594 return init_or_cleanup(1);
595}
596
597static void __exit nf_conntrack_l3proto_ipv6_fini(void) 541static void __exit nf_conntrack_l3proto_ipv6_fini(void)
598{ 542{
599 init_or_cleanup(0); 543 synchronize_net();
544#ifdef CONFIG_SYSCTL
545 unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
546#endif
547 nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
548 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
549 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
550 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
551 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
552 nf_ct_frag6_cleanup();
600} 553}
601 554
602module_init(nf_conntrack_l3proto_ipv6_init); 555module_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 09945c333055..86c6703265d0 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,
233 return -NF_ACCEPT; 233 return -NF_ACCEPT;
234 } 234 }
235 235
236 if (hooknum != NF_IP6_PRE_ROUTING) 236 if (hooknum == NF_IP6_PRE_ROUTING &&
237 goto skipped; 237 nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
238
239 /* Ignore it if the checksum's bogus. */
240 if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
241 skb->len - dataoff, IPPROTO_ICMPV6,
242 skb_checksum(skb, dataoff,
243 skb->len - dataoff, 0))) {
244 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, 238 nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
245 "nf_ct_icmpv6: ICMPv6 checksum failed\n"); 239 "nf_ct_icmpv6: ICMPv6 checksum failed\n");
246 return -NF_ACCEPT; 240 return -NF_ACCEPT;
247 } 241 }
248 242
249skipped:
250
251 /* is not error message ? */ 243 /* is not error message ? */
252 if (icmp6h->icmp6_type >= 128) 244 if (icmp6h->icmp6_type >= 128)
253 return NF_ACCEPT; 245 return NF_ACCEPT;
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 4238b1ed8860..779ddf77f4d4 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -38,7 +38,7 @@ static int fold_prot_inuse(struct proto *proto)
38 int res = 0; 38 int res = 0;
39 int cpu; 39 int cpu;
40 40
41 for_each_cpu(cpu) 41 for_each_possible_cpu(cpu)
42 res += proto->stats[cpu].inuse; 42 res += proto->stats[cpu].inuse;
43 43
44 return res; 44 return res;
@@ -140,7 +140,7 @@ fold_field(void *mib[], int offt)
140 unsigned long res = 0; 140 unsigned long res = 0;
141 int i; 141 int i;
142 142
143 for_each_cpu(i) { 143 for_each_possible_cpu(i) {
144 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt); 144 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
145 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt); 145 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
146 } 146 }
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index b67a45fb93e9..eef985e010ea 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -121,6 +121,10 @@ static __inline__ void fq_unlink(struct frag_queue *fq)
121 write_unlock(&ip6_frag_lock); 121 write_unlock(&ip6_frag_lock);
122} 122}
123 123
124/*
125 * callers should be careful not to use the hash value outside the ipfrag_lock
126 * as doing so could race with ipfrag_hash_rnd being recalculated.
127 */
124static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr, 128static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
125 struct in6_addr *daddr) 129 struct in6_addr *daddr)
126{ 130{
@@ -324,15 +328,16 @@ out:
324/* Creation primitives. */ 328/* Creation primitives. */
325 329
326 330
327static struct frag_queue *ip6_frag_intern(unsigned int hash, 331static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in)
328 struct frag_queue *fq_in)
329{ 332{
330 struct frag_queue *fq; 333 struct frag_queue *fq;
334 unsigned int hash;
331#ifdef CONFIG_SMP 335#ifdef CONFIG_SMP
332 struct hlist_node *n; 336 struct hlist_node *n;
333#endif 337#endif
334 338
335 write_lock(&ip6_frag_lock); 339 write_lock(&ip6_frag_lock);
340 hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr);
336#ifdef CONFIG_SMP 341#ifdef CONFIG_SMP
337 hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { 342 hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
338 if (fq->id == fq_in->id && 343 if (fq->id == fq_in->id &&
@@ -362,7 +367,7 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash,
362 367
363 368
364static struct frag_queue * 369static struct frag_queue *
365ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst) 370ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst)
366{ 371{
367 struct frag_queue *fq; 372 struct frag_queue *fq;
368 373
@@ -379,7 +384,7 @@ ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr
379 spin_lock_init(&fq->lock); 384 spin_lock_init(&fq->lock);
380 atomic_set(&fq->refcnt, 1); 385 atomic_set(&fq->refcnt, 1);
381 386
382 return ip6_frag_intern(hash, fq); 387 return ip6_frag_intern(fq);
383 388
384oom: 389oom:
385 IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); 390 IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
@@ -391,9 +396,10 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
391{ 396{
392 struct frag_queue *fq; 397 struct frag_queue *fq;
393 struct hlist_node *n; 398 struct hlist_node *n;
394 unsigned int hash = ip6qhashfn(id, src, dst); 399 unsigned int hash;
395 400
396 read_lock(&ip6_frag_lock); 401 read_lock(&ip6_frag_lock);
402 hash = ip6qhashfn(id, src, dst);
397 hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { 403 hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
398 if (fq->id == id && 404 if (fq->id == id &&
399 ipv6_addr_equal(src, &fq->saddr) && 405 ipv6_addr_equal(src, &fq->saddr) &&
@@ -405,7 +411,7 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
405 } 411 }
406 read_unlock(&ip6_frag_lock); 412 read_unlock(&ip6_frag_lock);
407 413
408 return ip6_frag_create(hash, id, src, dst); 414 return ip6_frag_create(id, src, dst);
409} 415}
410 416
411 417
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index c2d3e17beae6..6578c3080f47 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -397,7 +397,7 @@ static int ipip6_rcv(struct sk_buff *skb)
397 return 0; 397 return 0;
398 } 398 }
399 399
400 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); 400 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
401 kfree_skb(skb); 401 kfree_skb(skb);
402 read_unlock(&ipip6_lock); 402 read_unlock(&ipip6_lock);
403out: 403out:
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index 5659b52284bd..0ef9a35798d1 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -19,11 +19,13 @@
19 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> 19 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
20 */ 20 */
21 21
22#include <linux/icmpv6.h>
22#include <linux/init.h> 23#include <linux/init.h>
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/mutex.h> 25#include <linux/mutex.h>
25#include <linux/netdevice.h> 26#include <linux/netdevice.h>
26#include <linux/skbuff.h> 27#include <linux/skbuff.h>
28#include <net/ipv6.h>
27#include <net/protocol.h> 29#include <net/protocol.h>
28#include <net/xfrm.h> 30#include <net/xfrm.h>
29 31
@@ -87,10 +89,16 @@ static int tunnel6_rcv(struct sk_buff **pskb)
87 struct sk_buff *skb = *pskb; 89 struct sk_buff *skb = *pskb;
88 struct xfrm6_tunnel *handler; 90 struct xfrm6_tunnel *handler;
89 91
92 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
93 goto drop;
94
90 for (handler = tunnel6_handlers; handler; handler = handler->next) 95 for (handler = tunnel6_handlers; handler; handler = handler->next)
91 if (!handler->handler(skb)) 96 if (!handler->handler(skb))
92 return 0; 97 return 0;
93 98
99 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
100
101drop:
94 kfree_skb(skb); 102 kfree_skb(skb);
95 return 0; 103 return 0;
96} 104}
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index cccf8b76f046..00cfdee18dca 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)
32{ 32{
33 int err; 33 int err;
34 u32 seq; 34 u32 seq;
35 struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH]; 35 struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
36 struct xfrm_state *x; 36 struct xfrm_state *x;
37 int xfrm_nr = 0; 37 int xfrm_nr = 0;
38 int decaps = 0; 38 int decaps = 0;
@@ -65,7 +65,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
65 if (xfrm_state_check_expire(x)) 65 if (xfrm_state_check_expire(x))
66 goto drop_unlock; 66 goto drop_unlock;
67 67
68 nexthdr = x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb); 68 nexthdr = x->type->input(x, skb);
69 if (nexthdr <= 0) 69 if (nexthdr <= 0)
70 goto drop_unlock; 70 goto drop_unlock;
71 71
@@ -79,7 +79,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
79 79
80 spin_unlock(&x->lock); 80 spin_unlock(&x->lock);
81 81
82 xfrm_vec[xfrm_nr++].xvec = x; 82 xfrm_vec[xfrm_nr++] = x;
83 83
84 if (x->props.mode) { /* XXX */ 84 if (x->props.mode) { /* XXX */
85 if (nexthdr != IPPROTO_IPV6) 85 if (nexthdr != IPPROTO_IPV6)
@@ -118,7 +118,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
118 if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) 118 if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
119 goto drop; 119 goto drop;
120 120
121 memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); 121 memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
122 xfrm_nr * sizeof(xfrm_vec[0]));
122 skb->sp->len += xfrm_nr; 123 skb->sp->len += xfrm_nr;
123 skb->ip_summed = CHECKSUM_NONE; 124 skb->ip_summed = CHECKSUM_NONE;
124 125
@@ -149,7 +150,7 @@ drop_unlock:
149 xfrm_state_put(x); 150 xfrm_state_put(x);
150drop: 151drop:
151 while (--xfrm_nr >= 0) 152 while (--xfrm_nr >= 0)
152 xfrm_state_put(xfrm_vec[xfrm_nr].xvec); 153 xfrm_state_put(xfrm_vec[xfrm_nr]);
153 kfree_skb(skb); 154 kfree_skb(skb);
154 return -1; 155 return -1;
155} 156}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 91cce8b2d7a5..88c840f1beb6 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -191,16 +191,18 @@ error:
191static inline void 191static inline void
192_decode_session6(struct sk_buff *skb, struct flowi *fl) 192_decode_session6(struct sk_buff *skb, struct flowi *fl)
193{ 193{
194 u16 offset = sizeof(struct ipv6hdr); 194 u16 offset = skb->h.raw - skb->nh.raw;
195 struct ipv6hdr *hdr = skb->nh.ipv6h; 195 struct ipv6hdr *hdr = skb->nh.ipv6h;
196 struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); 196 struct ipv6_opt_hdr *exthdr;
197 u8 nexthdr = skb->nh.ipv6h->nexthdr; 197 u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff];
198 198
199 memset(fl, 0, sizeof(struct flowi)); 199 memset(fl, 0, sizeof(struct flowi));
200 ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr); 200 ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
201 ipv6_addr_copy(&fl->fl6_src, &hdr->saddr); 201 ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
202 202
203 while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) { 203 while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
204 exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
205
204 switch (nexthdr) { 206 switch (nexthdr) {
205 case NEXTHDR_ROUTING: 207 case NEXTHDR_ROUTING:
206 case NEXTHDR_HOP: 208 case NEXTHDR_HOP:
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index a8f6776c518d..d37768e5064f 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)
351 return 0; 351 return 0;
352} 352}
353 353
354static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) 354static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
355{ 355{
356 return 0; 356 return 0;
357} 357}
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 8f3addf0724c..d62e0f9b9da3 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)
118 u16 pdulen = eth_hdr(skb)->h_proto, 118 u16 pdulen = eth_hdr(skb)->h_proto,
119 data_size = ntohs(pdulen) - llc_len; 119 data_size = ntohs(pdulen) - llc_len;
120 120
121 skb_trim(skb, data_size); 121 if (unlikely(pskb_trim_rcsum(skb, data_size)))
122 return 0;
122 } 123 }
123 return 1; 124 return 1;
124} 125}
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 332acb37b385..e2893effdfaa 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -231,6 +231,15 @@ config NETFILTER_XT_MATCH_DCCP
231 If you want to compile it as a module, say M here and read 231 If you want to compile it as a module, say M here and read
232 <file:Documentation/modules.txt>. If unsure, say `N'. 232 <file:Documentation/modules.txt>. If unsure, say `N'.
233 233
234config NETFILTER_XT_MATCH_ESP
235 tristate '"ESP" match support'
236 depends on NETFILTER_XTABLES
237 help
238 This match extension allows you to match a range of SPIs
239 inside ESP header of IPSec packets.
240
241 To compile it as a module, choose M here. If unsure, say N.
242
234config NETFILTER_XT_MATCH_HELPER 243config NETFILTER_XT_MATCH_HELPER
235 tristate '"helper" match support' 244 tristate '"helper" match support'
236 depends on NETFILTER_XTABLES 245 depends on NETFILTER_XTABLES
@@ -289,6 +298,16 @@ config NETFILTER_XT_MATCH_POLICY
289 298
290 To compile it as a module, choose M here. If unsure, say N. 299 To compile it as a module, choose M here. If unsure, say N.
291 300
301config NETFILTER_XT_MATCH_MULTIPORT
302 tristate "Multiple port match support"
303 depends on NETFILTER_XTABLES
304 help
305 Multiport matching allows you to match TCP or UDP packets based on
306 a series of source or destination ports: normally a rule can only
307 match a single range of ports.
308
309 To compile it as a module, choose M here. If unsure, say N.
310
292config NETFILTER_XT_MATCH_PHYSDEV 311config NETFILTER_XT_MATCH_PHYSDEV
293 tristate '"physdev" match support' 312 tristate '"physdev" match support'
294 depends on NETFILTER_XTABLES && BRIDGE_NETFILTER 313 depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 9558727f5e79..95b7e416512d 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -35,11 +35,13 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
35obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o 35obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
36obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o 36obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
37obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o 37obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
38obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
38obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o 39obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
39obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o 40obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
40obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o 41obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
41obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o 42obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
42obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o 43obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
44obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
43obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o 45obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
44obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o 46obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
45obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o 47obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 1ceb1a6c254b..8455a32ea5c4 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -27,6 +27,29 @@
27 27
28#include "nf_internals.h" 28#include "nf_internals.h"
29 29
30static DEFINE_SPINLOCK(afinfo_lock);
31
32struct nf_afinfo *nf_afinfo[NPROTO];
33EXPORT_SYMBOL(nf_afinfo);
34
35int nf_register_afinfo(struct nf_afinfo *afinfo)
36{
37 spin_lock(&afinfo_lock);
38 rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);
39 spin_unlock(&afinfo_lock);
40 return 0;
41}
42EXPORT_SYMBOL_GPL(nf_register_afinfo);
43
44void nf_unregister_afinfo(struct nf_afinfo *afinfo)
45{
46 spin_lock(&afinfo_lock);
47 rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
48 spin_unlock(&afinfo_lock);
49 synchronize_rcu();
50}
51EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
52
30/* In this code, we can be waiting indefinitely for userspace to 53/* In this code, we can be waiting indefinitely for userspace to
31 * service a packet if a hook returns NF_QUEUE. We could keep a count 54 * service a packet if a hook returns NF_QUEUE. We could keep a count
32 * of skbuffs queued for userspace, and not deregister a hook unless 55 * of skbuffs queued for userspace, and not deregister a hook unless
@@ -63,6 +86,34 @@ void nf_unregister_hook(struct nf_hook_ops *reg)
63} 86}
64EXPORT_SYMBOL(nf_unregister_hook); 87EXPORT_SYMBOL(nf_unregister_hook);
65 88
89int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
90{
91 unsigned int i;
92 int err = 0;
93
94 for (i = 0; i < n; i++) {
95 err = nf_register_hook(&reg[i]);
96 if (err)
97 goto err;
98 }
99 return err;
100
101err:
102 if (i > 0)
103 nf_unregister_hooks(reg, i);
104 return err;
105}
106EXPORT_SYMBOL(nf_register_hooks);
107
108void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
109{
110 unsigned int i;
111
112 for (i = 0; i < n; i++)
113 nf_unregister_hook(&reg[i]);
114}
115EXPORT_SYMBOL(nf_unregister_hooks);
116
66unsigned int nf_iterate(struct list_head *head, 117unsigned int nf_iterate(struct list_head *head,
67 struct sk_buff **skb, 118 struct sk_buff **skb,
68 int hook, 119 int hook,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 56389c83557c..f9b83f91371a 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)
146 struct nf_conntrack_ecache *ecache; 146 struct nf_conntrack_ecache *ecache;
147 int cpu; 147 int cpu;
148 148
149 for_each_cpu(cpu) { 149 for_each_possible_cpu(cpu) {
150 ecache = &per_cpu(nf_conntrack_ecache, cpu); 150 ecache = &per_cpu(nf_conntrack_ecache, cpu);
151 if (ecache->ct) 151 if (ecache->ct)
152 nf_ct_put(ecache->ct); 152 nf_ct_put(ecache->ct);
@@ -178,9 +178,6 @@ static struct {
178 /* allocated slab cache + modules which uses this slab cache */ 178 /* allocated slab cache + modules which uses this slab cache */
179 int use; 179 int use;
180 180
181 /* Initialization */
182 int (*init_conntrack)(struct nf_conn *, u_int32_t);
183
184} nf_ct_cache[NF_CT_F_NUM]; 181} nf_ct_cache[NF_CT_F_NUM];
185 182
186/* protect members of nf_ct_cache except of "use" */ 183/* 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)
208 205
209 preempt_disable(); 206 preempt_disable();
210 p = __nf_ct_proto_find(l3proto, protocol); 207 p = __nf_ct_proto_find(l3proto, protocol);
211 if (p) { 208 if (!try_module_get(p->me))
212 if (!try_module_get(p->me)) 209 p = &nf_conntrack_generic_protocol;
213 p = &nf_conntrack_generic_protocol;
214 }
215 preempt_enable(); 210 preempt_enable();
216 211
217 return p; 212 return p;
@@ -229,10 +224,8 @@ nf_ct_l3proto_find_get(u_int16_t l3proto)
229 224
230 preempt_disable(); 225 preempt_disable();
231 p = __nf_ct_l3proto_find(l3proto); 226 p = __nf_ct_l3proto_find(l3proto);
232 if (p) { 227 if (!try_module_get(p->me))
233 if (!try_module_get(p->me)) 228 p = &nf_conntrack_generic_l3proto;
234 p = &nf_conntrack_generic_l3proto;
235 }
236 preempt_enable(); 229 preempt_enable();
237 230
238 return p; 231 return p;
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 7de4f06c63c5..3fc58e454d4e 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 = {
94 .print_conntrack = generic_print_conntrack, 94 .print_conntrack = generic_print_conntrack,
95 .prepare = generic_prepare, 95 .prepare = generic_prepare,
96 .get_features = generic_get_features, 96 .get_features = generic_get_features,
97 .me = THIS_MODULE,
98}; 97};
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 0e0e9d7b34c8..bd10eb944b65 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[])
1022 return err; 1022 return err;
1023 } 1023 }
1024 1024
1025#if defined(CONFIG_IP_NF_CONNTRACK_MARK) 1025#if defined(CONFIG_NF_CONNTRACK_MARK)
1026 if (cda[CTA_MARK-1]) 1026 if (cda[CTA_MARK-1])
1027 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); 1027 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
1028#endif 1028#endif
@@ -1062,7 +1062,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
1062 return err; 1062 return err;
1063 } 1063 }
1064 1064
1065#if defined(CONFIG_IP_NF_CONNTRACK_MARK) 1065#if defined(CONFIG_NF_CONNTRACK_MARK)
1066 if (cda[CTA_MARK-1]) 1066 if (cda[CTA_MARK-1])
1067 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); 1067 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
1068#endif 1068#endif
@@ -1687,7 +1687,7 @@ static void __exit ctnetlink_exit(void)
1687 printk("ctnetlink: unregistering from nfnetlink.\n"); 1687 printk("ctnetlink: unregistering from nfnetlink.\n");
1688 1688
1689#ifdef CONFIG_NF_CONNTRACK_EVENTS 1689#ifdef CONFIG_NF_CONNTRACK_EVENTS
1690 nf_conntrack_unregister_notifier(&ctnl_notifier_exp); 1690 nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
1691 nf_conntrack_unregister_notifier(&ctnl_notifier); 1691 nf_conntrack_unregister_notifier(&ctnl_notifier);
1692#endif 1692#endif
1693 1693
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6492ed66fb3c..69899f27d26a 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,
799 unsigned int dataoff, 799 unsigned int dataoff,
800 enum ip_conntrack_info *ctinfo, 800 enum ip_conntrack_info *ctinfo,
801 int pf, 801 int pf,
802 unsigned int hooknum, 802 unsigned int hooknum)
803 int(*csum)(const struct sk_buff *,unsigned int))
804{ 803{
805 struct tcphdr _tcph, *th; 804 struct tcphdr _tcph, *th;
806 unsigned int tcplen = skb->len - dataoff; 805 unsigned int tcplen = skb->len - dataoff;
@@ -830,9 +829,8 @@ static int tcp_error(struct sk_buff *skb,
830 */ 829 */
831 /* FIXME: Source route IP option packets --RR */ 830 /* FIXME: Source route IP option packets --RR */
832 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || 831 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
833 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) 832 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
834 && skb->ip_summed != CHECKSUM_UNNECESSARY 833 nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
835 && csum(skb, dataoff)) {
836 if (LOG_INVALID(IPPROTO_TCP)) 834 if (LOG_INVALID(IPPROTO_TCP))
837 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 835 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
838 "nf_ct_tcp: bad TCP checksum "); 836 "nf_ct_tcp: bad TCP checksum ");
@@ -851,44 +849,6 @@ static int tcp_error(struct sk_buff *skb,
851 return NF_ACCEPT; 849 return NF_ACCEPT;
852} 850}
853 851
854static int csum4(const struct sk_buff *skb, unsigned int dataoff)
855{
856 return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
857 skb->len - dataoff, IPPROTO_TCP,
858 skb->ip_summed == CHECKSUM_HW ? skb->csum
859 : skb_checksum(skb, dataoff,
860 skb->len - dataoff, 0));
861}
862
863static int csum6(const struct sk_buff *skb, unsigned int dataoff)
864{
865 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
866 skb->len - dataoff, IPPROTO_TCP,
867 skb->ip_summed == CHECKSUM_HW
868 ? csum_sub(skb->csum,
869 skb_checksum(skb, 0, dataoff, 0))
870 : skb_checksum(skb, dataoff, skb->len - dataoff,
871 0));
872}
873
874static int tcp_error4(struct sk_buff *skb,
875 unsigned int dataoff,
876 enum ip_conntrack_info *ctinfo,
877 int pf,
878 unsigned int hooknum)
879{
880 return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
881}
882
883static int tcp_error6(struct sk_buff *skb,
884 unsigned int dataoff,
885 enum ip_conntrack_info *ctinfo,
886 int pf,
887 unsigned int hooknum)
888{
889 return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
890}
891
892/* Returns verdict for packet, or -1 for invalid. */ 852/* Returns verdict for packet, or -1 for invalid. */
893static int tcp_packet(struct nf_conn *conntrack, 853static int tcp_packet(struct nf_conn *conntrack,
894 const struct sk_buff *skb, 854 const struct sk_buff *skb,
@@ -1218,7 +1178,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
1218 .print_conntrack = tcp_print_conntrack, 1178 .print_conntrack = tcp_print_conntrack,
1219 .packet = tcp_packet, 1179 .packet = tcp_packet,
1220 .new = tcp_new, 1180 .new = tcp_new,
1221 .error = tcp_error4, 1181 .error = tcp_error,
1222#if defined(CONFIG_NF_CT_NETLINK) || \ 1182#if defined(CONFIG_NF_CT_NETLINK) || \
1223 defined(CONFIG_NF_CT_NETLINK_MODULE) 1183 defined(CONFIG_NF_CT_NETLINK_MODULE)
1224 .to_nfattr = tcp_to_nfattr, 1184 .to_nfattr = tcp_to_nfattr,
@@ -1239,7 +1199,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
1239 .print_conntrack = tcp_print_conntrack, 1199 .print_conntrack = tcp_print_conntrack,
1240 .packet = tcp_packet, 1200 .packet = tcp_packet,
1241 .new = tcp_new, 1201 .new = tcp_new,
1242 .error = tcp_error6, 1202 .error = tcp_error,
1243#if defined(CONFIG_NF_CT_NETLINK) || \ 1203#if defined(CONFIG_NF_CT_NETLINK) || \
1244 defined(CONFIG_NF_CT_NETLINK_MODULE) 1204 defined(CONFIG_NF_CT_NETLINK_MODULE)
1245 .to_nfattr = tcp_to_nfattr, 1205 .to_nfattr = tcp_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 831d206344e0..d93edbfde9e3 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,
103static int udp_error(struct sk_buff *skb, unsigned int dataoff, 103static int udp_error(struct sk_buff *skb, unsigned int dataoff,
104 enum ip_conntrack_info *ctinfo, 104 enum ip_conntrack_info *ctinfo,
105 int pf, 105 int pf,
106 unsigned int hooknum, 106 unsigned int hooknum)
107 int (*csum)(const struct sk_buff *, unsigned int))
108{ 107{
109 unsigned int udplen = skb->len - dataoff; 108 unsigned int udplen = skb->len - dataoff;
110 struct udphdr _hdr, *hdr; 109 struct udphdr _hdr, *hdr;
@@ -136,9 +135,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
136 * and moreover root might send raw packets. 135 * and moreover root might send raw packets.
137 * FIXME: Source route IP option packets --RR */ 136 * FIXME: Source route IP option packets --RR */
138 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || 137 if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
139 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) 138 (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
140 && skb->ip_summed != CHECKSUM_UNNECESSARY 139 nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
141 && csum(skb, dataoff)) {
142 if (LOG_INVALID(IPPROTO_UDP)) 140 if (LOG_INVALID(IPPROTO_UDP))
143 nf_log_packet(pf, 0, skb, NULL, NULL, NULL, 141 nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
144 "nf_ct_udp: bad UDP checksum "); 142 "nf_ct_udp: bad UDP checksum ");
@@ -148,44 +146,6 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
148 return NF_ACCEPT; 146 return NF_ACCEPT;
149} 147}
150 148
151static int csum4(const struct sk_buff *skb, unsigned int dataoff)
152{
153 return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
154 skb->len - dataoff, IPPROTO_UDP,
155 skb->ip_summed == CHECKSUM_HW ? skb->csum
156 : skb_checksum(skb, dataoff,
157 skb->len - dataoff, 0));
158}
159
160static int csum6(const struct sk_buff *skb, unsigned int dataoff)
161{
162 return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
163 skb->len - dataoff, IPPROTO_UDP,
164 skb->ip_summed == CHECKSUM_HW
165 ? csum_sub(skb->csum,
166 skb_checksum(skb, 0, dataoff, 0))
167 : skb_checksum(skb, dataoff, skb->len - dataoff,
168 0));
169}
170
171static int udp_error4(struct sk_buff *skb,
172 unsigned int dataoff,
173 enum ip_conntrack_info *ctinfo,
174 int pf,
175 unsigned int hooknum)
176{
177 return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
178}
179
180static int udp_error6(struct sk_buff *skb,
181 unsigned int dataoff,
182 enum ip_conntrack_info *ctinfo,
183 int pf,
184 unsigned int hooknum)
185{
186 return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
187}
188
189struct nf_conntrack_protocol nf_conntrack_protocol_udp4 = 149struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
190{ 150{
191 .l3proto = PF_INET, 151 .l3proto = PF_INET,
@@ -197,7 +157,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
197 .print_conntrack = udp_print_conntrack, 157 .print_conntrack = udp_print_conntrack,
198 .packet = udp_packet, 158 .packet = udp_packet,
199 .new = udp_new, 159 .new = udp_new,
200 .error = udp_error4, 160 .error = udp_error,
201#if defined(CONFIG_NF_CT_NETLINK) || \ 161#if defined(CONFIG_NF_CT_NETLINK) || \
202 defined(CONFIG_NF_CT_NETLINK_MODULE) 162 defined(CONFIG_NF_CT_NETLINK_MODULE)
203 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, 163 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
@@ -216,7 +176,7 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
216 .print_conntrack = udp_print_conntrack, 176 .print_conntrack = udp_print_conntrack,
217 .packet = udp_packet, 177 .packet = udp_packet,
218 .new = udp_new, 178 .new = udp_new,
219 .error = udp_error6, 179 .error = udp_error,
220#if defined(CONFIG_NF_CT_NETLINK) || \ 180#if defined(CONFIG_NF_CT_NETLINK) || \
221 defined(CONFIG_NF_CT_NETLINK_MODULE) 181 defined(CONFIG_NF_CT_NETLINK_MODULE)
222 .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, 182 .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 c72aa3cd22e4..408960c6a544 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[] = {
649EXPORT_SYMBOL(nf_ct_log_invalid); 649EXPORT_SYMBOL(nf_ct_log_invalid);
650#endif /* CONFIG_SYSCTL */ 650#endif /* CONFIG_SYSCTL */
651 651
652static int init_or_cleanup(int init)
653{
654#ifdef CONFIG_PROC_FS
655 struct proc_dir_entry *proc, *proc_exp, *proc_stat;
656#endif
657 int ret = 0;
658
659 if (!init) goto cleanup;
660
661 ret = nf_conntrack_init();
662 if (ret < 0)
663 goto cleanup_nothing;
664
665#ifdef CONFIG_PROC_FS
666 proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
667 if (!proc) goto cleanup_init;
668
669 proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
670 &exp_file_ops);
671 if (!proc_exp) goto cleanup_proc;
672
673 proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
674 if (!proc_stat)
675 goto cleanup_proc_exp;
676
677 proc_stat->proc_fops = &ct_cpu_seq_fops;
678 proc_stat->owner = THIS_MODULE;
679#endif
680#ifdef CONFIG_SYSCTL
681 nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
682 if (nf_ct_sysctl_header == NULL) {
683 printk("nf_conntrack: can't register to sysctl.\n");
684 ret = -ENOMEM;
685 goto cleanup_proc_stat;
686 }
687#endif
688
689 return ret;
690
691 cleanup:
692#ifdef CONFIG_SYSCTL
693 unregister_sysctl_table(nf_ct_sysctl_header);
694 cleanup_proc_stat:
695#endif
696#ifdef CONFIG_PROC_FS
697 remove_proc_entry("nf_conntrack", proc_net_stat);
698 cleanup_proc_exp:
699 proc_net_remove("nf_conntrack_expect");
700 cleanup_proc:
701 proc_net_remove("nf_conntrack");
702 cleanup_init:
703#endif /* CNFIG_PROC_FS */
704 nf_conntrack_cleanup();
705 cleanup_nothing:
706 return ret;
707}
708
709int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) 652int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
710{ 653{
711 int ret = 0; 654 int ret = 0;
@@ -808,12 +751,66 @@ void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto)
808 751
809static int __init nf_conntrack_standalone_init(void) 752static int __init nf_conntrack_standalone_init(void)
810{ 753{
811 return init_or_cleanup(1); 754#ifdef CONFIG_PROC_FS
755 struct proc_dir_entry *proc, *proc_exp, *proc_stat;
756#endif
757 int ret = 0;
758
759 ret = nf_conntrack_init();
760 if (ret < 0)
761 return ret;
762
763#ifdef CONFIG_PROC_FS
764 proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
765 if (!proc) goto cleanup_init;
766
767 proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
768 &exp_file_ops);
769 if (!proc_exp) goto cleanup_proc;
770
771 proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
772 if (!proc_stat)
773 goto cleanup_proc_exp;
774
775 proc_stat->proc_fops = &ct_cpu_seq_fops;
776 proc_stat->owner = THIS_MODULE;
777#endif
778#ifdef CONFIG_SYSCTL
779 nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
780 if (nf_ct_sysctl_header == NULL) {
781 printk("nf_conntrack: can't register to sysctl.\n");
782 ret = -ENOMEM;
783 goto cleanup_proc_stat;
784 }
785#endif
786 return ret;
787
788#ifdef CONFIG_SYSCTL
789 cleanup_proc_stat:
790#endif
791#ifdef CONFIG_PROC_FS
792 remove_proc_entry("nf_conntrack", proc_net_stat);
793 cleanup_proc_exp:
794 proc_net_remove("nf_conntrack_expect");
795 cleanup_proc:
796 proc_net_remove("nf_conntrack");
797 cleanup_init:
798#endif /* CNFIG_PROC_FS */
799 nf_conntrack_cleanup();
800 return ret;
812} 801}
813 802
814static void __exit nf_conntrack_standalone_fini(void) 803static void __exit nf_conntrack_standalone_fini(void)
815{ 804{
816 init_or_cleanup(0); 805#ifdef CONFIG_SYSCTL
806 unregister_sysctl_table(nf_ct_sysctl_header);
807#endif
808#ifdef CONFIG_PROC_FS
809 remove_proc_entry("nf_conntrack", proc_net_stat);
810 proc_net_remove("nf_conntrack_expect");
811 proc_net_remove("nf_conntrack");
812#endif /* CNFIG_PROC_FS */
813 nf_conntrack_cleanup();
817} 814}
818 815
819module_init(nf_conntrack_standalone_init); 816module_init(nf_conntrack_standalone_init);
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index d9f0d7ef103b..ee8f70889f47 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -17,7 +17,6 @@
17 * for queueing and must reinject all packets it receives, no matter what. 17 * for queueing and must reinject all packets it receives, no matter what.
18 */ 18 */
19static struct nf_queue_handler *queue_handler[NPROTO]; 19static struct nf_queue_handler *queue_handler[NPROTO];
20static struct nf_queue_rerouter *queue_rerouter[NPROTO];
21 20
22static DEFINE_RWLOCK(queue_handler_lock); 21static DEFINE_RWLOCK(queue_handler_lock);
23 22
@@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf)
59} 58}
60EXPORT_SYMBOL(nf_unregister_queue_handler); 59EXPORT_SYMBOL(nf_unregister_queue_handler);
61 60
62int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
63{
64 if (pf >= NPROTO)
65 return -EINVAL;
66
67 write_lock_bh(&queue_handler_lock);
68 rcu_assign_pointer(queue_rerouter[pf], rer);
69 write_unlock_bh(&queue_handler_lock);
70
71 return 0;
72}
73EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
74
75int nf_unregister_queue_rerouter(int pf)
76{
77 if (pf >= NPROTO)
78 return -EINVAL;
79
80 write_lock_bh(&queue_handler_lock);
81 rcu_assign_pointer(queue_rerouter[pf], NULL);
82 write_unlock_bh(&queue_handler_lock);
83 synchronize_rcu();
84 return 0;
85}
86EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
87
88void nf_unregister_queue_handlers(struct nf_queue_handler *qh) 61void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
89{ 62{
90 int pf; 63 int pf;
@@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb,
116 struct net_device *physindev = NULL; 89 struct net_device *physindev = NULL;
117 struct net_device *physoutdev = NULL; 90 struct net_device *physoutdev = NULL;
118#endif 91#endif
119 struct nf_queue_rerouter *rerouter; 92 struct nf_afinfo *afinfo;
120 93
121 /* QUEUE == DROP if noone is waiting, to be safe. */ 94 /* QUEUE == DROP if noone is waiting, to be safe. */
122 read_lock(&queue_handler_lock); 95 read_lock(&queue_handler_lock);
@@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb,
126 return 1; 99 return 1;
127 } 100 }
128 101
129 info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC); 102 afinfo = nf_get_afinfo(pf);
103 if (!afinfo) {
104 read_unlock(&queue_handler_lock);
105 kfree_skb(*skb);
106 return 1;
107 }
108
109 info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC);
130 if (!info) { 110 if (!info) {
131 if (net_ratelimit()) 111 if (net_ratelimit())
132 printk(KERN_ERR "OOM queueing packet %p\n", 112 printk(KERN_ERR "OOM queueing packet %p\n",
@@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb,
158 if (physoutdev) dev_hold(physoutdev); 138 if (physoutdev) dev_hold(physoutdev);
159 } 139 }
160#endif 140#endif
161 rerouter = rcu_dereference(queue_rerouter[pf]); 141 afinfo->saveroute(*skb, info);
162 if (rerouter)
163 rerouter->save(*skb, info);
164
165 status = queue_handler[pf]->outfn(*skb, info, queuenum, 142 status = queue_handler[pf]->outfn(*skb, info, queuenum,
166 queue_handler[pf]->data); 143 queue_handler[pf]->data);
167 144
@@ -190,7 +167,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
190{ 167{
191 struct list_head *elem = &info->elem->list; 168 struct list_head *elem = &info->elem->list;
192 struct list_head *i; 169 struct list_head *i;
193 struct nf_queue_rerouter *rerouter; 170 struct nf_afinfo *afinfo;
194 171
195 rcu_read_lock(); 172 rcu_read_lock();
196 173
@@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
228 } 205 }
229 206
230 if (verdict == NF_ACCEPT) { 207 if (verdict == NF_ACCEPT) {
231 rerouter = rcu_dereference(queue_rerouter[info->pf]); 208 afinfo = nf_get_afinfo(info->pf);
232 if (rerouter && rerouter->reroute(&skb, info) < 0) 209 if (!afinfo || afinfo->reroute(&skb, info) < 0)
233 verdict = NF_DROP; 210 verdict = NF_DROP;
234 } 211 }
235 212
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 3e3f5448bacb..c60273cad778 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -1033,17 +1033,13 @@ static struct file_operations nful_file_ops = {
1033 1033
1034#endif /* PROC_FS */ 1034#endif /* PROC_FS */
1035 1035
1036static int 1036static int __init nfnetlink_log_init(void)
1037init_or_cleanup(int init)
1038{ 1037{
1039 int i, status = -ENOMEM; 1038 int i, status = -ENOMEM;
1040#ifdef CONFIG_PROC_FS 1039#ifdef CONFIG_PROC_FS
1041 struct proc_dir_entry *proc_nful; 1040 struct proc_dir_entry *proc_nful;
1042#endif 1041#endif
1043 1042
1044 if (!init)
1045 goto cleanup;
1046
1047 for (i = 0; i < INSTANCE_BUCKETS; i++) 1043 for (i = 0; i < INSTANCE_BUCKETS; i++)
1048 INIT_HLIST_HEAD(&instance_table[i]); 1044 INIT_HLIST_HEAD(&instance_table[i]);
1049 1045
@@ -1066,30 +1062,25 @@ init_or_cleanup(int init)
1066 goto cleanup_subsys; 1062 goto cleanup_subsys;
1067 proc_nful->proc_fops = &nful_file_ops; 1063 proc_nful->proc_fops = &nful_file_ops;
1068#endif 1064#endif
1069
1070 return status; 1065 return status;
1071 1066
1072cleanup:
1073 nf_log_unregister_logger(&nfulnl_logger);
1074#ifdef CONFIG_PROC_FS 1067#ifdef CONFIG_PROC_FS
1075 remove_proc_entry("nfnetlink_log", proc_net_netfilter);
1076cleanup_subsys: 1068cleanup_subsys:
1077#endif
1078 nfnetlink_subsys_unregister(&nfulnl_subsys); 1069 nfnetlink_subsys_unregister(&nfulnl_subsys);
1070#endif
1079cleanup_netlink_notifier: 1071cleanup_netlink_notifier:
1080 netlink_unregister_notifier(&nfulnl_rtnl_notifier); 1072 netlink_unregister_notifier(&nfulnl_rtnl_notifier);
1081 return status; 1073 return status;
1082} 1074}
1083 1075
1084static int __init nfnetlink_log_init(void)
1085{
1086
1087 return init_or_cleanup(1);
1088}
1089
1090static void __exit nfnetlink_log_fini(void) 1076static void __exit nfnetlink_log_fini(void)
1091{ 1077{
1092 init_or_cleanup(0); 1078 nf_log_unregister_logger(&nfulnl_logger);
1079#ifdef CONFIG_PROC_FS
1080 remove_proc_entry("nfnetlink_log", proc_net_netfilter);
1081#endif
1082 nfnetlink_subsys_unregister(&nfulnl_subsys);
1083 netlink_unregister_notifier(&nfulnl_rtnl_notifier);
1093} 1084}
1094 1085
1095MODULE_DESCRIPTION("netfilter userspace logging"); 1086MODULE_DESCRIPTION("netfilter userspace logging");
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index d0e62f68139f..86a4ac33de34 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1071,17 +1071,13 @@ static struct file_operations nfqnl_file_ops = {
1071 1071
1072#endif /* PROC_FS */ 1072#endif /* PROC_FS */
1073 1073
1074static int 1074static int __init nfnetlink_queue_init(void)
1075init_or_cleanup(int init)
1076{ 1075{
1077 int i, status = -ENOMEM; 1076 int i, status = -ENOMEM;
1078#ifdef CONFIG_PROC_FS 1077#ifdef CONFIG_PROC_FS
1079 struct proc_dir_entry *proc_nfqueue; 1078 struct proc_dir_entry *proc_nfqueue;
1080#endif 1079#endif
1081 1080
1082 if (!init)
1083 goto cleanup;
1084
1085 for (i = 0; i < INSTANCE_BUCKETS; i++) 1081 for (i = 0; i < INSTANCE_BUCKETS; i++)
1086 INIT_HLIST_HEAD(&instance_table[i]); 1082 INIT_HLIST_HEAD(&instance_table[i]);
1087 1083
@@ -1101,31 +1097,26 @@ init_or_cleanup(int init)
1101#endif 1097#endif
1102 1098
1103 register_netdevice_notifier(&nfqnl_dev_notifier); 1099 register_netdevice_notifier(&nfqnl_dev_notifier);
1104
1105 return status; 1100 return status;
1106 1101
1107cleanup:
1108 nf_unregister_queue_handlers(&nfqh);
1109 unregister_netdevice_notifier(&nfqnl_dev_notifier);
1110#ifdef CONFIG_PROC_FS 1102#ifdef CONFIG_PROC_FS
1111 remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
1112cleanup_subsys: 1103cleanup_subsys:
1113#endif
1114 nfnetlink_subsys_unregister(&nfqnl_subsys); 1104 nfnetlink_subsys_unregister(&nfqnl_subsys);
1105#endif
1115cleanup_netlink_notifier: 1106cleanup_netlink_notifier:
1116 netlink_unregister_notifier(&nfqnl_rtnl_notifier); 1107 netlink_unregister_notifier(&nfqnl_rtnl_notifier);
1117 return status; 1108 return status;
1118} 1109}
1119 1110
1120static int __init nfnetlink_queue_init(void)
1121{
1122
1123 return init_or_cleanup(1);
1124}
1125
1126static void __exit nfnetlink_queue_fini(void) 1111static void __exit nfnetlink_queue_fini(void)
1127{ 1112{
1128 init_or_cleanup(0); 1113 nf_unregister_queue_handlers(&nfqh);
1114 unregister_netdevice_notifier(&nfqnl_dev_notifier);
1115#ifdef CONFIG_PROC_FS
1116 remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
1117#endif
1118 nfnetlink_subsys_unregister(&nfqnl_subsys);
1119 netlink_unregister_notifier(&nfqnl_rtnl_notifier);
1129} 1120}
1130 1121
1131MODULE_DESCRIPTION("netfilter packet queue handler"); 1122MODULE_DESCRIPTION("netfilter packet queue handler");
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index a657ab5394c3..17abf60f9570 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -38,6 +38,7 @@ struct xt_af {
38 struct list_head match; 38 struct list_head match;
39 struct list_head target; 39 struct list_head target;
40 struct list_head tables; 40 struct list_head tables;
41 struct mutex compat_mutex;
41}; 42};
42 43
43static struct xt_af *xt; 44static struct xt_af *xt;
@@ -272,6 +273,54 @@ int xt_check_match(const struct xt_match *match, unsigned short family,
272} 273}
273EXPORT_SYMBOL_GPL(xt_check_match); 274EXPORT_SYMBOL_GPL(xt_check_match);
274 275
276#ifdef CONFIG_COMPAT
277int xt_compat_match(void *match, void **dstptr, int *size, int convert)
278{
279 struct xt_match *m;
280 struct compat_xt_entry_match *pcompat_m;
281 struct xt_entry_match *pm;
282 u_int16_t msize;
283 int off, ret;
284
285 ret = 0;
286 m = ((struct xt_entry_match *)match)->u.kernel.match;
287 off = XT_ALIGN(m->matchsize) - COMPAT_XT_ALIGN(m->matchsize);
288 switch (convert) {
289 case COMPAT_TO_USER:
290 pm = (struct xt_entry_match *)match;
291 msize = pm->u.user.match_size;
292 if (__copy_to_user(*dstptr, pm, msize)) {
293 ret = -EFAULT;
294 break;
295 }
296 msize -= off;
297 if (put_user(msize, (u_int16_t *)*dstptr))
298 ret = -EFAULT;
299 *size -= off;
300 *dstptr += msize;
301 break;
302 case COMPAT_FROM_USER:
303 pcompat_m = (struct compat_xt_entry_match *)match;
304 pm = (struct xt_entry_match *)*dstptr;
305 msize = pcompat_m->u.user.match_size;
306 memcpy(pm, pcompat_m, msize);
307 msize += off;
308 pm->u.user.match_size = msize;
309 *size += off;
310 *dstptr += msize;
311 break;
312 case COMPAT_CALC_SIZE:
313 *size += off;
314 break;
315 default:
316 ret = -ENOPROTOOPT;
317 break;
318 }
319 return ret;
320}
321EXPORT_SYMBOL_GPL(xt_compat_match);
322#endif
323
275int xt_check_target(const struct xt_target *target, unsigned short family, 324int xt_check_target(const struct xt_target *target, unsigned short family,
276 unsigned int size, const char *table, unsigned int hook_mask, 325 unsigned int size, const char *table, unsigned int hook_mask,
277 unsigned short proto, int inv_proto) 326 unsigned short proto, int inv_proto)
@@ -301,6 +350,54 @@ int xt_check_target(const struct xt_target *target, unsigned short family,
301} 350}
302EXPORT_SYMBOL_GPL(xt_check_target); 351EXPORT_SYMBOL_GPL(xt_check_target);
303 352
353#ifdef CONFIG_COMPAT
354int xt_compat_target(void *target, void **dstptr, int *size, int convert)
355{
356 struct xt_target *t;
357 struct compat_xt_entry_target *pcompat;
358 struct xt_entry_target *pt;
359 u_int16_t tsize;
360 int off, ret;
361
362 ret = 0;
363 t = ((struct xt_entry_target *)target)->u.kernel.target;
364 off = XT_ALIGN(t->targetsize) - COMPAT_XT_ALIGN(t->targetsize);
365 switch (convert) {
366 case COMPAT_TO_USER:
367 pt = (struct xt_entry_target *)target;
368 tsize = pt->u.user.target_size;
369 if (__copy_to_user(*dstptr, pt, tsize)) {
370 ret = -EFAULT;
371 break;
372 }
373 tsize -= off;
374 if (put_user(tsize, (u_int16_t *)*dstptr))
375 ret = -EFAULT;
376 *size -= off;
377 *dstptr += tsize;
378 break;
379 case COMPAT_FROM_USER:
380 pcompat = (struct compat_xt_entry_target *)target;
381 pt = (struct xt_entry_target *)*dstptr;
382 tsize = pcompat->u.user.target_size;
383 memcpy(pt, pcompat, tsize);
384 tsize += off;
385 pt->u.user.target_size = tsize;
386 *size += off;
387 *dstptr += tsize;
388 break;
389 case COMPAT_CALC_SIZE:
390 *size += off;
391 break;
392 default:
393 ret = -ENOPROTOOPT;
394 break;
395 }
396 return ret;
397}
398EXPORT_SYMBOL_GPL(xt_compat_target);
399#endif
400
304struct xt_table_info *xt_alloc_table_info(unsigned int size) 401struct xt_table_info *xt_alloc_table_info(unsigned int size)
305{ 402{
306 struct xt_table_info *newinfo; 403 struct xt_table_info *newinfo;
@@ -316,7 +413,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
316 413
317 newinfo->size = size; 414 newinfo->size = size;
318 415
319 for_each_cpu(cpu) { 416 for_each_possible_cpu(cpu) {
320 if (size <= PAGE_SIZE) 417 if (size <= PAGE_SIZE)
321 newinfo->entries[cpu] = kmalloc_node(size, 418 newinfo->entries[cpu] = kmalloc_node(size,
322 GFP_KERNEL, 419 GFP_KERNEL,
@@ -339,7 +436,7 @@ void xt_free_table_info(struct xt_table_info *info)
339{ 436{
340 int cpu; 437 int cpu;
341 438
342 for_each_cpu(cpu) { 439 for_each_possible_cpu(cpu) {
343 if (info->size <= PAGE_SIZE) 440 if (info->size <= PAGE_SIZE)
344 kfree(info->entries[cpu]); 441 kfree(info->entries[cpu]);
345 else 442 else
@@ -371,6 +468,19 @@ void xt_table_unlock(struct xt_table *table)
371} 468}
372EXPORT_SYMBOL_GPL(xt_table_unlock); 469EXPORT_SYMBOL_GPL(xt_table_unlock);
373 470
471#ifdef CONFIG_COMPAT
472void xt_compat_lock(int af)
473{
474 mutex_lock(&xt[af].compat_mutex);
475}
476EXPORT_SYMBOL_GPL(xt_compat_lock);
477
478void xt_compat_unlock(int af)
479{
480 mutex_unlock(&xt[af].compat_mutex);
481}
482EXPORT_SYMBOL_GPL(xt_compat_unlock);
483#endif
374 484
375struct xt_table_info * 485struct xt_table_info *
376xt_replace_table(struct xt_table *table, 486xt_replace_table(struct xt_table *table,
@@ -419,6 +529,7 @@ int xt_register_table(struct xt_table *table,
419 529
420 /* Simplifies replace_table code. */ 530 /* Simplifies replace_table code. */
421 table->private = bootstrap; 531 table->private = bootstrap;
532 rwlock_init(&table->lock);
422 if (!xt_replace_table(table, 0, newinfo, &ret)) 533 if (!xt_replace_table(table, 0, newinfo, &ret))
423 goto unlock; 534 goto unlock;
424 535
@@ -428,7 +539,6 @@ int xt_register_table(struct xt_table *table,
428 /* save number of initial entries */ 539 /* save number of initial entries */
429 private->initial_entries = private->number; 540 private->initial_entries = private->number;
430 541
431 rwlock_init(&table->lock);
432 list_prepend(&xt[table->af].tables, table); 542 list_prepend(&xt[table->af].tables, table);
433 543
434 ret = 0; 544 ret = 0;
@@ -671,6 +781,9 @@ static int __init xt_init(void)
671 781
672 for (i = 0; i < NPROTO; i++) { 782 for (i = 0; i < NPROTO; i++) {
673 mutex_init(&xt[i].mutex); 783 mutex_init(&xt[i].mutex);
784#ifdef CONFIG_COMPAT
785 mutex_init(&xt[i].compat_mutex);
786#endif
674 INIT_LIST_HEAD(&xt[i].target); 787 INIT_LIST_HEAD(&xt[i].target);
675 INIT_LIST_HEAD(&xt[i].match); 788 INIT_LIST_HEAD(&xt[i].match);
676 INIT_LIST_HEAD(&xt[i].tables); 789 INIT_LIST_HEAD(&xt[i].tables);
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/netfilter/xt_esp.c
index 3840b417a3c5..9dad6281e0c1 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -9,16 +9,22 @@
9 9
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/skbuff.h> 11#include <linux/skbuff.h>
12#include <linux/in.h>
12#include <linux/ip.h> 13#include <linux/ip.h>
13 14
14#include <linux/netfilter_ipv4/ipt_esp.h> 15#include <linux/netfilter/xt_esp.h>
16#include <linux/netfilter/x_tables.h>
17
15#include <linux/netfilter_ipv4/ip_tables.h> 18#include <linux/netfilter_ipv4/ip_tables.h>
19#include <linux/netfilter_ipv6/ip6_tables.h>
16 20
17MODULE_LICENSE("GPL"); 21MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>"); 22MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
19MODULE_DESCRIPTION("iptables ESP SPI match module"); 23MODULE_DESCRIPTION("x_tables ESP SPI match module");
24MODULE_ALIAS("ipt_esp");
25MODULE_ALIAS("ip6t_esp");
20 26
21#ifdef DEBUG_CONNTRACK 27#if 0
22#define duprintf(format, args...) printk(format , ## args) 28#define duprintf(format, args...) printk(format , ## args)
23#else 29#else
24#define duprintf(format, args...) 30#define duprintf(format, args...)
@@ -28,11 +34,11 @@ MODULE_DESCRIPTION("iptables ESP SPI match module");
28static inline int 34static inline int
29spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) 35spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
30{ 36{
31 int r=0; 37 int r = 0;
32 duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', 38 duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
33 min,spi,max); 39 min, spi, max);
34 r=(spi >= min && spi <= max) ^ invert; 40 r = (spi >= min && spi <= max) ^ invert;
35 duprintf(" result %s\n",r? "PASS" : "FAILED"); 41 duprintf(" result %s\n", r ? "PASS" : "FAILED");
36 return r; 42 return r;
37} 43}
38 44
@@ -47,14 +53,13 @@ match(const struct sk_buff *skb,
47 int *hotdrop) 53 int *hotdrop)
48{ 54{
49 struct ip_esp_hdr _esp, *eh; 55 struct ip_esp_hdr _esp, *eh;
50 const struct ipt_esp *espinfo = matchinfo; 56 const struct xt_esp *espinfo = matchinfo;
51 57
52 /* Must not be a fragment. */ 58 /* Must not be a fragment. */
53 if (offset) 59 if (offset)
54 return 0; 60 return 0;
55 61
56 eh = skb_header_pointer(skb, protoff, 62 eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp);
57 sizeof(_esp), &_esp);
58 if (eh == NULL) { 63 if (eh == NULL) {
59 /* We've been asked to examine this packet, and we 64 /* We've been asked to examine this packet, and we
60 * can't. Hence, no choice but to drop. 65 * can't. Hence, no choice but to drop.
@@ -64,9 +69,8 @@ match(const struct sk_buff *skb,
64 return 0; 69 return 0;
65 } 70 }
66 71
67 return spi_match(espinfo->spis[0], espinfo->spis[1], 72 return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi),
68 ntohl(eh->spi), 73 !!(espinfo->invflags & XT_ESP_INV_SPI));
69 !!(espinfo->invflags & IPT_ESP_INV_SPI));
70} 74}
71 75
72/* Called when user tries to insert an entry of this type. */ 76/* Called when user tries to insert an entry of this type. */
@@ -78,34 +82,55 @@ checkentry(const char *tablename,
78 unsigned int matchinfosize, 82 unsigned int matchinfosize,
79 unsigned int hook_mask) 83 unsigned int hook_mask)
80{ 84{
81 const struct ipt_esp *espinfo = matchinfo; 85 const struct xt_esp *espinfo = matchinfo;
82 86
83 /* Must specify no unknown invflags */ 87 if (espinfo->invflags & ~XT_ESP_INV_MASK) {
84 if (espinfo->invflags & ~IPT_ESP_INV_MASK) { 88 duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
85 duprintf("ipt_esp: unknown flags %X\n", espinfo->invflags);
86 return 0; 89 return 0;
87 } 90 }
91
88 return 1; 92 return 1;
89} 93}
90 94
91static struct ipt_match esp_match = { 95static struct xt_match esp_match = {
92 .name = "esp", 96 .name = "esp",
93 .match = match, 97 .family = AF_INET,
94 .matchsize = sizeof(struct ipt_esp),
95 .proto = IPPROTO_ESP, 98 .proto = IPPROTO_ESP,
96 .checkentry = checkentry, 99 .match = &match,
100 .matchsize = sizeof(struct xt_esp),
101 .checkentry = &checkentry,
97 .me = THIS_MODULE, 102 .me = THIS_MODULE,
98}; 103};
99 104
100static int __init ipt_esp_init(void) 105static struct xt_match esp6_match = {
106 .name = "esp",
107 .family = AF_INET6,
108 .proto = IPPROTO_ESP,
109 .match = &match,
110 .matchsize = sizeof(struct xt_esp),
111 .checkentry = &checkentry,
112 .me = THIS_MODULE,
113};
114
115static int __init xt_esp_init(void)
101{ 116{
102 return ipt_register_match(&esp_match); 117 int ret;
118 ret = xt_register_match(&esp_match);
119 if (ret)
120 return ret;
121
122 ret = xt_register_match(&esp6_match);
123 if (ret)
124 xt_unregister_match(&esp_match);
125
126 return ret;
103} 127}
104 128
105static void __exit ipt_esp_fini(void) 129static void __exit xt_esp_cleanup(void)
106{ 130{
107 ipt_unregister_match(&esp_match); 131 xt_unregister_match(&esp_match);
132 xt_unregister_match(&esp6_match);
108} 133}
109 134
110module_init(ipt_esp_init); 135module_init(xt_esp_init);
111module_exit(ipt_esp_fini); 136module_exit(xt_esp_cleanup);
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
new file mode 100644
index 000000000000..b56cd2baaac2
--- /dev/null
+++ b/net/netfilter/xt_multiport.c
@@ -0,0 +1,314 @@
1/* Kernel module to match one of a list of TCP/UDP ports: ports are in
2 the same place so we can treat them as equal. */
3
4/* (C) 1999-2001 Paul `Rusty' Russell
5 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/types.h>
14#include <linux/udp.h>
15#include <linux/skbuff.h>
16#include <linux/in.h>
17
18#include <linux/netfilter/xt_multiport.h>
19#include <linux/netfilter/x_tables.h>
20#include <linux/netfilter_ipv4/ip_tables.h>
21#include <linux/netfilter_ipv6/ip6_tables.h>
22
23MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
25MODULE_DESCRIPTION("x_tables multiple port match module");
26MODULE_ALIAS("ipt_multiport");
27MODULE_ALIAS("ip6t_multiport");
28
29#if 0
30#define duprintf(format, args...) printk(format , ## args)
31#else
32#define duprintf(format, args...)
33#endif
34
35/* Returns 1 if the port is matched by the test, 0 otherwise. */
36static inline int
37ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
38 u_int8_t count, u_int16_t src, u_int16_t dst)
39{
40 unsigned int i;
41 for (i = 0; i < count; i++) {
42 if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src)
43 return 1;
44
45 if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
46 return 1;
47 }
48
49 return 0;
50}
51
52/* Returns 1 if the port is matched by the test, 0 otherwise. */
53static inline int
54ports_match_v1(const struct xt_multiport_v1 *minfo,
55 u_int16_t src, u_int16_t dst)
56{
57 unsigned int i;
58 u_int16_t s, e;
59
60 for (i = 0; i < minfo->count; i++) {
61 s = minfo->ports[i];
62
63 if (minfo->pflags[i]) {
64 /* range port matching */
65 e = minfo->ports[++i];
66 duprintf("src or dst matches with %d-%d?\n", s, e);
67
68 if (minfo->flags == XT_MULTIPORT_SOURCE
69 && src >= s && src <= e)
70 return 1 ^ minfo->invert;
71 if (minfo->flags == XT_MULTIPORT_DESTINATION
72 && dst >= s && dst <= e)
73 return 1 ^ minfo->invert;
74 if (minfo->flags == XT_MULTIPORT_EITHER
75 && ((dst >= s && dst <= e)
76 || (src >= s && src <= e)))
77 return 1 ^ minfo->invert;
78 } else {
79 /* exact port matching */
80 duprintf("src or dst matches with %d?\n", s);
81
82 if (minfo->flags == XT_MULTIPORT_SOURCE
83 && src == s)
84 return 1 ^ minfo->invert;
85 if (minfo->flags == XT_MULTIPORT_DESTINATION
86 && dst == s)
87 return 1 ^ minfo->invert;
88 if (minfo->flags == XT_MULTIPORT_EITHER
89 && (src == s || dst == s))
90 return 1 ^ minfo->invert;
91 }
92 }
93
94 return minfo->invert;
95}
96
97static int
98match(const struct sk_buff *skb,
99 const struct net_device *in,
100 const struct net_device *out,
101 const struct xt_match *match,
102 const void *matchinfo,
103 int offset,
104 unsigned int protoff,
105 int *hotdrop)
106{
107 u16 _ports[2], *pptr;
108 const struct xt_multiport *multiinfo = matchinfo;
109
110 if (offset)
111 return 0;
112
113 pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
114 if (pptr == NULL) {
115 /* We've been asked to examine this packet, and we
116 * can't. Hence, no choice but to drop.
117 */
118 duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
119 *hotdrop = 1;
120 return 0;
121 }
122
123 return ports_match(multiinfo->ports,
124 multiinfo->flags, multiinfo->count,
125 ntohs(pptr[0]), ntohs(pptr[1]));
126}
127
128static int
129match_v1(const struct sk_buff *skb,
130 const struct net_device *in,
131 const struct net_device *out,
132 const struct xt_match *match,
133 const void *matchinfo,
134 int offset,
135 unsigned int protoff,
136 int *hotdrop)
137{
138 u16 _ports[2], *pptr;
139 const struct xt_multiport_v1 *multiinfo = matchinfo;
140
141 if (offset)
142 return 0;
143
144 pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
145 if (pptr == NULL) {
146 /* We've been asked to examine this packet, and we
147 * can't. Hence, no choice but to drop.
148 */
149 duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
150 *hotdrop = 1;
151 return 0;
152 }
153
154 return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
155}
156
157static inline int
158check(u_int16_t proto,
159 u_int8_t ip_invflags,
160 u_int8_t match_flags,
161 u_int8_t count)
162{
163 /* Must specify proto == TCP/UDP, no unknown flags or bad count */
164 return (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
165 && !(ip_invflags & XT_INV_PROTO)
166 && (match_flags == XT_MULTIPORT_SOURCE
167 || match_flags == XT_MULTIPORT_DESTINATION
168 || match_flags == XT_MULTIPORT_EITHER)
169 && count <= XT_MULTI_PORTS;
170}
171
172/* Called when user tries to insert an entry of this type. */
173static int
174checkentry(const char *tablename,
175 const void *info,
176 const struct xt_match *match,
177 void *matchinfo,
178 unsigned int matchsize,
179 unsigned int hook_mask)
180{
181 const struct ipt_ip *ip = info;
182 const struct xt_multiport *multiinfo = matchinfo;
183
184 return check(ip->proto, ip->invflags, multiinfo->flags,
185 multiinfo->count);
186}
187
188static int
189checkentry_v1(const char *tablename,
190 const void *info,
191 const struct xt_match *match,
192 void *matchinfo,
193 unsigned int matchsize,
194 unsigned int hook_mask)
195{
196 const struct ipt_ip *ip = info;
197 const struct xt_multiport_v1 *multiinfo = matchinfo;
198
199 return check(ip->proto, ip->invflags, multiinfo->flags,
200 multiinfo->count);
201}
202
203static int
204checkentry6(const char *tablename,
205 const void *info,
206 const struct xt_match *match,
207 void *matchinfo,
208 unsigned int matchsize,
209 unsigned int hook_mask)
210{
211 const struct ip6t_ip6 *ip = info;
212 const struct xt_multiport *multiinfo = matchinfo;
213
214 return check(ip->proto, ip->invflags, multiinfo->flags,
215 multiinfo->count);
216}
217
218static int
219checkentry6_v1(const char *tablename,
220 const void *info,
221 const struct xt_match *match,
222 void *matchinfo,
223 unsigned int matchsize,
224 unsigned int hook_mask)
225{
226 const struct ip6t_ip6 *ip = info;
227 const struct xt_multiport_v1 *multiinfo = matchinfo;
228
229 return check(ip->proto, ip->invflags, multiinfo->flags,
230 multiinfo->count);
231}
232
233static struct xt_match multiport_match = {
234 .name = "multiport",
235 .revision = 0,
236 .matchsize = sizeof(struct xt_multiport),
237 .match = &match,
238 .checkentry = &checkentry,
239 .family = AF_INET,
240 .me = THIS_MODULE,
241};
242
243static struct xt_match multiport_match_v1 = {
244 .name = "multiport",
245 .revision = 1,
246 .matchsize = sizeof(struct xt_multiport_v1),
247 .match = &match_v1,
248 .checkentry = &checkentry_v1,
249 .family = AF_INET,
250 .me = THIS_MODULE,
251};
252
253static struct xt_match multiport6_match = {
254 .name = "multiport",
255 .revision = 0,
256 .matchsize = sizeof(struct xt_multiport),
257 .match = &match,
258 .checkentry = &checkentry6,
259 .family = AF_INET6,
260 .me = THIS_MODULE,
261};
262
263static struct xt_match multiport6_match_v1 = {
264 .name = "multiport",
265 .revision = 1,
266 .matchsize = sizeof(struct xt_multiport_v1),
267 .match = &match_v1,
268 .checkentry = &checkentry6_v1,
269 .family = AF_INET6,
270 .me = THIS_MODULE,
271};
272
273static int __init xt_multiport_init(void)
274{
275 int ret;
276
277 ret = xt_register_match(&multiport_match);
278 if (ret)
279 goto out;
280
281 ret = xt_register_match(&multiport_match_v1);
282 if (ret)
283 goto out_unreg_multi_v0;
284
285 ret = xt_register_match(&multiport6_match);
286 if (ret)
287 goto out_unreg_multi_v1;
288
289 ret = xt_register_match(&multiport6_match_v1);
290 if (ret)
291 goto out_unreg_multi6_v0;
292
293 return ret;
294
295out_unreg_multi6_v0:
296 xt_unregister_match(&multiport6_match);
297out_unreg_multi_v1:
298 xt_unregister_match(&multiport_match_v1);
299out_unreg_multi_v0:
300 xt_unregister_match(&multiport_match);
301out:
302 return ret;
303}
304
305static void __exit xt_multiport_fini(void)
306{
307 xt_unregister_match(&multiport_match);
308 xt_unregister_match(&multiport_match_v1);
309 xt_unregister_match(&multiport6_match);
310 xt_unregister_match(&multiport6_match_v1);
311}
312
313module_init(xt_multiport_init);
314module_exit(xt_multiport_fini);
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 1099cb005fcc..a3aa62fbda6f 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,
71 return 0; 71 return 0;
72 e = &info->pol[pos]; 72 e = &info->pol[pos];
73 73
74 if (match_xfrm_state(sp->x[i].xvec, e, family)) { 74 if (match_xfrm_state(sp->xvec[i], e, family)) {
75 if (!strict) 75 if (!strict)
76 return 1; 76 return 1;
77 } else if (strict) 77 } else if (strict)
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 6056d20ef429..37640c6fc014 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)
69 DPRINTK("ipt_init_target: found %s\n", target->name); 69 DPRINTK("ipt_init_target: found %s\n", target->name);
70 t->u.kernel.target = target; 70 t->u.kernel.target = target;
71 71
72 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
73 table, hook, 0, 0);
74 if (ret)
75 return ret;
76
72 if (t->u.kernel.target->checkentry 77 if (t->u.kernel.target->checkentry
73 && !t->u.kernel.target->checkentry(table, NULL, 78 && !t->u.kernel.target->checkentry(table, NULL,
74 t->u.kernel.target, t->data, 79 t->u.kernel.target, t->data,
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index fa877f8f652c..24c348fa8922 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)
66} 66}
67 67
68#ifdef CONFIG_NET_CLS_ACT 68#ifdef CONFIG_NET_CLS_ACT
69static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, 69static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
70 int type, struct tc_action *a) 70 int type, struct tc_action *a)
71{ 71{
72 struct tcf_police *p; 72 struct tcf_police *p;
@@ -113,7 +113,7 @@ rtattr_failure:
113} 113}
114 114
115static inline int 115static inline int
116tcf_hash_search(struct tc_action *a, u32 index) 116tcf_act_police_hash_search(struct tc_action *a, u32 index)
117{ 117{
118 struct tcf_police *p = tcf_police_lookup(index); 118 struct tcf_police *p = tcf_police_lookup(index);
119 119
@@ -387,9 +387,9 @@ static struct tc_action_ops act_police_ops = {
387 .act = tcf_act_police, 387 .act = tcf_act_police,
388 .dump = tcf_act_police_dump, 388 .dump = tcf_act_police_dump,
389 .cleanup = tcf_act_police_cleanup, 389 .cleanup = tcf_act_police_cleanup,
390 .lookup = tcf_hash_search, 390 .lookup = tcf_act_police_hash_search,
391 .init = tcf_act_police_locate, 391 .init = tcf_act_police_locate,
392 .walk = tcf_generic_walker 392 .walk = tcf_act_police_walker
393}; 393};
394 394
395static int __init 395static int __init
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index d47a52c303a8..5b3b0e0ae7e5 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -69,7 +69,7 @@ fold_field(void *mib[], int nr)
69 unsigned long res = 0; 69 unsigned long res = 0;
70 int i; 70 int i;
71 71
72 for_each_cpu(i) { 72 for_each_possible_cpu(i) {
73 res += 73 res +=
74 *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) + 74 *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
75 sizeof (unsigned long) * nr)); 75 sizeof (unsigned long) * nr));
diff --git a/net/socket.c b/net/socket.c
index b13042f68c02..0ce12dfc7a71 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,
119static ssize_t sock_sendpage(struct file *file, struct page *page, 119static ssize_t sock_sendpage(struct file *file, struct page *page,
120 int offset, size_t size, loff_t *ppos, int more); 120 int offset, size_t size, loff_t *ppos, int more);
121 121
122extern ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
123 size_t len, unsigned int flags);
124
125
126/* 122/*
127 * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear 123 * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
128 * in the operation structures but are done directly via the socketcall() multiplexor. 124 * 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)
494 struct file *file; 490 struct file *file;
495 struct socket *sock; 491 struct socket *sock;
496 492
493 *err = -EBADF;
497 file = fget_light(fd, fput_needed); 494 file = fget_light(fd, fput_needed);
498 if (file) { 495 if (file) {
499 sock = sock_from_file(file, err); 496 sock = sock_from_file(file, err);
@@ -1418,7 +1415,8 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
1418 newfd = sock_alloc_fd(&newfile); 1415 newfd = sock_alloc_fd(&newfile);
1419 if (unlikely(newfd < 0)) { 1416 if (unlikely(newfd < 0)) {
1420 err = newfd; 1417 err = newfd;
1421 goto out_release; 1418 sock_release(newsock);
1419 goto out_put;
1422 } 1420 }
1423 1421
1424 err = sock_attach_fd(newsock, newfile); 1422 err = sock_attach_fd(newsock, newfile);
@@ -1455,10 +1453,8 @@ out_put:
1455out: 1453out:
1456 return err; 1454 return err;
1457out_fd: 1455out_fd:
1458 put_filp(newfile); 1456 fput(newfile);
1459 put_unused_fd(newfd); 1457 put_unused_fd(newfd);
1460out_release:
1461 sock_release(newsock);
1462 goto out_put; 1458 goto out_put;
1463} 1459}
1464 1460
@@ -2137,7 +2133,7 @@ void socket_seq_show(struct seq_file *seq)
2137 int cpu; 2133 int cpu;
2138 int counter = 0; 2134 int counter = 0;
2139 2135
2140 for_each_cpu(cpu) 2136 for_each_possible_cpu(cpu)
2141 counter += per_cpu(sockets_in_use, cpu); 2137 counter += per_cpu(sockets_in_use, cpu);
2142 2138
2143 /* It can be negative, by the way. 8) */ 2139 /* 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 900ef31f5a0e..519ebc17c028 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)
794 794
795out_err: 795out_err:
796 dprintk("RPC: gss_create_cred failed with error %d\n", err); 796 dprintk("RPC: gss_create_cred failed with error %d\n", err);
797 if (cred) gss_destroy_cred(&cred->gc_base);
798 return ERR_PTR(err); 797 return ERR_PTR(err);
799} 798}
800 799
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 97c981fa6b8e..76b969e6904f 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,
212 char *cksumname; 212 char *cksumname;
213 struct crypto_tfm *tfm = NULL; /* XXX add to ctx? */ 213 struct crypto_tfm *tfm = NULL; /* XXX add to ctx? */
214 struct scatterlist sg[1]; 214 struct scatterlist sg[1];
215 u32 code = GSS_S_FAILURE;
216 215
217 switch (cksumtype) { 216 switch (cksumtype) {
218 case CKSUMTYPE_RSA_MD5: 217 case CKSUMTYPE_RSA_MD5:
@@ -221,13 +220,11 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
221 default: 220 default:
222 dprintk("RPC: krb5_make_checksum:" 221 dprintk("RPC: krb5_make_checksum:"
223 " unsupported checksum %d", cksumtype); 222 " unsupported checksum %d", cksumtype);
224 goto out; 223 return GSS_S_FAILURE;
225 } 224 }
226 if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP))) 225 if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP)))
227 goto out; 226 return GSS_S_FAILURE;
228 cksum->len = crypto_tfm_alg_digestsize(tfm); 227 cksum->len = crypto_tfm_alg_digestsize(tfm);
229 if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL)
230 goto out;
231 228
232 crypto_digest_init(tfm); 229 crypto_digest_init(tfm);
233 sg_set_buf(sg, header, hdrlen); 230 sg_set_buf(sg, header, hdrlen);
@@ -235,10 +232,8 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
235 process_xdr_buf(body, body_offset, body->len - body_offset, 232 process_xdr_buf(body, body_offset, body->len - body_offset,
236 checksummer, tfm); 233 checksummer, tfm);
237 crypto_digest_final(tfm, cksum->data); 234 crypto_digest_final(tfm, cksum->data);
238 code = 0;
239out:
240 crypto_free_tfm(tfm); 235 crypto_free_tfm(tfm);
241 return code; 236 return 0;
242} 237}
243 238
244EXPORT_SYMBOL(make_checksum); 239EXPORT_SYMBOL(make_checksum);
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 4d7eb9e704da..d51e316c5821 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)
1122 integ_len)) 1122 integ_len))
1123 BUG(); 1123 BUG();
1124 if (resbuf->page_len == 0 1124 if (resbuf->page_len == 0
1125 && resbuf->tail[0].iov_len + RPC_MAX_AUTH_SIZE 1125 && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
1126 < PAGE_SIZE) { 1126 < PAGE_SIZE) {
1127 BUG_ON(resbuf->tail[0].iov_len); 1127 BUG_ON(resbuf->tail[0].iov_len);
1128 /* Use head for everything */ 1128 /* Use head for everything */
1129 resv = &resbuf->head[0]; 1129 resv = &resbuf->head[0];
1130 } else if (resbuf->tail[0].iov_base == NULL) { 1130 } else if (resbuf->tail[0].iov_base == NULL) {
1131 /* copied from nfsd4_encode_read */ 1131 if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
1132 svc_take_page(rqstp); 1132 > PAGE_SIZE)
1133 resbuf->tail[0].iov_base = page_address(rqstp 1133 goto out_err;
1134 ->rq_respages[rqstp->rq_resused-1]); 1134 resbuf->tail[0].iov_base =
1135 rqstp->rq_restailpage = rqstp->rq_resused-1; 1135 resbuf->head[0].iov_base
1136 + resbuf->head[0].iov_len;
1136 resbuf->tail[0].iov_len = 0; 1137 resbuf->tail[0].iov_len = 0;
1138 rqstp->rq_restailpage = 0;
1137 resv = &resbuf->tail[0]; 1139 resv = &resbuf->tail[0];
1138 } else { 1140 } else {
1139 resv = &resbuf->tail[0]; 1141 resv = &resbuf->tail[0];
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index dea529666d69..15c2db26767b 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -176,7 +176,8 @@ void rpc_count_iostats(struct rpc_task *task)
176 op_metrics->om_execute += execute; 176 op_metrics->om_execute += execute;
177} 177}
178 178
179void _print_name(struct seq_file *seq, unsigned int op, struct rpc_procinfo *procs) 179static void _print_name(struct seq_file *seq, unsigned int op,
180 struct rpc_procinfo *procs)
180{ 181{
181 if (procs[op].p_name) 182 if (procs[op].p_name)
182 seq_printf(seq, "\t%12s: ", procs[op].p_name); 183 seq_printf(seq, "\t%12s: ", procs[op].p_name);
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 953307a9df1d..a3bbc891f959 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)
229 publ->node, publ->ref, publ->key); 229 publ->node, publ->ref, publ->key);
230 assert(p == publ); 230 assert(p == publ);
231 write_unlock_bh(&tipc_nametbl_lock); 231 write_unlock_bh(&tipc_nametbl_lock);
232 if (publ) 232 kfree(publ);
233 kfree(publ);
234} 233}
235 234
236/** 235/**
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 8b9bf4a763b5..b1265187b4a8 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -55,12 +55,10 @@
55#include <asm/uaccess.h> 55#include <asm/uaccess.h>
56#include <linux/module.h> 56#include <linux/module.h>
57#include <linux/init.h> 57#include <linux/init.h>
58#include <linux/wanpipe.h>
59#include <linux/if_wanpipe.h> 58#include <linux/if_wanpipe.h>
60#include <linux/pkt_sched.h> 59#include <linux/pkt_sched.h>
61#include <linux/tcp_states.h> 60#include <linux/tcp_states.h>
62#include <linux/if_wanpipe_common.h> 61#include <linux/if_wanpipe_common.h>
63#include <linux/sdla_x25.h>
64 62
65#ifdef CONFIG_INET 63#ifdef CONFIG_INET
66#include <net/inet_common.h> 64#include <net/inet_common.h>
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 2407a7072327..b54971059f16 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -18,7 +18,7 @@ void __secpath_destroy(struct sec_path *sp)
18{ 18{
19 int i; 19 int i;
20 for (i = 0; i < sp->len; i++) 20 for (i = 0; i < sp->len; i++)
21 xfrm_state_put(sp->x[i].xvec); 21 xfrm_state_put(sp->xvec[i]);
22 kmem_cache_free(secpath_cachep, sp); 22 kmem_cache_free(secpath_cachep, sp);
23} 23}
24EXPORT_SYMBOL(__secpath_destroy); 24EXPORT_SYMBOL(__secpath_destroy);
@@ -37,7 +37,7 @@ struct sec_path *secpath_dup(struct sec_path *src)
37 37
38 memcpy(sp, src, sizeof(*sp)); 38 memcpy(sp, src, sizeof(*sp));
39 for (i = 0; i < sp->len; i++) 39 for (i = 0; i < sp->len; i++)
40 xfrm_state_hold(sp->x[i].xvec); 40 xfrm_state_hold(sp->xvec[i]);
41 } 41 }
42 atomic_set(&sp->refcnt, 1); 42 atomic_set(&sp->refcnt, 1);
43 return sp; 43 return sp;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f5eae9febd26..c3725fe2a8fb 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,
943 } else 943 } else
944 start = -1; 944 start = -1;
945 for (; idx < sp->len; idx++) { 945 for (; idx < sp->len; idx++) {
946 if (xfrm_state_ok(tmpl, sp->x[idx].xvec, family)) 946 if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
947 return ++idx; 947 return ++idx;
948 if (sp->x[idx].xvec->props.mode) 948 if (sp->xvec[idx]->props.mode)
949 break; 949 break;
950 } 950 }
951 return start; 951 return start;
@@ -968,7 +968,7 @@ EXPORT_SYMBOL(xfrm_decode_session);
968static inline int secpath_has_tunnel(struct sec_path *sp, int k) 968static inline int secpath_has_tunnel(struct sec_path *sp, int k)
969{ 969{
970 for (; k < sp->len; k++) { 970 for (; k < sp->len; k++) {
971 if (sp->x[k].xvec->props.mode) 971 if (sp->xvec[k]->props.mode)
972 return 1; 972 return 1;
973 } 973 }
974 974
@@ -994,8 +994,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
994 int i; 994 int i;
995 995
996 for (i=skb->sp->len-1; i>=0; i--) { 996 for (i=skb->sp->len-1; i>=0; i--) {
997 struct sec_decap_state *xvec = &(skb->sp->x[i]); 997 struct xfrm_state *x = skb->sp->xvec[i];
998 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family)) 998 if (!xfrm_selector_match(&x->sel, &fl, family))
999 return 0; 999 return 0;
1000 } 1000 }
1001 } 1001 }
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index a8e14dc1b04e..3dc3e1f3b7aa 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)
805 case XFRM_REPLAY_UPDATE: 805 case XFRM_REPLAY_UPDATE:
806 if (x->replay_maxdiff && 806 if (x->replay_maxdiff &&
807 (x->replay.seq - x->preplay.seq < x->replay_maxdiff) && 807 (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
808 (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) 808 (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
809 return; 809 if (x->xflags & XFRM_TIME_DEFER)
810 event = XFRM_REPLAY_TIMEOUT;
811 else
812 return;
813 }
810 814
811 break; 815 break;
812 816
813 case XFRM_REPLAY_TIMEOUT: 817 case XFRM_REPLAY_TIMEOUT:
814 if ((x->replay.seq == x->preplay.seq) && 818 if ((x->replay.seq == x->preplay.seq) &&
815 (x->replay.bitmap == x->preplay.bitmap) && 819 (x->replay.bitmap == x->preplay.bitmap) &&
816 (x->replay.oseq == x->preplay.oseq)) 820 (x->replay.oseq == x->preplay.oseq)) {
821 x->xflags |= XFRM_TIME_DEFER;
817 return; 822 return;
823 }
818 824
819 break; 825 break;
820 } 826 }
@@ -825,8 +831,10 @@ void xfrm_replay_notify(struct xfrm_state *x, int event)
825 km_state_notify(x, &c); 831 km_state_notify(x, &c);
826 832
827 if (x->replay_maxage && 833 if (x->replay_maxage &&
828 !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) 834 !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) {
829 xfrm_state_hold(x); 835 xfrm_state_hold(x);
836 x->xflags &= ~XFRM_TIME_DEFER;
837 }
830} 838}
831EXPORT_SYMBOL(xfrm_replay_notify); 839EXPORT_SYMBOL(xfrm_replay_notify);
832 840
@@ -836,10 +844,15 @@ static void xfrm_replay_timer_handler(unsigned long data)
836 844
837 spin_lock(&x->lock); 845 spin_lock(&x->lock);
838 846
839 if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID) 847 if (x->km.state == XFRM_STATE_VALID) {
840 xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); 848 if (xfrm_aevent_is_on())
849 xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
850 else
851 x->xflags |= XFRM_TIME_DEFER;
852 }
841 853
842 spin_unlock(&x->lock); 854 spin_unlock(&x->lock);
855 xfrm_state_put(x);
843} 856}
844 857
845int xfrm_replay_check(struct xfrm_state *x, u32 seq) 858int xfrm_replay_check(struct xfrm_state *x, u32 seq)