]> git.pld-linux.org Git - packages/kernel.git/blame - linux-net-2.6.19.patch
- up to 2.6.27.10
[packages/kernel.git] / linux-net-2.6.19.patch
CommitLineData
6b10f65d 1diff -Nur linux-2.6.18-rc5/net/Kconfig linux-2.6.19/net/Kconfig
2--- linux-2.6.18-rc5/net/Kconfig 2006-08-28 05:41:48.000000000 +0200
3+++ linux-2.6.19/net/Kconfig 2006-09-22 10:04:58.000000000 +0200
4@@ -249,6 +249,11 @@
5 config WIRELESS_EXT
6 bool
7
8+source "net/netlabel/Kconfig"
9+
10+config FIB_RULES
11+ bool
12+
13 endif # if NET
14 endmenu # Networking
15
16diff -Nur linux-2.6.18-rc5/net/Makefile linux-2.6.19/net/Makefile
17--- linux-2.6.18-rc5/net/Makefile 2006-08-28 05:41:48.000000000 +0200
18+++ linux-2.6.19/net/Makefile 2006-09-22 10:04:58.000000000 +0200
19@@ -46,6 +46,7 @@
20 obj-$(CONFIG_IP_SCTP) += sctp/
21 obj-$(CONFIG_IEEE80211) += ieee80211/
22 obj-$(CONFIG_TIPC) += tipc/
23+obj-$(CONFIG_NETLABEL) += netlabel/
24
25 ifeq ($(CONFIG_NET),y)
26 obj-$(CONFIG_SYSCTL) += sysctl_net.o
27diff -Nur linux-2.6.18-rc5/net/atm/atm_sysfs.c linux-2.6.19/net/atm/atm_sysfs.c
28--- linux-2.6.18-rc5/net/atm/atm_sysfs.c 2006-08-28 05:41:48.000000000 +0200
29+++ linux-2.6.19/net/atm/atm_sysfs.c 2006-09-22 10:04:58.000000000 +0200
30@@ -1,6 +1,5 @@
31 /* ATM driver model support. */
32
33-#include <linux/config.h>
34 #include <linux/kernel.h>
35 #include <linux/init.h>
36 #include <linux/kobject.h>
37diff -Nur linux-2.6.18-rc5/net/atm/mpc.c linux-2.6.19/net/atm/mpc.c
38--- linux-2.6.18-rc5/net/atm/mpc.c 2006-08-28 05:41:48.000000000 +0200
39+++ linux-2.6.19/net/atm/mpc.c 2006-09-22 10:04:58.000000000 +0200
40@@ -98,11 +98,6 @@
41 0
42 };
43
44-#ifdef CONFIG_PROC_FS
45-extern int mpc_proc_init(void);
46-extern void mpc_proc_clean(void);
47-#endif
48-
49 struct mpoa_client *mpcs = NULL; /* FIXME */
50 static struct atm_mpoa_qos *qos_head = NULL;
51 static DEFINE_TIMER(mpc_timer, NULL, 0, 0);
52diff -Nur linux-2.6.18-rc5/net/atm/mpc.h linux-2.6.19/net/atm/mpc.h
53--- linux-2.6.18-rc5/net/atm/mpc.h 2006-08-28 05:41:48.000000000 +0200
54+++ linux-2.6.19/net/atm/mpc.h 2006-09-22 10:04:58.000000000 +0200
55@@ -50,4 +50,7 @@
56 struct seq_file;
57 void atm_mpoa_disp_qos(struct seq_file *m);
58
59+int mpc_proc_init(void);
60+void mpc_proc_clean(void);
61+
62 #endif /* _MPC_H_ */
63diff -Nur linux-2.6.18-rc5/net/bridge/br_forward.c linux-2.6.19/net/bridge/br_forward.c
64--- linux-2.6.18-rc5/net/bridge/br_forward.c 2006-08-28 05:41:48.000000000 +0200
65+++ linux-2.6.19/net/bridge/br_forward.c 2006-09-22 10:04:58.000000000 +0200
66@@ -38,13 +38,10 @@
67 if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))
68 kfree_skb(skb);
69 else {
70-#ifdef CONFIG_BRIDGE_NETFILTER
71 /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */
72 if (nf_bridge_maybe_copy_header(skb))
73 kfree_skb(skb);
74- else
75-#endif
76- {
77+ else {
78 skb_push(skb, ETH_HLEN);
79
80 dev_queue_xmit(skb);
81diff -Nur linux-2.6.18-rc5/net/bridge/br_netfilter.c linux-2.6.19/net/bridge/br_netfilter.c
82--- linux-2.6.18-rc5/net/bridge/br_netfilter.c 2006-08-28 05:41:48.000000000 +0200
83+++ linux-2.6.19/net/bridge/br_netfilter.c 2006-09-22 10:04:58.000000000 +0200
84@@ -53,10 +53,10 @@
85
86 #ifdef CONFIG_SYSCTL
87 static struct ctl_table_header *brnf_sysctl_header;
88-static int brnf_call_iptables = 1;
89-static int brnf_call_ip6tables = 1;
90-static int brnf_call_arptables = 1;
91-static int brnf_filter_vlan_tagged = 1;
92+static int brnf_call_iptables __read_mostly = 1;
93+static int brnf_call_ip6tables __read_mostly = 1;
94+static int brnf_call_arptables __read_mostly = 1;
95+static int brnf_filter_vlan_tagged __read_mostly = 1;
96 #else
97 #define brnf_filter_vlan_tagged 1
98 #endif
99@@ -127,14 +127,37 @@
100
101 static inline void nf_bridge_save_header(struct sk_buff *skb)
102 {
103- int header_size = 16;
104+ int header_size = ETH_HLEN;
105
106 if (skb->protocol == htons(ETH_P_8021Q))
107- header_size = 18;
108+ header_size += VLAN_HLEN;
109
110 memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
111 }
112
113+/*
114+ * When forwarding bridge frames, we save a copy of the original
115+ * header before processing.
116+ */
117+int nf_bridge_copy_header(struct sk_buff *skb)
118+{
119+ int err;
120+ int header_size = ETH_HLEN;
121+
122+ if (skb->protocol == htons(ETH_P_8021Q))
123+ header_size += VLAN_HLEN;
124+
125+ err = skb_cow(skb, header_size);
126+ if (err)
127+ return err;
128+
129+ memcpy(skb->data - header_size, skb->nf_bridge->data, header_size);
130+
131+ if (skb->protocol == htons(ETH_P_8021Q))
132+ __skb_push(skb, VLAN_HLEN);
133+ return 0;
134+}
135+
136 /* PF_BRIDGE/PRE_ROUTING *********************************************/
137 /* Undo the changes made for ip6tables PREROUTING and continue the
138 * bridge PRE_ROUTING hook. */
139@@ -695,16 +718,6 @@
140 else
141 pf = PF_INET6;
142
143-#ifdef CONFIG_NETFILTER_DEBUG
144- /* Sometimes we get packets with NULL ->dst here (for example,
145- * running a dhcp client daemon triggers this). This should now
146- * be fixed, but let's keep the check around. */
147- if (skb->dst == NULL) {
148- printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
149- return NF_ACCEPT;
150- }
151-#endif
152-
153 nf_bridge = skb->nf_bridge;
154 nf_bridge->physoutdev = skb->dev;
155 realindev = nf_bridge->physindev;
156@@ -786,7 +799,7 @@
157 * keep the check just to be sure... */
158 if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) {
159 printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: "
160- "bad mac.raw pointer.");
161+ "bad mac.raw pointer.\n");
162 goto print_error;
163 }
164 #endif
165@@ -804,7 +817,7 @@
166
167 #ifdef CONFIG_NETFILTER_DEBUG
168 if (skb->dst == NULL) {
169- printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
170+ printk(KERN_INFO "br_netfilter post_routing: skb->dst == NULL\n");
171 goto print_error;
172 }
173 #endif
174@@ -841,6 +854,7 @@
175 }
176 printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw,
177 skb->data);
178+ dump_stack();
179 return NF_ACCEPT;
180 #endif
181 }
182diff -Nur linux-2.6.18-rc5/net/bridge/br_netlink.c linux-2.6.19/net/bridge/br_netlink.c
183--- linux-2.6.18-rc5/net/bridge/br_netlink.c 2006-08-28 05:41:48.000000000 +0200
184+++ linux-2.6.19/net/bridge/br_netlink.c 2006-09-22 10:04:58.000000000 +0200
185@@ -12,6 +12,7 @@
186
187 #include <linux/kernel.h>
188 #include <linux/rtnetlink.h>
189+#include <net/netlink.h>
190 #include "br_private.h"
191
192 /*
193@@ -76,26 +77,24 @@
194 void br_ifinfo_notify(int event, struct net_bridge_port *port)
195 {
196 struct sk_buff *skb;
197- int err = -ENOMEM;
198+ int payload = sizeof(struct ifinfomsg) + 128;
199+ int err = -ENOBUFS;
200
201 pr_debug("bridge notify event=%d\n", event);
202- skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128),
203- GFP_ATOMIC);
204- if (!skb)
205- goto err_out;
206+ skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
207+ if (skb == NULL)
208+ goto errout;
209+
210+ err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
211+ if (err < 0) {
212+ kfree_skb(skb);
213+ goto errout;
214+ }
215
216- err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0);
217+ err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
218+errout:
219 if (err < 0)
220- goto err_kfree;
221-
222- NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
223- netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
224- return;
225-
226-err_kfree:
227- kfree_skb(skb);
228-err_out:
229- netlink_set_err(rtnl, 0, RTNLGRP_LINK, err);
230+ rtnl_set_sk_err(RTNLGRP_LINK, err);
231 }
232
233 /*
234diff -Nur linux-2.6.18-rc5/net/bridge/netfilter/ebtables.c linux-2.6.19/net/bridge/netfilter/ebtables.c
235--- linux-2.6.18-rc5/net/bridge/netfilter/ebtables.c 2006-08-28 05:41:48.000000000 +0200
236+++ linux-2.6.19/net/bridge/netfilter/ebtables.c 2006-09-22 10:04:58.000000000 +0200
237@@ -37,30 +37,9 @@
238 #include <linux/netfilter_ipv4/listhelp.h>
239 #include <linux/mutex.h>
240
241-#if 0
242-/* use this for remote debugging
243- * Copyright (C) 1998 by Ori Pomerantz
244- * Print the string to the appropriate tty, the one
245- * the current task uses
246- */
247-static void print_string(char *str)
248-{
249- struct tty_struct *my_tty;
250-
251- /* The tty for the current task */
252- my_tty = current->signal->tty;
253- if (my_tty != NULL) {
254- my_tty->driver->write(my_tty, 0, str, strlen(str));
255- my_tty->driver->write(my_tty, 0, "\015\012", 2);
256- }
257-}
258-
259-#define BUGPRINT(args) print_string(args);
260-#else
261 #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
262 "report to author: "format, ## args)
263 /* #define BUGPRINT(format, args...) */
264-#endif
265 #define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
266 ": out of memory: "format, ## args)
267 /* #define MEMPRINT(format, args...) */
268diff -Nur linux-2.6.18-rc5/net/core/Makefile linux-2.6.19/net/core/Makefile
269--- linux-2.6.18-rc5/net/core/Makefile 2006-08-28 05:41:48.000000000 +0200
270+++ linux-2.6.19/net/core/Makefile 2006-09-22 10:04:58.000000000 +0200
271@@ -17,3 +17,4 @@
272 obj-$(CONFIG_WIRELESS_EXT) += wireless.o
273 obj-$(CONFIG_NETPOLL) += netpoll.o
274 obj-$(CONFIG_NET_DMA) += user_dma.o
275+obj-$(CONFIG_FIB_RULES) += fib_rules.o
276diff -Nur linux-2.6.18-rc5/net/core/datagram.c linux-2.6.19/net/core/datagram.c
277--- linux-2.6.18-rc5/net/core/datagram.c 2006-08-28 05:41:48.000000000 +0200
278+++ linux-2.6.19/net/core/datagram.c 2006-09-22 10:04:58.000000000 +0200
279@@ -417,7 +417,7 @@
280
281 sum = (u16)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
282 if (likely(!sum)) {
283- if (unlikely(skb->ip_summed == CHECKSUM_HW))
284+ if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
285 netdev_rx_csum_fault(skb->dev);
286 skb->ip_summed = CHECKSUM_UNNECESSARY;
287 }
288@@ -462,7 +462,7 @@
289 goto fault;
290 if ((unsigned short)csum_fold(csum))
291 goto csum_error;
292- if (unlikely(skb->ip_summed == CHECKSUM_HW))
293+ if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
294 netdev_rx_csum_fault(skb->dev);
295 iov->iov_len -= chunk;
296 iov->iov_base += chunk;
297diff -Nur linux-2.6.18-rc5/net/core/dev.c linux-2.6.19/net/core/dev.c
298--- linux-2.6.18-rc5/net/core/dev.c 2006-08-28 05:41:48.000000000 +0200
299+++ linux-2.6.19/net/core/dev.c 2006-09-22 10:04:58.000000000 +0200
300@@ -640,6 +640,8 @@
301 {
302 if (*name == '\0')
303 return 0;
304+ if (strlen(name) >= IFNAMSIZ)
305+ return 0;
306 if (!strcmp(name, ".") || !strcmp(name, ".."))
307 return 0;
308
309@@ -1166,12 +1168,12 @@
310 * Invalidate hardware checksum when packet is to be mangled, and
311 * complete checksum manually on outgoing path.
312 */
313-int skb_checksum_help(struct sk_buff *skb, int inward)
314+int skb_checksum_help(struct sk_buff *skb)
315 {
316 unsigned int csum;
317 int ret = 0, offset = skb->h.raw - skb->data;
318
319- if (inward)
320+ if (skb->ip_summed == CHECKSUM_COMPLETE)
321 goto out_set_summed;
322
323 if (unlikely(skb_shinfo(skb)->gso_size)) {
324@@ -1223,7 +1225,7 @@
325 skb->mac_len = skb->nh.raw - skb->data;
326 __skb_pull(skb, skb->mac_len);
327
328- if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
329+ if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) {
330 if (skb_header_cloned(skb) &&
331 (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
332 return ERR_PTR(err);
333@@ -1232,7 +1234,7 @@
334 rcu_read_lock();
335 list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
336 if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
337- if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
338+ if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) {
339 err = ptype->gso_send_check(skb);
340 segs = ERR_PTR(err);
341 if (err || skb_gso_ok(skb, features))
342@@ -1444,11 +1446,11 @@
343 /* If packet is not checksummed and device does not support
344 * checksumming for this protocol, complete checksumming here.
345 */
346- if (skb->ip_summed == CHECKSUM_HW &&
347+ if (skb->ip_summed == CHECKSUM_PARTIAL &&
348 (!(dev->features & NETIF_F_GEN_CSUM) &&
349 (!(dev->features & NETIF_F_IP_CSUM) ||
350 skb->protocol != htons(ETH_P_IP))))
351- if (skb_checksum_help(skb, 0))
352+ if (skb_checksum_help(skb))
353 goto out_kfree_skb;
354
355 gso:
356@@ -3191,13 +3193,15 @@
357 struct net_device *dev;
358 int alloc_size;
359
360+ BUG_ON(strlen(name) >= sizeof(dev->name));
361+
362 /* ensure 32-byte alignment of both the device and private area */
363 alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
364 alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
365
366 p = kzalloc(alloc_size, GFP_KERNEL);
367 if (!p) {
368- printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
369+ printk(KERN_ERR "alloc_netdev: Unable to allocate device.\n");
370 return NULL;
371 }
372
373diff -Nur linux-2.6.18-rc5/net/core/dev_mcast.c linux-2.6.19/net/core/dev_mcast.c
374--- linux-2.6.18-rc5/net/core/dev_mcast.c 2006-08-28 05:41:48.000000000 +0200
375+++ linux-2.6.19/net/core/dev_mcast.c 2006-09-22 10:04:58.000000000 +0200
376@@ -21,8 +21,7 @@
377 * 2 of the License, or (at your option) any later version.
378 */
379
380-#include <linux/config.h>
381-#include <linux/module.h>
382+#include <linux/module.h>
383 #include <asm/uaccess.h>
384 #include <asm/system.h>
385 #include <linux/bitops.h>
386diff -Nur linux-2.6.18-rc5/net/core/fib_rules.c linux-2.6.19/net/core/fib_rules.c
387--- linux-2.6.18-rc5/net/core/fib_rules.c 1970-01-01 01:00:00.000000000 +0100
388+++ linux-2.6.19/net/core/fib_rules.c 2006-09-22 10:04:58.000000000 +0200
389@@ -0,0 +1,421 @@
390+/*
391+ * net/core/fib_rules.c Generic Routing Rules
392+ *
393+ * This program is free software; you can redistribute it and/or
394+ * modify it under the terms of the GNU General Public License as
395+ * published by the Free Software Foundation, version 2.
396+ *
397+ * Authors: Thomas Graf <tgraf@suug.ch>
398+ */
399+
400+#include <linux/config.h>
401+#include <linux/types.h>
402+#include <linux/kernel.h>
403+#include <linux/list.h>
404+#include <net/fib_rules.h>
405+
406+static LIST_HEAD(rules_ops);
407+static DEFINE_SPINLOCK(rules_mod_lock);
408+
409+static void notify_rule_change(int event, struct fib_rule *rule,
410+ struct fib_rules_ops *ops, struct nlmsghdr *nlh,
411+ u32 pid);
412+
413+static struct fib_rules_ops *lookup_rules_ops(int family)
414+{
415+ struct fib_rules_ops *ops;
416+
417+ rcu_read_lock();
418+ list_for_each_entry_rcu(ops, &rules_ops, list) {
419+ if (ops->family == family) {
420+ if (!try_module_get(ops->owner))
421+ ops = NULL;
422+ rcu_read_unlock();
423+ return ops;
424+ }
425+ }
426+ rcu_read_unlock();
427+
428+ return NULL;
429+}
430+
431+static void rules_ops_put(struct fib_rules_ops *ops)
432+{
433+ if (ops)
434+ module_put(ops->owner);
435+}
436+
437+int fib_rules_register(struct fib_rules_ops *ops)
438+{
439+ int err = -EEXIST;
440+ struct fib_rules_ops *o;
441+
442+ if (ops->rule_size < sizeof(struct fib_rule))
443+ return -EINVAL;
444+
445+ if (ops->match == NULL || ops->configure == NULL ||
446+ ops->compare == NULL || ops->fill == NULL ||
447+ ops->action == NULL)
448+ return -EINVAL;
449+
450+ spin_lock(&rules_mod_lock);
451+ list_for_each_entry(o, &rules_ops, list)
452+ if (ops->family == o->family)
453+ goto errout;
454+
455+ list_add_tail_rcu(&ops->list, &rules_ops);
456+ err = 0;
457+errout:
458+ spin_unlock(&rules_mod_lock);
459+
460+ return err;
461+}
462+
463+EXPORT_SYMBOL_GPL(fib_rules_register);
464+
465+static void cleanup_ops(struct fib_rules_ops *ops)
466+{
467+ struct fib_rule *rule, *tmp;
468+
469+ list_for_each_entry_safe(rule, tmp, ops->rules_list, list) {
470+ list_del_rcu(&rule->list);
471+ fib_rule_put(rule);
472+ }
473+}
474+
475+int fib_rules_unregister(struct fib_rules_ops *ops)
476+{
477+ int err = 0;
478+ struct fib_rules_ops *o;
479+
480+ spin_lock(&rules_mod_lock);
481+ list_for_each_entry(o, &rules_ops, list) {
482+ if (o == ops) {
483+ list_del_rcu(&o->list);
484+ cleanup_ops(ops);
485+ goto out;
486+ }
487+ }
488+
489+ err = -ENOENT;
490+out:
491+ spin_unlock(&rules_mod_lock);
492+
493+ synchronize_rcu();
494+
495+ return err;
496+}
497+
498+EXPORT_SYMBOL_GPL(fib_rules_unregister);
499+
500+int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
501+ int flags, struct fib_lookup_arg *arg)
502+{
503+ struct fib_rule *rule;
504+ int err;
505+
506+ rcu_read_lock();
507+
508+ list_for_each_entry_rcu(rule, ops->rules_list, list) {
509+ if (rule->ifindex && (rule->ifindex != fl->iif))
510+ continue;
511+
512+ if (!ops->match(rule, fl, flags))
513+ continue;
514+
515+ err = ops->action(rule, fl, flags, arg);
516+ if (err != -EAGAIN) {
517+ fib_rule_get(rule);
518+ arg->rule = rule;
519+ goto out;
520+ }
521+ }
522+
523+ err = -ENETUNREACH;
524+out:
525+ rcu_read_unlock();
526+
527+ return err;
528+}
529+
530+EXPORT_SYMBOL_GPL(fib_rules_lookup);
531+
532+int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
533+{
534+ struct fib_rule_hdr *frh = nlmsg_data(nlh);
535+ struct fib_rules_ops *ops = NULL;
536+ struct fib_rule *rule, *r, *last = NULL;
537+ struct nlattr *tb[FRA_MAX+1];
538+ int err = -EINVAL;
539+
540+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
541+ goto errout;
542+
543+ ops = lookup_rules_ops(frh->family);
544+ if (ops == NULL) {
545+ err = EAFNOSUPPORT;
546+ goto errout;
547+ }
548+
549+ err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy);
550+ if (err < 0)
551+ goto errout;
552+
553+ rule = kzalloc(ops->rule_size, GFP_KERNEL);
554+ if (rule == NULL) {
555+ err = -ENOMEM;
556+ goto errout;
557+ }
558+
559+ if (tb[FRA_PRIORITY])
560+ rule->pref = nla_get_u32(tb[FRA_PRIORITY]);
561+
562+ if (tb[FRA_IFNAME]) {
563+ struct net_device *dev;
564+
565+ rule->ifindex = -1;
566+ nla_strlcpy(rule->ifname, tb[FRA_IFNAME], IFNAMSIZ);
567+ dev = __dev_get_by_name(rule->ifname);
568+ if (dev)
569+ rule->ifindex = dev->ifindex;
570+ }
571+
572+ rule->action = frh->action;
573+ rule->flags = frh->flags;
574+ rule->table = frh_get_table(frh, tb);
575+
576+ if (!rule->pref && ops->default_pref)
577+ rule->pref = ops->default_pref();
578+
579+ err = ops->configure(rule, skb, nlh, frh, tb);
580+ if (err < 0)
581+ goto errout_free;
582+
583+ list_for_each_entry(r, ops->rules_list, list) {
584+ if (r->pref > rule->pref)
585+ break;
586+ last = r;
587+ }
588+
589+ fib_rule_get(rule);
590+
591+ if (last)
592+ list_add_rcu(&rule->list, &last->list);
593+ else
594+ list_add_rcu(&rule->list, ops->rules_list);
595+
596+ notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid);
597+ rules_ops_put(ops);
598+ return 0;
599+
600+errout_free:
601+ kfree(rule);
602+errout:
603+ rules_ops_put(ops);
604+ return err;
605+}
606+
607+int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
608+{
609+ struct fib_rule_hdr *frh = nlmsg_data(nlh);
610+ struct fib_rules_ops *ops = NULL;
611+ struct fib_rule *rule;
612+ struct nlattr *tb[FRA_MAX+1];
613+ int err = -EINVAL;
614+
615+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
616+ goto errout;
617+
618+ ops = lookup_rules_ops(frh->family);
619+ if (ops == NULL) {
620+ err = EAFNOSUPPORT;
621+ goto errout;
622+ }
623+
624+ err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy);
625+ if (err < 0)
626+ goto errout;
627+
628+ list_for_each_entry(rule, ops->rules_list, list) {
629+ if (frh->action && (frh->action != rule->action))
630+ continue;
631+
632+ if (frh->table && (frh_get_table(frh, tb) != rule->table))
633+ continue;
634+
635+ if (tb[FRA_PRIORITY] &&
636+ (rule->pref != nla_get_u32(tb[FRA_PRIORITY])))
637+ continue;
638+
639+ if (tb[FRA_IFNAME] &&
640+ nla_strcmp(tb[FRA_IFNAME], rule->ifname))
641+ continue;
642+
643+ if (!ops->compare(rule, frh, tb))
644+ continue;
645+
646+ if (rule->flags & FIB_RULE_PERMANENT) {
647+ err = -EPERM;
648+ goto errout;
649+ }
650+
651+ list_del_rcu(&rule->list);
652+ synchronize_rcu();
653+ notify_rule_change(RTM_DELRULE, rule, ops, nlh,
654+ NETLINK_CB(skb).pid);
655+ fib_rule_put(rule);
656+ rules_ops_put(ops);
657+ return 0;
658+ }
659+
660+ err = -ENOENT;
661+errout:
662+ rules_ops_put(ops);
663+ return err;
664+}
665+
666+static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
667+ u32 pid, u32 seq, int type, int flags,
668+ struct fib_rules_ops *ops)
669+{
670+ struct nlmsghdr *nlh;
671+ struct fib_rule_hdr *frh;
672+
673+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
674+ if (nlh == NULL)
675+ return -1;
676+
677+ frh = nlmsg_data(nlh);
678+ frh->table = rule->table;
679+ NLA_PUT_U32(skb, FRA_TABLE, rule->table);
680+ frh->res1 = 0;
681+ frh->res2 = 0;
682+ frh->action = rule->action;
683+ frh->flags = rule->flags;
684+
685+ if (rule->ifname[0])
686+ NLA_PUT_STRING(skb, FRA_IFNAME, rule->ifname);
687+
688+ if (rule->pref)
689+ NLA_PUT_U32(skb, FRA_PRIORITY, rule->pref);
690+
691+ if (ops->fill(rule, skb, nlh, frh) < 0)
692+ goto nla_put_failure;
693+
694+ return nlmsg_end(skb, nlh);
695+
696+nla_put_failure:
697+ return nlmsg_cancel(skb, nlh);
698+}
699+
700+int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
701+{
702+ int idx = 0;
703+ struct fib_rule *rule;
704+ struct fib_rules_ops *ops;
705+
706+ ops = lookup_rules_ops(family);
707+ if (ops == NULL)
708+ return -EAFNOSUPPORT;
709+
710+ rcu_read_lock();
711+ list_for_each_entry(rule, ops->rules_list, list) {
712+ if (idx < cb->args[0])
713+ goto skip;
714+
715+ if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid,
716+ cb->nlh->nlmsg_seq, RTM_NEWRULE,
717+ NLM_F_MULTI, ops) < 0)
718+ break;
719+skip:
720+ idx++;
721+ }
722+ rcu_read_unlock();
723+ cb->args[0] = idx;
724+ rules_ops_put(ops);
725+
726+ return skb->len;
727+}
728+
729+EXPORT_SYMBOL_GPL(fib_rules_dump);
730+
731+static void notify_rule_change(int event, struct fib_rule *rule,
732+ struct fib_rules_ops *ops, struct nlmsghdr *nlh,
733+ u32 pid)
734+{
735+ struct sk_buff *skb;
736+ int err = -ENOBUFS;
737+
738+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
739+ if (skb == NULL)
740+ goto errout;
741+
742+ err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
743+ if (err < 0) {
744+ kfree_skb(skb);
745+ goto errout;
746+ }
747+
748+ err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
749+errout:
750+ if (err < 0)
751+ rtnl_set_sk_err(ops->nlgroup, err);
752+}
753+
754+static void attach_rules(struct list_head *rules, struct net_device *dev)
755+{
756+ struct fib_rule *rule;
757+
758+ list_for_each_entry(rule, rules, list) {
759+ if (rule->ifindex == -1 &&
760+ strcmp(dev->name, rule->ifname) == 0)
761+ rule->ifindex = dev->ifindex;
762+ }
763+}
764+
765+static void detach_rules(struct list_head *rules, struct net_device *dev)
766+{
767+ struct fib_rule *rule;
768+
769+ list_for_each_entry(rule, rules, list)
770+ if (rule->ifindex == dev->ifindex)
771+ rule->ifindex = -1;
772+}
773+
774+
775+static int fib_rules_event(struct notifier_block *this, unsigned long event,
776+ void *ptr)
777+{
778+ struct net_device *dev = ptr;
779+ struct fib_rules_ops *ops;
780+
781+ ASSERT_RTNL();
782+ rcu_read_lock();
783+
784+ switch (event) {
785+ case NETDEV_REGISTER:
786+ list_for_each_entry(ops, &rules_ops, list)
787+ attach_rules(ops->rules_list, dev);
788+ break;
789+
790+ case NETDEV_UNREGISTER:
791+ list_for_each_entry(ops, &rules_ops, list)
792+ detach_rules(ops->rules_list, dev);
793+ break;
794+ }
795+
796+ rcu_read_unlock();
797+
798+ return NOTIFY_DONE;
799+}
800+
801+static struct notifier_block fib_rules_notifier = {
802+ .notifier_call = fib_rules_event,
803+};
804+
805+static int __init fib_rules_init(void)
806+{
807+ return register_netdevice_notifier(&fib_rules_notifier);
808+}
809+
810+subsys_initcall(fib_rules_init);
811diff -Nur linux-2.6.18-rc5/net/core/filter.c linux-2.6.19/net/core/filter.c
812--- linux-2.6.18-rc5/net/core/filter.c 2006-08-28 05:41:48.000000000 +0200
813+++ linux-2.6.19/net/core/filter.c 2006-09-22 10:04:58.000000000 +0200
814@@ -422,10 +422,10 @@
815 if (!err) {
816 struct sk_filter *old_fp;
817
818- spin_lock_bh(&sk->sk_lock.slock);
819- old_fp = sk->sk_filter;
820- sk->sk_filter = fp;
821- spin_unlock_bh(&sk->sk_lock.slock);
822+ rcu_read_lock_bh();
823+ old_fp = rcu_dereference(sk->sk_filter);
824+ rcu_assign_pointer(sk->sk_filter, fp);
825+ rcu_read_unlock_bh();
826 fp = old_fp;
827 }
828
829diff -Nur linux-2.6.18-rc5/net/core/flow.c linux-2.6.19/net/core/flow.c
830--- linux-2.6.18-rc5/net/core/flow.c 2006-08-28 05:41:48.000000000 +0200
831+++ linux-2.6.19/net/core/flow.c 2006-09-22 10:04:58.000000000 +0200
832@@ -32,7 +32,6 @@
833 u8 dir;
834 struct flowi key;
835 u32 genid;
836- u32 sk_sid;
837 void *object;
838 atomic_t *object_ref;
839 };
840@@ -165,7 +164,7 @@
841 return 0;
842 }
843
844-void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir,
845+void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
846 flow_resolve_t resolver)
847 {
848 struct flow_cache_entry *fle, **head;
849@@ -189,7 +188,6 @@
850 for (fle = *head; fle; fle = fle->next) {
851 if (fle->family == family &&
852 fle->dir == dir &&
853- fle->sk_sid == sk_sid &&
854 flow_key_compare(key, &fle->key) == 0) {
855 if (fle->genid == atomic_read(&flow_cache_genid)) {
856 void *ret = fle->object;
857@@ -214,7 +212,6 @@
858 *head = fle;
859 fle->family = family;
860 fle->dir = dir;
861- fle->sk_sid = sk_sid;
862 memcpy(&fle->key, key, sizeof(*key));
863 fle->object = NULL;
864 flow_count(cpu)++;
865@@ -226,7 +223,7 @@
866 void *obj;
867 atomic_t *obj_ref;
868
869- resolver(key, sk_sid, family, dir, &obj, &obj_ref);
870+ resolver(key, family, dir, &obj, &obj_ref);
871
872 if (fle) {
873 fle->genid = atomic_read(&flow_cache_genid);
874@@ -346,12 +343,8 @@
875
876 flow_cachep = kmem_cache_create("flow_cache",
877 sizeof(struct flow_cache_entry),
878- 0, SLAB_HWCACHE_ALIGN,
879+ 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
880 NULL, NULL);
881-
882- if (!flow_cachep)
883- panic("NET: failed to allocate flow cache slab\n");
884-
885 flow_hash_shift = 10;
886 flow_lwm = 2 * flow_hash_size;
887 flow_hwm = 4 * flow_hash_size;
888diff -Nur linux-2.6.18-rc5/net/core/neighbour.c linux-2.6.19/net/core/neighbour.c
889--- linux-2.6.18-rc5/net/core/neighbour.c 2006-08-28 05:41:48.000000000 +0200
890+++ linux-2.6.19/net/core/neighbour.c 2006-09-22 10:04:58.000000000 +0200
891@@ -30,6 +30,7 @@
892 #include <net/dst.h>
893 #include <net/sock.h>
894 #include <net/netevent.h>
895+#include <net/netlink.h>
896 #include <linux/rtnetlink.h>
897 #include <linux/random.h>
898 #include <linux/string.h>
899@@ -888,7 +889,7 @@
900 return rc;
901 }
902
903-static __inline__ void neigh_update_hhs(struct neighbour *neigh)
904+static void neigh_update_hhs(struct neighbour *neigh)
905 {
906 struct hh_cache *hh;
907 void (*update)(struct hh_cache*, struct net_device*, unsigned char *) =
908@@ -1338,14 +1339,10 @@
909 neigh_rand_reach_time(tbl->parms.base_reachable_time);
910
911 if (!tbl->kmem_cachep)
912- tbl->kmem_cachep = kmem_cache_create(tbl->id,
913- tbl->entry_size,
914- 0, SLAB_HWCACHE_ALIGN,
915- NULL, NULL);
916-
917- if (!tbl->kmem_cachep)
918- panic("cannot create neighbour cache");
919-
920+ tbl->kmem_cachep =
921+ kmem_cache_create(tbl->id, tbl->entry_size, 0,
922+ SLAB_HWCACHE_ALIGN|SLAB_PANIC,
923+ NULL, NULL);
924 tbl->stats = alloc_percpu(struct neigh_statistics);
925 if (!tbl->stats)
926 panic("cannot create neighbour cache statistics");
927@@ -1437,48 +1434,62 @@
928
929 int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
930 {
931- struct ndmsg *ndm = NLMSG_DATA(nlh);
932- struct rtattr **nda = arg;
933+ struct ndmsg *ndm;
934+ struct nlattr *dst_attr;
935 struct neigh_table *tbl;
936 struct net_device *dev = NULL;
937- int err = -ENODEV;
938+ int err = -EINVAL;
939
940- if (ndm->ndm_ifindex &&
941- (dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL)
942+ if (nlmsg_len(nlh) < sizeof(*ndm))
943 goto out;
944
945+ dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
946+ if (dst_attr == NULL)
947+ goto out;
948+
949+ ndm = nlmsg_data(nlh);
950+ if (ndm->ndm_ifindex) {
951+ dev = dev_get_by_index(ndm->ndm_ifindex);
952+ if (dev == NULL) {
953+ err = -ENODEV;
954+ goto out;
955+ }
956+ }
957+
958 read_lock(&neigh_tbl_lock);
959 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
960- struct rtattr *dst_attr = nda[NDA_DST - 1];
961- struct neighbour *n;
962+ struct neighbour *neigh;
963
964 if (tbl->family != ndm->ndm_family)
965 continue;
966 read_unlock(&neigh_tbl_lock);
967
968- err = -EINVAL;
969- if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
970+ if (nla_len(dst_attr) < tbl->key_len)
971 goto out_dev_put;
972
973 if (ndm->ndm_flags & NTF_PROXY) {
974- err = pneigh_delete(tbl, RTA_DATA(dst_attr), dev);
975+ err = pneigh_delete(tbl, nla_data(dst_attr), dev);
976 goto out_dev_put;
977 }
978
979- if (!dev)
980- goto out;
981+ if (dev == NULL)
982+ goto out_dev_put;
983
984- n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev);
985- if (n) {
986- err = neigh_update(n, NULL, NUD_FAILED,
987- NEIGH_UPDATE_F_OVERRIDE|
988- NEIGH_UPDATE_F_ADMIN);
989- neigh_release(n);
990+ neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
991+ if (neigh == NULL) {
992+ err = -ENOENT;
993+ goto out_dev_put;
994 }
995+
996+ err = neigh_update(neigh, NULL, NUD_FAILED,
997+ NEIGH_UPDATE_F_OVERRIDE |
998+ NEIGH_UPDATE_F_ADMIN);
999+ neigh_release(neigh);
1000 goto out_dev_put;
1001 }
1002 read_unlock(&neigh_tbl_lock);
1003- err = -EADDRNOTAVAIL;
1004+ err = -EAFNOSUPPORT;
1005+
1006 out_dev_put:
1007 if (dev)
1008 dev_put(dev);
1009@@ -1488,76 +1499,88 @@
1010
1011 int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1012 {
1013- struct ndmsg *ndm = NLMSG_DATA(nlh);
1014- struct rtattr **nda = arg;
1015+ struct ndmsg *ndm;
1016+ struct nlattr *tb[NDA_MAX+1];
1017 struct neigh_table *tbl;
1018 struct net_device *dev = NULL;
1019- int err = -ENODEV;
1020+ int err;
1021
1022- if (ndm->ndm_ifindex &&
1023- (dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL)
1024+ err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1025+ if (err < 0)
1026 goto out;
1027
1028+ err = -EINVAL;
1029+ if (tb[NDA_DST] == NULL)
1030+ goto out;
1031+
1032+ ndm = nlmsg_data(nlh);
1033+ if (ndm->ndm_ifindex) {
1034+ dev = dev_get_by_index(ndm->ndm_ifindex);
1035+ if (dev == NULL) {
1036+ err = -ENODEV;
1037+ goto out;
1038+ }
1039+
1040+ if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
1041+ goto out_dev_put;
1042+ }
1043+
1044 read_lock(&neigh_tbl_lock);
1045 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
1046- struct rtattr *lladdr_attr = nda[NDA_LLADDR - 1];
1047- struct rtattr *dst_attr = nda[NDA_DST - 1];
1048- int override = 1;
1049- struct neighbour *n;
1050+ int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1051+ struct neighbour *neigh;
1052+ void *dst, *lladdr;
1053
1054 if (tbl->family != ndm->ndm_family)
1055 continue;
1056 read_unlock(&neigh_tbl_lock);
1057
1058- err = -EINVAL;
1059- if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
1060+ if (nla_len(tb[NDA_DST]) < tbl->key_len)
1061 goto out_dev_put;
1062+ dst = nla_data(tb[NDA_DST]);
1063+ lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
1064
1065 if (ndm->ndm_flags & NTF_PROXY) {
1066- err = -ENOBUFS;
1067- if (pneigh_lookup(tbl, RTA_DATA(dst_attr), dev, 1))
1068- err = 0;
1069+ err = 0;
1070+ if (pneigh_lookup(tbl, dst, dev, 1) == NULL)
1071+ err = -ENOBUFS;
1072 goto out_dev_put;
1073 }
1074
1075- err = -EINVAL;
1076- if (!dev)
1077- goto out;
1078- if (lladdr_attr && RTA_PAYLOAD(lladdr_attr) < dev->addr_len)
1079+ if (dev == NULL)
1080 goto out_dev_put;
1081+
1082+ neigh = neigh_lookup(tbl, dst, dev);
1083+ if (neigh == NULL) {
1084+ if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1085+ err = -ENOENT;
1086+ goto out_dev_put;
1087+ }
1088
1089- n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev);
1090- if (n) {
1091- if (nlh->nlmsg_flags & NLM_F_EXCL) {
1092- err = -EEXIST;
1093- neigh_release(n);
1094+ neigh = __neigh_lookup_errno(tbl, dst, dev);
1095+ if (IS_ERR(neigh)) {
1096+ err = PTR_ERR(neigh);
1097 goto out_dev_put;
1098 }
1099-
1100- override = nlh->nlmsg_flags & NLM_F_REPLACE;
1101- } else if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1102- err = -ENOENT;
1103- goto out_dev_put;
1104 } else {
1105- n = __neigh_lookup_errno(tbl, RTA_DATA(dst_attr), dev);
1106- if (IS_ERR(n)) {
1107- err = PTR_ERR(n);
1108+ if (nlh->nlmsg_flags & NLM_F_EXCL) {
1109+ err = -EEXIST;
1110+ neigh_release(neigh);
1111 goto out_dev_put;
1112 }
1113- }
1114
1115- err = neigh_update(n,
1116- lladdr_attr ? RTA_DATA(lladdr_attr) : NULL,
1117- ndm->ndm_state,
1118- (override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
1119- NEIGH_UPDATE_F_ADMIN);
1120+ if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1121+ flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1122+ }
1123
1124- neigh_release(n);
1125+ err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1126+ neigh_release(neigh);
1127 goto out_dev_put;
1128 }
1129
1130 read_unlock(&neigh_tbl_lock);
1131- err = -EADDRNOTAVAIL;
1132+ err = -EAFNOSUPPORT;
1133+
1134 out_dev_put:
1135 if (dev)
1136 dev_put(dev);
1137@@ -1567,56 +1590,59 @@
1138
1139 static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1140 {
1141- struct rtattr *nest = NULL;
1142-
1143- nest = RTA_NEST(skb, NDTA_PARMS);
1144+ struct nlattr *nest;
1145+
1146+ nest = nla_nest_start(skb, NDTA_PARMS);
1147+ if (nest == NULL)
1148+ return -ENOBUFS;
1149
1150 if (parms->dev)
1151- RTA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex);
1152+ NLA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex);
1153
1154- RTA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt));
1155- RTA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len);
1156- RTA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen);
1157- RTA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes);
1158- RTA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes);
1159- RTA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes);
1160- RTA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time);
1161- RTA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME,
1162+ NLA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt));
1163+ NLA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len);
1164+ NLA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen);
1165+ NLA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes);
1166+ NLA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes);
1167+ NLA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes);
1168+ NLA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time);
1169+ NLA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME,
1170 parms->base_reachable_time);
1171- RTA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime);
1172- RTA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time);
1173- RTA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time);
1174- RTA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay);
1175- RTA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay);
1176- RTA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime);
1177+ NLA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime);
1178+ NLA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time);
1179+ NLA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time);
1180+ NLA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay);
1181+ NLA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay);
1182+ NLA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime);
1183
1184- return RTA_NEST_END(skb, nest);
1185+ return nla_nest_end(skb, nest);
1186
1187-rtattr_failure:
1188- return RTA_NEST_CANCEL(skb, nest);
1189+nla_put_failure:
1190+ return nla_nest_cancel(skb, nest);
1191 }
1192
1193-static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
1194- struct netlink_callback *cb)
1195+static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1196+ u32 pid, u32 seq, int type, int flags)
1197 {
1198 struct nlmsghdr *nlh;
1199 struct ndtmsg *ndtmsg;
1200
1201- nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg),
1202- NLM_F_MULTI);
1203+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1204+ if (nlh == NULL)
1205+ return -ENOBUFS;
1206
1207- ndtmsg = NLMSG_DATA(nlh);
1208+ ndtmsg = nlmsg_data(nlh);
1209
1210 read_lock_bh(&tbl->lock);
1211 ndtmsg->ndtm_family = tbl->family;
1212 ndtmsg->ndtm_pad1 = 0;
1213 ndtmsg->ndtm_pad2 = 0;
1214
1215- RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
1216- RTA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval);
1217- RTA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1);
1218- RTA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2);
1219- RTA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3);
1220+ NLA_PUT_STRING(skb, NDTA_NAME, tbl->id);
1221+ NLA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval);
1222+ NLA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1);
1223+ NLA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2);
1224+ NLA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3);
1225
1226 {
1227 unsigned long now = jiffies;
1228@@ -1635,7 +1661,7 @@
1229 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1230 };
1231
1232- RTA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
1233+ NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
1234 }
1235
1236 {
1237@@ -1660,55 +1686,50 @@
1238 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1239 }
1240
1241- RTA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst);
1242+ NLA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst);
1243 }
1244
1245 BUG_ON(tbl->parms.dev);
1246 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
1247- goto rtattr_failure;
1248+ goto nla_put_failure;
1249
1250 read_unlock_bh(&tbl->lock);
1251- return NLMSG_END(skb, nlh);
1252+ return nlmsg_end(skb, nlh);
1253
1254-rtattr_failure:
1255+nla_put_failure:
1256 read_unlock_bh(&tbl->lock);
1257- return NLMSG_CANCEL(skb, nlh);
1258-
1259-nlmsg_failure:
1260- return -1;
1261+ return nlmsg_cancel(skb, nlh);
1262 }
1263
1264-static int neightbl_fill_param_info(struct neigh_table *tbl,
1265+static int neightbl_fill_param_info(struct sk_buff *skb,
1266+ struct neigh_table *tbl,
1267 struct neigh_parms *parms,
1268- struct sk_buff *skb,
1269- struct netlink_callback *cb)
1270+ u32 pid, u32 seq, int type,
1271+ unsigned int flags)
1272 {
1273 struct ndtmsg *ndtmsg;
1274 struct nlmsghdr *nlh;
1275
1276- nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg),
1277- NLM_F_MULTI);
1278+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1279+ if (nlh == NULL)
1280+ return -ENOBUFS;
1281
1282- ndtmsg = NLMSG_DATA(nlh);
1283+ ndtmsg = nlmsg_data(nlh);
1284
1285 read_lock_bh(&tbl->lock);
1286 ndtmsg->ndtm_family = tbl->family;
1287 ndtmsg->ndtm_pad1 = 0;
1288 ndtmsg->ndtm_pad2 = 0;
1289- RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
1290
1291- if (neightbl_fill_parms(skb, parms) < 0)
1292- goto rtattr_failure;
1293+ if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1294+ neightbl_fill_parms(skb, parms) < 0)
1295+ goto errout;
1296
1297 read_unlock_bh(&tbl->lock);
1298- return NLMSG_END(skb, nlh);
1299-
1300-rtattr_failure:
1301+ return nlmsg_end(skb, nlh);
1302+errout:
1303 read_unlock_bh(&tbl->lock);
1304- return NLMSG_CANCEL(skb, nlh);
1305-
1306-nlmsg_failure:
1307- return -1;
1308+ return nlmsg_cancel(skb, nlh);
1309 }
1310
1311 static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
1312@@ -1724,28 +1745,61 @@
1313 return NULL;
1314 }
1315
1316+static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = {
1317+ [NDTA_NAME] = { .type = NLA_STRING },
1318+ [NDTA_THRESH1] = { .type = NLA_U32 },
1319+ [NDTA_THRESH2] = { .type = NLA_U32 },
1320+ [NDTA_THRESH3] = { .type = NLA_U32 },
1321+ [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1322+ [NDTA_PARMS] = { .type = NLA_NESTED },
1323+};
1324+
1325+static struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] __read_mostly = {
1326+ [NDTPA_IFINDEX] = { .type = NLA_U32 },
1327+ [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1328+ [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1329+ [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1330+ [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1331+ [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1332+ [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1333+ [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1334+ [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1335+ [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1336+ [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1337+ [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1338+ [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1339+};
1340+
1341 int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1342 {
1343 struct neigh_table *tbl;
1344- struct ndtmsg *ndtmsg = NLMSG_DATA(nlh);
1345- struct rtattr **tb = arg;
1346- int err = -EINVAL;
1347+ struct ndtmsg *ndtmsg;
1348+ struct nlattr *tb[NDTA_MAX+1];
1349+ int err;
1350+
1351+ err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1352+ nl_neightbl_policy);
1353+ if (err < 0)
1354+ goto errout;
1355
1356- if (!tb[NDTA_NAME - 1] || !RTA_PAYLOAD(tb[NDTA_NAME - 1]))
1357- return -EINVAL;
1358+ if (tb[NDTA_NAME] == NULL) {
1359+ err = -EINVAL;
1360+ goto errout;
1361+ }
1362
1363+ ndtmsg = nlmsg_data(nlh);
1364 read_lock(&neigh_tbl_lock);
1365 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
1366 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1367 continue;
1368
1369- if (!rtattr_strcmp(tb[NDTA_NAME - 1], tbl->id))
1370+ if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0)
1371 break;
1372 }
1373
1374 if (tbl == NULL) {
1375 err = -ENOENT;
1376- goto errout;
1377+ goto errout_locked;
1378 }
1379
1380 /*
1381@@ -1754,165 +1808,178 @@
1382 */
1383 write_lock_bh(&tbl->lock);
1384
1385- if (tb[NDTA_THRESH1 - 1])
1386- tbl->gc_thresh1 = RTA_GET_U32(tb[NDTA_THRESH1 - 1]);
1387-
1388- if (tb[NDTA_THRESH2 - 1])
1389- tbl->gc_thresh2 = RTA_GET_U32(tb[NDTA_THRESH2 - 1]);
1390-
1391- if (tb[NDTA_THRESH3 - 1])
1392- tbl->gc_thresh3 = RTA_GET_U32(tb[NDTA_THRESH3 - 1]);
1393-
1394- if (tb[NDTA_GC_INTERVAL - 1])
1395- tbl->gc_interval = RTA_GET_MSECS(tb[NDTA_GC_INTERVAL - 1]);
1396-
1397- if (tb[NDTA_PARMS - 1]) {
1398- struct rtattr *tbp[NDTPA_MAX];
1399+ if (tb[NDTA_PARMS]) {
1400+ struct nlattr *tbp[NDTPA_MAX+1];
1401 struct neigh_parms *p;
1402- u32 ifindex = 0;
1403+ int i, ifindex = 0;
1404
1405- if (rtattr_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS - 1]) < 0)
1406- goto rtattr_failure;
1407+ err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
1408+ nl_ntbl_parm_policy);
1409+ if (err < 0)
1410+ goto errout_tbl_lock;
1411
1412- if (tbp[NDTPA_IFINDEX - 1])
1413- ifindex = RTA_GET_U32(tbp[NDTPA_IFINDEX - 1]);
1414+ if (tbp[NDTPA_IFINDEX])
1415+ ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
1416
1417 p = lookup_neigh_params(tbl, ifindex);
1418 if (p == NULL) {
1419 err = -ENOENT;
1420- goto rtattr_failure;
1421+ goto errout_tbl_lock;
1422 }
1423-
1424- if (tbp[NDTPA_QUEUE_LEN - 1])
1425- p->queue_len = RTA_GET_U32(tbp[NDTPA_QUEUE_LEN - 1]);
1426-
1427- if (tbp[NDTPA_PROXY_QLEN - 1])
1428- p->proxy_qlen = RTA_GET_U32(tbp[NDTPA_PROXY_QLEN - 1]);
1429-
1430- if (tbp[NDTPA_APP_PROBES - 1])
1431- p->app_probes = RTA_GET_U32(tbp[NDTPA_APP_PROBES - 1]);
1432-
1433- if (tbp[NDTPA_UCAST_PROBES - 1])
1434- p->ucast_probes =
1435- RTA_GET_U32(tbp[NDTPA_UCAST_PROBES - 1]);
1436
1437- if (tbp[NDTPA_MCAST_PROBES - 1])
1438- p->mcast_probes =
1439- RTA_GET_U32(tbp[NDTPA_MCAST_PROBES - 1]);
1440-
1441- if (tbp[NDTPA_BASE_REACHABLE_TIME - 1])
1442- p->base_reachable_time =
1443- RTA_GET_MSECS(tbp[NDTPA_BASE_REACHABLE_TIME - 1]);
1444-
1445- if (tbp[NDTPA_GC_STALETIME - 1])
1446- p->gc_staletime =
1447- RTA_GET_MSECS(tbp[NDTPA_GC_STALETIME - 1]);
1448+ for (i = 1; i <= NDTPA_MAX; i++) {
1449+ if (tbp[i] == NULL)
1450+ continue;
1451
1452- if (tbp[NDTPA_DELAY_PROBE_TIME - 1])
1453- p->delay_probe_time =
1454- RTA_GET_MSECS(tbp[NDTPA_DELAY_PROBE_TIME - 1]);
1455+ switch (i) {
1456+ case NDTPA_QUEUE_LEN:
1457+ p->queue_len = nla_get_u32(tbp[i]);
1458+ break;
1459+ case NDTPA_PROXY_QLEN:
1460+ p->proxy_qlen = nla_get_u32(tbp[i]);
1461+ break;
1462+ case NDTPA_APP_PROBES:
1463+ p->app_probes = nla_get_u32(tbp[i]);
1464+ break;
1465+ case NDTPA_UCAST_PROBES:
1466+ p->ucast_probes = nla_get_u32(tbp[i]);
1467+ break;
1468+ case NDTPA_MCAST_PROBES:
1469+ p->mcast_probes = nla_get_u32(tbp[i]);
1470+ break;
1471+ case NDTPA_BASE_REACHABLE_TIME:
1472+ p->base_reachable_time = nla_get_msecs(tbp[i]);
1473+ break;
1474+ case NDTPA_GC_STALETIME:
1475+ p->gc_staletime = nla_get_msecs(tbp[i]);
1476+ break;
1477+ case NDTPA_DELAY_PROBE_TIME:
1478+ p->delay_probe_time = nla_get_msecs(tbp[i]);
1479+ break;
1480+ case NDTPA_RETRANS_TIME:
1481+ p->retrans_time = nla_get_msecs(tbp[i]);
1482+ break;
1483+ case NDTPA_ANYCAST_DELAY:
1484+ p->anycast_delay = nla_get_msecs(tbp[i]);
1485+ break;
1486+ case NDTPA_PROXY_DELAY:
1487+ p->proxy_delay = nla_get_msecs(tbp[i]);
1488+ break;
1489+ case NDTPA_LOCKTIME:
1490+ p->locktime = nla_get_msecs(tbp[i]);
1491+ break;
1492+ }
1493+ }
1494+ }
1495
1496- if (tbp[NDTPA_RETRANS_TIME - 1])
1497- p->retrans_time =
1498- RTA_GET_MSECS(tbp[NDTPA_RETRANS_TIME - 1]);
1499+ if (tb[NDTA_THRESH1])
1500+ tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
1501
1502- if (tbp[NDTPA_ANYCAST_DELAY - 1])
1503- p->anycast_delay =
1504- RTA_GET_MSECS(tbp[NDTPA_ANYCAST_DELAY - 1]);
1505+ if (tb[NDTA_THRESH2])
1506+ tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
1507
1508- if (tbp[NDTPA_PROXY_DELAY - 1])
1509- p->proxy_delay =
1510- RTA_GET_MSECS(tbp[NDTPA_PROXY_DELAY - 1]);
1511+ if (tb[NDTA_THRESH3])
1512+ tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
1513
1514- if (tbp[NDTPA_LOCKTIME - 1])
1515- p->locktime = RTA_GET_MSECS(tbp[NDTPA_LOCKTIME - 1]);
1516- }
1517+ if (tb[NDTA_GC_INTERVAL])
1518+ tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
1519
1520 err = 0;
1521
1522-rtattr_failure:
1523+errout_tbl_lock:
1524 write_unlock_bh(&tbl->lock);
1525-errout:
1526+errout_locked:
1527 read_unlock(&neigh_tbl_lock);
1528+errout:
1529 return err;
1530 }
1531
1532 int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
1533 {
1534- int idx, family;
1535- int s_idx = cb->args[0];
1536+ int family, tidx, nidx = 0;
1537+ int tbl_skip = cb->args[0];
1538+ int neigh_skip = cb->args[1];
1539 struct neigh_table *tbl;
1540
1541- family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family;
1542+ family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
1543
1544 read_lock(&neigh_tbl_lock);
1545- for (tbl = neigh_tables, idx = 0; tbl; tbl = tbl->next) {
1546+ for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
1547 struct neigh_parms *p;
1548
1549- if (idx < s_idx || (family && tbl->family != family))
1550+ if (tidx < tbl_skip || (family && tbl->family != family))
1551 continue;
1552
1553- if (neightbl_fill_info(tbl, skb, cb) <= 0)
1554+ if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).pid,
1555+ cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
1556+ NLM_F_MULTI) <= 0)
1557 break;
1558
1559- for (++idx, p = tbl->parms.next; p; p = p->next, idx++) {
1560- if (idx < s_idx)
1561+ for (nidx = 0, p = tbl->parms.next; p; p = p->next, nidx++) {
1562+ if (nidx < neigh_skip)
1563 continue;
1564
1565- if (neightbl_fill_param_info(tbl, p, skb, cb) <= 0)
1566+ if (neightbl_fill_param_info(skb, tbl, p,
1567+ NETLINK_CB(cb->skb).pid,
1568+ cb->nlh->nlmsg_seq,
1569+ RTM_NEWNEIGHTBL,
1570+ NLM_F_MULTI) <= 0)
1571 goto out;
1572 }
1573
1574+ neigh_skip = 0;
1575 }
1576 out:
1577 read_unlock(&neigh_tbl_lock);
1578- cb->args[0] = idx;
1579+ cb->args[0] = tidx;
1580+ cb->args[1] = nidx;
1581
1582 return skb->len;
1583 }
1584
1585-static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
1586- u32 pid, u32 seq, int event, unsigned int flags)
1587+static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
1588+ u32 pid, u32 seq, int type, unsigned int flags)
1589 {
1590 unsigned long now = jiffies;
1591- unsigned char *b = skb->tail;
1592 struct nda_cacheinfo ci;
1593- int locked = 0;
1594- u32 probes;
1595- struct nlmsghdr *nlh = NLMSG_NEW(skb, pid, seq, event,
1596- sizeof(struct ndmsg), flags);
1597- struct ndmsg *ndm = NLMSG_DATA(nlh);
1598+ struct nlmsghdr *nlh;
1599+ struct ndmsg *ndm;
1600+
1601+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
1602+ if (nlh == NULL)
1603+ return -ENOBUFS;
1604
1605- ndm->ndm_family = n->ops->family;
1606+ ndm = nlmsg_data(nlh);
1607+ ndm->ndm_family = neigh->ops->family;
1608 ndm->ndm_pad1 = 0;
1609 ndm->ndm_pad2 = 0;
1610- ndm->ndm_flags = n->flags;
1611- ndm->ndm_type = n->type;
1612- ndm->ndm_ifindex = n->dev->ifindex;
1613- RTA_PUT(skb, NDA_DST, n->tbl->key_len, n->primary_key);
1614- read_lock_bh(&n->lock);
1615- locked = 1;
1616- ndm->ndm_state = n->nud_state;
1617- if (n->nud_state & NUD_VALID)
1618- RTA_PUT(skb, NDA_LLADDR, n->dev->addr_len, n->ha);
1619- ci.ndm_used = now - n->used;
1620- ci.ndm_confirmed = now - n->confirmed;
1621- ci.ndm_updated = now - n->updated;
1622- ci.ndm_refcnt = atomic_read(&n->refcnt) - 1;
1623- probes = atomic_read(&n->probes);
1624- read_unlock_bh(&n->lock);
1625- locked = 0;
1626- RTA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci);
1627- RTA_PUT(skb, NDA_PROBES, sizeof(probes), &probes);
1628- nlh->nlmsg_len = skb->tail - b;
1629- return skb->len;
1630+ ndm->ndm_flags = neigh->flags;
1631+ ndm->ndm_type = neigh->type;
1632+ ndm->ndm_ifindex = neigh->dev->ifindex;
1633+
1634+ NLA_PUT(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key);
1635
1636-nlmsg_failure:
1637-rtattr_failure:
1638- if (locked)
1639- read_unlock_bh(&n->lock);
1640- skb_trim(skb, b - skb->data);
1641- return -1;
1642+ read_lock_bh(&neigh->lock);
1643+ ndm->ndm_state = neigh->nud_state;
1644+ if ((neigh->nud_state & NUD_VALID) &&
1645+ nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, neigh->ha) < 0) {
1646+ read_unlock_bh(&neigh->lock);
1647+ goto nla_put_failure;
1648+ }
1649+
1650+ ci.ndm_used = now - neigh->used;
1651+ ci.ndm_confirmed = now - neigh->confirmed;
1652+ ci.ndm_updated = now - neigh->updated;
1653+ ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
1654+ read_unlock_bh(&neigh->lock);
1655+
1656+ NLA_PUT_U32(skb, NDA_PROBES, atomic_read(&neigh->probes));
1657+ NLA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci);
1658+
1659+ return nlmsg_end(skb, nlh);
1660+
1661+nla_put_failure:
1662+ return nlmsg_cancel(skb, nlh);
1663 }
1664
1665
1666@@ -1956,7 +2023,7 @@
1667 int t, family, s_t;
1668
1669 read_lock(&neigh_tbl_lock);
1670- family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family;
1671+ family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
1672 s_t = cb->args[0];
1673
1674 for (tbl = neigh_tables, t = 0; tbl; tbl = tbl->next, t++) {
1675@@ -2335,41 +2402,35 @@
1676 #endif /* CONFIG_PROC_FS */
1677
1678 #ifdef CONFIG_ARPD
1679-void neigh_app_ns(struct neighbour *n)
1680+static void __neigh_notify(struct neighbour *n, int type, int flags)
1681 {
1682- struct nlmsghdr *nlh;
1683- int size = NLMSG_SPACE(sizeof(struct ndmsg) + 256);
1684- struct sk_buff *skb = alloc_skb(size, GFP_ATOMIC);
1685+ struct sk_buff *skb;
1686+ int err = -ENOBUFS;
1687
1688- if (!skb)
1689- return;
1690+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
1691+ if (skb == NULL)
1692+ goto errout;
1693
1694- if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH, 0) < 0) {
1695+ err = neigh_fill_info(skb, n, 0, 0, type, flags);
1696+ if (err < 0) {
1697 kfree_skb(skb);
1698- return;
1699+ goto errout;
1700 }
1701- nlh = (struct nlmsghdr *)skb->data;
1702- nlh->nlmsg_flags = NLM_F_REQUEST;
1703- NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH;
1704- netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC);
1705+
1706+ err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
1707+errout:
1708+ if (err < 0)
1709+ rtnl_set_sk_err(RTNLGRP_NEIGH, err);
1710 }
1711
1712-static void neigh_app_notify(struct neighbour *n)
1713+void neigh_app_ns(struct neighbour *n)
1714 {
1715- struct nlmsghdr *nlh;
1716- int size = NLMSG_SPACE(sizeof(struct ndmsg) + 256);
1717- struct sk_buff *skb = alloc_skb(size, GFP_ATOMIC);
1718-
1719- if (!skb)
1720- return;
1721+ __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
1722+}
1723
1724- if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH, 0) < 0) {
1725- kfree_skb(skb);
1726- return;
1727- }
1728- nlh = (struct nlmsghdr *)skb->data;
1729- NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH;
1730- netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC);
1731+static void neigh_app_notify(struct neighbour *n)
1732+{
1733+ __neigh_notify(n, RTM_NEWNEIGH, 0);
1734 }
1735
1736 #endif /* CONFIG_ARPD */
1737@@ -2383,7 +2444,7 @@
1738 ctl_table neigh_neigh_dir[2];
1739 ctl_table neigh_proto_dir[2];
1740 ctl_table neigh_root_dir[2];
1741-} neigh_sysctl_template = {
1742+} neigh_sysctl_template __read_mostly = {
1743 .neigh_vars = {
1744 {
1745 .ctl_name = NET_NEIGH_MCAST_SOLICIT,
1746@@ -2656,7 +2717,6 @@
1747 #endif /* CONFIG_SYSCTL */
1748
1749 EXPORT_SYMBOL(__neigh_event_send);
1750-EXPORT_SYMBOL(neigh_add);
1751 EXPORT_SYMBOL(neigh_changeaddr);
1752 EXPORT_SYMBOL(neigh_compat_output);
1753 EXPORT_SYMBOL(neigh_connected_output);
1754@@ -2676,11 +2736,8 @@
1755 EXPORT_SYMBOL(neigh_table_init);
1756 EXPORT_SYMBOL(neigh_table_init_no_netlink);
1757 EXPORT_SYMBOL(neigh_update);
1758-EXPORT_SYMBOL(neigh_update_hhs);
1759 EXPORT_SYMBOL(pneigh_enqueue);
1760 EXPORT_SYMBOL(pneigh_lookup);
1761-EXPORT_SYMBOL(neightbl_dump_info);
1762-EXPORT_SYMBOL(neightbl_set);
1763
1764 #ifdef CONFIG_ARPD
1765 EXPORT_SYMBOL(neigh_app_ns);
1766diff -Nur linux-2.6.18-rc5/net/core/netpoll.c linux-2.6.19/net/core/netpoll.c
1767--- linux-2.6.18-rc5/net/core/netpoll.c 2006-08-28 05:41:48.000000000 +0200
1768+++ linux-2.6.19/net/core/netpoll.c 2006-09-22 10:04:58.000000000 +0200
1769@@ -110,7 +110,7 @@
1770
1771 psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
1772
1773- if (skb->ip_summed == CHECKSUM_HW &&
1774+ if (skb->ip_summed == CHECKSUM_COMPLETE &&
1775 !(u16)csum_fold(csum_add(psum, skb->csum)))
1776 return 0;
1777
1778diff -Nur linux-2.6.18-rc5/net/core/rtnetlink.c linux-2.6.19/net/core/rtnetlink.c
1779--- linux-2.6.18-rc5/net/core/rtnetlink.c 2006-08-28 05:41:48.000000000 +0200
1780+++ linux-2.6.19/net/core/rtnetlink.c 2006-09-22 10:04:58.000000000 +0200
1781@@ -35,6 +35,7 @@
1782 #include <linux/init.h>
1783 #include <linux/security.h>
1784 #include <linux/mutex.h>
1785+#include <linux/if_addr.h>
1786
1787 #include <asm/uaccess.h>
1788 #include <asm/system.h>
1789@@ -49,6 +50,7 @@
1790 #include <net/udp.h>
1791 #include <net/sock.h>
1792 #include <net/pkt_sched.h>
1793+#include <net/fib_rules.h>
1794 #include <net/netlink.h>
1795 #ifdef CONFIG_NET_WIRELESS_RTNETLINK
1796 #include <linux/wireless.h>
1797@@ -56,6 +58,7 @@
1798 #endif /* CONFIG_NET_WIRELESS_RTNETLINK */
1799
1800 static DEFINE_MUTEX(rtnl_mutex);
1801+static struct sock *rtnl;
1802
1803 void rtnl_lock(void)
1804 {
1805@@ -93,8 +96,6 @@
1806 return 0;
1807 }
1808
1809-struct sock *rtnl;
1810-
1811 struct rtnetlink_link * rtnetlink_links[NPROTO];
1812
1813 static const int rtm_min[RTM_NR_FAMILIES] =
1814@@ -102,8 +103,7 @@
1815 [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
1816 [RTM_FAM(RTM_NEWADDR)] = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
1817 [RTM_FAM(RTM_NEWROUTE)] = NLMSG_LENGTH(sizeof(struct rtmsg)),
1818- [RTM_FAM(RTM_NEWNEIGH)] = NLMSG_LENGTH(sizeof(struct ndmsg)),
1819- [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct rtmsg)),
1820+ [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct fib_rule_hdr)),
1821 [RTM_FAM(RTM_NEWQDISC)] = NLMSG_LENGTH(sizeof(struct tcmsg)),
1822 [RTM_FAM(RTM_NEWTCLASS)] = NLMSG_LENGTH(sizeof(struct tcmsg)),
1823 [RTM_FAM(RTM_NEWTFILTER)] = NLMSG_LENGTH(sizeof(struct tcmsg)),
1824@@ -111,7 +111,6 @@
1825 [RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
1826 [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
1827 [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
1828- [RTM_FAM(RTM_NEWNEIGHTBL)] = NLMSG_LENGTH(sizeof(struct ndtmsg)),
1829 };
1830
1831 static const int rta_max[RTM_NR_FAMILIES] =
1832@@ -119,13 +118,11 @@
1833 [RTM_FAM(RTM_NEWLINK)] = IFLA_MAX,
1834 [RTM_FAM(RTM_NEWADDR)] = IFA_MAX,
1835 [RTM_FAM(RTM_NEWROUTE)] = RTA_MAX,
1836- [RTM_FAM(RTM_NEWNEIGH)] = NDA_MAX,
1837- [RTM_FAM(RTM_NEWRULE)] = RTA_MAX,
1838+ [RTM_FAM(RTM_NEWRULE)] = FRA_MAX,
1839 [RTM_FAM(RTM_NEWQDISC)] = TCA_MAX,
1840 [RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX,
1841 [RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX,
1842 [RTM_FAM(RTM_NEWACTION)] = TCAA_MAX,
1843- [RTM_FAM(RTM_NEWNEIGHTBL)] = NDTA_MAX,
1844 };
1845
1846 void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
1847@@ -168,24 +165,52 @@
1848 return err;
1849 }
1850
1851+int rtnl_unicast(struct sk_buff *skb, u32 pid)
1852+{
1853+ return nlmsg_unicast(rtnl, skb, pid);
1854+}
1855+
1856+int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
1857+ struct nlmsghdr *nlh, gfp_t flags)
1858+{
1859+ int report = 0;
1860+
1861+ if (nlh)
1862+ report = nlmsg_report(nlh);
1863+
1864+ return nlmsg_notify(rtnl, skb, pid, group, report, flags);
1865+}
1866+
1867+void rtnl_set_sk_err(u32 group, int error)
1868+{
1869+ netlink_set_err(rtnl, 0, group, error);
1870+}
1871+
1872 int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics)
1873 {
1874- struct rtattr *mx = (struct rtattr*)skb->tail;
1875- int i;
1876+ struct nlattr *mx;
1877+ int i, valid = 0;
1878
1879- RTA_PUT(skb, RTA_METRICS, 0, NULL);
1880- for (i=0; i<RTAX_MAX; i++) {
1881- if (metrics[i])
1882- RTA_PUT(skb, i+1, sizeof(u32), metrics+i);
1883- }
1884- mx->rta_len = skb->tail - (u8*)mx;
1885- if (mx->rta_len == RTA_LENGTH(0))
1886- skb_trim(skb, (u8*)mx - skb->data);
1887- return 0;
1888+ mx = nla_nest_start(skb, RTA_METRICS);
1889+ if (mx == NULL)
1890+ return -ENOBUFS;
1891+
1892+ for (i = 0; i < RTAX_MAX; i++) {
1893+ if (metrics[i]) {
1894+ valid++;
1895+ NLA_PUT_U32(skb, i+1, metrics[i]);
1896+ }
1897+ }
1898
1899-rtattr_failure:
1900- skb_trim(skb, (u8*)mx - skb->data);
1901- return -1;
1902+ if (!valid) {
1903+ nla_nest_cancel(skb, mx);
1904+ return 0;
1905+ }
1906+
1907+ return nla_nest_end(skb, mx);
1908+
1909+nla_put_failure:
1910+ return nla_nest_cancel(skb, mx);
1911 }
1912
1913
1914@@ -216,41 +241,73 @@
1915 }
1916 }
1917
1918-static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
1919- int type, u32 pid, u32 seq, u32 change,
1920- unsigned int flags)
1921-{
1922- struct ifinfomsg *r;
1923- struct nlmsghdr *nlh;
1924- unsigned char *b = skb->tail;
1925-
1926- nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags);
1927- r = NLMSG_DATA(nlh);
1928- r->ifi_family = AF_UNSPEC;
1929- r->__ifi_pad = 0;
1930- r->ifi_type = dev->type;
1931- r->ifi_index = dev->ifindex;
1932- r->ifi_flags = dev_get_flags(dev);
1933- r->ifi_change = change;
1934+static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
1935+ struct net_device_stats *b)
1936+{
1937+ a->rx_packets = b->rx_packets;
1938+ a->tx_packets = b->tx_packets;
1939+ a->rx_bytes = b->rx_bytes;
1940+ a->tx_bytes = b->tx_bytes;
1941+ a->rx_errors = b->rx_errors;
1942+ a->tx_errors = b->tx_errors;
1943+ a->rx_dropped = b->rx_dropped;
1944+ a->tx_dropped = b->tx_dropped;
1945+
1946+ a->multicast = b->multicast;
1947+ a->collisions = b->collisions;
1948+
1949+ a->rx_length_errors = b->rx_length_errors;
1950+ a->rx_over_errors = b->rx_over_errors;
1951+ a->rx_crc_errors = b->rx_crc_errors;
1952+ a->rx_frame_errors = b->rx_frame_errors;
1953+ a->rx_fifo_errors = b->rx_fifo_errors;
1954+ a->rx_missed_errors = b->rx_missed_errors;
1955+
1956+ a->tx_aborted_errors = b->tx_aborted_errors;
1957+ a->tx_carrier_errors = b->tx_carrier_errors;
1958+ a->tx_fifo_errors = b->tx_fifo_errors;
1959+ a->tx_heartbeat_errors = b->tx_heartbeat_errors;
1960+ a->tx_window_errors = b->tx_window_errors;
1961
1962- RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
1963+ a->rx_compressed = b->rx_compressed;
1964+ a->tx_compressed = b->tx_compressed;
1965+};
1966
1967- if (1) {
1968- u32 txqlen = dev->tx_queue_len;
1969- RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen);
1970- }
1971+static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
1972+ void *iwbuf, int iwbuflen, int type, u32 pid,
1973+ u32 seq, u32 change, unsigned int flags)
1974+{
1975+ struct ifinfomsg *ifm;
1976+ struct nlmsghdr *nlh;
1977+
1978+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
1979+ if (nlh == NULL)
1980+ return -ENOBUFS;
1981+
1982+ ifm = nlmsg_data(nlh);
1983+ ifm->ifi_family = AF_UNSPEC;
1984+ ifm->__ifi_pad = 0;
1985+ ifm->ifi_type = dev->type;
1986+ ifm->ifi_index = dev->ifindex;
1987+ ifm->ifi_flags = dev_get_flags(dev);
1988+ ifm->ifi_change = change;
1989+
1990+ NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
1991+ NLA_PUT_U32(skb, IFLA_TXQLEN, dev->tx_queue_len);
1992+ NLA_PUT_U32(skb, IFLA_WEIGHT, dev->weight);
1993+ NLA_PUT_U8(skb, IFLA_OPERSTATE,
1994+ netif_running(dev) ? dev->operstate : IF_OPER_DOWN);
1995+ NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode);
1996+ NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
1997
1998- if (1) {
1999- u32 weight = dev->weight;
2000- RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight);
2001- }
2002+ if (dev->ifindex != dev->iflink)
2003+ NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
2004
2005- if (1) {
2006- u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN;
2007- u8 link_mode = dev->link_mode;
2008- RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
2009- RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode);
2010- }
2011+ if (dev->master)
2012+ NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex);
2013+
2014+ if (dev->qdisc_sleeping)
2015+ NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc_sleeping->ops->id);
2016
2017 if (1) {
2018 struct rtnl_link_ifmap map = {
2019@@ -261,58 +318,38 @@
2020 .dma = dev->dma,
2021 .port = dev->if_port,
2022 };
2023- RTA_PUT(skb, IFLA_MAP, sizeof(map), &map);
2024+ NLA_PUT(skb, IFLA_MAP, sizeof(map), &map);
2025 }
2026
2027 if (dev->addr_len) {
2028- RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
2029- RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast);
2030- }
2031-
2032- if (1) {
2033- u32 mtu = dev->mtu;
2034- RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
2035- }
2036-
2037- if (dev->ifindex != dev->iflink) {
2038- u32 iflink = dev->iflink;
2039- RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink);
2040- }
2041-
2042- if (dev->qdisc_sleeping)
2043- RTA_PUT(skb, IFLA_QDISC,
2044- strlen(dev->qdisc_sleeping->ops->id) + 1,
2045- dev->qdisc_sleeping->ops->id);
2046-
2047- if (dev->master) {
2048- u32 master = dev->master->ifindex;
2049- RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master);
2050+ NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
2051+ NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast);
2052 }
2053
2054 if (dev->get_stats) {
2055- unsigned long *stats = (unsigned long*)dev->get_stats(dev);
2056+ struct net_device_stats *stats = dev->get_stats(dev);
2057 if (stats) {
2058- struct rtattr *a;
2059- __u32 *s;
2060- int i;
2061- int n = sizeof(struct rtnl_link_stats)/4;
2062-
2063- a = __RTA_PUT(skb, IFLA_STATS, n*4);
2064- s = RTA_DATA(a);
2065- for (i=0; i<n; i++)
2066- s[i] = stats[i];
2067+ struct nlattr *attr;
2068+
2069+ attr = nla_reserve(skb, IFLA_STATS,
2070+ sizeof(struct rtnl_link_stats));
2071+ if (attr == NULL)
2072+ goto nla_put_failure;
2073+
2074+ copy_rtnl_link_stats(nla_data(attr), stats);
2075 }
2076 }
2077- nlh->nlmsg_len = skb->tail - b;
2078- return skb->len;
2079
2080-nlmsg_failure:
2081-rtattr_failure:
2082- skb_trim(skb, b - skb->data);
2083- return -1;
2084+ if (iwbuf)
2085+ NLA_PUT(skb, IFLA_WIRELESS, iwbuflen, iwbuf);
2086+
2087+ return nlmsg_end(skb, nlh);
2088+
2089+nla_put_failure:
2090+ return nlmsg_cancel(skb, nlh);
2091 }
2092
2093-static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
2094+static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
2095 {
2096 int idx;
2097 int s_idx = cb->args[0];
2098@@ -322,10 +359,9 @@
2099 for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
2100 if (idx < s_idx)
2101 continue;
2102- if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK,
2103- NETLINK_CB(cb->skb).pid,
2104- cb->nlh->nlmsg_seq, 0,
2105- NLM_F_MULTI) <= 0)
2106+ if (rtnl_fill_ifinfo(skb, dev, NULL, 0, RTM_NEWLINK,
2107+ NETLINK_CB(cb->skb).pid,
2108+ cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0)
2109 break;
2110 }
2111 read_unlock(&dev_base_lock);
2112@@ -334,52 +370,70 @@
2113 return skb->len;
2114 }
2115
2116-static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2117+static struct nla_policy ifla_policy[IFLA_MAX+1] __read_mostly = {
2118+ [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
2119+ [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
2120+ [IFLA_MTU] = { .type = NLA_U32 },
2121+ [IFLA_TXQLEN] = { .type = NLA_U32 },
2122+ [IFLA_WEIGHT] = { .type = NLA_U32 },
2123+ [IFLA_OPERSTATE] = { .type = NLA_U8 },
2124+ [IFLA_LINKMODE] = { .type = NLA_U8 },
2125+};
2126+
2127+static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2128 {
2129- struct ifinfomsg *ifm = NLMSG_DATA(nlh);
2130- struct rtattr **ida = arg;
2131+ struct ifinfomsg *ifm;
2132 struct net_device *dev;
2133- int err, send_addr_notify = 0;
2134+ int err, send_addr_notify = 0, modified = 0;
2135+ struct nlattr *tb[IFLA_MAX+1];
2136+ char ifname[IFNAMSIZ];
2137+
2138+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
2139+ if (err < 0)
2140+ goto errout;
2141+
2142+ if (tb[IFLA_IFNAME])
2143+ nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
2144+ else
2145+ ifname[0] = '\0';
2146
2147+ err = -EINVAL;
2148+ ifm = nlmsg_data(nlh);
2149 if (ifm->ifi_index >= 0)
2150 dev = dev_get_by_index(ifm->ifi_index);
2151- else if (ida[IFLA_IFNAME - 1]) {
2152- char ifname[IFNAMSIZ];
2153-
2154- if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
2155- IFNAMSIZ) >= IFNAMSIZ)
2156- return -EINVAL;
2157+ else if (tb[IFLA_IFNAME])
2158 dev = dev_get_by_name(ifname);
2159- } else
2160- return -EINVAL;
2161+ else
2162+ goto errout;
2163
2164- if (!dev)
2165- return -ENODEV;
2166+ if (dev == NULL) {
2167+ err = -ENODEV;
2168+ goto errout;
2169+ }
2170
2171- err = -EINVAL;
2172+ if (tb[IFLA_ADDRESS] &&
2173+ nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
2174+ goto errout_dev;
2175
2176- if (ifm->ifi_flags)
2177- dev_change_flags(dev, ifm->ifi_flags);
2178+ if (tb[IFLA_BROADCAST] &&
2179+ nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
2180+ goto errout_dev;
2181
2182- if (ida[IFLA_MAP - 1]) {
2183+ if (tb[IFLA_MAP]) {
2184 struct rtnl_link_ifmap *u_map;
2185 struct ifmap k_map;
2186
2187 if (!dev->set_config) {
2188 err = -EOPNOTSUPP;
2189- goto out;
2190+ goto errout_dev;
2191 }
2192
2193 if (!netif_device_present(dev)) {
2194 err = -ENODEV;
2195- goto out;
2196+ goto errout_dev;
2197 }
2198-
2199- if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map)))
2200- goto out;
2201-
2202- u_map = RTA_DATA(ida[IFLA_MAP - 1]);
2203
2204+ u_map = nla_data(tb[IFLA_MAP]);
2205 k_map.mem_start = (unsigned long) u_map->mem_start;
2206 k_map.mem_end = (unsigned long) u_map->mem_end;
2207 k_map.base_addr = (unsigned short) u_map->base_addr;
2208@@ -388,200 +442,175 @@
2209 k_map.port = (unsigned char) u_map->port;
2210
2211 err = dev->set_config(dev, &k_map);
2212+ if (err < 0)
2213+ goto errout_dev;
2214
2215- if (err)
2216- goto out;
2217+ modified = 1;
2218 }
2219
2220- if (ida[IFLA_ADDRESS - 1]) {
2221+ if (tb[IFLA_ADDRESS]) {
2222 struct sockaddr *sa;
2223 int len;
2224
2225 if (!dev->set_mac_address) {
2226 err = -EOPNOTSUPP;
2227- goto out;
2228+ goto errout_dev;
2229 }
2230+
2231 if (!netif_device_present(dev)) {
2232 err = -ENODEV;
2233- goto out;
2234+ goto errout_dev;
2235 }
2236- if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
2237- goto out;
2238
2239 len = sizeof(sa_family_t) + dev->addr_len;
2240 sa = kmalloc(len, GFP_KERNEL);
2241 if (!sa) {
2242 err = -ENOMEM;
2243- goto out;
2244+ goto errout_dev;
2245 }
2246 sa->sa_family = dev->type;
2247- memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]),
2248+ memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
2249 dev->addr_len);
2250 err = dev->set_mac_address(dev, sa);
2251 kfree(sa);
2252 if (err)
2253- goto out;
2254+ goto errout_dev;
2255 send_addr_notify = 1;
2256+ modified = 1;
2257 }
2258
2259- if (ida[IFLA_BROADCAST - 1]) {
2260- if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len))
2261- goto out;
2262- memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]),
2263- dev->addr_len);
2264- send_addr_notify = 1;
2265+ if (tb[IFLA_MTU]) {
2266+ err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
2267+ if (err < 0)
2268+ goto errout_dev;
2269+ modified = 1;
2270+ }
2271+
2272+ /*
2273+ * Interface selected by interface index but interface
2274+ * name provided implies that a name change has been
2275+ * requested.
2276+ */
2277+ if (ifm->ifi_index >= 0 && ifname[0]) {
2278+ err = dev_change_name(dev, ifname);
2279+ if (err < 0)
2280+ goto errout_dev;
2281+ modified = 1;
2282 }
2283
2284- if (ida[IFLA_MTU - 1]) {
2285- if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
2286- goto out;
2287- err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1])));
2288-
2289- if (err)
2290- goto out;
2291-
2292+#ifdef CONFIG_NET_WIRELESS_RTNETLINK
2293+ if (tb[IFLA_WIRELESS]) {
2294+ /* Call Wireless Extensions.
2295+ * Various stuff checked in there... */
2296+ err = wireless_rtnetlink_set(dev, nla_data(tb[IFLA_WIRELESS]),
2297+ nla_len(tb[IFLA_WIRELESS]));
2298+ if (err < 0)
2299+ goto errout_dev;
2300 }
2301+#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
2302
2303- if (ida[IFLA_TXQLEN - 1]) {
2304- if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
2305- goto out;
2306-
2307- dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1]));
2308+ if (tb[IFLA_BROADCAST]) {
2309+ nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
2310+ send_addr_notify = 1;
2311 }
2312
2313- if (ida[IFLA_WEIGHT - 1]) {
2314- if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
2315- goto out;
2316
2317- dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1]));
2318- }
2319+ if (ifm->ifi_flags)
2320+ dev_change_flags(dev, ifm->ifi_flags);
2321
2322- if (ida[IFLA_OPERSTATE - 1]) {
2323- if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
2324- goto out;
2325+ if (tb[IFLA_TXQLEN])
2326+ dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
2327
2328- set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1])));
2329- }
2330+ if (tb[IFLA_WEIGHT])
2331+ dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
2332
2333- if (ida[IFLA_LINKMODE - 1]) {
2334- if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
2335- goto out;
2336+ if (tb[IFLA_OPERSTATE])
2337+ set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
2338
2339+ if (tb[IFLA_LINKMODE]) {
2340 write_lock_bh(&dev_base_lock);
2341- dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1]));
2342+ dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
2343 write_unlock_bh(&dev_base_lock);
2344 }
2345
2346- if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) {
2347- char ifname[IFNAMSIZ];
2348-
2349- if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
2350- IFNAMSIZ) >= IFNAMSIZ)
2351- goto out;
2352- err = dev_change_name(dev, ifname);
2353- if (err)
2354- goto out;
2355- }
2356-
2357-#ifdef CONFIG_NET_WIRELESS_RTNETLINK
2358- if (ida[IFLA_WIRELESS - 1]) {
2359-
2360- /* Call Wireless Extensions.
2361- * Various stuff checked in there... */
2362- err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
2363- if (err)
2364- goto out;
2365- }
2366-#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
2367-
2368 err = 0;
2369
2370-out:
2371+errout_dev:
2372+ if (err < 0 && modified && net_ratelimit())
2373+ printk(KERN_WARNING "A link change request failed with "
2374+ "some changes comitted already. Interface %s may "
2375+ "have been left with an inconsistent configuration, "
2376+ "please check.\n", dev->name);
2377+
2378 if (send_addr_notify)
2379 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
2380
2381 dev_put(dev);
2382+errout:
2383 return err;
2384 }
2385
2386-#ifdef CONFIG_NET_WIRELESS_RTNETLINK
2387-static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
2388+static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
2389 {
2390- struct ifinfomsg *ifm = NLMSG_DATA(in_nlh);
2391- struct rtattr **ida = arg;
2392- struct net_device *dev;
2393- struct ifinfomsg *r;
2394- struct nlmsghdr *nlh;
2395- int err = -ENOBUFS;
2396- struct sk_buff *skb;
2397- unsigned char *b;
2398- char *iw_buf = NULL;
2399+ struct ifinfomsg *ifm;
2400+ struct nlattr *tb[IFLA_MAX+1];
2401+ struct net_device *dev = NULL;
2402+ struct sk_buff *nskb;
2403+ char *iw_buf = NULL, *iw = NULL;
2404 int iw_buf_len = 0;
2405+ int err, payload;
2406
2407- if (ifm->ifi_index >= 0)
2408+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
2409+ if (err < 0)
2410+ goto errout;
2411+
2412+ ifm = nlmsg_data(nlh);
2413+ if (ifm->ifi_index >= 0) {
2414 dev = dev_get_by_index(ifm->ifi_index);
2415- else
2416+ if (dev == NULL)
2417+ return -ENODEV;
2418+ } else
2419 return -EINVAL;
2420- if (!dev)
2421- return -ENODEV;
2422
2423-#ifdef CONFIG_NET_WIRELESS_RTNETLINK
2424- if (ida[IFLA_WIRELESS - 1]) {
2425
2426+#ifdef CONFIG_NET_WIRELESS_RTNETLINK
2427+ if (tb[IFLA_WIRELESS]) {
2428 /* Call Wireless Extensions. We need to know the size before
2429 * we can alloc. Various stuff checked in there... */
2430- err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
2431- if (err)
2432- goto out;
2433+ err = wireless_rtnetlink_get(dev, nla_data(tb[IFLA_WIRELESS]),
2434+ nla_len(tb[IFLA_WIRELESS]),
2435+ &iw_buf, &iw_buf_len);
2436+ if (err < 0)
2437+ goto errout;
2438+
2439+ iw += IW_EV_POINT_OFF;
2440 }
2441 #endif /* CONFIG_NET_WIRELESS_RTNETLINK */
2442
2443- /* Create a skb big enough to include all the data.
2444- * Some requests are way bigger than 4k... Jean II */
2445- skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
2446- GFP_KERNEL);
2447- if (!skb)
2448- goto out;
2449- b = skb->tail;
2450-
2451- /* Put in the message the usual good stuff */
2452- nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
2453- RTM_NEWLINK, sizeof(*r));
2454- r = NLMSG_DATA(nlh);
2455- r->ifi_family = AF_UNSPEC;
2456- r->__ifi_pad = 0;
2457- r->ifi_type = dev->type;
2458- r->ifi_index = dev->ifindex;
2459- r->ifi_flags = dev->flags;
2460- r->ifi_change = 0;
2461-
2462- /* Put the wireless payload if it exist */
2463- if(iw_buf != NULL)
2464- RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
2465- iw_buf + IW_EV_POINT_OFF);
2466-
2467- nlh->nlmsg_len = skb->tail - b;
2468-
2469- /* Needed ? */
2470- NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
2471-
2472- err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
2473- if (err > 0)
2474- err = 0;
2475-out:
2476- if(iw_buf != NULL)
2477- kfree(iw_buf);
2478+ payload = NLMSG_ALIGN(sizeof(struct ifinfomsg) +
2479+ nla_total_size(iw_buf_len));
2480+ nskb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL);
2481+ if (nskb == NULL) {
2482+ err = -ENOBUFS;
2483+ goto errout;
2484+ }
2485+
2486+ err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
2487+ NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
2488+ if (err <= 0) {
2489+ kfree_skb(nskb);
2490+ goto errout;
2491+ }
2492+
2493+ err = rtnl_unicast(skb, NETLINK_CB(skb).pid);
2494+errout:
2495+ kfree(iw_buf);
2496 dev_put(dev);
2497- return err;
2498
2499-rtattr_failure:
2500-nlmsg_failure:
2501- kfree_skb(skb);
2502- goto out;
2503+ return err;
2504 }
2505-#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
2506
2507-static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
2508+static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
2509 {
2510 int idx;
2511 int s_idx = cb->family;
2512@@ -608,20 +637,22 @@
2513 void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
2514 {
2515 struct sk_buff *skb;
2516- int size = NLMSG_SPACE(sizeof(struct ifinfomsg) +
2517- sizeof(struct rtnl_link_ifmap) +
2518- sizeof(struct rtnl_link_stats) + 128);
2519-
2520- skb = alloc_skb(size, GFP_KERNEL);
2521- if (!skb)
2522- return;
2523+ int err = -ENOBUFS;
2524+
2525+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2526+ if (skb == NULL)
2527+ goto errout;
2528
2529- if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change, 0) < 0) {
2530+ err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
2531+ if (err < 0) {
2532 kfree_skb(skb);
2533- return;
2534+ goto errout;
2535 }
2536- NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
2537- netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_KERNEL);
2538+
2539+ err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
2540+errout:
2541+ if (err < 0)
2542+ rtnl_set_sk_err(RTNLGRP_LINK, err);
2543 }
2544
2545 /* Protected by RTNL sempahore. */
2546@@ -746,18 +777,19 @@
2547
2548 static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
2549 {
2550- [RTM_GETLINK - RTM_BASE] = {
2551-#ifdef CONFIG_NET_WIRELESS_RTNETLINK
2552- .doit = do_getlink,
2553-#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
2554- .dumpit = rtnetlink_dump_ifinfo },
2555- [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
2556- [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
2557- [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
2558+ [RTM_GETLINK - RTM_BASE] = { .doit = rtnl_getlink,
2559+ .dumpit = rtnl_dump_ifinfo },
2560+ [RTM_SETLINK - RTM_BASE] = { .doit = rtnl_setlink },
2561+ [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnl_dump_all },
2562+ [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnl_dump_all },
2563 [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add },
2564 [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete },
2565 [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info },
2566- [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
2567+#ifdef CONFIG_FIB_RULES
2568+ [RTM_NEWRULE - RTM_BASE] = { .doit = fib_nl_newrule },
2569+ [RTM_DELRULE - RTM_BASE] = { .doit = fib_nl_delrule },
2570+#endif
2571+ [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnl_dump_all },
2572 [RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info },
2573 [RTM_SETNEIGHTBL - RTM_BASE] = { .doit = neightbl_set },
2574 };
2575@@ -817,7 +849,9 @@
2576 EXPORT_SYMBOL(rtattr_parse);
2577 EXPORT_SYMBOL(rtnetlink_links);
2578 EXPORT_SYMBOL(rtnetlink_put_metrics);
2579-EXPORT_SYMBOL(rtnl);
2580 EXPORT_SYMBOL(rtnl_lock);
2581 EXPORT_SYMBOL(rtnl_trylock);
2582 EXPORT_SYMBOL(rtnl_unlock);
2583+EXPORT_SYMBOL(rtnl_unicast);
2584+EXPORT_SYMBOL(rtnl_notify);
2585+EXPORT_SYMBOL(rtnl_set_sk_err);
2586diff -Nur linux-2.6.18-rc5/net/core/skbuff.c linux-2.6.19/net/core/skbuff.c
2587--- linux-2.6.18-rc5/net/core/skbuff.c 2006-08-28 05:41:48.000000000 +0200
2588+++ linux-2.6.19/net/core/skbuff.c 2006-09-22 10:04:58.000000000 +0200
2589@@ -1397,7 +1397,7 @@
2590 unsigned int csum;
2591 long csstart;
2592
2593- if (skb->ip_summed == CHECKSUM_HW)
2594+ if (skb->ip_summed == CHECKSUM_PARTIAL)
2595 csstart = skb->h.raw - skb->data;
2596 else
2597 csstart = skb_headlen(skb);
2598@@ -1411,7 +1411,7 @@
2599 csum = skb_copy_and_csum_bits(skb, csstart, to + csstart,
2600 skb->len - csstart, 0);
2601
2602- if (skb->ip_summed == CHECKSUM_HW) {
2603+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
2604 long csstuff = csstart + skb->csum;
2605
2606 *((unsigned short *)(to + csstuff)) = csum_fold(csum);
2607@@ -1898,10 +1898,10 @@
2608 * @len: length of data pulled
2609 *
2610 * This function performs an skb_pull on the packet and updates
2611- * update the CHECKSUM_HW checksum. It should be used on receive
2612- * path processing instead of skb_pull unless you know that the
2613- * checksum difference is zero (e.g., a valid IP header) or you
2614- * are setting ip_summed to CHECKSUM_NONE.
2615+ * update the CHECKSUM_COMPLETE checksum. It should be used on
2616+ * receive path processing instead of skb_pull unless you know
2617+ * that the checksum difference is zero (e.g., a valid IP header)
2618+ * or you are setting ip_summed to CHECKSUM_NONE.
2619 */
2620 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
2621 {
2622@@ -1994,7 +1994,7 @@
2623 frag = skb_shinfo(nskb)->frags;
2624 k = 0;
2625
2626- nskb->ip_summed = CHECKSUM_HW;
2627+ nskb->ip_summed = CHECKSUM_PARTIAL;
2628 nskb->csum = skb->csum;
2629 memcpy(skb_put(nskb, hsize), skb->data + offset, hsize);
2630
2631@@ -2046,19 +2046,14 @@
2632 skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
2633 sizeof(struct sk_buff),
2634 0,
2635- SLAB_HWCACHE_ALIGN,
2636+ SLAB_HWCACHE_ALIGN|SLAB_PANIC,
2637 NULL, NULL);
2638- if (!skbuff_head_cache)
2639- panic("cannot create skbuff cache");
2640-
2641 skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache",
2642 (2*sizeof(struct sk_buff)) +
2643 sizeof(atomic_t),
2644 0,
2645- SLAB_HWCACHE_ALIGN,
2646+ SLAB_HWCACHE_ALIGN|SLAB_PANIC,
2647 NULL, NULL);
2648- if (!skbuff_fclone_cache)
2649- panic("cannot create skbuff cache");
2650 }
2651
2652 EXPORT_SYMBOL(___pskb_trim);
2653diff -Nur linux-2.6.18-rc5/net/core/sock.c linux-2.6.19/net/core/sock.c
2654--- linux-2.6.18-rc5/net/core/sock.c 2006-08-28 05:41:48.000000000 +0200
2655+++ linux-2.6.19/net/core/sock.c 2006-09-22 10:04:58.000000000 +0200
2656@@ -187,13 +187,13 @@
2657 #define SK_RMEM_MAX (_SK_MEM_OVERHEAD * _SK_MEM_PACKETS)
2658
2659 /* Run time adjustable parameters. */
2660-__u32 sysctl_wmem_max = SK_WMEM_MAX;
2661-__u32 sysctl_rmem_max = SK_RMEM_MAX;
2662-__u32 sysctl_wmem_default = SK_WMEM_MAX;
2663-__u32 sysctl_rmem_default = SK_RMEM_MAX;
2664+__u32 sysctl_wmem_max __read_mostly = SK_WMEM_MAX;
2665+__u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX;
2666+__u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX;
2667+__u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX;
2668
2669 /* Maximal space eaten by iovec or ancilliary data plus some space */
2670-int sysctl_optmem_max = sizeof(unsigned long)*(2*UIO_MAXIOV + 512);
2671+int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512);
2672
2673 static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
2674 {
2675@@ -247,11 +247,7 @@
2676 goto out;
2677 }
2678
2679- /* It would be deadlock, if sock_queue_rcv_skb is used
2680- with socket lock! We assume that users of this
2681- function are lock free.
2682- */
2683- err = sk_filter(sk, skb, 1);
2684+ err = sk_filter(sk, skb);
2685 if (err)
2686 goto out;
2687
2688@@ -278,7 +274,7 @@
2689 {
2690 int rc = NET_RX_SUCCESS;
2691
2692- if (sk_filter(sk, skb, 0))
2693+ if (sk_filter(sk, skb))
2694 goto discard_and_relse;
2695
2696 skb->dev = NULL;
2697@@ -606,15 +602,15 @@
2698 break;
2699
2700 case SO_DETACH_FILTER:
2701- spin_lock_bh(&sk->sk_lock.slock);
2702- filter = sk->sk_filter;
2703+ rcu_read_lock_bh();
2704+ filter = rcu_dereference(sk->sk_filter);
2705 if (filter) {
2706- sk->sk_filter = NULL;
2707- spin_unlock_bh(&sk->sk_lock.slock);
2708+ rcu_assign_pointer(sk->sk_filter, NULL);
2709 sk_filter_release(sk, filter);
2710+ rcu_read_unlock_bh();
2711 break;
2712 }
2713- spin_unlock_bh(&sk->sk_lock.slock);
2714+ rcu_read_unlock_bh();
2715 ret = -ENONET;
2716 break;
2717
2718@@ -884,10 +880,10 @@
2719 if (sk->sk_destruct)
2720 sk->sk_destruct(sk);
2721
2722- filter = sk->sk_filter;
2723+ filter = rcu_dereference(sk->sk_filter);
2724 if (filter) {
2725 sk_filter_release(sk, filter);
2726- sk->sk_filter = NULL;
2727+ rcu_assign_pointer(sk->sk_filter, NULL);
2728 }
2729
2730 sock_disable_timestamp(sk);
2731@@ -911,7 +907,7 @@
2732 if (newsk != NULL) {
2733 struct sk_filter *filter;
2734
2735- memcpy(newsk, sk, sk->sk_prot->obj_size);
2736+ sock_copy(newsk, sk);
2737
2738 /* SANITY */
2739 sk_node_init(&newsk->sk_node);
2740diff -Nur linux-2.6.18-rc5/net/core/utils.c linux-2.6.19/net/core/utils.c
2741--- linux-2.6.18-rc5/net/core/utils.c 2006-08-28 05:41:48.000000000 +0200
2742+++ linux-2.6.19/net/core/utils.c 2006-09-22 10:04:58.000000000 +0200
2743@@ -4,6 +4,7 @@
2744 * Authors:
2745 * net_random Alan Cox
2746 * net_ratelimit Andy Kleen
2747+ * in{4,6}_pton YOSHIFUJI Hideaki, Copyright (C)2006 USAGI/WIDE Project
2748 *
2749 * Created by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
2750 *
2751@@ -191,3 +192,215 @@
2752 }
2753
2754 EXPORT_SYMBOL(in_aton);
2755+
2756+#define IN6PTON_XDIGIT 0x00010000
2757+#define IN6PTON_DIGIT 0x00020000
2758+#define IN6PTON_COLON_MASK 0x00700000
2759+#define IN6PTON_COLON_1 0x00100000 /* single : requested */
2760+#define IN6PTON_COLON_2 0x00200000 /* second : requested */
2761+#define IN6PTON_COLON_1_2 0x00400000 /* :: requested */
2762+#define IN6PTON_DOT 0x00800000 /* . */
2763+#define IN6PTON_DELIM 0x10000000
2764+#define IN6PTON_NULL 0x20000000 /* first/tail */
2765+#define IN6PTON_UNKNOWN 0x40000000
2766+
2767+static inline int digit2bin(char c, char delim)
2768+{
2769+ if (c == delim || c == '\0')
2770+ return IN6PTON_DELIM;
2771+ if (c == '.')
2772+ return IN6PTON_DOT;
2773+ if (c >= '0' && c <= '9')
2774+ return (IN6PTON_DIGIT | (c - '0'));
2775+ return IN6PTON_UNKNOWN;
2776+}
2777+
2778+static inline int xdigit2bin(char c, char delim)
2779+{
2780+ if (c == delim || c == '\0')
2781+ return IN6PTON_DELIM;
2782+ if (c == ':')
2783+ return IN6PTON_COLON_MASK;
2784+ if (c == '.')
2785+ return IN6PTON_DOT;
2786+ if (c >= '0' && c <= '9')
2787+ return (IN6PTON_XDIGIT | IN6PTON_DIGIT| (c - '0'));
2788+ if (c >= 'a' && c <= 'f')
2789+ return (IN6PTON_XDIGIT | (c - 'a' + 10));
2790+ if (c >= 'A' && c <= 'F')
2791+ return (IN6PTON_XDIGIT | (c - 'A' + 10));
2792+ return IN6PTON_UNKNOWN;
2793+}
2794+
2795+int in4_pton(const char *src, int srclen,
2796+ u8 *dst,
2797+ char delim, const char **end)
2798+{
2799+ const char *s;
2800+ u8 *d;
2801+ u8 dbuf[4];
2802+ int ret = 0;
2803+ int i;
2804+ int w = 0;
2805+
2806+ if (srclen < 0)
2807+ srclen = strlen(src);
2808+ s = src;
2809+ d = dbuf;
2810+ i = 0;
2811+ while(1) {
2812+ int c;
2813+ c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
2814+ if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM))) {
2815+ goto out;
2816+ }
2817+ if (c & (IN6PTON_DOT | IN6PTON_DELIM)) {
2818+ if (w == 0)
2819+ goto out;
2820+ *d++ = w & 0xff;
2821+ w = 0;
2822+ i++;
2823+ if (c & IN6PTON_DELIM) {
2824+ if (i != 4)
2825+ goto out;
2826+ break;
2827+ }
2828+ goto cont;
2829+ }
2830+ w = (w * 10) + c;
2831+ if ((w & 0xffff) > 255) {
2832+ goto out;
2833+ }
2834+cont:
2835+ if (i >= 4)
2836+ goto out;
2837+ s++;
2838+ srclen--;
2839+ }
2840+ ret = 1;
2841+ memcpy(dst, dbuf, sizeof(dbuf));
2842+out:
2843+ if (end)
2844+ *end = s;
2845+ return ret;
2846+}
2847+
2848+EXPORT_SYMBOL(in4_pton);
2849+
2850+int in6_pton(const char *src, int srclen,
2851+ u8 *dst,
2852+ char delim, const char **end)
2853+{
2854+ const char *s, *tok = NULL;
2855+ u8 *d, *dc = NULL;
2856+ u8 dbuf[16];
2857+ int ret = 0;
2858+ int i;
2859+ int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL;
2860+ int w = 0;
2861+
2862+ memset(dbuf, 0, sizeof(dbuf));
2863+
2864+ s = src;
2865+ d = dbuf;
2866+ if (srclen < 0)
2867+ srclen = strlen(src);
2868+
2869+ while (1) {
2870+ int c;
2871+
2872+ c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
2873+ if (!(c & state))
2874+ goto out;
2875+ if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
2876+ /* process one 16-bit word */
2877+ if (!(state & IN6PTON_NULL)) {
2878+ *d++ = (w >> 8) & 0xff;
2879+ *d++ = w & 0xff;
2880+ }
2881+ w = 0;
2882+ if (c & IN6PTON_DELIM) {
2883+ /* We've processed last word */
2884+ break;
2885+ }
2886+ /*
2887+ * COLON_1 => XDIGIT
2888+ * COLON_2 => XDIGIT|DELIM
2889+ * COLON_1_2 => COLON_2
2890+ */
2891+ switch (state & IN6PTON_COLON_MASK) {
2892+ case IN6PTON_COLON_2:
2893+ dc = d;
2894+ state = IN6PTON_XDIGIT | IN6PTON_DELIM;
2895+ if (dc - dbuf >= sizeof(dbuf))
2896+ state |= IN6PTON_NULL;
2897+ break;
2898+ case IN6PTON_COLON_1|IN6PTON_COLON_1_2:
2899+ state = IN6PTON_XDIGIT | IN6PTON_COLON_2;
2900+ break;
2901+ case IN6PTON_COLON_1:
2902+ state = IN6PTON_XDIGIT;
2903+ break;
2904+ case IN6PTON_COLON_1_2:
2905+ state = IN6PTON_COLON_2;
2906+ break;
2907+ default:
2908+ state = 0;
2909+ }
2910+ tok = s + 1;
2911+ goto cont;
2912+ }
2913+
2914+ if (c & IN6PTON_DOT) {
2915+ ret = in4_pton(tok ? tok : s, srclen + (int)(s - tok), d, delim, &s);
2916+ if (ret > 0) {
2917+ d += 4;
2918+ break;
2919+ }
2920+ goto out;
2921+ }
2922+
2923+ w = (w << 4) | (0xff & c);
2924+ state = IN6PTON_COLON_1 | IN6PTON_DELIM;
2925+ if (!(w & 0xf000)) {
2926+ state |= IN6PTON_XDIGIT;
2927+ }
2928+ if (!dc && d + 2 < dbuf + sizeof(dbuf)) {
2929+ state |= IN6PTON_COLON_1_2;
2930+ state &= ~IN6PTON_DELIM;
2931+ }
2932+ if (d + 2 >= dbuf + sizeof(dbuf)) {
2933+ state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2);
2934+ }
2935+cont:
2936+ if ((dc && d + 4 < dbuf + sizeof(dbuf)) ||
2937+ d + 4 == dbuf + sizeof(dbuf)) {
2938+ state |= IN6PTON_DOT;
2939+ }
2940+ if (d >= dbuf + sizeof(dbuf)) {
2941+ state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK);
2942+ }
2943+ s++;
2944+ srclen--;
2945+ }
2946+
2947+ i = 15; d--;
2948+
2949+ if (dc) {
2950+ while(d >= dc)
2951+ dst[i--] = *d--;
2952+ while(i >= dc - dbuf)
2953+ dst[i--] = 0;
2954+ while(i >= 0)
2955+ dst[i--] = *d--;
2956+ } else
2957+ memcpy(dst, dbuf, sizeof(dbuf));
2958+
2959+ ret = 1;
2960+out:
2961+ if (end)
2962+ *end = s;
2963+ return ret;
2964+}
2965+
2966+EXPORT_SYMBOL(in6_pton);
2967diff -Nur linux-2.6.18-rc5/net/core/wireless.c linux-2.6.19/net/core/wireless.c
2968--- linux-2.6.18-rc5/net/core/wireless.c 2006-08-28 05:41:48.000000000 +0200
2969+++ linux-2.6.19/net/core/wireless.c 2006-09-22 10:04:58.000000000 +0200
2970@@ -72,7 +72,6 @@
2971
2972 /***************************** INCLUDES *****************************/
2973
2974-#include <linux/config.h> /* Not needed ??? */
2975 #include <linux/module.h>
2976 #include <linux/types.h> /* off_t */
2977 #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
2978@@ -86,6 +85,7 @@
2979
2980 #include <linux/wireless.h> /* Pretty obvious */
2981 #include <net/iw_handler.h> /* New driver API */
2982+#include <net/netlink.h>
2983
2984 #include <asm/uaccess.h> /* copy_to_user() */
2985
2986@@ -1850,7 +1850,7 @@
2987 struct sk_buff *skb;
2988
2989 while ((skb = skb_dequeue(&wireless_nlevent_queue)))
2990- netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
2991+ rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
2992 }
2993
2994 static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
2995diff -Nur linux-2.6.18-rc5/net/dccp/ackvec.c linux-2.6.19/net/dccp/ackvec.c
2996--- linux-2.6.18-rc5/net/dccp/ackvec.c 2006-08-28 05:41:48.000000000 +0200
2997+++ linux-2.6.19/net/dccp/ackvec.c 2006-09-22 10:04:58.000000000 +0200
2998@@ -142,14 +142,13 @@
2999 struct dccp_ackvec *av = kmem_cache_alloc(dccp_ackvec_slab, priority);
3000
3001 if (av != NULL) {
3002- av->dccpav_buf_head =
3003- av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
3004+ av->dccpav_buf_head = DCCP_MAX_ACKVEC_LEN - 1;
3005 av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1;
3006 av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
3007 av->dccpav_ack_ptr = 0;
3008 av->dccpav_time.tv_sec = 0;
3009 av->dccpav_time.tv_usec = 0;
3010- av->dccpav_sent_len = av->dccpav_vec_len = 0;
3011+ av->dccpav_vec_len = 0;
3012 INIT_LIST_HEAD(&av->dccpav_records);
3013 }
3014
3015@@ -353,11 +352,13 @@
3016 {
3017 struct dccp_ackvec_record *next;
3018
3019- av->dccpav_buf_tail = avr->dccpavr_ack_ptr - 1;
3020- if (av->dccpav_buf_tail == 0)
3021- av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
3022-
3023- av->dccpav_vec_len -= avr->dccpavr_sent_len;
3024+ /* sort out vector length */
3025+ if (av->dccpav_buf_head <= avr->dccpavr_ack_ptr)
3026+ av->dccpav_vec_len = avr->dccpavr_ack_ptr - av->dccpav_buf_head;
3027+ else
3028+ av->dccpav_vec_len = DCCP_MAX_ACKVEC_LEN - 1
3029+ - av->dccpav_buf_head
3030+ + avr->dccpavr_ack_ptr;
3031
3032 /* free records */
3033 list_for_each_entry_safe_from(avr, next, &av->dccpav_records,
3034@@ -434,8 +435,7 @@
3035 break;
3036 found:
3037 if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) {
3038- const u8 state = (*vector &
3039- DCCP_ACKVEC_STATE_MASK) >> 6;
3040+ const u8 state = *vector & DCCP_ACKVEC_STATE_MASK;
3041 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
3042 #ifdef CONFIG_IP_DCCP_DEBUG
3043 struct dccp_sock *dp = dccp_sk(sk);
3044diff -Nur linux-2.6.18-rc5/net/dccp/ackvec.h linux-2.6.19/net/dccp/ackvec.h
3045--- linux-2.6.18-rc5/net/dccp/ackvec.h 2006-08-28 05:41:48.000000000 +0200
3046+++ linux-2.6.19/net/dccp/ackvec.h 2006-09-22 10:04:58.000000000 +0200
3047@@ -54,9 +54,7 @@
3048 struct list_head dccpav_records;
3049 struct timeval dccpav_time;
3050 u8 dccpav_buf_head;
3051- u8 dccpav_buf_tail;
3052 u8 dccpav_ack_ptr;
3053- u8 dccpav_sent_len;
3054 u8 dccpav_vec_len;
3055 u8 dccpav_buf_nonce;
3056 u8 dccpav_ack_nonce;
3057@@ -107,7 +105,7 @@
3058
3059 static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)
3060 {
3061- return av->dccpav_sent_len != av->dccpav_vec_len;
3062+ return av->dccpav_vec_len;
3063 }
3064 #else /* CONFIG_IP_DCCP_ACKVEC */
3065 static inline int dccp_ackvec_init(void)
3066diff -Nur linux-2.6.18-rc5/net/dccp/ccids/Kconfig linux-2.6.19/net/dccp/ccids/Kconfig
3067--- linux-2.6.18-rc5/net/dccp/ccids/Kconfig 2006-08-28 05:41:48.000000000 +0200
3068+++ linux-2.6.19/net/dccp/ccids/Kconfig 2006-09-22 10:04:58.000000000 +0200
3069@@ -30,6 +30,14 @@
3070
3071 If in doubt, say M.
3072
3073+config IP_DCCP_CCID2_DEBUG
3074+ bool "CCID2 debug"
3075+ depends on IP_DCCP_CCID2
3076+ ---help---
3077+ Enable CCID2 debug messages.
3078+
3079+ If in doubt, say N.
3080+
3081 config IP_DCCP_CCID3
3082 tristate "CCID3 (TCP-Friendly) (EXPERIMENTAL)"
3083 depends on IP_DCCP
3084diff -Nur linux-2.6.18-rc5/net/dccp/ccids/ccid2.c linux-2.6.19/net/dccp/ccids/ccid2.c
3085--- linux-2.6.18-rc5/net/dccp/ccids/ccid2.c 2006-08-28 05:41:48.000000000 +0200
3086+++ linux-2.6.19/net/dccp/ccids/ccid2.c 2006-09-22 10:04:58.000000000 +0200
3087@@ -27,7 +27,6 @@
3088 *
3089 * BUGS:
3090 * - sequence number wrapping
3091- * - jiffies wrapping
3092 */
3093
3094 #include "../ccid.h"
3095@@ -36,8 +35,7 @@
3096
3097 static int ccid2_debug;
3098
3099-#undef CCID2_DEBUG
3100-#ifdef CCID2_DEBUG
3101+#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
3102 #define ccid2_pr_debug(format, a...) \
3103 do { if (ccid2_debug) \
3104 printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
3105@@ -46,9 +44,7 @@
3106 #define ccid2_pr_debug(format, a...)
3107 #endif
3108
3109-static const int ccid2_seq_len = 128;
3110-
3111-#ifdef CCID2_DEBUG
3112+#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
3113 static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
3114 {
3115 int len = 0;
3116@@ -71,8 +67,8 @@
3117
3118 /* packets are sent sequentially */
3119 BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq);
3120- BUG_ON(seqp->ccid2s_sent < prev->ccid2s_sent);
3121- BUG_ON(len > ccid2_seq_len);
3122+ BUG_ON(time_before(seqp->ccid2s_sent,
3123+ prev->ccid2s_sent));
3124
3125 seqp = prev;
3126 }
3127@@ -84,16 +80,57 @@
3128 do {
3129 seqp = seqp->ccid2s_prev;
3130 len++;
3131- BUG_ON(len > ccid2_seq_len);
3132 } while (seqp != hctx->ccid2hctx_seqh);
3133
3134- BUG_ON(len != ccid2_seq_len);
3135 ccid2_pr_debug("total len=%d\n", len);
3136+ BUG_ON(len != hctx->ccid2hctx_seqbufc * CCID2_SEQBUF_LEN);
3137 }
3138 #else
3139 #define ccid2_hc_tx_check_sanity(hctx) do {} while (0)
3140 #endif
3141
3142+static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num,
3143+ gfp_t gfp)
3144+{
3145+ struct ccid2_seq *seqp;
3146+ int i;
3147+
3148+ /* check if we have space to preserve the pointer to the buffer */
3149+ if (hctx->ccid2hctx_seqbufc >= (sizeof(hctx->ccid2hctx_seqbuf) /
3150+ sizeof(struct ccid2_seq*)))
3151+ return -ENOMEM;
3152+
3153+ /* allocate buffer and initialize linked list */
3154+ seqp = kmalloc(sizeof(*seqp) * num, gfp);
3155+ if (seqp == NULL)
3156+ return -ENOMEM;
3157+
3158+ for (i = 0; i < (num - 1); i++) {
3159+ seqp[i].ccid2s_next = &seqp[i + 1];
3160+ seqp[i + 1].ccid2s_prev = &seqp[i];
3161+ }
3162+ seqp[num - 1].ccid2s_next = seqp;
3163+ seqp->ccid2s_prev = &seqp[num - 1];
3164+
3165+ /* This is the first allocation. Initiate the head and tail. */
3166+ if (hctx->ccid2hctx_seqbufc == 0)
3167+ hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqt = seqp;
3168+ else {
3169+ /* link the existing list with the one we just created */
3170+ hctx->ccid2hctx_seqh->ccid2s_next = seqp;
3171+ seqp->ccid2s_prev = hctx->ccid2hctx_seqh;
3172+
3173+ hctx->ccid2hctx_seqt->ccid2s_prev = &seqp[num - 1];
3174+ seqp[num - 1].ccid2s_next = hctx->ccid2hctx_seqt;
3175+ }
3176+
3177+ /* store the original pointer to the buffer so we can free it */
3178+ hctx->ccid2hctx_seqbuf[hctx->ccid2hctx_seqbufc] = seqp;
3179+ hctx->ccid2hctx_seqbufc++;
3180+
3181+ return 0;
3182+}
3183+
3184 static int ccid2_hc_tx_send_packet(struct sock *sk,
3185 struct sk_buff *skb, int len)
3186 {
3187@@ -122,7 +159,7 @@
3188 }
3189 }
3190
3191- return 100; /* XXX */
3192+ return 1; /* XXX CCID should dequeue when ready instead of polling */
3193 }
3194
3195 static void ccid2_change_l_ack_ratio(struct sock *sk, int val)
3196@@ -150,10 +187,8 @@
3197 dp->dccps_l_ack_ratio = val;
3198 }
3199
3200-static void ccid2_change_cwnd(struct sock *sk, int val)
3201+static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, int val)
3202 {
3203- struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
3204-
3205 if (val == 0)
3206 val = 1;
3207
3208@@ -164,6 +199,17 @@
3209 hctx->ccid2hctx_cwnd = val;
3210 }
3211
3212+static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hctx, long val)
3213+{
3214+ ccid2_pr_debug("change SRTT to %ld\n", val);
3215+ hctx->ccid2hctx_srtt = val;
3216+}
3217+
3218+static void ccid2_change_pipe(struct ccid2_hc_tx_sock *hctx, long val)
3219+{
3220+ hctx->ccid2hctx_pipe = val;
3221+}
3222+
3223 static void ccid2_start_rto_timer(struct sock *sk);
3224
3225 static void ccid2_hc_tx_rto_expire(unsigned long data)
3226@@ -193,11 +239,11 @@
3227 ccid2_start_rto_timer(sk);
3228
3229 /* adjust pipe, cwnd etc */
3230- hctx->ccid2hctx_pipe = 0;
3231+ ccid2_change_pipe(hctx, 0);
3232 hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1;
3233 if (hctx->ccid2hctx_ssthresh < 2)
3234 hctx->ccid2hctx_ssthresh = 2;
3235- ccid2_change_cwnd(sk, 1);
3236+ ccid2_change_cwnd(hctx, 1);
3237
3238 /* clear state about stuff we sent */
3239 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh;
3240@@ -232,13 +278,14 @@
3241 {
3242 struct dccp_sock *dp = dccp_sk(sk);
3243 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
3244+ struct ccid2_seq *next;
3245 u64 seq;
3246
3247 ccid2_hc_tx_check_sanity(hctx);
3248
3249 BUG_ON(!hctx->ccid2hctx_sendwait);
3250 hctx->ccid2hctx_sendwait = 0;
3251- hctx->ccid2hctx_pipe++;
3252+ ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe + 1);
3253 BUG_ON(hctx->ccid2hctx_pipe < 0);
3254
3255 /* There is an issue. What if another packet is sent between
3256@@ -251,15 +298,23 @@
3257 hctx->ccid2hctx_seqh->ccid2s_seq = seq;
3258 hctx->ccid2hctx_seqh->ccid2s_acked = 0;
3259 hctx->ccid2hctx_seqh->ccid2s_sent = jiffies;
3260- hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next;
3261
3262- ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd,
3263- hctx->ccid2hctx_pipe);
3264+ next = hctx->ccid2hctx_seqh->ccid2s_next;
3265+ /* check if we need to alloc more space */
3266+ if (next == hctx->ccid2hctx_seqt) {
3267+ int rc;
3268+
3269+ ccid2_pr_debug("allocating more space in history\n");
3270+ rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_KERNEL);
3271+ BUG_ON(rc); /* XXX what do we do? */
3272
3273- if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) {
3274- /* XXX allocate more space */
3275- WARN_ON(1);
3276+ next = hctx->ccid2hctx_seqh->ccid2s_next;
3277+ BUG_ON(next == hctx->ccid2hctx_seqt);
3278 }
3279+ hctx->ccid2hctx_seqh = next;
3280+
3281+ ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd,
3282+ hctx->ccid2hctx_pipe);
3283
3284 hctx->ccid2hctx_sent++;
3285
3286@@ -295,7 +350,7 @@
3287 if (!timer_pending(&hctx->ccid2hctx_rtotimer))
3288 ccid2_start_rto_timer(sk);
3289
3290-#ifdef CCID2_DEBUG
3291+#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
3292 ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe);
3293 ccid2_pr_debug("Sent: seq=%llu\n", seq);
3294 do {
3295@@ -398,7 +453,7 @@
3296 /* increase every 2 acks */
3297 hctx->ccid2hctx_ssacks++;
3298 if (hctx->ccid2hctx_ssacks == 2) {
3299- ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1);
3300+ ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd+1);
3301 hctx->ccid2hctx_ssacks = 0;
3302 *maxincr = *maxincr - 1;
3303 }
3304@@ -411,26 +466,28 @@
3305 hctx->ccid2hctx_acks++;
3306
3307 if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) {
3308- ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1);
3309+ ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd + 1);
3310 hctx->ccid2hctx_acks = 0;
3311 }
3312 }
3313
3314 /* update RTO */
3315 if (hctx->ccid2hctx_srtt == -1 ||
3316- (jiffies - hctx->ccid2hctx_lastrtt) >= hctx->ccid2hctx_srtt) {
3317- unsigned long r = jiffies - seqp->ccid2s_sent;
3318+ time_after(jiffies, hctx->ccid2hctx_lastrtt + hctx->ccid2hctx_srtt)) {
3319+ unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent;
3320 int s;
3321
3322 /* first measurement */
3323 if (hctx->ccid2hctx_srtt == -1) {
3324 ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
3325 r, jiffies, seqp->ccid2s_seq);
3326- hctx->ccid2hctx_srtt = r;
3327+ ccid2_change_srtt(hctx, r);
3328 hctx->ccid2hctx_rttvar = r >> 1;
3329 } else {
3330 /* RTTVAR */
3331 long tmp = hctx->ccid2hctx_srtt - r;
3332+ long srtt;
3333+
3334 if (tmp < 0)
3335 tmp *= -1;
3336
3337@@ -440,10 +497,12 @@
3338 hctx->ccid2hctx_rttvar += tmp;
3339
3340 /* SRTT */
3341- hctx->ccid2hctx_srtt *= 7;
3342- hctx->ccid2hctx_srtt >>= 3;
3343+ srtt = hctx->ccid2hctx_srtt;
3344+ srtt *= 7;
3345+ srtt >>= 3;
3346 tmp = r >> 3;
3347- hctx->ccid2hctx_srtt += tmp;
3348+ srtt += tmp;
3349+ ccid2_change_srtt(hctx, srtt);
3350 }
3351 s = hctx->ccid2hctx_rttvar << 2;
3352 /* clock granularity is 1 when based on jiffies */
3353@@ -479,13 +538,29 @@
3354 {
3355 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
3356
3357- hctx->ccid2hctx_pipe--;
3358+ ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe-1);
3359 BUG_ON(hctx->ccid2hctx_pipe < 0);
3360
3361 if (hctx->ccid2hctx_pipe == 0)
3362 ccid2_hc_tx_kill_rto_timer(sk);
3363 }
3364
3365+static void ccid2_congestion_event(struct ccid2_hc_tx_sock *hctx,
3366+ struct ccid2_seq *seqp)
3367+{
3368+ if (time_before(seqp->ccid2s_sent, hctx->ccid2hctx_last_cong)) {
3369+ ccid2_pr_debug("Multiple losses in an RTT---treating as one\n");
3370+ return;
3371+ }
3372+
3373+ hctx->ccid2hctx_last_cong = jiffies;
3374+
3375+ ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd >> 1);
3376+ hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd;
3377+ if (hctx->ccid2hctx_ssthresh < 2)
3378+ hctx->ccid2hctx_ssthresh = 2;
3379+}
3380+
3381 static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
3382 {
3383 struct dccp_sock *dp = dccp_sk(sk);
3384@@ -496,7 +571,6 @@
3385 unsigned char veclen;
3386 int offset = 0;
3387 int done = 0;
3388- int loss = 0;
3389 unsigned int maxincr = 0;
3390
3391 ccid2_hc_tx_check_sanity(hctx);
3392@@ -582,15 +656,16 @@
3393 * run length
3394 */
3395 while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {
3396- const u8 state = (*vector &
3397- DCCP_ACKVEC_STATE_MASK) >> 6;
3398+ const u8 state = *vector &
3399+ DCCP_ACKVEC_STATE_MASK;
3400
3401 /* new packet received or marked */
3402 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&
3403 !seqp->ccid2s_acked) {
3404 if (state ==
3405 DCCP_ACKVEC_STATE_ECN_MARKED) {
3406- loss = 1;
3407+ ccid2_congestion_event(hctx,
3408+ seqp);
3409 } else
3410 ccid2_new_ack(sk, seqp,
3411 &maxincr);
3412@@ -642,7 +717,13 @@
3413 /* check for lost packets */
3414 while (1) {
3415 if (!seqp->ccid2s_acked) {
3416- loss = 1;
3417+ ccid2_pr_debug("Packet lost: %llu\n",
3418+ seqp->ccid2s_seq);
3419+ /* XXX need to traverse from tail -> head in
3420+ * order to detect multiple congestion events in
3421+ * one ack vector.
3422+ */
3423+ ccid2_congestion_event(hctx, seqp);
3424 ccid2_hc_tx_dec_pipe(sk);
3425 }
3426 if (seqp == hctx->ccid2hctx_seqt)
3427@@ -661,53 +742,33 @@
3428 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next;
3429 }
3430
3431- if (loss) {
3432- /* XXX do bit shifts guarantee a 0 as the new bit? */
3433- ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd >> 1);
3434- hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd;
3435- if (hctx->ccid2hctx_ssthresh < 2)
3436- hctx->ccid2hctx_ssthresh = 2;
3437- }
3438-
3439 ccid2_hc_tx_check_sanity(hctx);
3440 }
3441
3442 static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
3443 {
3444 struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
3445- int seqcount = ccid2_seq_len;
3446- int i;
3447
3448- /* XXX init variables with proper values */
3449- hctx->ccid2hctx_cwnd = 1;
3450- hctx->ccid2hctx_ssthresh = 10;
3451+ ccid2_change_cwnd(hctx, 1);
3452+ /* Initialize ssthresh to infinity. This means that we will exit the
3453+ * initial slow-start after the first packet loss. This is what we
3454+ * want.
3455+ */
3456+ hctx->ccid2hctx_ssthresh = ~0;
3457 hctx->ccid2hctx_numdupack = 3;
3458+ hctx->ccid2hctx_seqbufc = 0;
3459
3460 /* XXX init ~ to window size... */
3461- hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) *
3462- seqcount, gfp_any());
3463- if (hctx->ccid2hctx_seqbuf == NULL)
3464+ if (ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_ATOMIC) != 0)
3465 return -ENOMEM;
3466
3467- for (i = 0; i < (seqcount - 1); i++) {
3468- hctx->ccid2hctx_seqbuf[i].ccid2s_next =
3469- &hctx->ccid2hctx_seqbuf[i + 1];
3470- hctx->ccid2hctx_seqbuf[i + 1].ccid2s_prev =
3471- &hctx->ccid2hctx_seqbuf[i];
3472- }
3473- hctx->ccid2hctx_seqbuf[seqcount - 1].ccid2s_next =
3474- hctx->ccid2hctx_seqbuf;
3475- hctx->ccid2hctx_seqbuf->ccid2s_prev =
3476- &hctx->ccid2hctx_seqbuf[seqcount - 1];
3477-
3478- hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqbuf;
3479- hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh;
3480 hctx->ccid2hctx_sent = 0;
3481 hctx->ccid2hctx_rto = 3 * HZ;
3482- hctx->ccid2hctx_srtt = -1;
3483+ ccid2_change_srtt(hctx, -1);
3484 hctx->ccid2hctx_rttvar = -1;
3485 hctx->ccid2hctx_lastrtt = 0;
3486 hctx->ccid2hctx_rpdupack = -1;
3487+ hctx->ccid2hctx_last_cong = jiffies;
3488
3489 hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire;
3490 hctx->ccid2hctx_rtotimer.data = (unsigned long)sk;
3491@@ -720,10 +781,13 @@
3492 static void ccid2_hc_tx_exit(struct sock *sk)
3493 {
3494 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
3495+ int i;
3496
3497 ccid2_hc_tx_kill_rto_timer(sk);
3498- kfree(hctx->ccid2hctx_seqbuf);
3499- hctx->ccid2hctx_seqbuf = NULL;
3500+
3501+ for (i = 0; i < hctx->ccid2hctx_seqbufc; i++)
3502+ kfree(hctx->ccid2hctx_seqbuf[i]);
3503+ hctx->ccid2hctx_seqbufc = 0;
3504 }
3505
3506 static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
3507diff -Nur linux-2.6.18-rc5/net/dccp/ccids/ccid2.h linux-2.6.19/net/dccp/ccids/ccid2.h
3508--- linux-2.6.18-rc5/net/dccp/ccids/ccid2.h 2006-08-28 05:41:48.000000000 +0200
3509+++ linux-2.6.19/net/dccp/ccids/ccid2.h 2006-09-22 10:04:58.000000000 +0200
3510@@ -35,6 +35,9 @@
3511 struct ccid2_seq *ccid2s_next;
3512 };
3513
3514+#define CCID2_SEQBUF_LEN 256
3515+#define CCID2_SEQBUF_MAX 128
3516+
3517 /** struct ccid2_hc_tx_sock - CCID2 TX half connection
3518 *
3519 * @ccid2hctx_ssacks - ACKs recv in slow start
3520@@ -50,10 +53,11 @@
3521 int ccid2hctx_cwnd;
3522 int ccid2hctx_ssacks;
3523 int ccid2hctx_acks;
3524- int ccid2hctx_ssthresh;
3525+ unsigned int ccid2hctx_ssthresh;
3526 int ccid2hctx_pipe;
3527 int ccid2hctx_numdupack;
3528- struct ccid2_seq *ccid2hctx_seqbuf;
3529+ struct ccid2_seq *ccid2hctx_seqbuf[CCID2_SEQBUF_MAX];
3530+ int ccid2hctx_seqbufc;
3531 struct ccid2_seq *ccid2hctx_seqh;
3532 struct ccid2_seq *ccid2hctx_seqt;
3533 long ccid2hctx_rto;
3534@@ -67,6 +71,7 @@
3535 u64 ccid2hctx_rpseq;
3536 int ccid2hctx_rpdupack;
3537 int ccid2hctx_sendwait;
3538+ unsigned long ccid2hctx_last_cong;
3539 };
3540
3541 struct ccid2_hc_rx_sock {
3542diff -Nur linux-2.6.18-rc5/net/dccp/ccids/ccid3.c linux-2.6.19/net/dccp/ccids/ccid3.c
3543--- linux-2.6.18-rc5/net/dccp/ccids/ccid3.c 2006-08-28 05:41:48.000000000 +0200
3544+++ linux-2.6.19/net/dccp/ccids/ccid3.c 2006-09-22 10:04:58.000000000 +0200
3545@@ -900,7 +900,7 @@
3546 static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
3547 {
3548 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
3549- struct dccp_li_hist_entry *next, *head;
3550+ struct dccp_li_hist_entry *head;
3551 u64 seq_temp;
3552
3553 if (list_empty(&hcrx->ccid3hcrx_li_hist)) {
3554@@ -908,15 +908,15 @@
3555 &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss))
3556 return;
3557
3558- next = (struct dccp_li_hist_entry *)
3559- hcrx->ccid3hcrx_li_hist.next;
3560- next->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
3561+ head = list_entry(hcrx->ccid3hcrx_li_hist.next,
3562+ struct dccp_li_hist_entry, dccplih_node);
3563+ head->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
3564 } else {
3565 struct dccp_li_hist_entry *entry;
3566 struct list_head *tail;
3567
3568- head = (struct dccp_li_hist_entry *)
3569- hcrx->ccid3hcrx_li_hist.next;
3570+ head = list_entry(hcrx->ccid3hcrx_li_hist.next,
3571+ struct dccp_li_hist_entry, dccplih_node);
3572 /* FIXME win count check removed as was wrong */
3573 /* should make this check with receive history */
3574 /* and compare there as per section 10.2 of RFC4342 */
3575diff -Nur linux-2.6.18-rc5/net/dccp/dccp.h linux-2.6.19/net/dccp/dccp.h
3576--- linux-2.6.18-rc5/net/dccp/dccp.h 2006-08-28 05:41:48.000000000 +0200
3577+++ linux-2.6.19/net/dccp/dccp.h 2006-09-22 10:04:58.000000000 +0200
3578@@ -130,7 +130,7 @@
3579 extern void dccp_send_sync(struct sock *sk, const u64 seq,
3580 const enum dccp_pkt_type pkt_type);
3581
3582-extern int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo);
3583+extern void dccp_write_xmit(struct sock *sk, int block);
3584 extern void dccp_write_space(struct sock *sk);
3585
3586 extern void dccp_init_xmit_timers(struct sock *sk);
3587diff -Nur linux-2.6.18-rc5/net/dccp/feat.h linux-2.6.19/net/dccp/feat.h
3588--- linux-2.6.18-rc5/net/dccp/feat.h 2006-08-28 05:41:48.000000000 +0200
3589+++ linux-2.6.19/net/dccp/feat.h 2006-09-22 10:04:58.000000000 +0200
3590@@ -27,5 +27,10 @@
3591 extern int dccp_feat_init(struct dccp_minisock *dmsk);
3592
3593 extern int dccp_feat_default_sequence_window;
3594+extern int dccp_feat_default_rx_ccid;
3595+extern int dccp_feat_default_tx_ccid;
3596+extern int dccp_feat_default_ack_ratio;
3597+extern int dccp_feat_default_send_ack_vector;
3598+extern int dccp_feat_default_send_ndp_count;
3599
3600 #endif /* _DCCP_FEAT_H */
3601diff -Nur linux-2.6.18-rc5/net/dccp/ipv4.c linux-2.6.19/net/dccp/ipv4.c
3602--- linux-2.6.18-rc5/net/dccp/ipv4.c 2006-08-28 05:41:48.000000000 +0200
3603+++ linux-2.6.19/net/dccp/ipv4.c 2006-09-22 10:04:58.000000000 +0200
3604@@ -501,6 +501,9 @@
3605
3606 dccp_openreq_init(req, &dp, skb);
3607
3608+ if (security_inet_conn_request(sk, skb, req))
3609+ goto drop_and_free;
3610+
3611 ireq = inet_rsk(req);
3612 ireq->loc_addr = daddr;
3613 ireq->rmt_addr = saddr;
3614@@ -605,10 +608,10 @@
3615 if (req != NULL)
3616 return dccp_check_req(sk, skb, req, prev);
3617
3618- nsk = __inet_lookup_established(&dccp_hashinfo,
3619- iph->saddr, dh->dccph_sport,
3620- iph->daddr, ntohs(dh->dccph_dport),
3621- inet_iif(skb));
3622+ nsk = inet_lookup_established(&dccp_hashinfo,
3623+ iph->saddr, dh->dccph_sport,
3624+ iph->daddr, dh->dccph_dport,
3625+ inet_iif(skb));
3626 if (nsk != NULL) {
3627 if (nsk->sk_state != DCCP_TIME_WAIT) {
3628 bh_lock_sock(nsk);
3629@@ -678,6 +681,7 @@
3630 }
3631 };
3632
3633+ security_skb_classify_flow(skb, &fl);
3634 if (ip_route_output_flow(&rt, &fl, sk, 0)) {
3635 IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
3636 return NULL;
3637@@ -921,7 +925,7 @@
3638 * Look up flow ID in table and get corresponding socket */
3639 sk = __inet_lookup(&dccp_hashinfo,
3640 skb->nh.iph->saddr, dh->dccph_sport,
3641- skb->nh.iph->daddr, ntohs(dh->dccph_dport),
3642+ skb->nh.iph->daddr, dh->dccph_dport,
3643 inet_iif(skb));
3644
3645 /*
3646diff -Nur linux-2.6.18-rc5/net/dccp/ipv6.c linux-2.6.19/net/dccp/ipv6.c
3647--- linux-2.6.18-rc5/net/dccp/ipv6.c 2006-08-28 05:41:48.000000000 +0200
3648+++ linux-2.6.19/net/dccp/ipv6.c 2006-09-22 10:04:58.000000000 +0200
3649@@ -201,6 +201,7 @@
3650 fl.oif = sk->sk_bound_dev_if;
3651 fl.fl_ip_dport = usin->sin6_port;
3652 fl.fl_ip_sport = inet->sport;
3653+ security_sk_classify_flow(sk, &fl);
3654
3655 if (np->opt != NULL && np->opt->srcrt != NULL) {
3656 const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
3657@@ -230,7 +231,7 @@
3658 ipv6_addr_copy(&np->saddr, saddr);
3659 inet->rcv_saddr = LOOPBACK4_IPV6;
3660
3661- __ip6_dst_store(sk, dst, NULL);
3662+ __ip6_dst_store(sk, dst, NULL, NULL);
3663
3664 icsk->icsk_ext_hdr_len = 0;
3665 if (np->opt != NULL)
3666@@ -322,6 +323,7 @@
3667 fl.oif = sk->sk_bound_dev_if;
3668 fl.fl_ip_dport = inet->dport;
3669 fl.fl_ip_sport = inet->sport;
3670+ security_sk_classify_flow(sk, &fl);
3671
3672 err = ip6_dst_lookup(sk, &dst, &fl);
3673 if (err) {
3674@@ -422,6 +424,7 @@
3675 fl.oif = ireq6->iif;
3676 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
3677 fl.fl_ip_sport = inet_sk(sk)->sport;
3678+ security_req_classify_flow(req, &fl);
3679
3680 if (dst == NULL) {
3681 opt = np->opt;
3682@@ -566,6 +569,7 @@
3683 fl.oif = inet6_iif(rxskb);
3684 fl.fl_ip_dport = dh->dccph_dport;
3685 fl.fl_ip_sport = dh->dccph_sport;
3686+ security_skb_classify_flow(rxskb, &fl);
3687
3688 /* sk = NULL, but it is safe for now. RST socket required. */
3689 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
3690@@ -622,6 +626,7 @@
3691 fl.oif = inet6_iif(rxskb);
3692 fl.fl_ip_dport = dh->dccph_dport;
3693 fl.fl_ip_sport = dh->dccph_sport;
3694+ security_req_classify_flow(req, &fl);
3695
3696 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
3697 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
3698@@ -704,6 +709,9 @@
3699
3700 dccp_openreq_init(req, &dp, skb);
3701
3702+ if (security_inet_conn_request(sk, skb, req))
3703+ goto drop_and_free;
3704+
3705 ireq6 = inet6_rsk(req);
3706 ireq = inet_rsk(req);
3707 ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
3708@@ -842,6 +850,7 @@
3709 fl.oif = sk->sk_bound_dev_if;
3710 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
3711 fl.fl_ip_sport = inet_sk(sk)->sport;
3712+ security_sk_classify_flow(sk, &fl);
3713
3714 if (ip6_dst_lookup(sk, &dst, &fl))
3715 goto out;
3716@@ -863,7 +872,7 @@
3717 * comment in that function for the gory details. -acme
3718 */
3719
3720- __ip6_dst_store(newsk, dst, NULL);
3721+ __ip6_dst_store(newsk, dst, NULL, NULL);
3722 newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM |
3723 NETIF_F_TSO);
3724 newdp6 = (struct dccp6_sock *)newsk;
3725@@ -961,7 +970,7 @@
3726 if (skb->protocol == htons(ETH_P_IP))
3727 return dccp_v4_do_rcv(sk, skb);
3728
3729- if (sk_filter(sk, skb, 0))
3730+ if (sk_filter(sk, skb))
3731 goto discard;
3732
3733 /*
3734diff -Nur linux-2.6.18-rc5/net/dccp/output.c linux-2.6.19/net/dccp/output.c
3735--- linux-2.6.18-rc5/net/dccp/output.c 2006-08-28 05:41:48.000000000 +0200
3736+++ linux-2.6.19/net/dccp/output.c 2006-09-22 10:04:58.000000000 +0200
3737@@ -198,7 +198,7 @@
3738 while (1) {
3739 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
3740
3741- if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
3742+ if (sk->sk_err)
3743 goto do_error;
3744 if (!*timeo)
3745 goto do_nonblock;
3746@@ -234,37 +234,72 @@
3747 goto out;
3748 }
3749
3750-int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo)
3751+static void dccp_write_xmit_timer(unsigned long data) {
3752+ struct sock *sk = (struct sock *)data;
3753+ struct dccp_sock *dp = dccp_sk(sk);
3754+
3755+ bh_lock_sock(sk);
3756+ if (sock_owned_by_user(sk))
3757+ sk_reset_timer(sk, &dp->dccps_xmit_timer, jiffies+1);
3758+ else
3759+ dccp_write_xmit(sk, 0);
3760+ bh_unlock_sock(sk);
3761+ sock_put(sk);
3762+}
3763+
3764+void dccp_write_xmit(struct sock *sk, int block)
3765 {
3766- const struct dccp_sock *dp = dccp_sk(sk);
3767- int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb,
3768- skb->len);
3769+ struct dccp_sock *dp = dccp_sk(sk);
3770+ struct sk_buff *skb;
3771+ long timeo = 30000; /* If a packet is taking longer than 2 secs
3772+ we have other issues */
3773
3774- if (err > 0)
3775- err = dccp_wait_for_ccid(sk, skb, timeo);
3776+ while ((skb = skb_peek(&sk->sk_write_queue))) {
3777+ int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb,
3778+ skb->len);
3779
3780- if (err == 0) {
3781- struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
3782- const int len = skb->len;
3783+ if (err > 0) {
3784+ if (!block) {
3785+ sk_reset_timer(sk, &dp->dccps_xmit_timer,
3786+ msecs_to_jiffies(err)+jiffies);
3787+ break;
3788+ } else
3789+ err = dccp_wait_for_ccid(sk, skb, &timeo);
3790+ if (err) {
3791+ printk(KERN_CRIT "%s:err at dccp_wait_for_ccid"
3792+ " %d\n", __FUNCTION__, err);
3793+ dump_stack();
3794+ }
3795+ }
3796
3797- if (sk->sk_state == DCCP_PARTOPEN) {
3798- /* See 8.1.5. Handshake Completion */
3799- inet_csk_schedule_ack(sk);
3800- inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
3801+ skb_dequeue(&sk->sk_write_queue);
3802+ if (err == 0) {
3803+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
3804+ const int len = skb->len;
3805+
3806+ if (sk->sk_state == DCCP_PARTOPEN) {
3807+ /* See 8.1.5. Handshake Completion */
3808+ inet_csk_schedule_ack(sk);
3809+ inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
3810 inet_csk(sk)->icsk_rto,
3811 DCCP_RTO_MAX);
3812- dcb->dccpd_type = DCCP_PKT_DATAACK;
3813- } else if (dccp_ack_pending(sk))
3814- dcb->dccpd_type = DCCP_PKT_DATAACK;
3815- else
3816- dcb->dccpd_type = DCCP_PKT_DATA;
3817-
3818- err = dccp_transmit_skb(sk, skb);
3819- ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);
3820- } else
3821- kfree_skb(skb);
3822-
3823- return err;
3824+ dcb->dccpd_type = DCCP_PKT_DATAACK;
3825+ } else if (dccp_ack_pending(sk))
3826+ dcb->dccpd_type = DCCP_PKT_DATAACK;
3827+ else
3828+ dcb->dccpd_type = DCCP_PKT_DATA;
3829+
3830+ err = dccp_transmit_skb(sk, skb);
3831+ ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);
3832+ if (err) {
3833+ printk(KERN_CRIT "%s:err from "
3834+ "ccid_hc_tx_packet_sent %d\n",
3835+ __FUNCTION__, err);
3836+ dump_stack();
3837+ }
3838+ } else
3839+ kfree(skb);
3840+ }
3841 }
3842
3843 int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
3844@@ -426,6 +461,9 @@
3845 dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
3846
3847 icsk->icsk_retransmits = 0;
3848+ init_timer(&dp->dccps_xmit_timer);
3849+ dp->dccps_xmit_timer.data = (unsigned long)sk;
3850+ dp->dccps_xmit_timer.function = dccp_write_xmit_timer;
3851 }
3852
3853 int dccp_connect(struct sock *sk)
3854@@ -560,8 +598,10 @@
3855 DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ;
3856
3857 if (active) {
3858+ dccp_write_xmit(sk, 1);
3859 dccp_skb_entail(sk, skb);
3860 dccp_transmit_skb(sk, skb_clone(skb, prio));
3861+ /* FIXME do we need a retransmit timer here? */
3862 } else
3863 dccp_transmit_skb(sk, skb);
3864 }
3865diff -Nur linux-2.6.18-rc5/net/dccp/proto.c linux-2.6.19/net/dccp/proto.c
3866--- linux-2.6.18-rc5/net/dccp/proto.c 2006-08-28 05:41:48.000000000 +0200
3867+++ linux-2.6.19/net/dccp/proto.c 2006-09-22 10:04:58.000000000 +0200
3868@@ -662,17 +662,8 @@
3869 if (rc != 0)
3870 goto out_discard;
3871
3872- rc = dccp_write_xmit(sk, skb, &timeo);
3873- /*
3874- * XXX we don't use sk_write_queue, so just discard the packet.
3875- * Current plan however is to _use_ sk_write_queue with
3876- * an algorith similar to tcp_sendmsg, where the main difference
3877- * is that in DCCP we have to respect packet boundaries, so
3878- * no coalescing of skbs.
3879- *
3880- * This bug was _quickly_ found & fixed by just looking at an OSTRA
3881- * generated callgraph 8) -acme
3882- */
3883+ skb_queue_tail(&sk->sk_write_queue, skb);
3884+ dccp_write_xmit(sk,0);
3885 out_release:
3886 release_sock(sk);
3887 return rc ? : len;
3888@@ -846,6 +837,7 @@
3889
3890 void dccp_close(struct sock *sk, long timeout)
3891 {
3892+ struct dccp_sock *dp = dccp_sk(sk);
3893 struct sk_buff *skb;
3894 int state;
3895
3896@@ -862,6 +854,8 @@
3897 goto adjudge_to_death;
3898 }
3899
3900+ sk_stop_timer(sk, &dp->dccps_xmit_timer);
3901+
3902 /*
3903 * We need to flush the recv. buffs. We do this only on the
3904 * descriptor close, not protocol-sourced closes, because the
3905diff -Nur linux-2.6.18-rc5/net/dccp/sysctl.c linux-2.6.19/net/dccp/sysctl.c
3906--- linux-2.6.18-rc5/net/dccp/sysctl.c 2006-08-28 05:41:48.000000000 +0200
3907+++ linux-2.6.19/net/dccp/sysctl.c 2006-09-22 10:04:58.000000000 +0200
3908@@ -11,18 +11,12 @@
3909
3910 #include <linux/mm.h>
3911 #include <linux/sysctl.h>
3912+#include "feat.h"
3913
3914 #ifndef CONFIG_SYSCTL
3915 #error This file should not be compiled without CONFIG_SYSCTL defined
3916 #endif
3917
3918-extern int dccp_feat_default_sequence_window;
3919-extern int dccp_feat_default_rx_ccid;
3920-extern int dccp_feat_default_tx_ccid;
3921-extern int dccp_feat_default_ack_ratio;
3922-extern int dccp_feat_default_send_ack_vector;
3923-extern int dccp_feat_default_send_ndp_count;
3924-
3925 static struct ctl_table dccp_default_table[] = {
3926 {
3927 .ctl_name = NET_DCCP_DEFAULT_SEQ_WINDOW,
3928diff -Nur linux-2.6.18-rc5/net/decnet/Kconfig linux-2.6.19/net/decnet/Kconfig
3929--- linux-2.6.18-rc5/net/decnet/Kconfig 2006-08-28 05:41:48.000000000 +0200
3930+++ linux-2.6.19/net/decnet/Kconfig 2006-09-22 10:04:58.000000000 +0200
3931@@ -27,6 +27,7 @@
3932 config DECNET_ROUTER
3933 bool "DECnet: router support (EXPERIMENTAL)"
3934 depends on DECNET && EXPERIMENTAL
3935+ select FIB_RULES
3936 ---help---
3937 Add support for turning your DECnet Endnode into a level 1 or 2
3938 router. This is an experimental, but functional option. If you
3939diff -Nur linux-2.6.18-rc5/net/decnet/af_decnet.c linux-2.6.19/net/decnet/af_decnet.c
3940--- linux-2.6.18-rc5/net/decnet/af_decnet.c 2006-08-28 05:41:48.000000000 +0200
3941+++ linux-2.6.19/net/decnet/af_decnet.c 2006-09-22 10:04:58.000000000 +0200
3942@@ -130,6 +130,7 @@
3943 #include <linux/poll.h>
3944 #include <net/neighbour.h>
3945 #include <net/dst.h>
3946+#include <net/fib_rules.h>
3947 #include <net/dn.h>
3948 #include <net/dn_nsp.h>
3949 #include <net/dn_dev.h>
3950diff -Nur linux-2.6.18-rc5/net/decnet/dn_dev.c linux-2.6.19/net/decnet/dn_dev.c
3951--- linux-2.6.18-rc5/net/decnet/dn_dev.c 2006-08-28 05:41:48.000000000 +0200
3952+++ linux-2.6.19/net/decnet/dn_dev.c 2006-09-22 10:04:58.000000000 +0200
3953@@ -34,6 +34,7 @@
3954 #include <linux/seq_file.h>
3955 #include <linux/timer.h>
3956 #include <linux/string.h>
3957+#include <linux/if_addr.h>
3958 #include <linux/if_arp.h>
3959 #include <linux/if_ether.h>
3960 #include <linux/skbuff.h>
3961@@ -45,6 +46,7 @@
3962 #include <net/neighbour.h>
3963 #include <net/dst.h>
3964 #include <net/flow.h>
3965+#include <net/fib_rules.h>
3966 #include <net/dn.h>
3967 #include <net/dn_dev.h>
3968 #include <net/dn_route.h>
3969@@ -744,20 +746,23 @@
3970 static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
3971 {
3972 struct sk_buff *skb;
3973- int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
3974+ int payload = sizeof(struct ifaddrmsg) + 128;
3975+ int err = -ENOBUFS;
3976
3977- skb = alloc_skb(size, GFP_KERNEL);
3978- if (!skb) {
3979- netlink_set_err(rtnl, 0, RTNLGRP_DECnet_IFADDR, ENOBUFS);
3980- return;
3981- }
3982- if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
3983+ skb = alloc_skb(nlmsg_total_size(payload), GFP_KERNEL);
3984+ if (skb == NULL)
3985+ goto errout;
3986+
3987+ err = dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0);
3988+ if (err < 0) {
3989 kfree_skb(skb);
3990- netlink_set_err(rtnl, 0, RTNLGRP_DECnet_IFADDR, EINVAL);
3991- return;
3992+ goto errout;
3993 }
3994- NETLINK_CB(skb).dst_group = RTNLGRP_DECnet_IFADDR;
3995- netlink_broadcast(rtnl, skb, 0, RTNLGRP_DECnet_IFADDR, GFP_KERNEL);
3996+
3997+ err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
3998+errout:
3999+ if (err < 0)
4000+ rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err);
4001 }
4002
4003 static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
4004@@ -1417,8 +1422,6 @@
4005 [RTM_DELROUTE - RTM_BASE] = { .doit = dn_fib_rtm_delroute, },
4006 [RTM_GETROUTE - RTM_BASE] = { .doit = dn_cache_getroute,
4007 .dumpit = dn_fib_dump, },
4008- [RTM_NEWRULE - RTM_BASE] = { .doit = dn_fib_rtm_newrule, },
4009- [RTM_DELRULE - RTM_BASE] = { .doit = dn_fib_rtm_delrule, },
4010 [RTM_GETRULE - RTM_BASE] = { .dumpit = dn_fib_dump_rules, },
4011 #else
4012 [RTM_GETROUTE - RTM_BASE] = { .doit = dn_cache_getroute,
4013diff -Nur linux-2.6.18-rc5/net/decnet/dn_fib.c linux-2.6.19/net/decnet/dn_fib.c
4014--- linux-2.6.18-rc5/net/decnet/dn_fib.c 2006-08-28 05:41:48.000000000 +0200
4015+++ linux-2.6.19/net/decnet/dn_fib.c 2006-09-22 10:04:58.000000000 +0200
4016@@ -34,6 +34,7 @@
4017 #include <net/neighbour.h>
4018 #include <net/dst.h>
4019 #include <net/flow.h>
4020+#include <net/fib_rules.h>
4021 #include <net/dn.h>
4022 #include <net/dn_route.h>
4023 #include <net/dn_fib.h>
4024@@ -54,11 +55,9 @@
4025
4026 #define endfor_nexthops(fi) }
4027
4028-extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
4029-
4030 static DEFINE_SPINLOCK(dn_fib_multipath_lock);
4031 static struct dn_fib_info *dn_fib_info_list;
4032-static DEFINE_RWLOCK(dn_fib_info_lock);
4033+static DEFINE_SPINLOCK(dn_fib_info_lock);
4034
4035 static struct
4036 {
4037@@ -79,6 +78,9 @@
4038 [RTN_XRESOLVE] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
4039 };
4040
4041+static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force);
4042+static int dn_fib_sync_up(struct net_device *dev);
4043+
4044 void dn_fib_free_info(struct dn_fib_info *fi)
4045 {
4046 if (fi->fib_dead == 0) {
4047@@ -96,7 +98,7 @@
4048
4049 void dn_fib_release_info(struct dn_fib_info *fi)
4050 {
4051- write_lock(&dn_fib_info_lock);
4052+ spin_lock(&dn_fib_info_lock);
4053 if (fi && --fi->fib_treeref == 0) {
4054 if (fi->fib_next)
4055 fi->fib_next->fib_prev = fi->fib_prev;
4056@@ -107,7 +109,7 @@
4057 fi->fib_dead = 1;
4058 dn_fib_info_put(fi);
4059 }
4060- write_unlock(&dn_fib_info_lock);
4061+ spin_unlock(&dn_fib_info_lock);
4062 }
4063
4064 static inline int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi)
4065@@ -378,13 +380,13 @@
4066
4067 fi->fib_treeref++;
4068 atomic_inc(&fi->fib_clntref);
4069- write_lock(&dn_fib_info_lock);
4070+ spin_lock(&dn_fib_info_lock);
4071 fi->fib_next = dn_fib_info_list;
4072 fi->fib_prev = NULL;
4073 if (dn_fib_info_list)
4074 dn_fib_info_list->fib_prev = fi;
4075 dn_fib_info_list = fi;
4076- write_unlock(&dn_fib_info_lock);
4077+ spin_unlock(&dn_fib_info_lock);
4078 return fi;
4079
4080 err_inval:
4081@@ -490,7 +492,8 @@
4082 if (attr) {
4083 if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)
4084 return -EINVAL;
4085- if (i != RTA_MULTIPATH && i != RTA_METRICS)
4086+ if (i != RTA_MULTIPATH && i != RTA_METRICS &&
4087+ i != RTA_TABLE)
4088 rta[i-1] = (struct rtattr *)RTA_DATA(attr);
4089 }
4090 }
4091@@ -507,7 +510,7 @@
4092 if (dn_fib_check_attr(r, rta))
4093 return -EINVAL;
4094
4095- tb = dn_fib_get_table(r->rtm_table, 0);
4096+ tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 0);
4097 if (tb)
4098 return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
4099
4100@@ -523,46 +526,13 @@
4101 if (dn_fib_check_attr(r, rta))
4102 return -EINVAL;
4103
4104- tb = dn_fib_get_table(r->rtm_table, 1);
4105+ tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 1);
4106 if (tb)
4107 return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
4108
4109 return -ENOBUFS;
4110 }
4111
4112-
4113-int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
4114-{
4115- int t;
4116- int s_t;
4117- struct dn_fib_table *tb;
4118-
4119- if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
4120- ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
4121- return dn_cache_dump(skb, cb);
4122-
4123- s_t = cb->args[0];
4124- if (s_t == 0)
4125- s_t = cb->args[0] = RT_MIN_TABLE;
4126-
4127- for(t = s_t; t <= RT_TABLE_MAX; t++) {
4128- if (t < s_t)
4129- continue;
4130- if (t > s_t)
4131- memset(&cb->args[1], 0,
4132- sizeof(cb->args) - sizeof(cb->args[0]));
4133- tb = dn_fib_get_table(t, 0);
4134- if (tb == NULL)
4135- continue;
4136- if (tb->dump(tb, skb, cb) < 0)
4137- break;
4138- }
4139-
4140- cb->args[0] = t;
4141-
4142- return skb->len;
4143-}
4144-
4145 static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa)
4146 {
4147 struct dn_fib_table *tb;
4148@@ -682,7 +652,7 @@
4149 return NOTIFY_DONE;
4150 }
4151
4152-int dn_fib_sync_down(__le16 local, struct net_device *dev, int force)
4153+static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force)
4154 {
4155 int ret = 0;
4156 int scope = RT_SCOPE_NOWHERE;
4157@@ -726,7 +696,7 @@
4158 }
4159
4160
4161-int dn_fib_sync_up(struct net_device *dev)
4162+static int dn_fib_sync_up(struct net_device *dev)
4163 {
4164 int ret = 0;
4165
4166@@ -760,22 +730,6 @@
4167 return ret;
4168 }
4169
4170-void dn_fib_flush(void)
4171-{
4172- int flushed = 0;
4173- struct dn_fib_table *tb;
4174- int id;
4175-
4176- for(id = RT_TABLE_MAX; id > 0; id--) {
4177- if ((tb = dn_fib_get_table(id, 0)) == NULL)
4178- continue;
4179- flushed += tb->flush(tb);
4180- }
4181-
4182- if (flushed)
4183- dn_rt_cache_flush(-1);
4184-}
4185-
4186 static struct notifier_block dn_fib_dnaddr_notifier = {
4187 .notifier_call = dn_fib_dnaddr_event,
4188 };
4189diff -Nur linux-2.6.18-rc5/net/decnet/dn_nsp_in.c linux-2.6.19/net/decnet/dn_nsp_in.c
4190--- linux-2.6.18-rc5/net/decnet/dn_nsp_in.c 2006-08-28 05:41:48.000000000 +0200
4191+++ linux-2.6.19/net/decnet/dn_nsp_in.c 2006-09-22 10:04:58.000000000 +0200
4192@@ -586,7 +586,7 @@
4193 goto out;
4194 }
4195
4196- err = sk_filter(sk, skb, 0);
4197+ err = sk_filter(sk, skb);
4198 if (err)
4199 goto out;
4200
4201diff -Nur linux-2.6.18-rc5/net/decnet/dn_route.c linux-2.6.19/net/decnet/dn_route.c
4202--- linux-2.6.18-rc5/net/decnet/dn_route.c 2006-08-28 05:41:48.000000000 +0200
4203+++ linux-2.6.19/net/decnet/dn_route.c 2006-09-22 10:04:58.000000000 +0200
4204@@ -80,6 +80,7 @@
4205 #include <net/neighbour.h>
4206 #include <net/dst.h>
4207 #include <net/flow.h>
4208+#include <net/fib_rules.h>
4209 #include <net/dn.h>
4210 #include <net/dn_dev.h>
4211 #include <net/dn_nsp.h>
4212@@ -1284,7 +1285,7 @@
4213 dev_hold(out_dev);
4214
4215 if (res.r)
4216- src_map = dn_fib_rules_policy(fl.fld_src, &res, &flags);
4217+ src_map = fl.fld_src; /* no NAT support for now */
4218
4219 gateway = DN_FIB_RES_GW(res);
4220 if (res.type == RTN_NAT) {
4221@@ -1485,6 +1486,7 @@
4222 r->rtm_src_len = 0;
4223 r->rtm_tos = 0;
4224 r->rtm_table = RT_TABLE_MAIN;
4225+ RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
4226 r->rtm_type = rt->rt_type;
4227 r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
4228 r->rtm_scope = RT_SCOPE_UNIVERSE;
4229@@ -1609,9 +1611,7 @@
4230 goto out_free;
4231 }
4232
4233- err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
4234-
4235- return err;
4236+ return rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
4237
4238 out_free:
4239 kfree_skb(skb);
4240@@ -1781,14 +1781,9 @@
4241 {
4242 int i, goal, order;
4243
4244- dn_dst_ops.kmem_cachep = kmem_cache_create("dn_dst_cache",
4245- sizeof(struct dn_route),
4246- 0, SLAB_HWCACHE_ALIGN,
4247- NULL, NULL);
4248-
4249- if (!dn_dst_ops.kmem_cachep)
4250- panic("DECnet: Failed to allocate dn_dst_cache\n");
4251-
4252+ dn_dst_ops.kmem_cachep =
4253+ kmem_cache_create("dn_dst_cache", sizeof(struct dn_route), 0,
4254+ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
4255 init_timer(&dn_route_timer);
4256 dn_route_timer.function = dn_dst_check_expire;
4257 dn_route_timer.expires = jiffies + decnet_dst_gc_interval * HZ;
4258diff -Nur linux-2.6.18-rc5/net/decnet/dn_rules.c linux-2.6.19/net/decnet/dn_rules.c
4259--- linux-2.6.18-rc5/net/decnet/dn_rules.c 2006-08-28 05:41:48.000000000 +0200
4260+++ linux-2.6.19/net/decnet/dn_rules.c 2006-09-22 10:04:58.000000000 +0200
4261@@ -11,259 +11,213 @@
4262 *
4263 *
4264 * Changes:
4265+ * Steve Whitehouse <steve@chygwyn.com>
4266+ * Updated for Thomas Graf's generic rules
4267 *
4268 */
4269-#include <linux/string.h>
4270 #include <linux/net.h>
4271-#include <linux/socket.h>
4272-#include <linux/sockios.h>
4273 #include <linux/init.h>
4274-#include <linux/skbuff.h>
4275 #include <linux/netlink.h>
4276 #include <linux/rtnetlink.h>
4277-#include <linux/proc_fs.h>
4278 #include <linux/netdevice.h>
4279-#include <linux/timer.h>
4280 #include <linux/spinlock.h>
4281-#include <linux/in_route.h>
4282 #include <linux/list.h>
4283 #include <linux/rcupdate.h>
4284-#include <asm/atomic.h>
4285-#include <asm/uaccess.h>
4286 #include <net/neighbour.h>
4287 #include <net/dst.h>
4288 #include <net/flow.h>
4289+#include <net/fib_rules.h>
4290 #include <net/dn.h>
4291 #include <net/dn_fib.h>
4292 #include <net/dn_neigh.h>
4293 #include <net/dn_dev.h>
4294
4295+static struct fib_rules_ops dn_fib_rules_ops;
4296+
4297 struct dn_fib_rule
4298 {
4299- struct hlist_node r_hlist;
4300- atomic_t r_clntref;
4301- u32 r_preference;
4302- unsigned char r_table;
4303- unsigned char r_action;
4304- unsigned char r_dst_len;
4305- unsigned char r_src_len;
4306- __le16 r_src;
4307- __le16 r_srcmask;
4308- __le16 r_dst;
4309- __le16 r_dstmask;
4310- __le16 r_srcmap;
4311- u8 r_flags;
4312+ struct fib_rule common;
4313+ unsigned char dst_len;
4314+ unsigned char src_len;
4315+ __le16 src;
4316+ __le16 srcmask;
4317+ __le16 dst;
4318+ __le16 dstmask;
4319+ __le16 srcmap;
4320+ u8 flags;
4321 #ifdef CONFIG_DECNET_ROUTE_FWMARK
4322- u32 r_fwmark;
4323+ u32 fwmark;
4324+ u32 fwmask;
4325 #endif
4326- int r_ifindex;
4327- char r_ifname[IFNAMSIZ];
4328- int r_dead;
4329- struct rcu_head rcu;
4330 };
4331
4332 static struct dn_fib_rule default_rule = {
4333- .r_clntref = ATOMIC_INIT(2),
4334- .r_preference = 0x7fff,
4335- .r_table = RT_TABLE_MAIN,
4336- .r_action = RTN_UNICAST
4337+ .common = {
4338+ .refcnt = ATOMIC_INIT(2),
4339+ .pref = 0x7fff,
4340+ .table = RT_TABLE_MAIN,
4341+ .action = FR_ACT_TO_TBL,
4342+ },
4343 };
4344
4345-static struct hlist_head dn_fib_rules;
4346+static LIST_HEAD(dn_fib_rules);
4347+
4348
4349-int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
4350+int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res)
4351 {
4352- struct rtattr **rta = arg;
4353- struct rtmsg *rtm = NLMSG_DATA(nlh);
4354- struct dn_fib_rule *r;
4355- struct hlist_node *node;
4356- int err = -ESRCH;
4357-
4358- hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
4359- if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 2) == 0) &&
4360- rtm->rtm_src_len == r->r_src_len &&
4361- rtm->rtm_dst_len == r->r_dst_len &&
4362- (!rta[RTA_DST-1] || memcmp(RTA_DATA(rta[RTA_DST-1]), &r->r_dst, 2) == 0) &&
4363-#ifdef CONFIG_DECNET_ROUTE_FWMARK
4364- (!rta[RTA_PROTOINFO-1] || memcmp(RTA_DATA(rta[RTA_PROTOINFO-1]), &r->r_fwmark, 4) == 0) &&
4365-#endif
4366- (!rtm->rtm_type || rtm->rtm_type == r->r_action) &&
4367- (!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) &&
4368- (!rta[RTA_IIF-1] || rtattr_strcmp(rta[RTA_IIF-1], r->r_ifname) == 0) &&
4369- (!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) {
4370-
4371- err = -EPERM;
4372- if (r == &default_rule)
4373- break;
4374-
4375- hlist_del_rcu(&r->r_hlist);
4376- r->r_dead = 1;
4377- dn_fib_rule_put(r);
4378- err = 0;
4379- break;
4380- }
4381- }
4382+ struct fib_lookup_arg arg = {
4383+ .result = res,
4384+ };
4385+ int err;
4386+
4387+ err = fib_rules_lookup(&dn_fib_rules_ops, flp, 0, &arg);
4388+ res->r = arg.rule;
4389
4390 return err;
4391 }
4392
4393-static inline void dn_fib_rule_put_rcu(struct rcu_head *head)
4394+static int dn_fib_rule_action(struct fib_rule *rule, struct flowi *flp,
4395+ int flags, struct fib_lookup_arg *arg)
4396 {
4397- struct dn_fib_rule *r = container_of(head, struct dn_fib_rule, rcu);
4398- kfree(r);
4399-}
4400+ int err = -EAGAIN;
4401+ struct dn_fib_table *tbl;
4402
4403-void dn_fib_rule_put(struct dn_fib_rule *r)
4404-{
4405- if (atomic_dec_and_test(&r->r_clntref)) {
4406- if (r->r_dead)
4407- call_rcu(&r->rcu, dn_fib_rule_put_rcu);
4408- else
4409- printk(KERN_DEBUG "Attempt to free alive dn_fib_rule\n");
4410- }
4411+ switch(rule->action) {
4412+ case FR_ACT_TO_TBL:
4413+ break;
4414+
4415+ case FR_ACT_UNREACHABLE:
4416+ err = -ENETUNREACH;
4417+ goto errout;
4418+
4419+ case FR_ACT_PROHIBIT:
4420+ err = -EACCES;
4421+ goto errout;
4422+
4423+ case FR_ACT_BLACKHOLE:
4424+ default:
4425+ err = -EINVAL;
4426+ goto errout;
4427+ }
4428+
4429+ tbl = dn_fib_get_table(rule->table, 0);
4430+ if (tbl == NULL)
4431+ goto errout;
4432+
4433+ err = tbl->lookup(tbl, flp, (struct dn_fib_res *)arg->result);
4434+ if (err > 0)
4435+ err = -EAGAIN;
4436+errout:
4437+ return err;
4438 }
4439
4440+static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
4441+ [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
4442+ [FRA_PRIORITY] = { .type = NLA_U32 },
4443+ [FRA_SRC] = { .type = NLA_U16 },
4444+ [FRA_DST] = { .type = NLA_U16 },
4445+ [FRA_FWMARK] = { .type = NLA_U32 },
4446+ [FRA_FWMASK] = { .type = NLA_U32 },
4447+ [FRA_TABLE] = { .type = NLA_U32 },
4448+};
4449
4450-int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
4451+static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
4452 {
4453- struct rtattr **rta = arg;
4454- struct rtmsg *rtm = NLMSG_DATA(nlh);
4455- struct dn_fib_rule *r, *new_r, *last = NULL;
4456- struct hlist_node *node = NULL;
4457- unsigned char table_id;
4458-
4459- if (rtm->rtm_src_len > 16 || rtm->rtm_dst_len > 16)
4460- return -EINVAL;
4461-
4462- if (rta[RTA_IIF-1] && RTA_PAYLOAD(rta[RTA_IIF-1]) > IFNAMSIZ)
4463- return -EINVAL;
4464-
4465- if (rtm->rtm_type == RTN_NAT)
4466- return -EINVAL;
4467-
4468- table_id = rtm->rtm_table;
4469- if (table_id == RT_TABLE_UNSPEC) {
4470- struct dn_fib_table *tb;
4471- if (rtm->rtm_type == RTN_UNICAST) {
4472- if ((tb = dn_fib_empty_table()) == NULL)
4473- return -ENOBUFS;
4474- table_id = tb->n;
4475- }
4476- }
4477+ struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
4478+ u16 daddr = fl->fld_dst;
4479+ u16 saddr = fl->fld_src;
4480+
4481+ if (((saddr ^ r->src) & r->srcmask) ||
4482+ ((daddr ^ r->dst) & r->dstmask))
4483+ return 0;
4484
4485- new_r = kzalloc(sizeof(*new_r), GFP_KERNEL);
4486- if (!new_r)
4487- return -ENOMEM;
4488-
4489- if (rta[RTA_SRC-1])
4490- memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 2);
4491- if (rta[RTA_DST-1])
4492- memcpy(&new_r->r_dst, RTA_DATA(rta[RTA_DST-1]), 2);
4493- if (rta[RTA_GATEWAY-1])
4494- memcpy(&new_r->r_srcmap, RTA_DATA(rta[RTA_GATEWAY-1]), 2);
4495- new_r->r_src_len = rtm->rtm_src_len;
4496- new_r->r_dst_len = rtm->rtm_dst_len;
4497- new_r->r_srcmask = dnet_make_mask(rtm->rtm_src_len);
4498- new_r->r_dstmask = dnet_make_mask(rtm->rtm_dst_len);
4499 #ifdef CONFIG_DECNET_ROUTE_FWMARK
4500- if (rta[RTA_PROTOINFO-1])
4501- memcpy(&new_r->r_fwmark, RTA_DATA(rta[RTA_PROTOINFO-1]), 4);
4502+ if ((r->fwmark ^ fl->fld_fwmark) & r->fwmask)
4503+ return 0;
4504 #endif
4505- new_r->r_action = rtm->rtm_type;
4506- new_r->r_flags = rtm->rtm_flags;
4507- if (rta[RTA_PRIORITY-1])
4508- memcpy(&new_r->r_preference, RTA_DATA(rta[RTA_PRIORITY-1]), 4);
4509- new_r->r_table = table_id;
4510- if (rta[RTA_IIF-1]) {
4511- struct net_device *dev;
4512- rtattr_strlcpy(new_r->r_ifname, rta[RTA_IIF-1], IFNAMSIZ);
4513- new_r->r_ifindex = -1;
4514- dev = dev_get_by_name(new_r->r_ifname);
4515- if (dev) {
4516- new_r->r_ifindex = dev->ifindex;
4517- dev_put(dev);
4518- }
4519- }
4520
4521- r = container_of(dn_fib_rules.first, struct dn_fib_rule, r_hlist);
4522- if (!new_r->r_preference) {
4523- if (r && r->r_hlist.next != NULL) {
4524- r = container_of(r->r_hlist.next, struct dn_fib_rule, r_hlist);
4525- if (r->r_preference)
4526- new_r->r_preference = r->r_preference - 1;
4527+ return 1;
4528+}
4529+
4530+static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
4531+ struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
4532+ struct nlattr **tb)
4533+{
4534+ int err = -EINVAL;
4535+ struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
4536+
4537+ if (frh->src_len > 16 || frh->dst_len > 16 || frh->tos)
4538+ goto errout;
4539+
4540+ if (rule->table == RT_TABLE_UNSPEC) {
4541+ if (rule->action == FR_ACT_TO_TBL) {
4542+ struct dn_fib_table *table;
4543+
4544+ table = dn_fib_empty_table();
4545+ if (table == NULL) {
4546+ err = -ENOBUFS;
4547+ goto errout;
4548+ }
4549+
4550+ rule->table = table->n;
4551 }
4552 }
4553
4554- hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
4555- if (r->r_preference > new_r->r_preference)
4556- break;
4557- last = r;
4558+ if (tb[FRA_SRC])
4559+ r->src = nla_get_u16(tb[FRA_SRC]);
4560+
4561+ if (tb[FRA_DST])
4562+ r->dst = nla_get_u16(tb[FRA_DST]);
4563+
4564+#ifdef CONFIG_DECNET_ROUTE_FWMARK
4565+ if (tb[FRA_FWMARK]) {
4566+ r->fwmark = nla_get_u32(tb[FRA_FWMARK]);
4567+ if (r->fwmark)
4568+ /* compatibility: if the mark value is non-zero all bits
4569+ * are compared unless a mask is explicitly specified.
4570+ */
4571+ r->fwmask = 0xFFFFFFFF;
4572 }
4573- atomic_inc(&new_r->r_clntref);
4574
4575- if (last)
4576- hlist_add_after_rcu(&last->r_hlist, &new_r->r_hlist);
4577- else
4578- hlist_add_before_rcu(&new_r->r_hlist, &r->r_hlist);
4579- return 0;
4580-}
4581+ if (tb[FRA_FWMASK])
4582+ r->fwmask = nla_get_u32(tb[FRA_FWMASK]);
4583+#endif
4584
4585+ r->src_len = frh->src_len;
4586+ r->srcmask = dnet_make_mask(r->src_len);
4587+ r->dst_len = frh->dst_len;
4588+ r->dstmask = dnet_make_mask(r->dst_len);
4589+ err = 0;
4590+errout:
4591+ return err;
4592+}
4593
4594-int dn_fib_lookup(const struct flowi *flp, struct dn_fib_res *res)
4595+static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
4596+ struct nlattr **tb)
4597 {
4598- struct dn_fib_rule *r, *policy;
4599- struct dn_fib_table *tb;
4600- __le16 saddr = flp->fld_src;
4601- __le16 daddr = flp->fld_dst;
4602- struct hlist_node *node;
4603- int err;
4604+ struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
4605+
4606+ if (frh->src_len && (r->src_len != frh->src_len))
4607+ return 0;
4608
4609- rcu_read_lock();
4610+ if (frh->dst_len && (r->dst_len != frh->dst_len))
4611+ return 0;
4612
4613- hlist_for_each_entry_rcu(r, node, &dn_fib_rules, r_hlist) {
4614- if (((saddr^r->r_src) & r->r_srcmask) ||
4615- ((daddr^r->r_dst) & r->r_dstmask) ||
4616 #ifdef CONFIG_DECNET_ROUTE_FWMARK
4617- (r->r_fwmark && r->r_fwmark != flp->fld_fwmark) ||
4618+ if (tb[FRA_FWMARK] && (r->fwmark != nla_get_u32(tb[FRA_FWMARK])))
4619+ return 0;
4620+
4621+ if (tb[FRA_FWMASK] && (r->fwmask != nla_get_u32(tb[FRA_FWMASK])))
4622+ return 0;
4623 #endif
4624- (r->r_ifindex && r->r_ifindex != flp->iif))
4625- continue;
4626
4627- switch(r->r_action) {
4628- case RTN_UNICAST:
4629- case RTN_NAT:
4630- policy = r;
4631- break;
4632- case RTN_UNREACHABLE:
4633- rcu_read_unlock();
4634- return -ENETUNREACH;
4635- default:
4636- case RTN_BLACKHOLE:
4637- rcu_read_unlock();
4638- return -EINVAL;
4639- case RTN_PROHIBIT:
4640- rcu_read_unlock();
4641- return -EACCES;
4642- }
4643+ if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC])))
4644+ return 0;
4645
4646- if ((tb = dn_fib_get_table(r->r_table, 0)) == NULL)
4647- continue;
4648- err = tb->lookup(tb, flp, res);
4649- if (err == 0) {
4650- res->r = policy;
4651- if (policy)
4652- atomic_inc(&policy->r_clntref);
4653- rcu_read_unlock();
4654- return 0;
4655- }
4656- if (err < 0 && err != -EAGAIN) {
4657- rcu_read_unlock();
4658- return err;
4659- }
4660- }
4661+ if (tb[FRA_DST] && (r->dst != nla_get_u16(tb[FRA_DST])))
4662+ return 0;
4663
4664- rcu_read_unlock();
4665- return -ESRCH;
4666+ return 1;
4667 }
4668
4669 unsigned dnet_addr_type(__le16 addr)
4670@@ -271,7 +225,7 @@
4671 struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } };
4672 struct dn_fib_res res;
4673 unsigned ret = RTN_UNICAST;
4674- struct dn_fib_table *tb = dn_fib_tables[RT_TABLE_LOCAL];
4675+ struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0);
4676
4677 res.r = NULL;
4678
4679@@ -284,142 +238,79 @@
4680 return ret;
4681 }
4682
4683-__le16 dn_fib_rules_policy(__le16 saddr, struct dn_fib_res *res, unsigned *flags)
4684+static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
4685+ struct nlmsghdr *nlh, struct fib_rule_hdr *frh)
4686 {
4687- struct dn_fib_rule *r = res->r;
4688+ struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
4689
4690- if (r->r_action == RTN_NAT) {
4691- int addrtype = dnet_addr_type(r->r_srcmap);
4692-
4693- if (addrtype == RTN_NAT) {
4694- saddr = (saddr&~r->r_srcmask)|r->r_srcmap;
4695- *flags |= RTCF_SNAT;
4696- } else if (addrtype == RTN_LOCAL || r->r_srcmap == 0) {
4697- saddr = r->r_srcmap;
4698- *flags |= RTCF_MASQ;
4699- }
4700- }
4701- return saddr;
4702-}
4703+ frh->family = AF_DECnet;
4704+ frh->dst_len = r->dst_len;
4705+ frh->src_len = r->src_len;
4706+ frh->tos = 0;
4707
4708-static void dn_fib_rules_detach(struct net_device *dev)
4709-{
4710- struct hlist_node *node;
4711- struct dn_fib_rule *r;
4712-
4713- hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
4714- if (r->r_ifindex == dev->ifindex)
4715- r->r_ifindex = -1;
4716- }
4717-}
4718+#ifdef CONFIG_DECNET_ROUTE_FWMARK
4719+ if (r->fwmark)
4720+ NLA_PUT_U32(skb, FRA_FWMARK, r->fwmark);
4721+ if (r->fwmask || r->fwmark)
4722+ NLA_PUT_U32(skb, FRA_FWMASK, r->fwmask);
4723+#endif
4724+ if (r->dst_len)
4725+ NLA_PUT_U16(skb, FRA_DST, r->dst);
4726+ if (r->src_len)
4727+ NLA_PUT_U16(skb, FRA_SRC, r->src);
4728
4729-static void dn_fib_rules_attach(struct net_device *dev)
4730-{
4731- struct hlist_node *node;
4732- struct dn_fib_rule *r;
4733+ return 0;
4734
4735- hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
4736- if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0)
4737- r->r_ifindex = dev->ifindex;
4738- }
4739+nla_put_failure:
4740+ return -ENOBUFS;
4741 }
4742
4743-static int dn_fib_rules_event(struct notifier_block *this, unsigned long event, void *ptr)
4744+static u32 dn_fib_rule_default_pref(void)
4745 {
4746- struct net_device *dev = ptr;
4747+ struct list_head *pos;
4748+ struct fib_rule *rule;
4749
4750- switch(event) {
4751- case NETDEV_UNREGISTER:
4752- dn_fib_rules_detach(dev);
4753- dn_fib_sync_down(0, dev, 1);
4754- case NETDEV_REGISTER:
4755- dn_fib_rules_attach(dev);
4756- dn_fib_sync_up(dev);
4757+ if (!list_empty(&dn_fib_rules)) {
4758+ pos = dn_fib_rules.next;
4759+ if (pos->next != &dn_fib_rules) {
4760+ rule = list_entry(pos->next, struct fib_rule, list);
4761+ if (rule->pref)
4762+ return rule->pref - 1;
4763+ }
4764 }
4765
4766- return NOTIFY_DONE;
4767-}
4768-
4769-
4770-static struct notifier_block dn_fib_rules_notifier = {
4771- .notifier_call = dn_fib_rules_event,
4772-};
4773-
4774-static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r,
4775- struct netlink_callback *cb, unsigned int flags)
4776-{
4777- struct rtmsg *rtm;
4778- struct nlmsghdr *nlh;
4779- unsigned char *b = skb->tail;
4780-
4781-
4782- nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
4783- rtm = NLMSG_DATA(nlh);
4784- rtm->rtm_family = AF_DECnet;
4785- rtm->rtm_dst_len = r->r_dst_len;
4786- rtm->rtm_src_len = r->r_src_len;
4787- rtm->rtm_tos = 0;
4788-#ifdef CONFIG_DECNET_ROUTE_FWMARK
4789- if (r->r_fwmark)
4790- RTA_PUT(skb, RTA_PROTOINFO, 4, &r->r_fwmark);
4791-#endif
4792- rtm->rtm_table = r->r_table;
4793- rtm->rtm_protocol = 0;
4794- rtm->rtm_scope = 0;
4795- rtm->rtm_type = r->r_action;
4796- rtm->rtm_flags = r->r_flags;
4797-
4798- if (r->r_dst_len)
4799- RTA_PUT(skb, RTA_DST, 2, &r->r_dst);
4800- if (r->r_src_len)
4801- RTA_PUT(skb, RTA_SRC, 2, &r->r_src);
4802- if (r->r_ifname[0])
4803- RTA_PUT(skb, RTA_IIF, IFNAMSIZ, &r->r_ifname);
4804- if (r->r_preference)
4805- RTA_PUT(skb, RTA_PRIORITY, 4, &r->r_preference);
4806- if (r->r_srcmap)
4807- RTA_PUT(skb, RTA_GATEWAY, 2, &r->r_srcmap);
4808- nlh->nlmsg_len = skb->tail - b;
4809- return skb->len;
4810-
4811-nlmsg_failure:
4812-rtattr_failure:
4813- skb_trim(skb, b - skb->data);
4814- return -1;
4815+ return 0;
4816 }
4817
4818 int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
4819 {
4820- int idx = 0;
4821- int s_idx = cb->args[0];
4822- struct dn_fib_rule *r;
4823- struct hlist_node *node;
4824-
4825- rcu_read_lock();
4826- hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
4827- if (idx < s_idx)
4828- goto next;
4829- if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
4830- break;
4831-next:
4832- idx++;
4833- }
4834- rcu_read_unlock();
4835- cb->args[0] = idx;
4836-
4837- return skb->len;
4838+ return fib_rules_dump(skb, cb, AF_DECnet);
4839 }
4840
4841+static struct fib_rules_ops dn_fib_rules_ops = {
4842+ .family = AF_DECnet,
4843+ .rule_size = sizeof(struct dn_fib_rule),
4844+ .action = dn_fib_rule_action,
4845+ .match = dn_fib_rule_match,
4846+ .configure = dn_fib_rule_configure,
4847+ .compare = dn_fib_rule_compare,
4848+ .fill = dn_fib_rule_fill,
4849+ .default_pref = dn_fib_rule_default_pref,
4850+ .nlgroup = RTNLGRP_DECnet_RULE,
4851+ .policy = dn_fib_rule_policy,
4852+ .rules_list = &dn_fib_rules,
4853+ .owner = THIS_MODULE,
4854+};
4855+
4856 void __init dn_fib_rules_init(void)
4857 {
4858- INIT_HLIST_HEAD(&dn_fib_rules);
4859- hlist_add_head(&default_rule.r_hlist, &dn_fib_rules);
4860- register_netdevice_notifier(&dn_fib_rules_notifier);
4861+ list_add_tail(&default_rule.common.list, &dn_fib_rules);
4862+ fib_rules_register(&dn_fib_rules_ops);
4863 }
4864
4865 void __exit dn_fib_rules_cleanup(void)
4866 {
4867- unregister_netdevice_notifier(&dn_fib_rules_notifier);
4868+ fib_rules_unregister(&dn_fib_rules_ops);
4869 }
4870
4871
4872diff -Nur linux-2.6.18-rc5/net/decnet/dn_table.c linux-2.6.19/net/decnet/dn_table.c
4873--- linux-2.6.18-rc5/net/decnet/dn_table.c 2006-08-28 05:41:48.000000000 +0200
4874+++ linux-2.6.19/net/decnet/dn_table.c 2006-09-22 10:04:58.000000000 +0200
4875@@ -30,6 +30,7 @@
4876 #include <net/neighbour.h>
4877 #include <net/dst.h>
4878 #include <net/flow.h>
4879+#include <net/fib_rules.h>
4880 #include <net/dn.h>
4881 #include <net/dn_route.h>
4882 #include <net/dn_fib.h>
4883@@ -74,9 +75,9 @@
4884 for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
4885
4886 #define RT_TABLE_MIN 1
4887-
4888+#define DN_FIB_TABLE_HASHSZ 256
4889+static struct hlist_head dn_fib_table_hash[DN_FIB_TABLE_HASHSZ];
4890 static DEFINE_RWLOCK(dn_fib_tables_lock);
4891-struct dn_fib_table *dn_fib_tables[RT_TABLE_MAX + 1];
4892
4893 static kmem_cache_t *dn_hash_kmem __read_mostly;
4894 static int dn_fib_hash_zombies;
4895@@ -263,7 +264,7 @@
4896 }
4897
4898 static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
4899- u8 tb_id, u8 type, u8 scope, void *dst, int dst_len,
4900+ u32 tb_id, u8 type, u8 scope, void *dst, int dst_len,
4901 struct dn_fib_info *fi, unsigned int flags)
4902 {
4903 struct rtmsg *rtm;
4904@@ -277,6 +278,7 @@
4905 rtm->rtm_src_len = 0;
4906 rtm->rtm_tos = 0;
4907 rtm->rtm_table = tb_id;
4908+ RTA_PUT_U32(skb, RTA_TABLE, tb_id);
4909 rtm->rtm_flags = fi->fib_flags;
4910 rtm->rtm_scope = scope;
4911 rtm->rtm_type = type;
4912@@ -326,29 +328,29 @@
4913 }
4914
4915
4916-static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, int tb_id,
4917+static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
4918 struct nlmsghdr *nlh, struct netlink_skb_parms *req)
4919 {
4920 struct sk_buff *skb;
4921 u32 pid = req ? req->pid : 0;
4922- int size = NLMSG_SPACE(sizeof(struct rtmsg) + 256);
4923+ int err = -ENOBUFS;
4924
4925- skb = alloc_skb(size, GFP_KERNEL);
4926- if (!skb)
4927- return;
4928-
4929- if (dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
4930- f->fn_type, f->fn_scope, &f->fn_key, z,
4931- DN_FIB_INFO(f), 0) < 0) {
4932+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
4933+ if (skb == NULL)
4934+ goto errout;
4935+
4936+ err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
4937+ f->fn_type, f->fn_scope, &f->fn_key, z,
4938+ DN_FIB_INFO(f), 0);
4939+ if (err < 0) {
4940 kfree_skb(skb);
4941- return;
4942+ goto errout;
4943 }
4944- NETLINK_CB(skb).dst_group = RTNLGRP_DECnet_ROUTE;
4945- if (nlh->nlmsg_flags & NLM_F_ECHO)
4946- atomic_inc(&skb->users);
4947- netlink_broadcast(rtnl, skb, pid, RTNLGRP_DECnet_ROUTE, GFP_KERNEL);
4948- if (nlh->nlmsg_flags & NLM_F_ECHO)
4949- netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
4950+
4951+ err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
4952+errout:
4953+ if (err < 0)
4954+ rtnl_set_sk_err(RTNLGRP_DECnet_ROUTE, err);
4955 }
4956
4957 static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
4958@@ -359,7 +361,7 @@
4959 {
4960 int i, s_i;
4961
4962- s_i = cb->args[3];
4963+ s_i = cb->args[4];
4964 for(i = 0; f; i++, f = f->fn_next) {
4965 if (i < s_i)
4966 continue;
4967@@ -372,11 +374,11 @@
4968 (f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type,
4969 f->fn_scope, &f->fn_key, dz->dz_order,
4970 f->fn_info, NLM_F_MULTI) < 0) {
4971- cb->args[3] = i;
4972+ cb->args[4] = i;
4973 return -1;
4974 }
4975 }
4976- cb->args[3] = i;
4977+ cb->args[4] = i;
4978 return skb->len;
4979 }
4980
4981@@ -387,20 +389,20 @@
4982 {
4983 int h, s_h;
4984
4985- s_h = cb->args[2];
4986+ s_h = cb->args[3];
4987 for(h = 0; h < dz->dz_divisor; h++) {
4988 if (h < s_h)
4989 continue;
4990 if (h > s_h)
4991- memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0]));
4992+ memset(&cb->args[4], 0, sizeof(cb->args) - 4*sizeof(cb->args[0]));
4993 if (dz->dz_hash == NULL || dz->dz_hash[h] == NULL)
4994 continue;
4995 if (dn_hash_dump_bucket(skb, cb, tb, dz, dz->dz_hash[h]) < 0) {
4996- cb->args[2] = h;
4997+ cb->args[3] = h;
4998 return -1;
4999 }
5000 }
5001- cb->args[2] = h;
5002+ cb->args[3] = h;
5003 return skb->len;
5004 }
5005
5006@@ -411,26 +413,63 @@
5007 struct dn_zone *dz;
5008 struct dn_hash *table = (struct dn_hash *)tb->data;
5009
5010- s_m = cb->args[1];
5011+ s_m = cb->args[2];
5012 read_lock(&dn_fib_tables_lock);
5013 for(dz = table->dh_zone_list, m = 0; dz; dz = dz->dz_next, m++) {
5014 if (m < s_m)
5015 continue;
5016 if (m > s_m)
5017- memset(&cb->args[2], 0, sizeof(cb->args) - 2*sizeof(cb->args[0]));
5018+ memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0]));
5019
5020 if (dn_hash_dump_zone(skb, cb, tb, dz) < 0) {
5021- cb->args[1] = m;
5022+ cb->args[2] = m;
5023 read_unlock(&dn_fib_tables_lock);
5024 return -1;
5025 }
5026 }
5027 read_unlock(&dn_fib_tables_lock);
5028- cb->args[1] = m;
5029+ cb->args[2] = m;
5030
5031 return skb->len;
5032 }
5033
5034+int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
5035+{
5036+ unsigned int h, s_h;
5037+ unsigned int e = 0, s_e;
5038+ struct dn_fib_table *tb;
5039+ struct hlist_node *node;
5040+ int dumped = 0;
5041+
5042+ if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
5043+ ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
5044+ return dn_cache_dump(skb, cb);
5045+
5046+ s_h = cb->args[0];
5047+ s_e = cb->args[1];
5048+
5049+ for (h = s_h; h < DN_FIB_TABLE_HASHSZ; h++, s_h = 0) {
5050+ e = 0;
5051+ hlist_for_each_entry(tb, node, &dn_fib_table_hash[h], hlist) {
5052+ if (e < s_e)
5053+ goto next;
5054+ if (dumped)
5055+ memset(&cb->args[2], 0, sizeof(cb->args) -
5056+ 2 * sizeof(cb->args[0]));
5057+ if (tb->dump(tb, skb, cb) < 0)
5058+ goto out;
5059+ dumped = 1;
5060+next:
5061+ e++;
5062+ }
5063+ }
5064+out:
5065+ cb->args[1] = e;
5066+ cb->args[0] = h;
5067+
5068+ return skb->len;
5069+}
5070+
5071 static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req)
5072 {
5073 struct dn_hash *table = (struct dn_hash *)tb->data;
5074@@ -739,9 +778,11 @@
5075 }
5076
5077
5078-struct dn_fib_table *dn_fib_get_table(int n, int create)
5079+struct dn_fib_table *dn_fib_get_table(u32 n, int create)
5080 {
5081 struct dn_fib_table *t;
5082+ struct hlist_node *node;
5083+ unsigned int h;
5084
5085 if (n < RT_TABLE_MIN)
5086 return NULL;
5087@@ -749,8 +790,15 @@
5088 if (n > RT_TABLE_MAX)
5089 return NULL;
5090
5091- if (dn_fib_tables[n])
5092- return dn_fib_tables[n];
5093+ h = n & (DN_FIB_TABLE_HASHSZ - 1);
5094+ rcu_read_lock();
5095+ hlist_for_each_entry_rcu(t, node, &dn_fib_table_hash[h], hlist) {
5096+ if (t->n == n) {
5097+ rcu_read_unlock();
5098+ return t;
5099+ }
5100+ }
5101+ rcu_read_unlock();
5102
5103 if (!create)
5104 return NULL;
5105@@ -771,33 +819,37 @@
5106 t->flush = dn_fib_table_flush;
5107 t->dump = dn_fib_table_dump;
5108 memset(t->data, 0, sizeof(struct dn_hash));
5109- dn_fib_tables[n] = t;
5110+ hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]);
5111
5112 return t;
5113 }
5114
5115-static void dn_fib_del_tree(int n)
5116-{
5117- struct dn_fib_table *t;
5118-
5119- write_lock(&dn_fib_tables_lock);
5120- t = dn_fib_tables[n];
5121- dn_fib_tables[n] = NULL;
5122- write_unlock(&dn_fib_tables_lock);
5123-
5124- kfree(t);
5125-}
5126-
5127 struct dn_fib_table *dn_fib_empty_table(void)
5128 {
5129- int id;
5130+ u32 id;
5131
5132 for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++)
5133- if (dn_fib_tables[id] == NULL)
5134+ if (dn_fib_get_table(id, 0) == NULL)
5135 return dn_fib_get_table(id, 1);
5136 return NULL;
5137 }
5138
5139+void dn_fib_flush(void)
5140+{
5141+ int flushed = 0;
5142+ struct dn_fib_table *tb;
5143+ struct hlist_node *node;
5144+ unsigned int h;
5145+
5146+ for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
5147+ hlist_for_each_entry(tb, node, &dn_fib_table_hash[h], hlist)
5148+ flushed += tb->flush(tb);
5149+ }
5150+
5151+ if (flushed)
5152+ dn_rt_cache_flush(-1);
5153+}
5154+
5155 void __init dn_fib_table_init(void)
5156 {
5157 dn_hash_kmem = kmem_cache_create("dn_fib_info_cache",
5158@@ -808,10 +860,17 @@
5159
5160 void __exit dn_fib_table_cleanup(void)
5161 {
5162- int i;
5163-
5164- for (i = RT_TABLE_MIN; i <= RT_TABLE_MAX; ++i)
5165- dn_fib_del_tree(i);
5166+ struct dn_fib_table *t;
5167+ struct hlist_node *node, *next;
5168+ unsigned int h;
5169
5170- return;
5171+ write_lock(&dn_fib_tables_lock);
5172+ for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
5173+ hlist_for_each_entry_safe(t, node, next, &dn_fib_table_hash[h],
5174+ hlist) {
5175+ hlist_del(&t->hlist);
5176+ kfree(t);
5177+ }
5178+ }
5179+ write_unlock(&dn_fib_tables_lock);
5180 }
5181diff -Nur linux-2.6.18-rc5/net/ethernet/eth.c linux-2.6.19/net/ethernet/eth.c
5182--- linux-2.6.18-rc5/net/ethernet/eth.c 2006-08-28 05:41:48.000000000 +0200
5183+++ linux-2.6.19/net/ethernet/eth.c 2006-09-22 10:04:58.000000000 +0200
5184@@ -64,81 +64,79 @@
5185
5186 __setup("ether=", netdev_boot_setup);
5187
5188-/*
5189- * Create the Ethernet MAC header for an arbitrary protocol layer
5190+/**
5191+ * eth_header - create the Ethernet header
5192+ * @skb: buffer to alter
5193+ * @dev: source device
5194+ * @type: Ethernet type field
5195+ * @daddr: destination address (NULL leave destination address)
5196+ * @saddr: source address (NULL use device source address)
5197+ * @len: packet length (<= skb->len)
5198+ *
5199 *
5200- * saddr=NULL means use device source address
5201- * daddr=NULL means leave destination address (eg unresolved arp)
5202+ * Set the protocol type. For a packet of type ETH_P_802_3 we put the length
5203+ * in here instead. It is up to the 802.2 layer to carry protocol information.
5204 */
5205-
5206 int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
5207- void *daddr, void *saddr, unsigned len)
5208+ void *daddr, void *saddr, unsigned len)
5209 {
5210- struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
5211+ struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN);
5212
5213- /*
5214- * Set the protocol type. For a packet of type ETH_P_802_3 we put the length
5215- * in here instead. It is up to the 802.2 layer to carry protocol information.
5216- */
5217-
5218- if(type!=ETH_P_802_3)
5219+ if (type != ETH_P_802_3)
5220 eth->h_proto = htons(type);
5221 else
5222 eth->h_proto = htons(len);
5223
5224 /*
5225- * Set the source hardware address.
5226+ * Set the source hardware address.
5227 */
5228-
5229- if(!saddr)
5230+
5231+ if (!saddr)
5232 saddr = dev->dev_addr;
5233- memcpy(eth->h_source,saddr,dev->addr_len);
5234+ memcpy(eth->h_source, saddr, dev->addr_len);
5235
5236- if(daddr)
5237- {
5238- memcpy(eth->h_dest,daddr,dev->addr_len);
5239+ if (daddr) {
5240+ memcpy(eth->h_dest, daddr, dev->addr_len);
5241 return ETH_HLEN;
5242 }
5243-
5244+
5245 /*
5246- * Anyway, the loopback-device should never use this function...
5247+ * Anyway, the loopback-device should never use this function...
5248 */
5249
5250- if (dev->flags & (IFF_LOOPBACK|IFF_NOARP))
5251- {
5252+ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
5253 memset(eth->h_dest, 0, dev->addr_len);
5254 return ETH_HLEN;
5255 }
5256-
5257+
5258 return -ETH_HLEN;
5259 }
5260
5261-
5262-/*
5263- * Rebuild the Ethernet MAC header. This is called after an ARP
5264- * (or in future other address resolution) has completed on this
5265- * sk_buff. We now let ARP fill in the other fields.
5266+/**
5267+ * eth_rebuild_header- rebuild the Ethernet MAC header.
5268+ * @skb: socket buffer to update
5269 *
5270- * This routine CANNOT use cached dst->neigh!
5271- * Really, it is used only when dst->neigh is wrong.
5272+ * This is called after an ARP or IPV6 ndisc it's resolution on this
5273+ * sk_buff. We now let protocol (ARP) fill in the other fields.
5274+ *
5275+ * This routine CANNOT use cached dst->neigh!
5276+ * Really, it is used only when dst->neigh is wrong.
5277 */
5278-
5279 int eth_rebuild_header(struct sk_buff *skb)
5280 {
5281 struct ethhdr *eth = (struct ethhdr *)skb->data;
5282 struct net_device *dev = skb->dev;
5283
5284- switch (eth->h_proto)
5285- {
5286+ switch (eth->h_proto) {
5287 #ifdef CONFIG_INET
5288 case __constant_htons(ETH_P_IP):
5289- return arp_find(eth->h_dest, skb);
5290-#endif
5291+ return arp_find(eth->h_dest, skb);
5292+#endif
5293 default:
5294 printk(KERN_DEBUG
5295- "%s: unable to resolve type %X addresses.\n",
5296+ "%s: unable to resolve type %X addresses.\n",
5297 dev->name, (int)eth->h_proto);
5298-
5299+
5300 memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
5301 break;
5302 }
5303@@ -146,62 +144,70 @@
5304 return 0;
5305 }
5306
5307-
5308-/*
5309- * Determine the packet's protocol ID. The rule here is that we
5310- * assume 802.3 if the type field is short enough to be a length.
5311- * This is normal practice and works for any 'now in use' protocol.
5312+/**
5313+ * eth_type_trans - determine the packet's protocol ID.
5314+ * @skb: received socket data
5315+ * @dev: receiving network device
5316+ *
5317+ * The rule here is that we
5318+ * assume 802.3 if the type field is short enough to be a length.
5319+ * This is normal practice and works for any 'now in use' protocol.
5320 */
5321-
5322 __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
5323 {
5324 struct ethhdr *eth;
5325 unsigned char *rawp;
5326-
5327+
5328 skb->mac.raw = skb->data;
5329- skb_pull(skb,ETH_HLEN);
5330+ skb_pull(skb, ETH_HLEN);
5331 eth = eth_hdr(skb);
5332-
5333+
5334 if (is_multicast_ether_addr(eth->h_dest)) {
5335 if (!compare_ether_addr(eth->h_dest, dev->broadcast))
5336 skb->pkt_type = PACKET_BROADCAST;
5337 else
5338 skb->pkt_type = PACKET_MULTICAST;
5339 }
5340-
5341+
5342 /*
5343- * This ALLMULTI check should be redundant by 1.4
5344- * so don't forget to remove it.
5345+ * This ALLMULTI check should be redundant by 1.4
5346+ * so don't forget to remove it.
5347 *
5348- * Seems, you forgot to remove it. All silly devices
5349- * seems to set IFF_PROMISC.
5350+ * Seems, you forgot to remove it. All silly devices
5351+ * seems to set IFF_PROMISC.
5352 */
5353-
5354- else if(1 /*dev->flags&IFF_PROMISC*/) {
5355+
5356+ else if (1 /*dev->flags&IFF_PROMISC */ ) {
5357 if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr)))
5358 skb->pkt_type = PACKET_OTHERHOST;
5359 }
5360-
5361+
5362 if (ntohs(eth->h_proto) >= 1536)
5363 return eth->h_proto;
5364-
5365+
5366 rawp = skb->data;
5367-
5368+
5369 /*
5370- * This is a magic hack to spot IPX packets. Older Novell breaks
5371- * the protocol design and runs IPX over 802.3 without an 802.2 LLC
5372- * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
5373- * won't work for fault tolerant netware but does for the rest.
5374+ * This is a magic hack to spot IPX packets. Older Novell breaks
5375+ * the protocol design and runs IPX over 802.3 without an 802.2 LLC
5376+ * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
5377+ * won't work for fault tolerant netware but does for the rest.
5378 */
5379 if (*(unsigned short *)rawp == 0xFFFF)
5380 return htons(ETH_P_802_3);
5381-
5382+
5383 /*
5384- * Real 802.2 LLC
5385+ * Real 802.2 LLC
5386 */
5387 return htons(ETH_P_802_2);
5388 }
5389+EXPORT_SYMBOL(eth_type_trans);
5390
5391+/**
5392+ * eth_header_parse - extract hardware address from packet
5393+ * @skb: packet to extract header from
5394+ * @haddr: destination buffer
5395+ */
5396 static int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
5397 {
5398 struct ethhdr *eth = eth_hdr(skb);
5399@@ -209,14 +215,20 @@
5400 return ETH_ALEN;
5401 }
5402
5403+/**
5404+ * eth_header_cache - fill cache entry from neighbour
5405+ * @neigh: source neighbour
5406+ * @hh: destination cache entry
5407+ * Create an Ethernet header template from the neighbour.
5408+ */
5409 int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
5410 {
5411 unsigned short type = hh->hh_type;
5412 struct ethhdr *eth;
5413 struct net_device *dev = neigh->dev;
5414
5415- eth = (struct ethhdr*)
5416- (((u8*)hh->hh_data) + (HH_DATA_OFF(sizeof(*eth))));
5417+ eth = (struct ethhdr *)
5418+ (((u8 *) hh->hh_data) + (HH_DATA_OFF(sizeof(*eth))));
5419
5420 if (type == __constant_htons(ETH_P_802_3))
5421 return -1;
5422@@ -228,27 +240,47 @@
5423 return 0;
5424 }
5425
5426-/*
5427+/**
5428+ * eth_header_cache_update - update cache entry
5429+ * @hh: destination cache entry
5430+ * @dev: network device
5431+ * @haddr: new hardware address
5432+ *
5433 * Called by Address Resolution module to notify changes in address.
5434 */
5435-
5436-void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr)
5437+void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev,
5438+ unsigned char *haddr)
5439 {
5440- memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
5441+ memcpy(((u8 *) hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
5442 haddr, dev->addr_len);
5443 }
5444
5445-EXPORT_SYMBOL(eth_type_trans);
5446-
5447+/**
5448+ * eth_mac_addr - set new Ethernet hardware address
5449+ * @dev: network device
5450+ * @p: socket address
5451+ * Change hardware address of device.
5452+ *
5453+ * This doesn't change hardware matching, so needs to be overridden
5454+ * for most real devices.
5455+ */
5456 static int eth_mac_addr(struct net_device *dev, void *p)
5457 {
5458- struct sockaddr *addr=p;
5459+ struct sockaddr *addr = p;
5460 if (netif_running(dev))
5461 return -EBUSY;
5462- memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
5463+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
5464 return 0;
5465 }
5466
5467+/**
5468+ * eth_change_mtu - set new MTU size
5469+ * @dev: network device
5470+ * @new_mtu: new Maximum Transfer Unit
5471+ *
5472+ * Allow changing MTU size. Needs to be overridden for devices
5473+ * supporting jumbo frames.
5474+ */
5475 static int eth_change_mtu(struct net_device *dev, int new_mtu)
5476 {
5477 if (new_mtu < 68 || new_mtu > ETH_DATA_LEN)
5478@@ -257,8 +289,10 @@
5479 return 0;
5480 }
5481
5482-/*
5483- * Fill in the fields of the device structure with ethernet-generic values.
5484+/**
5485+ * ether_setup - setup Ethernet network device
5486+ * @dev: network device
5487+ * Fill in the fields of the device structure with Ethernet-generic values.
5488 */
5489 void ether_setup(struct net_device *dev)
5490 {
5491@@ -277,21 +311,21 @@
5492 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
5493 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
5494
5495- memset(dev->broadcast,0xFF, ETH_ALEN);
5496+ memset(dev->broadcast, 0xFF, ETH_ALEN);
5497
5498 }
5499 EXPORT_SYMBOL(ether_setup);
5500
5501 /**
5502- * alloc_etherdev - Allocates and sets up an ethernet device
5503+ * alloc_etherdev - Allocates and sets up an Ethernet device
5504 * @sizeof_priv: Size of additional driver-private structure to be allocated
5505- * for this ethernet device
5506+ * for this Ethernet device
5507 *
5508- * Fill in the fields of the device structure with ethernet-generic
5509+ * Fill in the fields of the device structure with Ethernet-generic
5510 * values. Basically does everything except registering the device.
5511 *
5512 * Constructs a new net device, complete with a private data area of
5513- * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for
5514+ * size (sizeof_priv). A 32-byte (not bit) alignment is enforced for
5515 * this private data area.
5516 */
5517
5518diff -Nur linux-2.6.18-rc5/net/ipv4/Kconfig linux-2.6.19/net/ipv4/Kconfig
5519--- linux-2.6.18-rc5/net/ipv4/Kconfig 2006-08-28 05:41:48.000000000 +0200
5520+++ linux-2.6.19/net/ipv4/Kconfig 2006-09-22 10:04:58.000000000 +0200
5521@@ -88,6 +88,7 @@
5522 config IP_MULTIPLE_TABLES
5523 bool "IP: policy routing"
5524 depends on IP_ADVANCED_ROUTER
5525+ select FIB_RULES
5526 ---help---
5527 Normally, a router decides what to do with a received packet based
5528 solely on the packet's final destination address. If you say Y here,
5529diff -Nur linux-2.6.18-rc5/net/ipv4/Makefile linux-2.6.19/net/ipv4/Makefile
5530--- linux-2.6.18-rc5/net/ipv4/Makefile 2006-08-28 05:41:48.000000000 +0200
5531+++ linux-2.6.19/net/ipv4/Makefile 2006-09-22 10:04:58.000000000 +0200
5532@@ -47,6 +47,7 @@
5533 obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o
5534 obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
5535 obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
5536+obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
5537
5538 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
5539 xfrm4_output.o
5540diff -Nur linux-2.6.18-rc5/net/ipv4/af_inet.c linux-2.6.19/net/ipv4/af_inet.c
5541--- linux-2.6.18-rc5/net/ipv4/af_inet.c 2006-08-28 05:41:48.000000000 +0200
5542+++ linux-2.6.19/net/ipv4/af_inet.c 2006-09-22 10:04:58.000000000 +0200
5543@@ -67,7 +67,6 @@
5544 * 2 of the License, or (at your option) any later version.
5545 */
5546
5547-#include <linux/config.h>
5548 #include <linux/err.h>
5549 #include <linux/errno.h>
5550 #include <linux/types.h>
5551@@ -392,7 +391,7 @@
5552 }
5553
5554 /* It is off by default, see below. */
5555-int sysctl_ip_nonlocal_bind;
5556+int sysctl_ip_nonlocal_bind __read_mostly;
5557
5558 int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
5559 {
5560@@ -988,7 +987,7 @@
5561 * Shall we try to damage output packets if routing dev changes?
5562 */
5563
5564-int sysctl_ip_dynaddr;
5565+int sysctl_ip_dynaddr __read_mostly;
5566
5567 static int inet_sk_reselect_saddr(struct sock *sk)
5568 {
5569@@ -1074,6 +1073,7 @@
5570 },
5571 };
5572
5573+ security_sk_classify_flow(sk, &fl);
5574 err = ip_route_output_flow(&rt, &fl, sk, 0);
5575 }
5576 if (!err)
5577@@ -1254,10 +1254,7 @@
5578 struct list_head *r;
5579 int rc = -EINVAL;
5580
5581- if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) {
5582- printk(KERN_CRIT "%s: panic\n", __FUNCTION__);
5583- goto out;
5584- }
5585+ BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));
5586
5587 rc = proto_register(&tcp_prot, 1);
5588 if (rc)
5589diff -Nur linux-2.6.18-rc5/net/ipv4/ah4.c linux-2.6.19/net/ipv4/ah4.c
5590--- linux-2.6.18-rc5/net/ipv4/ah4.c 2006-08-28 05:41:48.000000000 +0200
5591+++ linux-2.6.19/net/ipv4/ah4.c 2006-09-22 10:04:58.000000000 +0200
5592@@ -34,7 +34,7 @@
5593 switch (*optptr) {
5594 case IPOPT_SEC:
5595 case 0x85: /* Some "Extended Security" crap. */
5596- case 0x86: /* Another "Commercial Security" crap. */
5597+ case IPOPT_CIPSO:
5598 case IPOPT_RA:
5599 case 0x80|21: /* RFC1770 */
5600 break;
5601@@ -253,7 +253,7 @@
5602 goto error;
5603
5604 x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len);
5605- if (x->props.mode)
5606+ if (x->props.mode == XFRM_MODE_TUNNEL)
5607 x->props.header_len += sizeof(struct iphdr);
5608 x->data = ahp;
5609
5610diff -Nur linux-2.6.18-rc5/net/ipv4/cipso_ipv4.c linux-2.6.19/net/ipv4/cipso_ipv4.c
5611--- linux-2.6.18-rc5/net/ipv4/cipso_ipv4.c 1970-01-01 01:00:00.000000000 +0100
5612+++ linux-2.6.19/net/ipv4/cipso_ipv4.c 2006-09-22 10:04:58.000000000 +0200
5613@@ -0,0 +1,1607 @@
5614+/*
5615+ * CIPSO - Commercial IP Security Option
5616+ *
5617+ * This is an implementation of the CIPSO 2.2 protocol as specified in
5618+ * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
5619+ * FIPS-188, copies of both documents can be found in the Documentation
5620+ * directory. While CIPSO never became a full IETF RFC standard many vendors
5621+ * have chosen to adopt the protocol and over the years it has become a
5622+ * de-facto standard for labeled networking.
5623+ *
5624+ * Author: Paul Moore <paul.moore@hp.com>
5625+ *
5626+ */
5627+
5628+/*
5629+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
5630+ *
5631+ * This program is free software; you can redistribute it and/or modify
5632+ * it under the terms of the GNU General Public License as published by
5633+ * the Free Software Foundation; either version 2 of the License, or
5634+ * (at your option) any later version.
5635+ *
5636+ * This program is distributed in the hope that it will be useful,
5637+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5638+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
5639+ * the GNU General Public License for more details.
5640+ *
5641+ * You should have received a copy of the GNU General Public License
5642+ * along with this program; if not, write to the Free Software
5643+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5644+ *
5645+ */
5646+
5647+#include <linux/init.h>
5648+#include <linux/types.h>
5649+#include <linux/rcupdate.h>
5650+#include <linux/list.h>
5651+#include <linux/spinlock.h>
5652+#include <linux/string.h>
5653+#include <linux/jhash.h>
5654+#include <net/ip.h>
5655+#include <net/icmp.h>
5656+#include <net/tcp.h>
5657+#include <net/netlabel.h>
5658+#include <net/cipso_ipv4.h>
5659+#include <asm/bug.h>
5660+
5661+struct cipso_v4_domhsh_entry {
5662+ char *domain;
5663+ u32 valid;
5664+ struct list_head list;
5665+ struct rcu_head rcu;
5666+};
5667+
5668+/* List of available DOI definitions */
5669+/* XXX - Updates should be minimal so having a single lock for the
5670+ * cipso_v4_doi_list and the cipso_v4_doi_list->dom_list should be
5671+ * okay. */
5672+/* XXX - This currently assumes a minimal number of different DOIs in use,
5673+ * if in practice there are a lot of different DOIs this list should
5674+ * probably be turned into a hash table or something similar so we
5675+ * can do quick lookups. */
5676+static DEFINE_SPINLOCK(cipso_v4_doi_list_lock);
5677+static struct list_head cipso_v4_doi_list = LIST_HEAD_INIT(cipso_v4_doi_list);
5678+
5679+/* Label mapping cache */
5680+int cipso_v4_cache_enabled = 1;
5681+int cipso_v4_cache_bucketsize = 10;
5682+#define CIPSO_V4_CACHE_BUCKETBITS 7
5683+#define CIPSO_V4_CACHE_BUCKETS (1 << CIPSO_V4_CACHE_BUCKETBITS)
5684+#define CIPSO_V4_CACHE_REORDERLIMIT 10
5685+struct cipso_v4_map_cache_bkt {
5686+ spinlock_t lock;
5687+ u32 size;
5688+ struct list_head list;
5689+};
5690+struct cipso_v4_map_cache_entry {
5691+ u32 hash;
5692+ unsigned char *key;
5693+ size_t key_len;
5694+
5695+ struct netlbl_lsm_cache lsm_data;
5696+
5697+ u32 activity;
5698+ struct list_head list;
5699+};
5700+static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL;
5701+
5702+/* Restricted bitmap (tag #1) flags */
5703+int cipso_v4_rbm_optfmt = 0;
5704+int cipso_v4_rbm_strictvalid = 1;
5705+
5706+/*
5707+ * Helper Functions
5708+ */
5709+
5710+/**
5711+ * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit
5712+ * @bitmap: the bitmap
5713+ * @bitmap_len: length in bits
5714+ * @offset: starting offset
5715+ * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
5716+ *
5717+ * Description:
5718+ * Starting at @offset, walk the bitmap from left to right until either the
5719+ * desired bit is found or we reach the end. Return the bit offset, -1 if
5720+ * not found, or -2 if error.
5721+ */
5722+static int cipso_v4_bitmap_walk(const unsigned char *bitmap,
5723+ u32 bitmap_len,
5724+ u32 offset,
5725+ u8 state)
5726+{
5727+ u32 bit_spot;
5728+ u32 byte_offset;
5729+ unsigned char bitmask;
5730+ unsigned char byte;
5731+
5732+ /* gcc always rounds to zero when doing integer division */
5733+ byte_offset = offset / 8;
5734+ byte = bitmap[byte_offset];
5735+ bit_spot = offset;
5736+ bitmask = 0x80 >> (offset % 8);
5737+
5738+ while (bit_spot < bitmap_len) {
5739+ if ((state && (byte & bitmask) == bitmask) ||
5740+ (state == 0 && (byte & bitmask) == 0))
5741+ return bit_spot;
5742+
5743+ bit_spot++;
5744+ bitmask >>= 1;
5745+ if (bitmask == 0) {
5746+ byte = bitmap[++byte_offset];
5747+ bitmask = 0x80;
5748+ }
5749+ }
5750+
5751+ return -1;
5752+}
5753+
5754+/**
5755+ * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap
5756+ * @bitmap: the bitmap
5757+ * @bit: the bit
5758+ * @state: if non-zero, set the bit (1) else clear the bit (0)
5759+ *
5760+ * Description:
5761+ * Set a single bit in the bitmask. Returns zero on success, negative values
5762+ * on error.
5763+ */
5764+static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
5765+ u32 bit,
5766+ u8 state)
5767+{
5768+ u32 byte_spot;
5769+ u8 bitmask;
5770+
5771+ /* gcc always rounds to zero when doing integer division */
5772+ byte_spot = bit / 8;
5773+ bitmask = 0x80 >> (bit % 8);
5774+ if (state)
5775+ bitmap[byte_spot] |= bitmask;
5776+ else
5777+ bitmap[byte_spot] &= ~bitmask;
5778+}
5779+
5780+/**
5781+ * cipso_v4_doi_domhsh_free - Frees a domain list entry
5782+ * @entry: the entry's RCU field
5783+ *
5784+ * Description:
5785+ * This function is designed to be used as a callback to the call_rcu()
5786+ * function so that the memory allocated to a domain list entry can be released
5787+ * safely.
5788+ *
5789+ */
5790+static void cipso_v4_doi_domhsh_free(struct rcu_head *entry)
5791+{
5792+ struct cipso_v4_domhsh_entry *ptr;
5793+
5794+ ptr = container_of(entry, struct cipso_v4_domhsh_entry, rcu);
5795+ kfree(ptr->domain);
5796+ kfree(ptr);
5797+}
5798+
5799+/**
5800+ * cipso_v4_cache_entry_free - Frees a cache entry
5801+ * @entry: the entry to free
5802+ *
5803+ * Description:
5804+ * This function frees the memory associated with a cache entry.
5805+ *
5806+ */
5807+static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
5808+{
5809+ if (entry->lsm_data.free)
5810+ entry->lsm_data.free(entry->lsm_data.data);
5811+ kfree(entry->key);
5812+ kfree(entry);
5813+}
5814+
5815+/**
5816+ * cipso_v4_map_cache_hash - Hashing function for the CIPSO cache
5817+ * @key: the hash key
5818+ * @key_len: the length of the key in bytes
5819+ *
5820+ * Description:
5821+ * The CIPSO tag hashing function. Returns a 32-bit hash value.
5822+ *
5823+ */
5824+static u32 cipso_v4_map_cache_hash(const unsigned char *key, u32 key_len)
5825+{
5826+ return jhash(key, key_len, 0);
5827+}
5828+
5829+/*
5830+ * Label Mapping Cache Functions
5831+ */
5832+
5833+/**
5834+ * cipso_v4_cache_init - Initialize the CIPSO cache
5835+ *
5836+ * Description:
5837+ * Initializes the CIPSO label mapping cache, this function should be called
5838+ * before any of the other functions defined in this file. Returns zero on
5839+ * success, negative values on error.
5840+ *
5841+ */
5842+static int cipso_v4_cache_init(void)
5843+{
5844+ u32 iter;
5845+
5846+ cipso_v4_cache = kcalloc(CIPSO_V4_CACHE_BUCKETS,
5847+ sizeof(struct cipso_v4_map_cache_bkt),
5848+ GFP_KERNEL);
5849+ if (cipso_v4_cache == NULL)
5850+ return -ENOMEM;
5851+
5852+ for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
5853+ spin_lock_init(&cipso_v4_cache[iter].lock);
5854+ cipso_v4_cache[iter].size = 0;
5855+ INIT_LIST_HEAD(&cipso_v4_cache[iter].list);
5856+ }
5857+
5858+ return 0;
5859+}
5860+
5861+/**
5862+ * cipso_v4_cache_invalidate - Invalidates the current CIPSO cache
5863+ *
5864+ * Description:
5865+ * Invalidates and frees any entries in the CIPSO cache. Returns zero on
5866+ * success and negative values on failure.
5867+ *
5868+ */
5869+void cipso_v4_cache_invalidate(void)
5870+{
5871+ struct cipso_v4_map_cache_entry *entry, *tmp_entry;
5872+ u32 iter;
5873+
5874+ for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
5875+ spin_lock(&cipso_v4_cache[iter].lock);
5876+ list_for_each_entry_safe(entry,
5877+ tmp_entry,
5878+ &cipso_v4_cache[iter].list, list) {
5879+ list_del(&entry->list);
5880+ cipso_v4_cache_entry_free(entry);
5881+ }
5882+ cipso_v4_cache[iter].size = 0;
5883+ spin_unlock(&cipso_v4_cache[iter].lock);
5884+ }
5885+
5886+ return;
5887+}
5888+
5889+/**
5890+ * cipso_v4_cache_check - Check the CIPSO cache for a label mapping
5891+ * @key: the buffer to check
5892+ * @key_len: buffer length in bytes
5893+ * @secattr: the security attribute struct to use
5894+ *
5895+ * Description:
5896+ * This function checks the cache to see if a label mapping already exists for
5897+ * the given key. If there is a match then the cache is adjusted and the
5898+ * @secattr struct is populated with the correct LSM security attributes. The
5899+ * cache is adjusted in the following manner if the entry is not already the
5900+ * first in the cache bucket:
5901+ *
5902+ * 1. The cache entry's activity counter is incremented
5903+ * 2. The previous (higher ranking) entry's activity counter is decremented
5904+ * 3. If the difference between the two activity counters is geater than
5905+ * CIPSO_V4_CACHE_REORDERLIMIT the two entries are swapped
5906+ *
5907+ * Returns zero on success, -ENOENT for a cache miss, and other negative values
5908+ * on error.
5909+ *
5910+ */
5911+static int cipso_v4_cache_check(const unsigned char *key,
5912+ u32 key_len,
5913+ struct netlbl_lsm_secattr *secattr)
5914+{
5915+ u32 bkt;
5916+ struct cipso_v4_map_cache_entry *entry;
5917+ struct cipso_v4_map_cache_entry *prev_entry = NULL;
5918+ u32 hash;
5919+
5920+ if (!cipso_v4_cache_enabled)
5921+ return -ENOENT;
5922+
5923+ hash = cipso_v4_map_cache_hash(key, key_len);
5924+ bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
5925+ spin_lock(&cipso_v4_cache[bkt].lock);
5926+ list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
5927+ if (entry->hash == hash &&
5928+ entry->key_len == key_len &&
5929+ memcmp(entry->key, key, key_len) == 0) {
5930+ entry->activity += 1;
5931+ secattr->cache.free = entry->lsm_data.free;
5932+ secattr->cache.data = entry->lsm_data.data;
5933+ if (prev_entry == NULL) {
5934+ spin_unlock(&cipso_v4_cache[bkt].lock);
5935+ return 0;
5936+ }
5937+
5938+ if (prev_entry->activity > 0)
5939+ prev_entry->activity -= 1;
5940+ if (entry->activity > prev_entry->activity &&
5941+ entry->activity - prev_entry->activity >
5942+ CIPSO_V4_CACHE_REORDERLIMIT) {
5943+ __list_del(entry->list.prev, entry->list.next);
5944+ __list_add(&entry->list,
5945+ prev_entry->list.prev,
5946+ &prev_entry->list);
5947+ }
5948+
5949+ spin_unlock(&cipso_v4_cache[bkt].lock);
5950+ return 0;
5951+ }
5952+ prev_entry = entry;
5953+ }
5954+ spin_unlock(&cipso_v4_cache[bkt].lock);
5955+
5956+ return -ENOENT;
5957+}
5958+
5959+/**
5960+ * cipso_v4_cache_add - Add an entry to the CIPSO cache
5961+ * @skb: the packet
5962+ * @secattr: the packet's security attributes
5963+ *
5964+ * Description:
5965+ * Add a new entry into the CIPSO label mapping cache. Add the new entry to
5966+ * head of the cache bucket's list, if the cache bucket is out of room remove
5967+ * the last entry in the list first. It is important to note that there is
5968+ * currently no checking for duplicate keys. Returns zero on success,
5969+ * negative values on failure.
5970+ *
5971+ */
5972+int cipso_v4_cache_add(const struct sk_buff *skb,
5973+ const struct netlbl_lsm_secattr *secattr)
5974+{
5975+ int ret_val = -EPERM;
5976+ u32 bkt;
5977+ struct cipso_v4_map_cache_entry *entry = NULL;
5978+ struct cipso_v4_map_cache_entry *old_entry = NULL;
5979+ unsigned char *cipso_ptr;
5980+ u32 cipso_ptr_len;
5981+
5982+ if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0)
5983+ return 0;
5984+
5985+ cipso_ptr = CIPSO_V4_OPTPTR(skb);
5986+ cipso_ptr_len = cipso_ptr[1];
5987+
5988+ entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
5989+ if (entry == NULL)
5990+ return -ENOMEM;
5991+ entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC);
5992+ if (entry->key == NULL) {
5993+ ret_val = -ENOMEM;
5994+ goto cache_add_failure;
5995+ }
5996+ memcpy(entry->key, cipso_ptr, cipso_ptr_len);
5997+ entry->key_len = cipso_ptr_len;
5998+ entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
5999+ entry->lsm_data.free = secattr->cache.free;
6000+ entry->lsm_data.data = secattr->cache.data;
6001+
6002+ bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
6003+ spin_lock(&cipso_v4_cache[bkt].lock);
6004+ if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
6005+ list_add(&entry->list, &cipso_v4_cache[bkt].list);
6006+ cipso_v4_cache[bkt].size += 1;
6007+ } else {
6008+ old_entry = list_entry(cipso_v4_cache[bkt].list.prev,
6009+ struct cipso_v4_map_cache_entry, list);
6010+ list_del(&old_entry->list);
6011+ list_add(&entry->list, &cipso_v4_cache[bkt].list);
6012+ cipso_v4_cache_entry_free(old_entry);
6013+ }
6014+ spin_unlock(&cipso_v4_cache[bkt].lock);
6015+
6016+ return 0;
6017+
6018+cache_add_failure:
6019+ if (entry)
6020+ cipso_v4_cache_entry_free(entry);
6021+ return ret_val;
6022+}
6023+
6024+/*
6025+ * DOI List Functions
6026+ */
6027+
6028+/**
6029+ * cipso_v4_doi_search - Searches for a DOI definition
6030+ * @doi: the DOI to search for
6031+ *
6032+ * Description:
6033+ * Search the DOI definition list for a DOI definition with a DOI value that
6034+ * matches @doi. The caller is responsibile for calling rcu_read_[un]lock().
6035+ * Returns a pointer to the DOI definition on success and NULL on failure.
6036+ */
6037+static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
6038+{
6039+ struct cipso_v4_doi *iter;
6040+
6041+ list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
6042+ if (iter->doi == doi && iter->valid)
6043+ return iter;
6044+ return NULL;
6045+}
6046+
6047+/**
6048+ * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine
6049+ * @doi_def: the DOI structure
6050+ *
6051+ * Description:
6052+ * The caller defines a new DOI for use by the CIPSO engine and calls this
6053+ * function to add it to the list of acceptable domains. The caller must
6054+ * ensure that the mapping table specified in @doi_def->map meets all of the
6055+ * requirements of the mapping type (see cipso_ipv4.h for details). Returns
6056+ * zero on success and non-zero on failure.
6057+ *
6058+ */
6059+int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
6060+{
6061+ if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
6062+ return -EINVAL;
6063+
6064+ doi_def->valid = 1;
6065+ INIT_RCU_HEAD(&doi_def->rcu);
6066+ INIT_LIST_HEAD(&doi_def->dom_list);
6067+
6068+ rcu_read_lock();
6069+ if (cipso_v4_doi_search(doi_def->doi) != NULL)
6070+ goto doi_add_failure_rlock;
6071+ spin_lock(&cipso_v4_doi_list_lock);
6072+ if (cipso_v4_doi_search(doi_def->doi) != NULL)
6073+ goto doi_add_failure_slock;
6074+ list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
6075+ spin_unlock(&cipso_v4_doi_list_lock);
6076+ rcu_read_unlock();
6077+
6078+ return 0;
6079+
6080+doi_add_failure_slock:
6081+ spin_unlock(&cipso_v4_doi_list_lock);
6082+doi_add_failure_rlock:
6083+ rcu_read_unlock();
6084+ return -EEXIST;
6085+}
6086+
6087+/**
6088+ * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
6089+ * @doi: the DOI value
6090+ * @callback: the DOI cleanup/free callback
6091+ *
6092+ * Description:
6093+ * Removes a DOI definition from the CIPSO engine, @callback is called to
6094+ * free any memory. The NetLabel routines will be called to release their own
6095+ * LSM domain mappings as well as our own domain list. Returns zero on
6096+ * success and negative values on failure.
6097+ *
6098+ */
6099+int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head))
6100+{
6101+ struct cipso_v4_doi *doi_def;
6102+ struct cipso_v4_domhsh_entry *dom_iter;
6103+
6104+ rcu_read_lock();
6105+ if (cipso_v4_doi_search(doi) != NULL) {
6106+ spin_lock(&cipso_v4_doi_list_lock);
6107+ doi_def = cipso_v4_doi_search(doi);
6108+ if (doi_def == NULL) {
6109+ spin_unlock(&cipso_v4_doi_list_lock);
6110+ rcu_read_unlock();
6111+ return -ENOENT;
6112+ }
6113+ doi_def->valid = 0;
6114+ list_del_rcu(&doi_def->list);
6115+ spin_unlock(&cipso_v4_doi_list_lock);
6116+ list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
6117+ if (dom_iter->valid)
6118+ netlbl_domhsh_remove(dom_iter->domain);
6119+ cipso_v4_cache_invalidate();
6120+ rcu_read_unlock();
6121+
6122+ call_rcu(&doi_def->rcu, callback);
6123+ return 0;
6124+ }
6125+ rcu_read_unlock();
6126+
6127+ return -ENOENT;
6128+}
6129+
6130+/**
6131+ * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition
6132+ * @doi: the DOI value
6133+ *
6134+ * Description:
6135+ * Searches for a valid DOI definition and if one is found it is returned to
6136+ * the caller. Otherwise NULL is returned. The caller must ensure that
6137+ * rcu_read_lock() is held while accessing the returned definition.
6138+ *
6139+ */
6140+struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
6141+{
6142+ return cipso_v4_doi_search(doi);
6143+}
6144+
6145+/**
6146+ * cipso_v4_doi_dump_all - Dump all the CIPSO DOI definitions into a sk_buff
6147+ * @headroom: the amount of headroom to allocate for the sk_buff
6148+ *
6149+ * Description:
6150+ * Dump a list of all the configured DOI values into a sk_buff. The returned
6151+ * sk_buff has room at the front of the sk_buff for @headroom bytes. See
6152+ * net/netlabel/netlabel_cipso_v4.h for the LISTALL message format. This
6153+ * function may fail if another process is changing the DOI list at the same
6154+ * time. Returns a pointer to a sk_buff on success, NULL on error.
6155+ *
6156+ */
6157+struct sk_buff *cipso_v4_doi_dump_all(size_t headroom)
6158+{
6159+ struct sk_buff *skb = NULL;
6160+ struct cipso_v4_doi *iter;
6161+ u32 doi_cnt = 0;
6162+ ssize_t buf_len;
6163+
6164+ buf_len = NETLBL_LEN_U32;
6165+ rcu_read_lock();
6166+ list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
6167+ if (iter->valid) {
6168+ doi_cnt += 1;
6169+ buf_len += 2 * NETLBL_LEN_U32;
6170+ }
6171+
6172+ skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
6173+ if (skb == NULL)
6174+ goto doi_dump_all_failure;
6175+
6176+ if (nla_put_u32(skb, NLA_U32, doi_cnt) != 0)
6177+ goto doi_dump_all_failure;
6178+ buf_len -= NETLBL_LEN_U32;
6179+ list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
6180+ if (iter->valid) {
6181+ if (buf_len < 2 * NETLBL_LEN_U32)
6182+ goto doi_dump_all_failure;
6183+ if (nla_put_u32(skb, NLA_U32, iter->doi) != 0)
6184+ goto doi_dump_all_failure;
6185+ if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
6186+ goto doi_dump_all_failure;
6187+ buf_len -= 2 * NETLBL_LEN_U32;
6188+ }
6189+ rcu_read_unlock();
6190+
6191+ return skb;
6192+
6193+doi_dump_all_failure:
6194+ rcu_read_unlock();
6195+ kfree(skb);
6196+ return NULL;
6197+}
6198+
6199+/**
6200+ * cipso_v4_doi_dump - Dump a CIPSO DOI definition into a sk_buff
6201+ * @doi: the DOI value
6202+ * @headroom: the amount of headroom to allocate for the sk_buff
6203+ *
6204+ * Description:
6205+ * Lookup the DOI definition matching @doi and dump it's contents into a
6206+ * sk_buff. The returned sk_buff has room at the front of the sk_buff for
6207+ * @headroom bytes. See net/netlabel/netlabel_cipso_v4.h for the LIST message
6208+ * format. This function may fail if another process is changing the DOI list
6209+ * at the same time. Returns a pointer to a sk_buff on success, NULL on error.
6210+ *
6211+ */
6212+struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom)
6213+{
6214+ struct sk_buff *skb = NULL;
6215+ struct cipso_v4_doi *iter;
6216+ u32 tag_cnt = 0;
6217+ u32 lvl_cnt = 0;
6218+ u32 cat_cnt = 0;
6219+ ssize_t buf_len;
6220+ ssize_t tmp;
6221+
6222+ rcu_read_lock();
6223+ iter = cipso_v4_doi_getdef(doi);
6224+ if (iter == NULL)
6225+ goto doi_dump_failure;
6226+ buf_len = NETLBL_LEN_U32;
6227+ switch (iter->type) {
6228+ case CIPSO_V4_MAP_PASS:
6229+ buf_len += NETLBL_LEN_U32;
6230+ while(tag_cnt < CIPSO_V4_TAG_MAXCNT &&
6231+ iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
6232+ tag_cnt += 1;
6233+ buf_len += NETLBL_LEN_U8;
6234+ }
6235+ break;
6236+ case CIPSO_V4_MAP_STD:
6237+ buf_len += 3 * NETLBL_LEN_U32;
6238+ while (tag_cnt < CIPSO_V4_TAG_MAXCNT &&
6239+ iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
6240+ tag_cnt += 1;
6241+ buf_len += NETLBL_LEN_U8;
6242+ }
6243+ for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
6244+ if (iter->map.std->lvl.local[tmp] !=
6245+ CIPSO_V4_INV_LVL) {
6246+ lvl_cnt += 1;
6247+ buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U8;
6248+ }
6249+ for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
6250+ if (iter->map.std->cat.local[tmp] !=
6251+ CIPSO_V4_INV_CAT) {
6252+ cat_cnt += 1;
6253+ buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U16;
6254+ }
6255+ break;
6256+ }
6257+
6258+ skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
6259+ if (skb == NULL)
6260+ goto doi_dump_failure;
6261+
6262+ if (nla_put_u32(skb, NLA_U32, iter->type) != 0)
6263+ goto doi_dump_failure;
6264+ buf_len -= NETLBL_LEN_U32;
6265+ if (iter != cipso_v4_doi_getdef(doi))
6266+ goto doi_dump_failure;
6267+ switch (iter->type) {
6268+ case CIPSO_V4_MAP_PASS:
6269+ if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
6270+ goto doi_dump_failure;
6271+ buf_len -= NETLBL_LEN_U32;
6272+ for (tmp = 0;
6273+ tmp < CIPSO_V4_TAG_MAXCNT &&
6274+ iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
6275+ tmp++) {
6276+ if (buf_len < NETLBL_LEN_U8)
6277+ goto doi_dump_failure;
6278+ if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
6279+ goto doi_dump_failure;
6280+ buf_len -= NETLBL_LEN_U8;
6281+ }
6282+ break;
6283+ case CIPSO_V4_MAP_STD:
6284+ if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0)
6285+ goto doi_dump_failure;
6286+ if (nla_put_u32(skb, NLA_U32, lvl_cnt) != 0)
6287+ goto doi_dump_failure;
6288+ if (nla_put_u32(skb, NLA_U32, cat_cnt) != 0)
6289+ goto doi_dump_failure;
6290+ buf_len -= 3 * NETLBL_LEN_U32;
6291+ for (tmp = 0;
6292+ tmp < CIPSO_V4_TAG_MAXCNT &&
6293+ iter->tags[tmp] != CIPSO_V4_TAG_INVALID;
6294+ tmp++) {
6295+ if (buf_len < NETLBL_LEN_U8)
6296+ goto doi_dump_failure;
6297+ if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0)
6298+ goto doi_dump_failure;
6299+ buf_len -= NETLBL_LEN_U8;
6300+ }
6301+ for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++)
6302+ if (iter->map.std->lvl.local[tmp] !=
6303+ CIPSO_V4_INV_LVL) {
6304+ if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U8)
6305+ goto doi_dump_failure;
6306+ if (nla_put_u32(skb, NLA_U32, tmp) != 0)
6307+ goto doi_dump_failure;
6308+ if (nla_put_u8(skb,
6309+ NLA_U8,
6310+ iter->map.std->lvl.local[tmp]) != 0)
6311+ goto doi_dump_failure;
6312+ buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U8;
6313+ }
6314+ for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++)
6315+ if (iter->map.std->cat.local[tmp] !=
6316+ CIPSO_V4_INV_CAT) {
6317+ if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U16)
6318+ goto doi_dump_failure;
6319+ if (nla_put_u32(skb, NLA_U32, tmp) != 0)
6320+ goto doi_dump_failure;
6321+ if (nla_put_u16(skb,
6322+ NLA_U16,
6323+ iter->map.std->cat.local[tmp]) != 0)
6324+ goto doi_dump_failure;
6325+ buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U16;
6326+ }
6327+ break;
6328+ }
6329+ rcu_read_unlock();
6330+
6331+ return skb;
6332+
6333+doi_dump_failure:
6334+ rcu_read_unlock();
6335+ kfree(skb);
6336+ return NULL;
6337+}
6338+
6339+/**
6340+ * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition
6341+ * @doi_def: the DOI definition
6342+ * @domain: the domain to add
6343+ *
6344+ * Description:
6345+ * Adds the @domain to the the DOI specified by @doi_def, this function
6346+ * should only be called by external functions (i.e. NetLabel). This function
6347+ * does allocate memory. Returns zero on success, negative values on failure.
6348+ *
6349+ */
6350+int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
6351+{
6352+ struct cipso_v4_domhsh_entry *iter;
6353+ struct cipso_v4_domhsh_entry *new_dom;
6354+
6355+ new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL);
6356+ if (new_dom == NULL)
6357+ return -ENOMEM;
6358+ if (domain) {
6359+ new_dom->domain = kstrdup(domain, GFP_KERNEL);
6360+ if (new_dom->domain == NULL) {
6361+ kfree(new_dom);
6362+ return -ENOMEM;
6363+ }
6364+ }
6365+ new_dom->valid = 1;
6366+ INIT_RCU_HEAD(&new_dom->rcu);
6367+
6368+ rcu_read_lock();
6369+ spin_lock(&cipso_v4_doi_list_lock);
6370+ list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
6371+ if (iter->valid &&
6372+ ((domain != NULL && iter->domain != NULL &&
6373+ strcmp(iter->domain, domain) == 0) ||
6374+ (domain == NULL && iter->domain == NULL))) {
6375+ spin_unlock(&cipso_v4_doi_list_lock);
6376+ rcu_read_unlock();
6377+ kfree(new_dom->domain);
6378+ kfree(new_dom);
6379+ return -EEXIST;
6380+ }
6381+ list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
6382+ spin_unlock(&cipso_v4_doi_list_lock);
6383+ rcu_read_unlock();
6384+
6385+ return 0;
6386+}
6387+
6388+/**
6389+ * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition
6390+ * @doi_def: the DOI definition
6391+ * @domain: the domain to remove
6392+ *
6393+ * Description:
6394+ * Removes the @domain from the DOI specified by @doi_def, this function
6395+ * should only be called by external functions (i.e. NetLabel). Returns zero
6396+ * on success and negative values on error.
6397+ *
6398+ */
6399+int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
6400+ const char *domain)
6401+{
6402+ struct cipso_v4_domhsh_entry *iter;
6403+
6404+ rcu_read_lock();
6405+ spin_lock(&cipso_v4_doi_list_lock);
6406+ list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
6407+ if (iter->valid &&
6408+ ((domain != NULL && iter->domain != NULL &&
6409+ strcmp(iter->domain, domain) == 0) ||
6410+ (domain == NULL && iter->domain == NULL))) {
6411+ iter->valid = 0;
6412+ list_del_rcu(&iter->list);
6413+ spin_unlock(&cipso_v4_doi_list_lock);
6414+ rcu_read_unlock();
6415+ call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
6416+
6417+ return 0;
6418+ }
6419+ spin_unlock(&cipso_v4_doi_list_lock);
6420+ rcu_read_unlock();
6421+
6422+ return -ENOENT;
6423+}
6424+
6425+/*
6426+ * Label Mapping Functions
6427+ */
6428+
6429+/**
6430+ * cipso_v4_map_lvl_valid - Checks to see if the given level is understood
6431+ * @doi_def: the DOI definition
6432+ * @level: the level to check
6433+ *
6434+ * Description:
6435+ * Checks the given level against the given DOI definition and returns a
6436+ * negative value if the level does not have a valid mapping and a zero value
6437+ * if the level is defined by the DOI.
6438+ *
6439+ */
6440+static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level)
6441+{
6442+ switch (doi_def->type) {
6443+ case CIPSO_V4_MAP_PASS:
6444+ return 0;
6445+ case CIPSO_V4_MAP_STD:
6446+ if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL)
6447+ return 0;
6448+ break;
6449+ }
6450+
6451+ return -EFAULT;
6452+}
6453+
6454+/**
6455+ * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network
6456+ * @doi_def: the DOI definition
6457+ * @host_lvl: the host MLS level
6458+ * @net_lvl: the network/CIPSO MLS level
6459+ *
6460+ * Description:
6461+ * Perform a label mapping to translate a local MLS level to the correct
6462+ * CIPSO level using the given DOI definition. Returns zero on success,
6463+ * negative values otherwise.
6464+ *
6465+ */
6466+static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
6467+ u32 host_lvl,
6468+ u32 *net_lvl)
6469+{
6470+ switch (doi_def->type) {
6471+ case CIPSO_V4_MAP_PASS:
6472+ *net_lvl = host_lvl;
6473+ return 0;
6474+ case CIPSO_V4_MAP_STD:
6475+ if (host_lvl < doi_def->map.std->lvl.local_size) {
6476+ *net_lvl = doi_def->map.std->lvl.local[host_lvl];
6477+ return 0;
6478+ }
6479+ break;
6480+ }
6481+
6482+ return -EINVAL;
6483+}
6484+
6485+/**
6486+ * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host
6487+ * @doi_def: the DOI definition
6488+ * @net_lvl: the network/CIPSO MLS level
6489+ * @host_lvl: the host MLS level
6490+ *
6491+ * Description:
6492+ * Perform a label mapping to translate a CIPSO level to the correct local MLS
6493+ * level using the given DOI definition. Returns zero on success, negative
6494+ * values otherwise.
6495+ *
6496+ */
6497+static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
6498+ u32 net_lvl,
6499+ u32 *host_lvl)
6500+{
6501+ struct cipso_v4_std_map_tbl *map_tbl;
6502+
6503+ switch (doi_def->type) {
6504+ case CIPSO_V4_MAP_PASS:
6505+ *host_lvl = net_lvl;
6506+ return 0;
6507+ case CIPSO_V4_MAP_STD:
6508+ map_tbl = doi_def->map.std;
6509+ if (net_lvl < map_tbl->lvl.cipso_size &&
6510+ map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) {
6511+ *host_lvl = doi_def->map.std->lvl.cipso[net_lvl];
6512+ return 0;
6513+ }
6514+ break;
6515+ }
6516+
6517+ return -EINVAL;
6518+}
6519+
6520+/**
6521+ * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid
6522+ * @doi_def: the DOI definition
6523+ * @bitmap: category bitmap
6524+ * @bitmap_len: bitmap length in bytes
6525+ *
6526+ * Description:
6527+ * Checks the given category bitmap against the given DOI definition and
6528+ * returns a negative value if any of the categories in the bitmap do not have
6529+ * a valid mapping and a zero value if all of the categories are valid.
6530+ *
6531+ */
6532+static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
6533+ const unsigned char *bitmap,
6534+ u32 bitmap_len)
6535+{
6536+ int cat = -1;
6537+ u32 bitmap_len_bits = bitmap_len * 8;
6538+ u32 cipso_cat_size = doi_def->map.std->cat.cipso_size;
6539+ u32 *cipso_array = doi_def->map.std->cat.cipso;
6540+
6541+ switch (doi_def->type) {
6542+ case CIPSO_V4_MAP_PASS:
6543+ return 0;
6544+ case CIPSO_V4_MAP_STD:
6545+ for (;;) {
6546+ cat = cipso_v4_bitmap_walk(bitmap,
6547+ bitmap_len_bits,
6548+ cat + 1,
6549+ 1);
6550+ if (cat < 0)
6551+ break;
6552+ if (cat >= cipso_cat_size ||
6553+ cipso_array[cat] >= CIPSO_V4_INV_CAT)
6554+ return -EFAULT;
6555+ }
6556+
6557+ if (cat == -1)
6558+ return 0;
6559+ break;
6560+ }
6561+
6562+ return -EFAULT;
6563+}
6564+
6565+/**
6566+ * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
6567+ * @doi_def: the DOI definition
6568+ * @host_cat: the category bitmap in host format
6569+ * @host_cat_len: the length of the host's category bitmap in bytes
6570+ * @net_cat: the zero'd out category bitmap in network/CIPSO format
6571+ * @net_cat_len: the length of the CIPSO bitmap in bytes
6572+ *
6573+ * Description:
6574+ * Perform a label mapping to translate a local MLS category bitmap to the
6575+ * correct CIPSO bitmap using the given DOI definition. Returns the minimum
6576+ * size in bytes of the network bitmap on success, negative values otherwise.
6577+ *
6578+ */
6579+static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
6580+ const unsigned char *host_cat,
6581+ u32 host_cat_len,
6582+ unsigned char *net_cat,
6583+ u32 net_cat_len)
6584+{
6585+ int host_spot = -1;
6586+ u32 net_spot;
6587+ u32 net_spot_max = 0;
6588+ u32 host_clen_bits = host_cat_len * 8;
6589+ u32 net_clen_bits = net_cat_len * 8;
6590+ u32 host_cat_size = doi_def->map.std->cat.local_size;
6591+ u32 *host_cat_array = doi_def->map.std->cat.local;
6592+
6593+ switch (doi_def->type) {
6594+ case CIPSO_V4_MAP_PASS:
6595+ net_spot_max = host_cat_len - 1;
6596+ while (net_spot_max > 0 && host_cat[net_spot_max] == 0)
6597+ net_spot_max--;
6598+ if (net_spot_max > net_cat_len)
6599+ return -EINVAL;
6600+ memcpy(net_cat, host_cat, net_spot_max);
6601+ return net_spot_max;
6602+ case CIPSO_V4_MAP_STD:
6603+ for (;;) {
6604+ host_spot = cipso_v4_bitmap_walk(host_cat,
6605+ host_clen_bits,
6606+ host_spot + 1,
6607+ 1);
6608+ if (host_spot < 0)
6609+ break;
6610+ if (host_spot >= host_cat_size)
6611+ return -EPERM;
6612+
6613+ net_spot = host_cat_array[host_spot];
6614+ if (net_spot >= net_clen_bits)
6615+ return -ENOSPC;
6616+ cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
6617+
6618+ if (net_spot > net_spot_max)
6619+ net_spot_max = net_spot;
6620+ }
6621+
6622+ if (host_spot == -2)
6623+ return -EFAULT;
6624+
6625+ if (++net_spot_max % 8)
6626+ return net_spot_max / 8 + 1;
6627+ return net_spot_max / 8;
6628+ }
6629+
6630+ return -EINVAL;
6631+}
6632+
6633+/**
6634+ * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host
6635+ * @doi_def: the DOI definition
6636+ * @net_cat: the category bitmap in network/CIPSO format
6637+ * @net_cat_len: the length of the CIPSO bitmap in bytes
6638+ * @host_cat: the zero'd out category bitmap in host format
6639+ * @host_cat_len: the length of the host's category bitmap in bytes
6640+ *
6641+ * Description:
6642+ * Perform a label mapping to translate a CIPSO bitmap to the correct local
6643+ * MLS category bitmap using the given DOI definition. Returns the minimum
6644+ * size in bytes of the host bitmap on success, negative values otherwise.
6645+ *
6646+ */
6647+static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
6648+ const unsigned char *net_cat,
6649+ u32 net_cat_len,
6650+ unsigned char *host_cat,
6651+ u32 host_cat_len)
6652+{
6653+ u32 host_spot;
6654+ u32 host_spot_max = 0;
6655+ int net_spot = -1;
6656+ u32 net_clen_bits = net_cat_len * 8;
6657+ u32 host_clen_bits = host_cat_len * 8;
6658+ u32 net_cat_size = doi_def->map.std->cat.cipso_size;
6659+ u32 *net_cat_array = doi_def->map.std->cat.cipso;
6660+
6661+ switch (doi_def->type) {
6662+ case CIPSO_V4_MAP_PASS:
6663+ if (net_cat_len > host_cat_len)
6664+ return -EINVAL;
6665+ memcpy(host_cat, net_cat, net_cat_len);
6666+ return net_cat_len;
6667+ case CIPSO_V4_MAP_STD:
6668+ for (;;) {
6669+ net_spot = cipso_v4_bitmap_walk(net_cat,
6670+ net_clen_bits,
6671+ net_spot + 1,
6672+ 1);
6673+ if (net_spot < 0)
6674+ break;
6675+ if (net_spot >= net_cat_size ||
6676+ net_cat_array[net_spot] >= CIPSO_V4_INV_CAT)
6677+ return -EPERM;
6678+
6679+ host_spot = net_cat_array[net_spot];
6680+ if (host_spot >= host_clen_bits)
6681+ return -ENOSPC;
6682+ cipso_v4_bitmap_setbit(host_cat, host_spot, 1);
6683+
6684+ if (host_spot > host_spot_max)
6685+ host_spot_max = host_spot;
6686+ }
6687+
6688+ if (net_spot == -2)
6689+ return -EFAULT;
6690+
6691+ if (++host_spot_max % 8)
6692+ return host_spot_max / 8 + 1;
6693+ return host_spot_max / 8;
6694+ }
6695+
6696+ return -EINVAL;
6697+}
6698+
6699+/*
6700+ * Protocol Handling Functions
6701+ */
6702+
6703+#define CIPSO_V4_HDR_LEN 6
6704+
6705+/**
6706+ * cipso_v4_gentag_hdr - Generate a CIPSO option header
6707+ * @doi_def: the DOI definition
6708+ * @len: the total tag length in bytes
6709+ * @buf: the CIPSO option buffer
6710+ *
6711+ * Description:
6712+ * Write a CIPSO header into the beginning of @buffer. Return zero on success,
6713+ * negative values on failure.
6714+ *
6715+ */
6716+static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
6717+ u32 len,
6718+ unsigned char *buf)
6719+{
6720+ if (CIPSO_V4_HDR_LEN + len > 40)
6721+ return -ENOSPC;
6722+
6723+ buf[0] = IPOPT_CIPSO;
6724+ buf[1] = CIPSO_V4_HDR_LEN + len;
6725+ *(u32 *)&buf[2] = htonl(doi_def->doi);
6726+
6727+ return 0;
6728+}
6729+
6730+#define CIPSO_V4_TAG1_CAT_LEN 30
6731+
6732+/**
6733+ * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
6734+ * @doi_def: the DOI definition
6735+ * @secattr: the security attributes
6736+ * @buffer: the option buffer
6737+ * @buffer_len: length of buffer in bytes
6738+ *
6739+ * Description:
6740+ * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The
6741+ * actual buffer length may be larger than the indicated size due to
6742+ * translation between host and network category bitmaps. Returns zero on
6743+ * success, negative values on failure.
6744+ *
6745+ */
6746+static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
6747+ const struct netlbl_lsm_secattr *secattr,
6748+ unsigned char **buffer,
6749+ u32 *buffer_len)
6750+{
6751+ int ret_val = -EPERM;
6752+ unsigned char *buf = NULL;
6753+ u32 buf_len;
6754+ u32 level;
6755+
6756+ if (secattr->mls_cat) {
6757+ buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN,
6758+ GFP_ATOMIC);
6759+ if (buf == NULL)
6760+ return -ENOMEM;
6761+
6762+ ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
6763+ secattr->mls_cat,
6764+ secattr->mls_cat_len,
6765+ &buf[CIPSO_V4_HDR_LEN + 4],
6766+ CIPSO_V4_TAG1_CAT_LEN);
6767+ if (ret_val < 0)
6768+ goto gentag_failure;
6769+
6770+ /* This will send packets using the "optimized" format when
6771+ * possibile as specified in section 3.4.2.6 of the
6772+ * CIPSO draft. */
6773+ if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10))
6774+ ret_val = 10;
6775+
6776+ buf_len = 4 + ret_val;
6777+ } else {
6778+ buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC);
6779+ if (buf == NULL)
6780+ return -ENOMEM;
6781+ buf_len = 4;
6782+ }
6783+
6784+ ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
6785+ if (ret_val != 0)
6786+ goto gentag_failure;
6787+
6788+ ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf);
6789+ if (ret_val != 0)
6790+ goto gentag_failure;
6791+
6792+ buf[CIPSO_V4_HDR_LEN] = 0x01;
6793+ buf[CIPSO_V4_HDR_LEN + 1] = buf_len;
6794+ buf[CIPSO_V4_HDR_LEN + 3] = level;
6795+
6796+ *buffer = buf;
6797+ *buffer_len = CIPSO_V4_HDR_LEN + buf_len;
6798+
6799+ return 0;
6800+
6801+gentag_failure:
6802+ kfree(buf);
6803+ return ret_val;
6804+}
6805+
6806+/**
6807+ * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
6808+ * @doi_def: the DOI definition
6809+ * @tag: the CIPSO tag
6810+ * @secattr: the security attributes
6811+ *
6812+ * Description:
6813+ * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
6814+ * attributes in @secattr. Return zero on success, negatives values on
6815+ * failure.
6816+ *
6817+ */
6818+static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
6819+ const unsigned char *tag,
6820+ struct netlbl_lsm_secattr *secattr)
6821+{
6822+ int ret_val;
6823+ u8 tag_len = tag[1];
6824+ u32 level;
6825+
6826+ ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
6827+ if (ret_val != 0)
6828+ return ret_val;
6829+ secattr->mls_lvl = level;
6830+ secattr->mls_lvl_vld = 1;
6831+
6832+ if (tag_len > 4) {
6833+ switch (doi_def->type) {
6834+ case CIPSO_V4_MAP_PASS:
6835+ secattr->mls_cat_len = tag_len - 4;
6836+ break;
6837+ case CIPSO_V4_MAP_STD:
6838+ secattr->mls_cat_len =
6839+ doi_def->map.std->cat.local_size;
6840+ break;
6841+ }
6842+ secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC);
6843+ if (secattr->mls_cat == NULL)
6844+ return -ENOMEM;
6845+
6846+ ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
6847+ &tag[4],
6848+ tag_len - 4,
6849+ secattr->mls_cat,
6850+ secattr->mls_cat_len);
6851+ if (ret_val < 0) {
6852+ kfree(secattr->mls_cat);
6853+ return ret_val;
6854+ }
6855+ secattr->mls_cat_len = ret_val;
6856+ }
6857+
6858+ return 0;
6859+}
6860+
6861+/**
6862+ * cipso_v4_validate - Validate a CIPSO option
6863+ * @option: the start of the option, on error it is set to point to the error
6864+ *
6865+ * Description:
6866+ * This routine is called to validate a CIPSO option, it checks all of the
6867+ * fields to ensure that they are at least valid, see the draft snippet below
6868+ * for details. If the option is valid then a zero value is returned and
6869+ * the value of @option is unchanged. If the option is invalid then a
6870+ * non-zero value is returned and @option is adjusted to point to the
6871+ * offending portion of the option. From the IETF draft ...
6872+ *
6873+ * "If any field within the CIPSO options, such as the DOI identifier, is not
6874+ * recognized the IP datagram is discarded and an ICMP 'parameter problem'
6875+ * (type 12) is generated and returned. The ICMP code field is set to 'bad
6876+ * parameter' (code 0) and the pointer is set to the start of the CIPSO field
6877+ * that is unrecognized."
6878+ *
6879+ */
6880+int cipso_v4_validate(unsigned char **option)
6881+{
6882+ unsigned char *opt = *option;
6883+ unsigned char *tag;
6884+ unsigned char opt_iter;
6885+ unsigned char err_offset = 0;
6886+ u8 opt_len;
6887+ u8 tag_len;
6888+ struct cipso_v4_doi *doi_def = NULL;
6889+ u32 tag_iter;
6890+
6891+ /* caller already checks for length values that are too large */
6892+ opt_len = opt[1];
6893+ if (opt_len < 8) {
6894+ err_offset = 1;
6895+ goto validate_return;
6896+ }
6897+
6898+ rcu_read_lock();
6899+ doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2])));
6900+ if (doi_def == NULL) {
6901+ err_offset = 2;
6902+ goto validate_return_locked;
6903+ }
6904+
6905+ opt_iter = 6;
6906+ tag = opt + opt_iter;
6907+ while (opt_iter < opt_len) {
6908+ for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];)
6909+ if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID ||
6910+ ++tag_iter == CIPSO_V4_TAG_MAXCNT) {
6911+ err_offset = opt_iter;
6912+ goto validate_return_locked;
6913+ }
6914+
6915+ tag_len = tag[1];
6916+ if (tag_len > (opt_len - opt_iter)) {
6917+ err_offset = opt_iter + 1;
6918+ goto validate_return_locked;
6919+ }
6920+
6921+ switch (tag[0]) {
6922+ case CIPSO_V4_TAG_RBITMAP:
6923+ if (tag_len < 4) {
6924+ err_offset = opt_iter + 1;
6925+ goto validate_return_locked;
6926+ }
6927+
6928+ /* We are already going to do all the verification
6929+ * necessary at the socket layer so from our point of
6930+ * view it is safe to turn these checks off (and less
6931+ * work), however, the CIPSO draft says we should do
6932+ * all the CIPSO validations here but it doesn't
6933+ * really specify _exactly_ what we need to validate
6934+ * ... so, just make it a sysctl tunable. */
6935+ if (cipso_v4_rbm_strictvalid) {
6936+ if (cipso_v4_map_lvl_valid(doi_def,
6937+ tag[3]) < 0) {
6938+ err_offset = opt_iter + 3;
6939+ goto validate_return_locked;
6940+ }
6941+ if (tag_len > 4 &&
6942+ cipso_v4_map_cat_rbm_valid(doi_def,
6943+ &tag[4],
6944+ tag_len - 4) < 0) {
6945+ err_offset = opt_iter + 4;
6946+ goto validate_return_locked;
6947+ }
6948+ }
6949+ break;
6950+ default:
6951+ err_offset = opt_iter;
6952+ goto validate_return_locked;
6953+ }
6954+
6955+ tag += tag_len;
6956+ opt_iter += tag_len;
6957+ }
6958+
6959+validate_return_locked:
6960+ rcu_read_unlock();
6961+validate_return:
6962+ *option = opt + err_offset;
6963+ return err_offset;
6964+}
6965+
6966+/**
6967+ * cipso_v4_error - Send the correct reponse for a bad packet
6968+ * @skb: the packet
6969+ * @error: the error code
6970+ * @gateway: CIPSO gateway flag
6971+ *
6972+ * Description:
6973+ * Based on the error code given in @error, send an ICMP error message back to
6974+ * the originating host. From the IETF draft ...
6975+ *
6976+ * "If the contents of the CIPSO [option] are valid but the security label is
6977+ * outside of the configured host or port label range, the datagram is
6978+ * discarded and an ICMP 'destination unreachable' (type 3) is generated and
6979+ * returned. The code field of the ICMP is set to 'communication with
6980+ * destination network administratively prohibited' (code 9) or to
6981+ * 'communication with destination host administratively prohibited'
6982+ * (code 10). The value of the code is dependent on whether the originator
6983+ * of the ICMP message is acting as a CIPSO host or a CIPSO gateway. The
6984+ * recipient of the ICMP message MUST be able to handle either value. The
6985+ * same procedure is performed if a CIPSO [option] can not be added to an
6986+ * IP packet because it is too large to fit in the IP options area."
6987+ *
6988+ * "If the error is triggered by receipt of an ICMP message, the message is
6989+ * discarded and no response is permitted (consistent with general ICMP
6990+ * processing rules)."
6991+ *
6992+ */
6993+void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
6994+{
6995+ if (skb->nh.iph->protocol == IPPROTO_ICMP || error != -EACCES)
6996+ return;
6997+
6998+ if (gateway)
6999+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
7000+ else
7001+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
7002+}
7003+
7004+/**
7005+ * cipso_v4_socket_setattr - Add a CIPSO option to a socket
7006+ * @sock: the socket
7007+ * @doi_def: the CIPSO DOI to use
7008+ * @secattr: the specific security attributes of the socket
7009+ *
7010+ * Description:
7011+ * Set the CIPSO option on the given socket using the DOI definition and
7012+ * security attributes passed to the function. This function requires
7013+ * exclusive access to @sock->sk, which means it either needs to be in the
7014+ * process of being created or locked via lock_sock(sock->sk). Returns zero on
7015+ * success and negative values on failure.
7016+ *
7017+ */
7018+int cipso_v4_socket_setattr(const struct socket *sock,
7019+ const struct cipso_v4_doi *doi_def,
7020+ const struct netlbl_lsm_secattr *secattr)
7021+{
7022+ int ret_val = -EPERM;
7023+ u32 iter;
7024+ unsigned char *buf = NULL;
7025+ u32 buf_len = 0;
7026+ u32 opt_len;
7027+ struct ip_options *opt = NULL;
7028+ struct sock *sk;
7029+ struct inet_sock *sk_inet;
7030+ struct inet_connection_sock *sk_conn;
7031+
7032+ /* In the case of sock_create_lite(), the sock->sk field is not
7033+ * defined yet but it is not a problem as the only users of these
7034+ * "lite" PF_INET sockets are functions which do an accept() call
7035+ * afterwards so we will label the socket as part of the accept(). */
7036+ sk = sock->sk;
7037+ if (sk == NULL)
7038+ return 0;
7039+
7040+ /* XXX - This code assumes only one tag per CIPSO option which isn't
7041+ * really a good assumption to make but since we only support the MAC
7042+ * tags right now it is a safe assumption. */
7043+ iter = 0;
7044+ do {
7045+ switch (doi_def->tags[iter]) {
7046+ case CIPSO_V4_TAG_RBITMAP:
7047+ ret_val = cipso_v4_gentag_rbm(doi_def,
7048+ secattr,
7049+ &buf,
7050+ &buf_len);
7051+ break;
7052+ default:
7053+ ret_val = -EPERM;
7054+ goto socket_setattr_failure;
7055+ }
7056+
7057+ iter++;
7058+ } while (ret_val != 0 &&
7059+ iter < CIPSO_V4_TAG_MAXCNT &&
7060+ doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
7061+ if (ret_val != 0)
7062+ goto socket_setattr_failure;
7063+
7064+ /* We can't use ip_options_get() directly because it makes a call to
7065+ * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
7066+ * we can't block here. */
7067+ opt_len = (buf_len + 3) & ~3;
7068+ opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
7069+ if (opt == NULL) {
7070+ ret_val = -ENOMEM;
7071+ goto socket_setattr_failure;
7072+ }
7073+ memcpy(opt->__data, buf, buf_len);
7074+ opt->optlen = opt_len;
7075+ opt->is_data = 1;
7076+ kfree(buf);
7077+ buf = NULL;
7078+ ret_val = ip_options_compile(opt, NULL);
7079+ if (ret_val != 0)
7080+ goto socket_setattr_failure;
7081+
7082+ sk_inet = inet_sk(sk);
7083+ if (sk_inet->is_icsk) {
7084+ sk_conn = inet_csk(sk);
7085+ if (sk_inet->opt)
7086+ sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen;
7087+ sk_conn->icsk_ext_hdr_len += opt->optlen;
7088+ sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
7089+ }
7090+ opt = xchg(&sk_inet->opt, opt);
7091+ kfree(opt);
7092+
7093+ return 0;
7094+
7095+socket_setattr_failure:
7096+ kfree(buf);
7097+ kfree(opt);
7098+ return ret_val;
7099+}
7100+
7101+/**
7102+ * cipso_v4_socket_getattr - Get the security attributes from a socket
7103+ * @sock: the socket
7104+ * @secattr: the security attributes
7105+ *
7106+ * Description:
7107+ * Query @sock to see if there is a CIPSO option attached to the socket and if
7108+ * there is return the CIPSO security attributes in @secattr. Returns zero on
7109+ * success and negative values on failure.
7110+ *
7111+ */
7112+int cipso_v4_socket_getattr(const struct socket *sock,
7113+ struct netlbl_lsm_secattr *secattr)
7114+{
7115+ int ret_val = -ENOMSG;
7116+ struct sock *sk;
7117+ struct inet_sock *sk_inet;
7118+ unsigned char *cipso_ptr;
7119+ u32 doi;
7120+ struct cipso_v4_doi *doi_def;
7121+
7122+ sk = sock->sk;
7123+ lock_sock(sk);
7124+ sk_inet = inet_sk(sk);
7125+ if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
7126+ goto socket_getattr_return;
7127+ cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
7128+ sizeof(struct iphdr);
7129+ ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
7130+ if (ret_val == 0)
7131+ goto socket_getattr_return;
7132+
7133+ doi = ntohl(*(u32 *)&cipso_ptr[2]);
7134+ rcu_read_lock();
7135+ doi_def = cipso_v4_doi_getdef(doi);
7136+ if (doi_def == NULL) {
7137+ rcu_read_unlock();
7138+ goto socket_getattr_return;
7139+ }
7140+ switch (cipso_ptr[6]) {
7141+ case CIPSO_V4_TAG_RBITMAP:
7142+ ret_val = cipso_v4_parsetag_rbm(doi_def,
7143+ &cipso_ptr[6],
7144+ secattr);
7145+ break;
7146+ }
7147+ rcu_read_unlock();
7148+
7149+socket_getattr_return:
7150+ release_sock(sk);
7151+ return ret_val;
7152+}
7153+
7154+/**
7155+ * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
7156+ * @skb: the packet
7157+ * @secattr: the security attributes
7158+ *
7159+ * Description:
7160+ * Parse the given packet's CIPSO option and return the security attributes.
7161+ * Returns zero on success and negative values on failure.
7162+ *
7163+ */
7164+int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
7165+ struct netlbl_lsm_secattr *secattr)
7166+{
7167+ int ret_val = -ENOMSG;
7168+ unsigned char *cipso_ptr;
7169+ u32 doi;
7170+ struct cipso_v4_doi *doi_def;
7171+
7172+ if (!CIPSO_V4_OPTEXIST(skb))
7173+ return -ENOMSG;
7174+ cipso_ptr = CIPSO_V4_OPTPTR(skb);
7175+ if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
7176+ return 0;
7177+
7178+ doi = ntohl(*(u32 *)&cipso_ptr[2]);
7179+ rcu_read_lock();
7180+ doi_def = cipso_v4_doi_getdef(doi);
7181+ if (doi_def == NULL)
7182+ goto skbuff_getattr_return;
7183+ switch (cipso_ptr[6]) {
7184+ case CIPSO_V4_TAG_RBITMAP:
7185+ ret_val = cipso_v4_parsetag_rbm(doi_def,
7186+ &cipso_ptr[6],
7187+ secattr);
7188+ break;
7189+ }
7190+
7191+skbuff_getattr_return:
7192+ rcu_read_unlock();
7193+ return ret_val;
7194+}
7195+
7196+/*
7197+ * Setup Functions
7198+ */
7199+
7200+/**
7201+ * cipso_v4_init - Initialize the CIPSO module
7202+ *
7203+ * Description:
7204+ * Initialize the CIPSO module and prepare it for use. Returns zero on success
7205+ * and negative values on failure.
7206+ *
7207+ */
7208+static int __init cipso_v4_init(void)
7209+{
7210+ int ret_val;
7211+
7212+ ret_val = cipso_v4_cache_init();
7213+ if (ret_val != 0)
7214+ panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n",
7215+ ret_val);
7216+
7217+ return 0;
7218+}
7219+
7220+subsys_initcall(cipso_v4_init);
7221diff -Nur linux-2.6.18-rc5/net/ipv4/devinet.c linux-2.6.19/net/ipv4/devinet.c
7222--- linux-2.6.18-rc5/net/ipv4/devinet.c 2006-08-28 05:41:48.000000000 +0200
7223+++ linux-2.6.19/net/ipv4/devinet.c 2006-09-22 10:04:58.000000000 +0200
7224@@ -43,6 +43,7 @@
7225 #include <linux/in.h>
7226 #include <linux/errno.h>
7227 #include <linux/interrupt.h>
7228+#include <linux/if_addr.h>
7229 #include <linux/if_ether.h>
7230 #include <linux/inet.h>
7231 #include <linux/netdevice.h>
7232@@ -62,6 +63,7 @@
7233 #include <net/ip.h>
7234 #include <net/route.h>
7235 #include <net/ip_fib.h>
7236+#include <net/netlink.h>
7237
7238 struct ipv4_devconf ipv4_devconf = {
7239 .accept_redirects = 1,
7240@@ -78,7 +80,15 @@
7241 .accept_source_route = 1,
7242 };
7243
7244-static void rtmsg_ifa(int event, struct in_ifaddr *);
7245+static struct nla_policy ifa_ipv4_policy[IFA_MAX+1] __read_mostly = {
7246+ [IFA_LOCAL] = { .type = NLA_U32 },
7247+ [IFA_ADDRESS] = { .type = NLA_U32 },
7248+ [IFA_BROADCAST] = { .type = NLA_U32 },
7249+ [IFA_ANYCAST] = { .type = NLA_U32 },
7250+ [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
7251+};
7252+
7253+static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
7254
7255 static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
7256 static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
7257@@ -229,8 +239,8 @@
7258 return 0;
7259 }
7260
7261-static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
7262- int destroy)
7263+static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
7264+ int destroy, struct nlmsghdr *nlh, u32 pid)
7265 {
7266 struct in_ifaddr *promote = NULL;
7267 struct in_ifaddr *ifa, *ifa1 = *ifap;
7268@@ -263,7 +273,7 @@
7269 if (!do_promote) {
7270 *ifap1 = ifa->ifa_next;
7271
7272- rtmsg_ifa(RTM_DELADDR, ifa);
7273+ rtmsg_ifa(RTM_DELADDR, ifa, nlh, pid);
7274 blocking_notifier_call_chain(&inetaddr_chain,
7275 NETDEV_DOWN, ifa);
7276 inet_free_ifa(ifa);
7277@@ -288,7 +298,7 @@
7278 is valid, it will try to restore deleted routes... Grr.
7279 So that, this order is correct.
7280 */
7281- rtmsg_ifa(RTM_DELADDR, ifa1);
7282+ rtmsg_ifa(RTM_DELADDR, ifa1, nlh, pid);
7283 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
7284
7285 if (promote) {
7286@@ -300,7 +310,7 @@
7287 }
7288
7289 promote->ifa_flags &= ~IFA_F_SECONDARY;
7290- rtmsg_ifa(RTM_NEWADDR, promote);
7291+ rtmsg_ifa(RTM_NEWADDR, promote, nlh, pid);
7292 blocking_notifier_call_chain(&inetaddr_chain,
7293 NETDEV_UP, promote);
7294 for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) {
7295@@ -319,7 +329,14 @@
7296 }
7297 }
7298
7299-static int inet_insert_ifa(struct in_ifaddr *ifa)
7300+static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
7301+ int destroy)
7302+{
7303+ __inet_del_ifa(in_dev, ifap, destroy, NULL, 0);
7304+}
7305+
7306+static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
7307+ u32 pid)
7308 {
7309 struct in_device *in_dev = ifa->ifa_dev;
7310 struct in_ifaddr *ifa1, **ifap, **last_primary;
7311@@ -364,12 +381,17 @@
7312 /* Send message first, then call notifier.
7313 Notifier will trigger FIB update, so that
7314 listeners of netlink will know about new ifaddr */
7315- rtmsg_ifa(RTM_NEWADDR, ifa);
7316+ rtmsg_ifa(RTM_NEWADDR, ifa, nlh, pid);
7317 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
7318
7319 return 0;
7320 }
7321
7322+static int inet_insert_ifa(struct in_ifaddr *ifa)
7323+{
7324+ return __inet_insert_ifa(ifa, NULL, 0);
7325+}
7326+
7327 static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
7328 {
7329 struct in_device *in_dev = __in_dev_get_rtnl(dev);
7330@@ -421,87 +443,134 @@
7331
7332 static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
7333 {
7334- struct rtattr **rta = arg;
7335+ struct nlattr *tb[IFA_MAX+1];
7336 struct in_device *in_dev;
7337- struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
7338+ struct ifaddrmsg *ifm;
7339 struct in_ifaddr *ifa, **ifap;
7340+ int err = -EINVAL;
7341
7342 ASSERT_RTNL();
7343
7344- if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL)
7345- goto out;
7346+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
7347+ if (err < 0)
7348+ goto errout;
7349+
7350+ ifm = nlmsg_data(nlh);
7351+ in_dev = inetdev_by_index(ifm->ifa_index);
7352+ if (in_dev == NULL) {
7353+ err = -ENODEV;
7354+ goto errout;
7355+ }
7356+
7357 __in_dev_put(in_dev);
7358
7359 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
7360 ifap = &ifa->ifa_next) {
7361- if ((rta[IFA_LOCAL - 1] &&
7362- memcmp(RTA_DATA(rta[IFA_LOCAL - 1]),
7363- &ifa->ifa_local, 4)) ||
7364- (rta[IFA_LABEL - 1] &&
7365- rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) ||
7366- (rta[IFA_ADDRESS - 1] &&
7367- (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
7368- !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]),
7369- ifa))))
7370+ if (tb[IFA_LOCAL] &&
7371+ ifa->ifa_local != nla_get_u32(tb[IFA_LOCAL]))
7372 continue;
7373- inet_del_ifa(in_dev, ifap, 1);
7374+
7375+ if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
7376+ continue;
7377+
7378+ if (tb[IFA_ADDRESS] &&
7379+ (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
7380+ !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa)))
7381+ continue;
7382+
7383+ __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).pid);
7384 return 0;
7385 }
7386-out:
7387- return -EADDRNOTAVAIL;
7388+
7389+ err = -EADDRNOTAVAIL;
7390+errout:
7391+ return err;
7392 }
7393
7394-static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
7395+static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
7396 {
7397- struct rtattr **rta = arg;
7398+ struct nlattr *tb[IFA_MAX+1];
7399+ struct in_ifaddr *ifa;
7400+ struct ifaddrmsg *ifm;
7401 struct net_device *dev;
7402 struct in_device *in_dev;
7403- struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
7404- struct in_ifaddr *ifa;
7405- int rc = -EINVAL;
7406+ int err = -EINVAL;
7407
7408- ASSERT_RTNL();
7409+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
7410+ if (err < 0)
7411+ goto errout;
7412
7413- if (ifm->ifa_prefixlen > 32 || !rta[IFA_LOCAL - 1])
7414- goto out;
7415+ ifm = nlmsg_data(nlh);
7416+ if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL)
7417+ goto errout;
7418
7419- rc = -ENODEV;
7420- if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
7421- goto out;
7422+ dev = __dev_get_by_index(ifm->ifa_index);
7423+ if (dev == NULL) {
7424+ err = -ENODEV;
7425+ goto errout;
7426+ }
7427
7428- rc = -ENOBUFS;
7429- if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) {
7430+ in_dev = __in_dev_get_rtnl(dev);
7431+ if (in_dev == NULL) {
7432 in_dev = inetdev_init(dev);
7433- if (!in_dev)
7434- goto out;
7435+ if (in_dev == NULL) {
7436+ err = -ENOBUFS;
7437+ goto errout;
7438+ }
7439 }
7440
7441- if ((ifa = inet_alloc_ifa()) == NULL)
7442- goto out;
7443+ ifa = inet_alloc_ifa();
7444+ if (ifa == NULL) {
7445+ /*
7446+ * A potential indev allocation can be left alive, it stays
7447+ * assigned to its device and is destroy with it.
7448+ */
7449+ err = -ENOBUFS;
7450+ goto errout;
7451+ }
7452+
7453+ in_dev_hold(in_dev);
7454+
7455+ if (tb[IFA_ADDRESS] == NULL)
7456+ tb[IFA_ADDRESS] = tb[IFA_LOCAL];
7457
7458- if (!rta[IFA_ADDRESS - 1])
7459- rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1];
7460- memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL - 1]), 4);
7461- memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS - 1]), 4);
7462 ifa->ifa_prefixlen = ifm->ifa_prefixlen;
7463 ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen);
7464- if (rta[IFA_BROADCAST - 1])
7465- memcpy(&ifa->ifa_broadcast,
7466- RTA_DATA(rta[IFA_BROADCAST - 1]), 4);
7467- if (rta[IFA_ANYCAST - 1])
7468- memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST - 1]), 4);
7469 ifa->ifa_flags = ifm->ifa_flags;
7470 ifa->ifa_scope = ifm->ifa_scope;
7471- in_dev_hold(in_dev);
7472- ifa->ifa_dev = in_dev;
7473- if (rta[IFA_LABEL - 1])
7474- rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL - 1], IFNAMSIZ);
7475+ ifa->ifa_dev = in_dev;
7476+
7477+ ifa->ifa_local = nla_get_u32(tb[IFA_LOCAL]);
7478+ ifa->ifa_address = nla_get_u32(tb[IFA_ADDRESS]);
7479+
7480+ if (tb[IFA_BROADCAST])
7481+ ifa->ifa_broadcast = nla_get_u32(tb[IFA_BROADCAST]);
7482+
7483+ if (tb[IFA_ANYCAST])
7484+ ifa->ifa_anycast = nla_get_u32(tb[IFA_ANYCAST]);
7485+
7486+ if (tb[IFA_LABEL])
7487+ nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
7488 else
7489 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
7490
7491- rc = inet_insert_ifa(ifa);
7492-out:
7493- return rc;
7494+ return ifa;
7495+
7496+errout:
7497+ return ERR_PTR(err);
7498+}
7499+
7500+static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
7501+{
7502+ struct in_ifaddr *ifa;
7503+
7504+ ASSERT_RTNL();
7505+
7506+ ifa = rtm_to_ifaddr(nlh);
7507+ if (IS_ERR(ifa))
7508+ return PTR_ERR(ifa);
7509+
7510+ return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).pid);
7511 }
7512
7513 /*
7514@@ -1056,32 +1125,37 @@
7515 {
7516 struct ifaddrmsg *ifm;
7517 struct nlmsghdr *nlh;
7518- unsigned char *b = skb->tail;
7519
7520- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
7521- ifm = NLMSG_DATA(nlh);
7522+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
7523+ if (nlh == NULL)
7524+ return -ENOBUFS;
7525+
7526+ ifm = nlmsg_data(nlh);
7527 ifm->ifa_family = AF_INET;
7528 ifm->ifa_prefixlen = ifa->ifa_prefixlen;
7529 ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT;
7530 ifm->ifa_scope = ifa->ifa_scope;
7531 ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
7532+
7533 if (ifa->ifa_address)
7534- RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address);
7535+ NLA_PUT_U32(skb, IFA_ADDRESS, ifa->ifa_address);
7536+
7537 if (ifa->ifa_local)
7538- RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local);
7539+ NLA_PUT_U32(skb, IFA_LOCAL, ifa->ifa_local);
7540+
7541 if (ifa->ifa_broadcast)
7542- RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast);
7543+ NLA_PUT_U32(skb, IFA_BROADCAST, ifa->ifa_broadcast);
7544+
7545 if (ifa->ifa_anycast)
7546- RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast);
7547+ NLA_PUT_U32(skb, IFA_ANYCAST, ifa->ifa_anycast);
7548+
7549 if (ifa->ifa_label[0])
7550- RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
7551- nlh->nlmsg_len = skb->tail - b;
7552- return skb->len;
7553+ NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label);
7554+
7555+ return nlmsg_end(skb, nlh);
7556
7557-nlmsg_failure:
7558-rtattr_failure:
7559- skb_trim(skb, b - skb->data);
7560- return -1;
7561+nla_put_failure:
7562+ return nlmsg_cancel(skb, nlh);
7563 }
7564
7565 static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
7566@@ -1127,19 +1201,27 @@
7567 return skb->len;
7568 }
7569
7570-static void rtmsg_ifa(int event, struct in_ifaddr* ifa)
7571+static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
7572+ u32 pid)
7573 {
7574- int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + 128);
7575- struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
7576+ struct sk_buff *skb;
7577+ u32 seq = nlh ? nlh->nlmsg_seq : 0;
7578+ int err = -ENOBUFS;
7579+
7580+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
7581+ if (skb == NULL)
7582+ goto errout;
7583
7584- if (!skb)
7585- netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS);
7586- else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
7587+ err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
7588+ if (err < 0) {
7589 kfree_skb(skb);
7590- netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL);
7591- } else {
7592- netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_IFADDR, GFP_KERNEL);
7593+ goto errout;
7594 }
7595+
7596+ err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
7597+errout:
7598+ if (err < 0)
7599+ rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err);
7600 }
7601
7602 static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = {
7603@@ -1151,9 +1233,7 @@
7604 [RTM_GETROUTE - RTM_BASE] = { .doit = inet_rtm_getroute,
7605 .dumpit = inet_dump_fib, },
7606 #ifdef CONFIG_IP_MULTIPLE_TABLES
7607- [RTM_NEWRULE - RTM_BASE] = { .doit = inet_rtm_newrule, },
7608- [RTM_DELRULE - RTM_BASE] = { .doit = inet_rtm_delrule, },
7609- [RTM_GETRULE - RTM_BASE] = { .dumpit = inet_dump_rules, },
7610+ [RTM_GETRULE - RTM_BASE] = { .dumpit = fib4_rules_dump, },
7611 #endif
7612 };
7613
7614diff -Nur linux-2.6.18-rc5/net/ipv4/esp4.c linux-2.6.19/net/ipv4/esp4.c
7615--- linux-2.6.18-rc5/net/ipv4/esp4.c 2006-08-28 05:41:48.000000000 +0200
7616+++ linux-2.6.19/net/ipv4/esp4.c 2006-09-22 10:04:58.000000000 +0200
7617@@ -91,9 +91,13 @@
7618 esph->seq_no = htonl(++x->replay.oseq);
7619 xfrm_aevent_doreplay(x);
7620
7621- if (esp->conf.ivlen)
7622+ if (esp->conf.ivlen) {
7623+ if (unlikely(!esp->conf.ivinitted)) {
7624+ get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
7625+ esp->conf.ivinitted = 1;
7626+ }
7627 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
7628-
7629+ }
7630 do {
7631 struct scatterlist *sg = &esp->sgbuf[0];
7632
7633@@ -237,7 +241,7 @@
7634 * as per draft-ietf-ipsec-udp-encaps-06,
7635 * section 3.1.2
7636 */
7637- if (!x->props.mode)
7638+ if (x->props.mode == XFRM_MODE_TRANSPORT)
7639 skb->ip_summed = CHECKSUM_UNNECESSARY;
7640 }
7641
7642@@ -256,7 +260,7 @@
7643 struct esp_data *esp = x->data;
7644 u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
7645
7646- if (x->props.mode) {
7647+ if (x->props.mode == XFRM_MODE_TUNNEL) {
7648 mtu = ALIGN(mtu + 2, blksize);
7649 } else {
7650 /* The worst case. */
7651@@ -363,12 +367,12 @@
7652 esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
7653 if (unlikely(esp->conf.ivec == NULL))
7654 goto error;
7655- get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
7656+ esp->conf.ivinitted = 0;
7657 }
7658 if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len))
7659 goto error;
7660 x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
7661- if (x->props.mode)
7662+ if (x->props.mode == XFRM_MODE_TUNNEL)
7663 x->props.header_len += sizeof(struct iphdr);
7664 if (x->encap) {
7665 struct xfrm_encap_tmpl *encap = x->encap;
7666diff -Nur linux-2.6.18-rc5/net/ipv4/fib_frontend.c linux-2.6.19/net/ipv4/fib_frontend.c
7667--- linux-2.6.18-rc5/net/ipv4/fib_frontend.c 2006-08-28 05:41:48.000000000 +0200
7668+++ linux-2.6.19/net/ipv4/fib_frontend.c 2006-09-22 10:04:58.000000000 +0200
7669@@ -32,10 +32,12 @@
7670 #include <linux/inet.h>
7671 #include <linux/inetdevice.h>
7672 #include <linux/netdevice.h>
7673+#include <linux/if_addr.h>
7674 #include <linux/if_arp.h>
7675 #include <linux/skbuff.h>
7676 #include <linux/netlink.h>
7677 #include <linux/init.h>
7678+#include <linux/list.h>
7679
7680 #include <net/ip.h>
7681 #include <net/protocol.h>
7682@@ -50,48 +52,67 @@
7683
7684 #ifndef CONFIG_IP_MULTIPLE_TABLES
7685
7686-#define RT_TABLE_MIN RT_TABLE_MAIN
7687-
7688 struct fib_table *ip_fib_local_table;
7689 struct fib_table *ip_fib_main_table;
7690
7691-#else
7692+#define FIB_TABLE_HASHSZ 1
7693+static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
7694
7695-#define RT_TABLE_MIN 1
7696+#else
7697
7698-struct fib_table *fib_tables[RT_TABLE_MAX+1];
7699+#define FIB_TABLE_HASHSZ 256
7700+static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
7701
7702-struct fib_table *__fib_new_table(int id)
7703+struct fib_table *fib_new_table(u32 id)
7704 {
7705 struct fib_table *tb;
7706+ unsigned int h;
7707
7708+ if (id == 0)
7709+ id = RT_TABLE_MAIN;
7710+ tb = fib_get_table(id);
7711+ if (tb)
7712+ return tb;
7713 tb = fib_hash_init(id);
7714 if (!tb)
7715 return NULL;
7716- fib_tables[id] = tb;
7717+ h = id & (FIB_TABLE_HASHSZ - 1);
7718+ hlist_add_head_rcu(&tb->tb_hlist, &fib_table_hash[h]);
7719 return tb;
7720 }
7721
7722+struct fib_table *fib_get_table(u32 id)
7723+{
7724+ struct fib_table *tb;
7725+ struct hlist_node *node;
7726+ unsigned int h;
7727
7728+ if (id == 0)
7729+ id = RT_TABLE_MAIN;
7730+ h = id & (FIB_TABLE_HASHSZ - 1);
7731+ rcu_read_lock();
7732+ hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb_hlist) {
7733+ if (tb->tb_id == id) {
7734+ rcu_read_unlock();
7735+ return tb;
7736+ }
7737+ }
7738+ rcu_read_unlock();
7739+ return NULL;
7740+}
7741 #endif /* CONFIG_IP_MULTIPLE_TABLES */
7742
7743-
7744 static void fib_flush(void)
7745 {
7746 int flushed = 0;
7747-#ifdef CONFIG_IP_MULTIPLE_TABLES
7748 struct fib_table *tb;
7749- int id;
7750+ struct hlist_node *node;
7751+ unsigned int h;
7752
7753- for (id = RT_TABLE_MAX; id>0; id--) {
7754- if ((tb = fib_get_table(id))==NULL)
7755- continue;
7756- flushed += tb->tb_flush(tb);
7757- }
7758-#else /* CONFIG_IP_MULTIPLE_TABLES */
7759- flushed += ip_fib_main_table->tb_flush(ip_fib_main_table);
7760- flushed += ip_fib_local_table->tb_flush(ip_fib_local_table);
7761-#endif /* CONFIG_IP_MULTIPLE_TABLES */
7762+ for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
7763+ hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist)
7764+ flushed += tb->tb_flush(tb);
7765+ }
7766
7767 if (flushed)
7768 rt_cache_flush(-1);
7769@@ -232,42 +253,190 @@
7770
7771 #ifndef CONFIG_IP_NOSIOCRT
7772
7773+static inline u32 sk_extract_addr(struct sockaddr *addr)
7774+{
7775+ return ((struct sockaddr_in *) addr)->sin_addr.s_addr;
7776+}
7777+
7778+static int put_rtax(struct nlattr *mx, int len, int type, u32 value)
7779+{
7780+ struct nlattr *nla;
7781+
7782+ nla = (struct nlattr *) ((char *) mx + len);
7783+ nla->nla_type = type;
7784+ nla->nla_len = nla_attr_size(4);
7785+ *(u32 *) nla_data(nla) = value;
7786+
7787+ return len + nla_total_size(4);
7788+}
7789+
7790+static int rtentry_to_fib_config(int cmd, struct rtentry *rt,
7791+ struct fib_config *cfg)
7792+{
7793+ u32 addr;
7794+ int plen;
7795+
7796+ memset(cfg, 0, sizeof(*cfg));
7797+
7798+ if (rt->rt_dst.sa_family != AF_INET)
7799+ return -EAFNOSUPPORT;
7800+
7801+ /*
7802+ * Check mask for validity:
7803+ * a) it must be contiguous.
7804+ * b) destination must have all host bits clear.
7805+ * c) if application forgot to set correct family (AF_INET),
7806+ * reject request unless it is absolutely clear i.e.
7807+ * both family and mask are zero.
7808+ */
7809+ plen = 32;
7810+ addr = sk_extract_addr(&rt->rt_dst);
7811+ if (!(rt->rt_flags & RTF_HOST)) {
7812+ u32 mask = sk_extract_addr(&rt->rt_genmask);
7813+
7814+ if (rt->rt_genmask.sa_family != AF_INET) {
7815+ if (mask || rt->rt_genmask.sa_family)
7816+ return -EAFNOSUPPORT;
7817+ }
7818+
7819+ if (bad_mask(mask, addr))
7820+ return -EINVAL;
7821+
7822+ plen = inet_mask_len(mask);
7823+ }
7824+
7825+ cfg->fc_dst_len = plen;
7826+ cfg->fc_dst = addr;
7827+
7828+ if (cmd != SIOCDELRT) {
7829+ cfg->fc_nlflags = NLM_F_CREATE;
7830+ cfg->fc_protocol = RTPROT_BOOT;
7831+ }
7832+
7833+ if (rt->rt_metric)
7834+ cfg->fc_priority = rt->rt_metric - 1;
7835+
7836+ if (rt->rt_flags & RTF_REJECT) {
7837+ cfg->fc_scope = RT_SCOPE_HOST;
7838+ cfg->fc_type = RTN_UNREACHABLE;
7839+ return 0;
7840+ }
7841+
7842+ cfg->fc_scope = RT_SCOPE_NOWHERE;
7843+ cfg->fc_type = RTN_UNICAST;
7844+
7845+ if (rt->rt_dev) {
7846+ char *colon;
7847+ struct net_device *dev;
7848+ char devname[IFNAMSIZ];
7849+
7850+ if (copy_from_user(devname, rt->rt_dev, IFNAMSIZ-1))
7851+ return -EFAULT;
7852+
7853+ devname[IFNAMSIZ-1] = 0;
7854+ colon = strchr(devname, ':');
7855+ if (colon)
7856+ *colon = 0;
7857+ dev = __dev_get_by_name(devname);
7858+ if (!dev)
7859+ return -ENODEV;
7860+ cfg->fc_oif = dev->ifindex;
7861+ if (colon) {
7862+ struct in_ifaddr *ifa;
7863+ struct in_device *in_dev = __in_dev_get_rtnl(dev);
7864+ if (!in_dev)
7865+ return -ENODEV;
7866+ *colon = ':';
7867+ for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next)
7868+ if (strcmp(ifa->ifa_label, devname) == 0)
7869+ break;
7870+ if (ifa == NULL)
7871+ return -ENODEV;
7872+ cfg->fc_prefsrc = ifa->ifa_local;
7873+ }
7874+ }
7875+
7876+ addr = sk_extract_addr(&rt->rt_gateway);
7877+ if (rt->rt_gateway.sa_family == AF_INET && addr) {
7878+ cfg->fc_gw = addr;
7879+ if (rt->rt_flags & RTF_GATEWAY &&
7880+ inet_addr_type(addr) == RTN_UNICAST)
7881+ cfg->fc_scope = RT_SCOPE_UNIVERSE;
7882+ }
7883+
7884+ if (cmd == SIOCDELRT)
7885+ return 0;
7886+
7887+ if (rt->rt_flags & RTF_GATEWAY && !cfg->fc_gw)
7888+ return -EINVAL;
7889+
7890+ if (cfg->fc_scope == RT_SCOPE_NOWHERE)
7891+ cfg->fc_scope = RT_SCOPE_LINK;
7892+
7893+ if (rt->rt_flags & (RTF_MTU | RTF_WINDOW | RTF_IRTT)) {
7894+ struct nlattr *mx;
7895+ int len = 0;
7896+
7897+ mx = kzalloc(3 * nla_total_size(4), GFP_KERNEL);
7898+ if (mx == NULL)
7899+ return -ENOMEM;
7900+
7901+ if (rt->rt_flags & RTF_MTU)
7902+ len = put_rtax(mx, len, RTAX_ADVMSS, rt->rt_mtu - 40);
7903+
7904+ if (rt->rt_flags & RTF_WINDOW)
7905+ len = put_rtax(mx, len, RTAX_WINDOW, rt->rt_window);
7906+
7907+ if (rt->rt_flags & RTF_IRTT)
7908+ len = put_rtax(mx, len, RTAX_RTT, rt->rt_irtt << 3);
7909+
7910+ cfg->fc_mx = mx;
7911+ cfg->fc_mx_len = len;
7912+ }
7913+
7914+ return 0;
7915+}
7916+
7917 /*
7918 * Handle IP routing ioctl calls. These are used to manipulate the routing tables
7919 */
7920
7921 int ip_rt_ioctl(unsigned int cmd, void __user *arg)
7922 {
7923+ struct fib_config cfg;
7924+ struct rtentry rt;
7925 int err;
7926- struct kern_rta rta;
7927- struct rtentry r;
7928- struct {
7929- struct nlmsghdr nlh;
7930- struct rtmsg rtm;
7931- } req;
7932
7933 switch (cmd) {
7934 case SIOCADDRT: /* Add a route */
7935 case SIOCDELRT: /* Delete a route */
7936 if (!capable(CAP_NET_ADMIN))
7937 return -EPERM;
7938- if (copy_from_user(&r, arg, sizeof(struct rtentry)))
7939+
7940+ if (copy_from_user(&rt, arg, sizeof(rt)))
7941 return -EFAULT;
7942+
7943 rtnl_lock();
7944- err = fib_convert_rtentry(cmd, &req.nlh, &req.rtm, &rta, &r);
7945+ err = rtentry_to_fib_config(cmd, &rt, &cfg);
7946 if (err == 0) {
7947+ struct fib_table *tb;
7948+
7949 if (cmd == SIOCDELRT) {
7950- struct fib_table *tb = fib_get_table(req.rtm.rtm_table);
7951- err = -ESRCH;
7952+ tb = fib_get_table(cfg.fc_table);
7953 if (tb)
7954- err = tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
7955+ err = tb->tb_delete(tb, &cfg);
7956+ else
7957+ err = -ESRCH;
7958 } else {
7959- struct fib_table *tb = fib_new_table(req.rtm.rtm_table);
7960- err = -ENOBUFS;
7961+ tb = fib_new_table(cfg.fc_table);
7962 if (tb)
7963- err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
7964+ err = tb->tb_insert(tb, &cfg);
7965+ else
7966+ err = -ENOBUFS;
7967 }
7968- kfree(rta.rta_mx);
7969+
7970+ /* allocated by rtentry_to_fib_config() */
7971+ kfree(cfg.fc_mx);
7972 }
7973 rtnl_unlock();
7974 return err;
7975@@ -284,77 +453,169 @@
7976
7977 #endif
7978
7979-static int inet_check_attr(struct rtmsg *r, struct rtattr **rta)
7980-{
7981- int i;
7982+struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = {
7983+ [RTA_DST] = { .type = NLA_U32 },
7984+ [RTA_SRC] = { .type = NLA_U32 },
7985+ [RTA_IIF] = { .type = NLA_U32 },
7986+ [RTA_OIF] = { .type = NLA_U32 },
7987+ [RTA_GATEWAY] = { .type = NLA_U32 },
7988+ [RTA_PRIORITY] = { .type = NLA_U32 },
7989+ [RTA_PREFSRC] = { .type = NLA_U32 },
7990+ [RTA_METRICS] = { .type = NLA_NESTED },
7991+ [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
7992+ [RTA_PROTOINFO] = { .type = NLA_U32 },
7993+ [RTA_FLOW] = { .type = NLA_U32 },
7994+ [RTA_MP_ALGO] = { .type = NLA_U32 },
7995+};
7996
7997- for (i=1; i<=RTA_MAX; i++, rta++) {
7998- struct rtattr *attr = *rta;
7999- if (attr) {
8000- if (RTA_PAYLOAD(attr) < 4)
8001- return -EINVAL;
8002- if (i != RTA_MULTIPATH && i != RTA_METRICS)
8003- *rta = (struct rtattr*)RTA_DATA(attr);
8004+static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
8005+ struct fib_config *cfg)
8006+{
8007+ struct nlattr *attr;
8008+ int err, remaining;
8009+ struct rtmsg *rtm;
8010+
8011+ err = nlmsg_validate(nlh, sizeof(*rtm), RTA_MAX, rtm_ipv4_policy);
8012+ if (err < 0)
8013+ goto errout;
8014+
8015+ memset(cfg, 0, sizeof(*cfg));
8016+
8017+ rtm = nlmsg_data(nlh);
8018+ cfg->fc_family = rtm->rtm_family;
8019+ cfg->fc_dst_len = rtm->rtm_dst_len;
8020+ cfg->fc_src_len = rtm->rtm_src_len;
8021+ cfg->fc_tos = rtm->rtm_tos;
8022+ cfg->fc_table = rtm->rtm_table;
8023+ cfg->fc_protocol = rtm->rtm_protocol;
8024+ cfg->fc_scope = rtm->rtm_scope;
8025+ cfg->fc_type = rtm->rtm_type;
8026+ cfg->fc_flags = rtm->rtm_flags;
8027+ cfg->fc_nlflags = nlh->nlmsg_flags;
8028+
8029+ cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
8030+ cfg->fc_nlinfo.nlh = nlh;
8031+
8032+ nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
8033+ switch (attr->nla_type) {
8034+ case RTA_DST:
8035+ cfg->fc_dst = nla_get_u32(attr);
8036+ break;
8037+ case RTA_SRC:
8038+ cfg->fc_src = nla_get_u32(attr);
8039+ break;
8040+ case RTA_OIF:
8041+ cfg->fc_oif = nla_get_u32(attr);
8042+ break;
8043+ case RTA_GATEWAY:
8044+ cfg->fc_gw = nla_get_u32(attr);
8045+ break;
8046+ case RTA_PRIORITY:
8047+ cfg->fc_priority = nla_get_u32(attr);
8048+ break;
8049+ case RTA_PREFSRC:
8050+ cfg->fc_prefsrc = nla_get_u32(attr);
8051+ break;
8052+ case RTA_METRICS:
8053+ cfg->fc_mx = nla_data(attr);
8054+ cfg->fc_mx_len = nla_len(attr);
8055+ break;
8056+ case RTA_MULTIPATH:
8057+ cfg->fc_mp = nla_data(attr);
8058+ cfg->fc_mp_len = nla_len(attr);
8059+ break;
8060+ case RTA_FLOW:
8061+ cfg->fc_flow = nla_get_u32(attr);
8062+ break;
8063+ case RTA_MP_ALGO:
8064+ cfg->fc_mp_alg = nla_get_u32(attr);
8065+ break;
8066+ case RTA_TABLE:
8067+ cfg->fc_table = nla_get_u32(attr);
8068+ break;
8069 }
8070 }
8071+
8072 return 0;
8073+errout:
8074+ return err;
8075 }
8076
8077 int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
8078 {
8079- struct fib_table * tb;
8080- struct rtattr **rta = arg;
8081- struct rtmsg *r = NLMSG_DATA(nlh);
8082+ struct fib_config cfg;
8083+ struct fib_table *tb;
8084+ int err;
8085
8086- if (inet_check_attr(r, rta))
8087- return -EINVAL;
8088+ err = rtm_to_fib_config(skb, nlh, &cfg);
8089+ if (err < 0)
8090+ goto errout;
8091+
8092+ tb = fib_get_table(cfg.fc_table);
8093+ if (tb == NULL) {
8094+ err = -ESRCH;
8095+ goto errout;
8096+ }
8097
8098- tb = fib_get_table(r->rtm_table);
8099- if (tb)
8100- return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
8101- return -ESRCH;
8102+ err = tb->tb_delete(tb, &cfg);
8103+errout:
8104+ return err;
8105 }
8106
8107 int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
8108 {
8109- struct fib_table * tb;
8110- struct rtattr **rta = arg;
8111- struct rtmsg *r = NLMSG_DATA(nlh);
8112+ struct fib_config cfg;
8113+ struct fib_table *tb;
8114+ int err;
8115
8116- if (inet_check_attr(r, rta))
8117- return -EINVAL;
8118+ err = rtm_to_fib_config(skb, nlh, &cfg);
8119+ if (err < 0)
8120+ goto errout;
8121+
8122+ tb = fib_new_table(cfg.fc_table);
8123+ if (tb == NULL) {
8124+ err = -ENOBUFS;
8125+ goto errout;
8126+ }
8127
8128- tb = fib_new_table(r->rtm_table);
8129- if (tb)
8130- return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
8131- return -ENOBUFS;
8132+ err = tb->tb_insert(tb, &cfg);
8133+errout:
8134+ return err;
8135 }
8136
8137 int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
8138 {
8139- int t;
8140- int s_t;
8141+ unsigned int h, s_h;
8142+ unsigned int e = 0, s_e;
8143 struct fib_table *tb;
8144+ struct hlist_node *node;
8145+ int dumped = 0;
8146
8147- if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
8148- ((struct rtmsg*)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
8149+ if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
8150+ ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED)
8151 return ip_rt_dump(skb, cb);
8152
8153- s_t = cb->args[0];
8154- if (s_t == 0)
8155- s_t = cb->args[0] = RT_TABLE_MIN;
8156+ s_h = cb->args[0];
8157+ s_e = cb->args[1];
8158
8159- for (t=s_t; t<=RT_TABLE_MAX; t++) {
8160- if (t < s_t) continue;
8161- if (t > s_t)
8162- memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
8163- if ((tb = fib_get_table(t))==NULL)
8164- continue;
8165- if (tb->tb_dump(tb, skb, cb) < 0)
8166- break;
8167+ for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
8168+ e = 0;
8169+ hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist) {
8170+ if (e < s_e)
8171+ goto next;
8172+ if (dumped)
8173+ memset(&cb->args[2], 0, sizeof(cb->args) -
8174+ 2 * sizeof(cb->args[0]));
8175+ if (tb->tb_dump(tb, skb, cb) < 0)
8176+ goto out;
8177+ dumped = 1;
8178+next:
8179+ e++;
8180+ }
8181 }
8182-
8183- cb->args[0] = t;
8184+out:
8185+ cb->args[1] = e;
8186+ cb->args[0] = h;
8187
8188 return skb->len;
8189 }
8190@@ -366,17 +627,19 @@
8191 only when netlink is already locked.
8192 */
8193
8194-static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr *ifa)
8195+static void fib_magic(int cmd, int type, u32 dst, int dst_len,
8196+ struct in_ifaddr *ifa)
8197 {
8198- struct fib_table * tb;
8199- struct {
8200- struct nlmsghdr nlh;
8201- struct rtmsg rtm;
8202- } req;
8203- struct kern_rta rta;
8204-
8205- memset(&req.rtm, 0, sizeof(req.rtm));
8206- memset(&rta, 0, sizeof(rta));
8207+ struct fib_table *tb;
8208+ struct fib_config cfg = {
8209+ .fc_protocol = RTPROT_KERNEL,
8210+ .fc_type = type,
8211+ .fc_dst = dst,
8212+ .fc_dst_len = dst_len,
8213+ .fc_prefsrc = ifa->ifa_local,
8214+ .fc_oif = ifa->ifa_dev->dev->ifindex,
8215+ .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
8216+ };
8217
8218 if (type == RTN_UNICAST)
8219 tb = fib_new_table(RT_TABLE_MAIN);
8220@@ -386,26 +649,17 @@
8221 if (tb == NULL)
8222 return;
8223
8224- req.nlh.nlmsg_len = sizeof(req);
8225- req.nlh.nlmsg_type = cmd;
8226- req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
8227- req.nlh.nlmsg_pid = 0;
8228- req.nlh.nlmsg_seq = 0;
8229-
8230- req.rtm.rtm_dst_len = dst_len;
8231- req.rtm.rtm_table = tb->tb_id;
8232- req.rtm.rtm_protocol = RTPROT_KERNEL;
8233- req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
8234- req.rtm.rtm_type = type;
8235-
8236- rta.rta_dst = &dst;
8237- rta.rta_prefsrc = &ifa->ifa_local;
8238- rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
8239+ cfg.fc_table = tb->tb_id;
8240+
8241+ if (type != RTN_LOCAL)
8242+ cfg.fc_scope = RT_SCOPE_LINK;
8243+ else
8244+ cfg.fc_scope = RT_SCOPE_HOST;
8245
8246 if (cmd == RTM_NEWROUTE)
8247- tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
8248+ tb->tb_insert(tb, &cfg);
8249 else
8250- tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL);
8251+ tb->tb_delete(tb, &cfg);
8252 }
8253
8254 void fib_add_ifaddr(struct in_ifaddr *ifa)
8255@@ -652,11 +906,17 @@
8256
8257 void __init ip_fib_init(void)
8258 {
8259+ unsigned int i;
8260+
8261+ for (i = 0; i < FIB_TABLE_HASHSZ; i++)
8262+ INIT_HLIST_HEAD(&fib_table_hash[i]);
8263 #ifndef CONFIG_IP_MULTIPLE_TABLES
8264 ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL);
8265+ hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]);
8266 ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN);
8267+ hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]);
8268 #else
8269- fib_rules_init();
8270+ fib4_rules_init();
8271 #endif
8272
8273 register_netdevice_notifier(&fib_netdev_notifier);
8274diff -Nur linux-2.6.18-rc5/net/ipv4/fib_hash.c linux-2.6.19/net/ipv4/fib_hash.c
8275--- linux-2.6.18-rc5/net/ipv4/fib_hash.c 2006-08-28 05:41:48.000000000 +0200
8276+++ linux-2.6.19/net/ipv4/fib_hash.c 2006-09-22 10:04:58.000000000 +0200
8277@@ -379,42 +379,39 @@
8278 return NULL;
8279 }
8280
8281-static int
8282-fn_hash_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
8283- struct nlmsghdr *n, struct netlink_skb_parms *req)
8284+static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg)
8285 {
8286 struct fn_hash *table = (struct fn_hash *) tb->tb_data;
8287 struct fib_node *new_f, *f;
8288 struct fib_alias *fa, *new_fa;
8289 struct fn_zone *fz;
8290 struct fib_info *fi;
8291- int z = r->rtm_dst_len;
8292- int type = r->rtm_type;
8293- u8 tos = r->rtm_tos;
8294+ u8 tos = cfg->fc_tos;
8295 u32 key;
8296 int err;
8297
8298- if (z > 32)
8299+ if (cfg->fc_dst_len > 32)
8300 return -EINVAL;
8301- fz = table->fn_zones[z];
8302- if (!fz && !(fz = fn_new_zone(table, z)))
8303+
8304+ fz = table->fn_zones[cfg->fc_dst_len];
8305+ if (!fz && !(fz = fn_new_zone(table, cfg->fc_dst_len)))
8306 return -ENOBUFS;
8307
8308 key = 0;
8309- if (rta->rta_dst) {
8310- u32 dst;
8311- memcpy(&dst, rta->rta_dst, 4);
8312- if (dst & ~FZ_MASK(fz))
8313+ if (cfg->fc_dst) {
8314+ if (cfg->fc_dst & ~FZ_MASK(fz))
8315 return -EINVAL;
8316- key = fz_key(dst, fz);
8317+ key = fz_key(cfg->fc_dst, fz);
8318 }
8319
8320- if ((fi = fib_create_info(r, rta, n, &err)) == NULL)
8321- return err;
8322+ fi = fib_create_info(cfg);
8323+ if (IS_ERR(fi))
8324+ return PTR_ERR(fi);
8325
8326 if (fz->fz_nent > (fz->fz_divisor<<1) &&
8327 fz->fz_divisor < FZ_MAX_DIVISOR &&
8328- (z==32 || (1<<z) > fz->fz_divisor))
8329+ (cfg->fc_dst_len == 32 ||
8330+ (1 << cfg->fc_dst_len) > fz->fz_divisor))
8331 fn_rehash_zone(fz);
8332
8333 f = fib_find_node(fz, key);
8334@@ -440,18 +437,18 @@
8335 struct fib_alias *fa_orig;
8336
8337 err = -EEXIST;
8338- if (n->nlmsg_flags & NLM_F_EXCL)
8339+ if (cfg->fc_nlflags & NLM_F_EXCL)
8340 goto out;
8341
8342- if (n->nlmsg_flags & NLM_F_REPLACE) {
8343+ if (cfg->fc_nlflags & NLM_F_REPLACE) {
8344 struct fib_info *fi_drop;
8345 u8 state;
8346
8347 write_lock_bh(&fib_hash_lock);
8348 fi_drop = fa->fa_info;
8349 fa->fa_info = fi;
8350- fa->fa_type = type;
8351- fa->fa_scope = r->rtm_scope;
8352+ fa->fa_type = cfg->fc_type;
8353+ fa->fa_scope = cfg->fc_scope;
8354 state = fa->fa_state;
8355 fa->fa_state &= ~FA_S_ACCESSED;
8356 fib_hash_genid++;
8357@@ -474,17 +471,17 @@
8358 break;
8359 if (fa->fa_info->fib_priority != fi->fib_priority)
8360 break;
8361- if (fa->fa_type == type &&
8362- fa->fa_scope == r->rtm_scope &&
8363+ if (fa->fa_type == cfg->fc_type &&
8364+ fa->fa_scope == cfg->fc_scope &&
8365 fa->fa_info == fi)
8366 goto out;
8367 }
8368- if (!(n->nlmsg_flags & NLM_F_APPEND))
8369+ if (!(cfg->fc_nlflags & NLM_F_APPEND))
8370 fa = fa_orig;
8371 }
8372
8373 err = -ENOENT;
8374- if (!(n->nlmsg_flags&NLM_F_CREATE))
8375+ if (!(cfg->fc_nlflags & NLM_F_CREATE))
8376 goto out;
8377
8378 err = -ENOBUFS;
8379@@ -506,8 +503,8 @@
8380
8381 new_fa->fa_info = fi;
8382 new_fa->fa_tos = tos;
8383- new_fa->fa_type = type;
8384- new_fa->fa_scope = r->rtm_scope;
8385+ new_fa->fa_type = cfg->fc_type;
8386+ new_fa->fa_scope = cfg->fc_scope;
8387 new_fa->fa_state = 0;
8388
8389 /*
8390@@ -526,7 +523,8 @@
8391 fz->fz_nent++;
8392 rt_cache_flush(-1);
8393
8394- rtmsg_fib(RTM_NEWROUTE, key, new_fa, z, tb->tb_id, n, req);
8395+ rtmsg_fib(RTM_NEWROUTE, key, new_fa, cfg->fc_dst_len, tb->tb_id,
8396+ &cfg->fc_nlinfo);
8397 return 0;
8398
8399 out_free_new_fa:
8400@@ -537,30 +535,25 @@
8401 }
8402
8403
8404-static int
8405-fn_hash_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
8406- struct nlmsghdr *n, struct netlink_skb_parms *req)
8407+static int fn_hash_delete(struct fib_table *tb, struct fib_config *cfg)
8408 {
8409 struct fn_hash *table = (struct fn_hash*)tb->tb_data;
8410 struct fib_node *f;
8411 struct fib_alias *fa, *fa_to_delete;
8412- int z = r->rtm_dst_len;
8413 struct fn_zone *fz;
8414 u32 key;
8415- u8 tos = r->rtm_tos;
8416
8417- if (z > 32)
8418+ if (cfg->fc_dst_len > 32)
8419 return -EINVAL;
8420- if ((fz = table->fn_zones[z]) == NULL)
8421+
8422+ if ((fz = table->fn_zones[cfg->fc_dst_len]) == NULL)
8423 return -ESRCH;
8424
8425 key = 0;
8426- if (rta->rta_dst) {
8427- u32 dst;
8428- memcpy(&dst, rta->rta_dst, 4);
8429- if (dst & ~FZ_MASK(fz))
8430+ if (cfg->fc_dst) {
8431+ if (cfg->fc_dst & ~FZ_MASK(fz))
8432 return -EINVAL;
8433- key = fz_key(dst, fz);
8434+ key = fz_key(cfg->fc_dst, fz);
8435 }
8436
8437 f = fib_find_node(fz, key);
8438@@ -568,7 +561,7 @@
8439 if (!f)
8440 fa = NULL;
8441 else
8442- fa = fib_find_alias(&f->fn_alias, tos, 0);
8443+ fa = fib_find_alias(&f->fn_alias, cfg->fc_tos, 0);
8444 if (!fa)
8445 return -ESRCH;
8446
8447@@ -577,16 +570,16 @@
8448 list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
8449 struct fib_info *fi = fa->fa_info;
8450
8451- if (fa->fa_tos != tos)
8452+ if (fa->fa_tos != cfg->fc_tos)
8453 break;
8454
8455- if ((!r->rtm_type ||
8456- fa->fa_type == r->rtm_type) &&
8457- (r->rtm_scope == RT_SCOPE_NOWHERE ||
8458- fa->fa_scope == r->rtm_scope) &&
8459- (!r->rtm_protocol ||
8460- fi->fib_protocol == r->rtm_protocol) &&
8461- fib_nh_match(r, n, rta, fi) == 0) {
8462+ if ((!cfg->fc_type ||
8463+ fa->fa_type == cfg->fc_type) &&
8464+ (cfg->fc_scope == RT_SCOPE_NOWHERE ||
8465+ fa->fa_scope == cfg->fc_scope) &&
8466+ (!cfg->fc_protocol ||
8467+ fi->fib_protocol == cfg->fc_protocol) &&
8468+ fib_nh_match(cfg, fi) == 0) {
8469 fa_to_delete = fa;
8470 break;
8471 }
8472@@ -596,7 +589,8 @@
8473 int kill_fn;
8474
8475 fa = fa_to_delete;
8476- rtmsg_fib(RTM_DELROUTE, key, fa, z, tb->tb_id, n, req);
8477+ rtmsg_fib(RTM_DELROUTE, key, fa, cfg->fc_dst_len,
8478+ tb->tb_id, &cfg->fc_nlinfo);
8479
8480 kill_fn = 0;
8481 write_lock_bh(&fib_hash_lock);
8482@@ -684,7 +678,7 @@
8483 struct fib_node *f;
8484 int i, s_i;
8485
8486- s_i = cb->args[3];
8487+ s_i = cb->args[4];
8488 i = 0;
8489 hlist_for_each_entry(f, node, head, fn_hash) {
8490 struct fib_alias *fa;
8491@@ -699,19 +693,19 @@
8492 tb->tb_id,
8493 fa->fa_type,
8494 fa->fa_scope,
8495- &f->fn_key,
8496+ f->fn_key,
8497 fz->fz_order,
8498 fa->fa_tos,
8499 fa->fa_info,
8500 NLM_F_MULTI) < 0) {
8501- cb->args[3] = i;
8502+ cb->args[4] = i;
8503 return -1;
8504 }
8505 next:
8506 i++;
8507 }
8508 }
8509- cb->args[3] = i;
8510+ cb->args[4] = i;
8511 return skb->len;
8512 }
8513
8514@@ -722,21 +716,21 @@
8515 {
8516 int h, s_h;
8517
8518- s_h = cb->args[2];
8519+ s_h = cb->args[3];
8520 for (h=0; h < fz->fz_divisor; h++) {
8521 if (h < s_h) continue;
8522 if (h > s_h)
8523- memset(&cb->args[3], 0,
8524- sizeof(cb->args) - 3*sizeof(cb->args[0]));
8525+ memset(&cb->args[4], 0,
8526+ sizeof(cb->args) - 4*sizeof(cb->args[0]));
8527 if (fz->fz_hash == NULL ||
8528 hlist_empty(&fz->fz_hash[h]))
8529 continue;
8530 if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h])<0) {
8531- cb->args[2] = h;
8532+ cb->args[3] = h;
8533 return -1;
8534 }
8535 }
8536- cb->args[2] = h;
8537+ cb->args[3] = h;
8538 return skb->len;
8539 }
8540
8541@@ -746,28 +740,28 @@
8542 struct fn_zone *fz;
8543 struct fn_hash *table = (struct fn_hash*)tb->tb_data;
8544
8545- s_m = cb->args[1];
8546+ s_m = cb->args[2];
8547 read_lock(&fib_hash_lock);
8548 for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
8549 if (m < s_m) continue;
8550 if (m > s_m)
8551- memset(&cb->args[2], 0,
8552- sizeof(cb->args) - 2*sizeof(cb->args[0]));
8553+ memset(&cb->args[3], 0,
8554+ sizeof(cb->args) - 3*sizeof(cb->args[0]));
8555 if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
8556- cb->args[1] = m;
8557+ cb->args[2] = m;
8558 read_unlock(&fib_hash_lock);
8559 return -1;
8560 }
8561 }
8562 read_unlock(&fib_hash_lock);
8563- cb->args[1] = m;
8564+ cb->args[2] = m;
8565 return skb->len;
8566 }
8567
8568 #ifdef CONFIG_IP_MULTIPLE_TABLES
8569-struct fib_table * fib_hash_init(int id)
8570+struct fib_table * fib_hash_init(u32 id)
8571 #else
8572-struct fib_table * __init fib_hash_init(int id)
8573+struct fib_table * __init fib_hash_init(u32 id)
8574 #endif
8575 {
8576 struct fib_table *tb;
8577diff -Nur linux-2.6.18-rc5/net/ipv4/fib_lookup.h linux-2.6.19/net/ipv4/fib_lookup.h
8578--- linux-2.6.18-rc5/net/ipv4/fib_lookup.h 2006-08-28 05:41:48.000000000 +0200
8579+++ linux-2.6.19/net/ipv4/fib_lookup.h 2006-09-22 10:04:58.000000000 +0200
8580@@ -23,19 +23,14 @@
8581 struct fib_result *res, __u32 zone, __u32 mask,
8582 int prefixlen);
8583 extern void fib_release_info(struct fib_info *);
8584-extern struct fib_info *fib_create_info(const struct rtmsg *r,
8585- struct kern_rta *rta,
8586- const struct nlmsghdr *,
8587- int *err);
8588-extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *,
8589- struct kern_rta *rta, struct fib_info *fi);
8590+extern struct fib_info *fib_create_info(struct fib_config *cfg);
8591+extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi);
8592 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
8593- u8 tb_id, u8 type, u8 scope, void *dst,
8594+ u32 tb_id, u8 type, u8 scope, u32 dst,
8595 int dst_len, u8 tos, struct fib_info *fi,
8596 unsigned int);
8597 extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
8598- int z, int tb_id,
8599- struct nlmsghdr *n, struct netlink_skb_parms *req);
8600+ int dst_len, u32 tb_id, struct nl_info *info);
8601 extern struct fib_alias *fib_find_alias(struct list_head *fah,
8602 u8 tos, u32 prio);
8603 extern int fib_detect_death(struct fib_info *fi, int order,
8604diff -Nur linux-2.6.18-rc5/net/ipv4/fib_rules.c linux-2.6.19/net/ipv4/fib_rules.c
8605--- linux-2.6.18-rc5/net/ipv4/fib_rules.c 2006-08-28 05:41:48.000000000 +0200
8606+++ linux-2.6.19/net/ipv4/fib_rules.c 2006-09-22 10:04:58.000000000 +0200
8607@@ -5,9 +5,8 @@
8608 *
8609 * IPv4 Forwarding Information Base: policy rules.
8610 *
8611- * Version: $Id$
8612- *
8613 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
8614+ * Thomas Graf <tgraf@suug.ch>
8615 *
8616 * This program is free software; you can redistribute it and/or
8617 * modify it under the terms of the GNU General Public License
8618@@ -19,463 +18,350 @@
8619 * Marc Boucher : routing by fwmark
8620 */
8621
8622-#include <asm/uaccess.h>
8623-#include <asm/system.h>
8624-#include <linux/bitops.h>
8625 #include <linux/types.h>
8626 #include <linux/kernel.h>
8627-#include <linux/sched.h>
8628-#include <linux/mm.h>
8629-#include <linux/string.h>
8630-#include <linux/socket.h>
8631-#include <linux/sockios.h>
8632-#include <linux/errno.h>
8633-#include <linux/in.h>
8634-#include <linux/inet.h>
8635-#include <linux/inetdevice.h>
8636 #include <linux/netdevice.h>
8637-#include <linux/if_arp.h>
8638-#include <linux/proc_fs.h>
8639-#include <linux/skbuff.h>
8640 #include <linux/netlink.h>
8641+#include <linux/inetdevice.h>
8642 #include <linux/init.h>
8643 #include <linux/list.h>
8644 #include <linux/rcupdate.h>
8645-
8646 #include <net/ip.h>
8647-#include <net/protocol.h>
8648 #include <net/route.h>
8649 #include <net/tcp.h>
8650-#include <net/sock.h>
8651 #include <net/ip_fib.h>
8652+#include <net/fib_rules.h>
8653
8654-#define FRprintk(a...)
8655+static struct fib_rules_ops fib4_rules_ops;
8656
8657-struct fib_rule
8658+struct fib4_rule
8659 {
8660- struct hlist_node hlist;
8661- atomic_t r_clntref;
8662- u32 r_preference;
8663- unsigned char r_table;
8664- unsigned char r_action;
8665- unsigned char r_dst_len;
8666- unsigned char r_src_len;
8667- u32 r_src;
8668- u32 r_srcmask;
8669- u32 r_dst;
8670- u32 r_dstmask;
8671- u32 r_srcmap;
8672- u8 r_flags;
8673- u8 r_tos;
8674+ struct fib_rule common;
8675+ u8 dst_len;
8676+ u8 src_len;
8677+ u8 tos;
8678+ u32 src;
8679+ u32 srcmask;
8680+ u32 dst;
8681+ u32 dstmask;
8682 #ifdef CONFIG_IP_ROUTE_FWMARK
8683- u32 r_fwmark;
8684+ u32 fwmark;
8685+ u32 fwmask;
8686 #endif
8687- int r_ifindex;
8688 #ifdef CONFIG_NET_CLS_ROUTE
8689- __u32 r_tclassid;
8690+ u32 tclassid;
8691 #endif
8692- char r_ifname[IFNAMSIZ];
8693- int r_dead;
8694- struct rcu_head rcu;
8695 };
8696
8697-static struct fib_rule default_rule = {
8698- .r_clntref = ATOMIC_INIT(2),
8699- .r_preference = 0x7FFF,
8700- .r_table = RT_TABLE_DEFAULT,
8701- .r_action = RTN_UNICAST,
8702+static struct fib4_rule default_rule = {
8703+ .common = {
8704+ .refcnt = ATOMIC_INIT(2),
8705+ .pref = 0x7FFF,
8706+ .table = RT_TABLE_DEFAULT,
8707+ .action = FR_ACT_TO_TBL,
8708+ },
8709 };
8710
8711-static struct fib_rule main_rule = {
8712- .r_clntref = ATOMIC_INIT(2),
8713- .r_preference = 0x7FFE,
8714- .r_table = RT_TABLE_MAIN,
8715- .r_action = RTN_UNICAST,
8716+static struct fib4_rule main_rule = {
8717+ .common = {
8718+ .refcnt = ATOMIC_INIT(2),
8719+ .pref = 0x7FFE,
8720+ .table = RT_TABLE_MAIN,
8721+ .action = FR_ACT_TO_TBL,
8722+ },
8723 };
8724
8725-static struct fib_rule local_rule = {
8726- .r_clntref = ATOMIC_INIT(2),
8727- .r_table = RT_TABLE_LOCAL,
8728- .r_action = RTN_UNICAST,
8729+static struct fib4_rule local_rule = {
8730+ .common = {
8731+ .refcnt = ATOMIC_INIT(2),
8732+ .table = RT_TABLE_LOCAL,
8733+ .action = FR_ACT_TO_TBL,
8734+ .flags = FIB_RULE_PERMANENT,
8735+ },
8736 };
8737
8738-static struct hlist_head fib_rules;
8739+static LIST_HEAD(fib4_rules);
8740+
8741+#ifdef CONFIG_NET_CLS_ROUTE
8742+u32 fib_rules_tclass(struct fib_result *res)
8743+{
8744+ return res->r ? ((struct fib4_rule *) res->r)->tclassid : 0;
8745+}
8746+#endif
8747
8748-/* writer func called from netlink -- rtnl_sem hold*/
8749+int fib_lookup(struct flowi *flp, struct fib_result *res)
8750+{
8751+ struct fib_lookup_arg arg = {
8752+ .result = res,
8753+ };
8754+ int err;
8755
8756-static void rtmsg_rule(int, struct fib_rule *);
8757+ err = fib_rules_lookup(&fib4_rules_ops, flp, 0, &arg);
8758+ res->r = arg.rule;
8759
8760-int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
8761+ return err;
8762+}
8763+
8764+static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,
8765+ int flags, struct fib_lookup_arg *arg)
8766 {
8767- struct rtattr **rta = arg;
8768- struct rtmsg *rtm = NLMSG_DATA(nlh);
8769- struct fib_rule *r;
8770- struct hlist_node *node;
8771- int err = -ESRCH;
8772-
8773- hlist_for_each_entry(r, node, &fib_rules, hlist) {
8774- if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 4) == 0) &&
8775- rtm->rtm_src_len == r->r_src_len &&
8776- rtm->rtm_dst_len == r->r_dst_len &&
8777- (!rta[RTA_DST-1] || memcmp(RTA_DATA(rta[RTA_DST-1]), &r->r_dst, 4) == 0) &&
8778- rtm->rtm_tos == r->r_tos &&
8779-#ifdef CONFIG_IP_ROUTE_FWMARK
8780- (!rta[RTA_PROTOINFO-1] || memcmp(RTA_DATA(rta[RTA_PROTOINFO-1]), &r->r_fwmark, 4) == 0) &&
8781-#endif
8782- (!rtm->rtm_type || rtm->rtm_type == r->r_action) &&
8783- (!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) &&
8784- (!rta[RTA_IIF-1] || rtattr_strcmp(rta[RTA_IIF-1], r->r_ifname) == 0) &&
8785- (!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) {
8786- err = -EPERM;
8787- if (r == &local_rule)
8788- break;
8789-
8790- hlist_del_rcu(&r->hlist);
8791- r->r_dead = 1;
8792- rtmsg_rule(RTM_DELRULE, r);
8793- fib_rule_put(r);
8794- err = 0;
8795- break;
8796- }
8797+ int err = -EAGAIN;
8798+ struct fib_table *tbl;
8799+
8800+ switch (rule->action) {
8801+ case FR_ACT_TO_TBL:
8802+ break;
8803+
8804+ case FR_ACT_UNREACHABLE:
8805+ err = -ENETUNREACH;
8806+ goto errout;
8807+
8808+ case FR_ACT_PROHIBIT:
8809+ err = -EACCES;
8810+ goto errout;
8811+
8812+ case FR_ACT_BLACKHOLE:
8813+ default:
8814+ err = -EINVAL;
8815+ goto errout;
8816 }
8817+
8818+ if ((tbl = fib_get_table(rule->table)) == NULL)
8819+ goto errout;
8820+
8821+ err = tbl->tb_lookup(tbl, flp, (struct fib_result *) arg->result);
8822+ if (err > 0)
8823+ err = -EAGAIN;
8824+errout:
8825 return err;
8826 }
8827
8828-/* Allocate new unique table id */
8829
8830-static struct fib_table *fib_empty_table(void)
8831+void fib_select_default(const struct flowi *flp, struct fib_result *res)
8832 {
8833- int id;
8834-
8835- for (id = 1; id <= RT_TABLE_MAX; id++)
8836- if (fib_tables[id] == NULL)
8837- return __fib_new_table(id);
8838- return NULL;
8839+ if (res->r && res->r->action == FR_ACT_TO_TBL &&
8840+ FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
8841+ struct fib_table *tb;
8842+ if ((tb = fib_get_table(res->r->table)) != NULL)
8843+ tb->tb_select_default(tb, flp, res);
8844+ }
8845 }
8846
8847-static inline void fib_rule_put_rcu(struct rcu_head *head)
8848+static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
8849 {
8850- struct fib_rule *r = container_of(head, struct fib_rule, rcu);
8851- kfree(r);
8852+ struct fib4_rule *r = (struct fib4_rule *) rule;
8853+ u32 daddr = fl->fl4_dst;
8854+ u32 saddr = fl->fl4_src;
8855+
8856+ if (((saddr ^ r->src) & r->srcmask) ||
8857+ ((daddr ^ r->dst) & r->dstmask))
8858+ return 0;
8859+
8860+ if (r->tos && (r->tos != fl->fl4_tos))
8861+ return 0;
8862+
8863+#ifdef CONFIG_IP_ROUTE_FWMARK
8864+ if ((r->fwmark ^ fl->fl4_fwmark) & r->fwmask)
8865+ return 0;
8866+#endif
8867+
8868+ return 1;
8869 }
8870
8871-void fib_rule_put(struct fib_rule *r)
8872+static struct fib_table *fib_empty_table(void)
8873 {
8874- if (atomic_dec_and_test(&r->r_clntref)) {
8875- if (r->r_dead)
8876- call_rcu(&r->rcu, fib_rule_put_rcu);
8877- else
8878- printk("Freeing alive rule %p\n", r);
8879- }
8880+ u32 id;
8881+
8882+ for (id = 1; id <= RT_TABLE_MAX; id++)
8883+ if (fib_get_table(id) == NULL)
8884+ return fib_new_table(id);
8885+ return NULL;
8886 }
8887
8888-/* writer func called from netlink -- rtnl_sem hold*/
8889+static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
8890+ [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
8891+ [FRA_PRIORITY] = { .type = NLA_U32 },
8892+ [FRA_SRC] = { .type = NLA_U32 },
8893+ [FRA_DST] = { .type = NLA_U32 },
8894+ [FRA_FWMARK] = { .type = NLA_U32 },
8895+ [FRA_FWMASK] = { .type = NLA_U32 },
8896+ [FRA_FLOW] = { .type = NLA_U32 },
8897+ [FRA_TABLE] = { .type = NLA_U32 },
8898+};
8899
8900-int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
8901-{
8902- struct rtattr **rta = arg;
8903- struct rtmsg *rtm = NLMSG_DATA(nlh);
8904- struct fib_rule *r, *new_r, *last = NULL;
8905- struct hlist_node *node = NULL;
8906- unsigned char table_id;
8907-
8908- if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 ||
8909- (rtm->rtm_tos & ~IPTOS_TOS_MASK))
8910- return -EINVAL;
8911-
8912- if (rta[RTA_IIF-1] && RTA_PAYLOAD(rta[RTA_IIF-1]) > IFNAMSIZ)
8913- return -EINVAL;
8914-
8915- table_id = rtm->rtm_table;
8916- if (table_id == RT_TABLE_UNSPEC) {
8917- struct fib_table *table;
8918- if (rtm->rtm_type == RTN_UNICAST) {
8919- if ((table = fib_empty_table()) == NULL)
8920- return -ENOBUFS;
8921- table_id = table->tb_id;
8922+static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
8923+ struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
8924+ struct nlattr **tb)
8925+{
8926+ int err = -EINVAL;
8927+ struct fib4_rule *rule4 = (struct fib4_rule *) rule;
8928+
8929+ if (frh->src_len > 32 || frh->dst_len > 32 ||
8930+ (frh->tos & ~IPTOS_TOS_MASK))
8931+ goto errout;
8932+
8933+ if (rule->table == RT_TABLE_UNSPEC) {
8934+ if (rule->action == FR_ACT_TO_TBL) {
8935+ struct fib_table *table;
8936+
8937+ table = fib_empty_table();
8938+ if (table == NULL) {
8939+ err = -ENOBUFS;
8940+ goto errout;
8941+ }
8942+
8943+ rule->table = table->tb_id;
8944 }
8945 }
8946
8947- new_r = kzalloc(sizeof(*new_r), GFP_KERNEL);
8948- if (!new_r)
8949- return -ENOMEM;
8950-
8951- if (rta[RTA_SRC-1])
8952- memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4);
8953- if (rta[RTA_DST-1])
8954- memcpy(&new_r->r_dst, RTA_DATA(rta[RTA_DST-1]), 4);
8955- if (rta[RTA_GATEWAY-1])
8956- memcpy(&new_r->r_srcmap, RTA_DATA(rta[RTA_GATEWAY-1]), 4);
8957- new_r->r_src_len = rtm->rtm_src_len;
8958- new_r->r_dst_len = rtm->rtm_dst_len;
8959- new_r->r_srcmask = inet_make_mask(rtm->rtm_src_len);
8960- new_r->r_dstmask = inet_make_mask(rtm->rtm_dst_len);
8961- new_r->r_tos = rtm->rtm_tos;
8962-#ifdef CONFIG_IP_ROUTE_FWMARK
8963- if (rta[RTA_PROTOINFO-1])
8964- memcpy(&new_r->r_fwmark, RTA_DATA(rta[RTA_PROTOINFO-1]), 4);
8965-#endif
8966- new_r->r_action = rtm->rtm_type;
8967- new_r->r_flags = rtm->rtm_flags;
8968- if (rta[RTA_PRIORITY-1])
8969- memcpy(&new_r->r_preference, RTA_DATA(rta[RTA_PRIORITY-1]), 4);
8970- new_r->r_table = table_id;
8971- if (rta[RTA_IIF-1]) {
8972- struct net_device *dev;
8973- rtattr_strlcpy(new_r->r_ifname, rta[RTA_IIF-1], IFNAMSIZ);
8974- new_r->r_ifindex = -1;
8975- dev = __dev_get_by_name(new_r->r_ifname);
8976- if (dev)
8977- new_r->r_ifindex = dev->ifindex;
8978- }
8979-#ifdef CONFIG_NET_CLS_ROUTE
8980- if (rta[RTA_FLOW-1])
8981- memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4);
8982-#endif
8983- r = container_of(fib_rules.first, struct fib_rule, hlist);
8984+ if (tb[FRA_SRC])
8985+ rule4->src = nla_get_u32(tb[FRA_SRC]);
8986
8987- if (!new_r->r_preference) {
8988- if (r && r->hlist.next != NULL) {
8989- r = container_of(r->hlist.next, struct fib_rule, hlist);
8990- if (r->r_preference)
8991- new_r->r_preference = r->r_preference - 1;
8992- }
8993- }
8994+ if (tb[FRA_DST])
8995+ rule4->dst = nla_get_u32(tb[FRA_DST]);
8996
8997- hlist_for_each_entry(r, node, &fib_rules, hlist) {
8998- if (r->r_preference > new_r->r_preference)
8999- break;
9000- last = r;
9001+#ifdef CONFIG_IP_ROUTE_FWMARK
9002+ if (tb[FRA_FWMARK]) {
9003+ rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]);
9004+ if (rule4->fwmark)
9005+ /* compatibility: if the mark value is non-zero all bits
9006+ * are compared unless a mask is explicitly specified.
9007+ */
9008+ rule4->fwmask = 0xFFFFFFFF;
9009 }
9010- atomic_inc(&new_r->r_clntref);
9011-
9012- if (last)
9013- hlist_add_after_rcu(&last->hlist, &new_r->hlist);
9014- else
9015- hlist_add_before_rcu(&new_r->hlist, &r->hlist);
9016
9017- rtmsg_rule(RTM_NEWRULE, new_r);
9018- return 0;
9019-}
9020+ if (tb[FRA_FWMASK])
9021+ rule4->fwmask = nla_get_u32(tb[FRA_FWMASK]);
9022+#endif
9023
9024 #ifdef CONFIG_NET_CLS_ROUTE
9025-u32 fib_rules_tclass(struct fib_result *res)
9026-{
9027- if (res->r)
9028- return res->r->r_tclassid;
9029- return 0;
9030-}
9031+ if (tb[FRA_FLOW])
9032+ rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
9033 #endif
9034
9035-/* callers should hold rtnl semaphore */
9036+ rule4->src_len = frh->src_len;
9037+ rule4->srcmask = inet_make_mask(rule4->src_len);
9038+ rule4->dst_len = frh->dst_len;
9039+ rule4->dstmask = inet_make_mask(rule4->dst_len);
9040+ rule4->tos = frh->tos;
9041+
9042+ err = 0;
9043+errout:
9044+ return err;
9045+}
9046
9047-static void fib_rules_detach(struct net_device *dev)
9048+static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
9049+ struct nlattr **tb)
9050 {
9051- struct hlist_node *node;
9052- struct fib_rule *r;
9053+ struct fib4_rule *rule4 = (struct fib4_rule *) rule;
9054
9055- hlist_for_each_entry(r, node, &fib_rules, hlist) {
9056- if (r->r_ifindex == dev->ifindex)
9057- r->r_ifindex = -1;
9058+ if (frh->src_len && (rule4->src_len != frh->src_len))
9059+ return 0;
9060
9061- }
9062-}
9063+ if (frh->dst_len && (rule4->dst_len != frh->dst_len))
9064+ return 0;
9065
9066-/* callers should hold rtnl semaphore */
9067+ if (frh->tos && (rule4->tos != frh->tos))
9068+ return 0;
9069
9070-static void fib_rules_attach(struct net_device *dev)
9071-{
9072- struct hlist_node *node;
9073- struct fib_rule *r;
9074+#ifdef CONFIG_IP_ROUTE_FWMARK
9075+ if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK])))
9076+ return 0;
9077
9078- hlist_for_each_entry(r, node, &fib_rules, hlist) {
9079- if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0)
9080- r->r_ifindex = dev->ifindex;
9081- }
9082-}
9083+ if (tb[FRA_FWMASK] && (rule4->fwmask != nla_get_u32(tb[FRA_FWMASK])))
9084+ return 0;
9085+#endif
9086
9087-int fib_lookup(const struct flowi *flp, struct fib_result *res)
9088-{
9089- int err;
9090- struct fib_rule *r, *policy;
9091- struct fib_table *tb;
9092- struct hlist_node *node;
9093-
9094- u32 daddr = flp->fl4_dst;
9095- u32 saddr = flp->fl4_src;
9096-
9097-FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
9098- NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src));
9099-
9100- rcu_read_lock();
9101-
9102- hlist_for_each_entry_rcu(r, node, &fib_rules, hlist) {
9103- if (((saddr^r->r_src) & r->r_srcmask) ||
9104- ((daddr^r->r_dst) & r->r_dstmask) ||
9105- (r->r_tos && r->r_tos != flp->fl4_tos) ||
9106-#ifdef CONFIG_IP_ROUTE_FWMARK
9107- (r->r_fwmark && r->r_fwmark != flp->fl4_fwmark) ||
9108+#ifdef CONFIG_NET_CLS_ROUTE
9109+ if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
9110+ return 0;
9111 #endif
9112- (r->r_ifindex && r->r_ifindex != flp->iif))
9113- continue;
9114
9115-FRprintk("tb %d r %d ", r->r_table, r->r_action);
9116- switch (r->r_action) {
9117- case RTN_UNICAST:
9118- policy = r;
9119- break;
9120- case RTN_UNREACHABLE:
9121- rcu_read_unlock();
9122- return -ENETUNREACH;
9123- default:
9124- case RTN_BLACKHOLE:
9125- rcu_read_unlock();
9126- return -EINVAL;
9127- case RTN_PROHIBIT:
9128- rcu_read_unlock();
9129- return -EACCES;
9130- }
9131+ if (tb[FRA_SRC] && (rule4->src != nla_get_u32(tb[FRA_SRC])))
9132+ return 0;
9133
9134- if ((tb = fib_get_table(r->r_table)) == NULL)
9135- continue;
9136- err = tb->tb_lookup(tb, flp, res);
9137- if (err == 0) {
9138- res->r = policy;
9139- if (policy)
9140- atomic_inc(&policy->r_clntref);
9141- rcu_read_unlock();
9142- return 0;
9143- }
9144- if (err < 0 && err != -EAGAIN) {
9145- rcu_read_unlock();
9146- return err;
9147- }
9148- }
9149-FRprintk("FAILURE\n");
9150- rcu_read_unlock();
9151- return -ENETUNREACH;
9152-}
9153+ if (tb[FRA_DST] && (rule4->dst != nla_get_u32(tb[FRA_DST])))
9154+ return 0;
9155
9156-void fib_select_default(const struct flowi *flp, struct fib_result *res)
9157-{
9158- if (res->r && res->r->r_action == RTN_UNICAST &&
9159- FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
9160- struct fib_table *tb;
9161- if ((tb = fib_get_table(res->r->r_table)) != NULL)
9162- tb->tb_select_default(tb, flp, res);
9163- }
9164+ return 1;
9165 }
9166
9167-static int fib_rules_event(struct notifier_block *this, unsigned long event, void *ptr)
9168+static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
9169+ struct nlmsghdr *nlh, struct fib_rule_hdr *frh)
9170 {
9171- struct net_device *dev = ptr;
9172-
9173- if (event == NETDEV_UNREGISTER)
9174- fib_rules_detach(dev);
9175- else if (event == NETDEV_REGISTER)
9176- fib_rules_attach(dev);
9177- return NOTIFY_DONE;
9178-}
9179+ struct fib4_rule *rule4 = (struct fib4_rule *) rule;
9180
9181+ frh->family = AF_INET;
9182+ frh->dst_len = rule4->dst_len;
9183+ frh->src_len = rule4->src_len;
9184+ frh->tos = rule4->tos;
9185
9186-static struct notifier_block fib_rules_notifier = {
9187- .notifier_call =fib_rules_event,
9188-};
9189-
9190-static __inline__ int inet_fill_rule(struct sk_buff *skb,
9191- struct fib_rule *r,
9192- u32 pid, u32 seq, int event,
9193- unsigned int flags)
9194-{
9195- struct rtmsg *rtm;
9196- struct nlmsghdr *nlh;
9197- unsigned char *b = skb->tail;
9198-
9199- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
9200- rtm = NLMSG_DATA(nlh);
9201- rtm->rtm_family = AF_INET;
9202- rtm->rtm_dst_len = r->r_dst_len;
9203- rtm->rtm_src_len = r->r_src_len;
9204- rtm->rtm_tos = r->r_tos;
9205 #ifdef CONFIG_IP_ROUTE_FWMARK
9206- if (r->r_fwmark)
9207- RTA_PUT(skb, RTA_PROTOINFO, 4, &r->r_fwmark);
9208+ if (rule4->fwmark)
9209+ NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark);
9210+
9211+ if (rule4->fwmask || rule4->fwmark)
9212+ NLA_PUT_U32(skb, FRA_FWMASK, rule4->fwmask);
9213 #endif
9214- rtm->rtm_table = r->r_table;
9215- rtm->rtm_protocol = 0;
9216- rtm->rtm_scope = 0;
9217- rtm->rtm_type = r->r_action;
9218- rtm->rtm_flags = r->r_flags;
9219-
9220- if (r->r_dst_len)
9221- RTA_PUT(skb, RTA_DST, 4, &r->r_dst);
9222- if (r->r_src_len)
9223- RTA_PUT(skb, RTA_SRC, 4, &r->r_src);
9224- if (r->r_ifname[0])
9225- RTA_PUT(skb, RTA_IIF, IFNAMSIZ, &r->r_ifname);
9226- if (r->r_preference)
9227- RTA_PUT(skb, RTA_PRIORITY, 4, &r->r_preference);
9228- if (r->r_srcmap)
9229- RTA_PUT(skb, RTA_GATEWAY, 4, &r->r_srcmap);
9230+
9231+ if (rule4->dst_len)
9232+ NLA_PUT_U32(skb, FRA_DST, rule4->dst);
9233+
9234+ if (rule4->src_len)
9235+ NLA_PUT_U32(skb, FRA_SRC, rule4->src);
9236+
9237 #ifdef CONFIG_NET_CLS_ROUTE
9238- if (r->r_tclassid)
9239- RTA_PUT(skb, RTA_FLOW, 4, &r->r_tclassid);
9240+ if (rule4->tclassid)
9241+ NLA_PUT_U32(skb, FRA_FLOW, rule4->tclassid);
9242 #endif
9243- nlh->nlmsg_len = skb->tail - b;
9244- return skb->len;
9245+ return 0;
9246
9247-nlmsg_failure:
9248-rtattr_failure:
9249- skb_trim(skb, b - skb->data);
9250- return -1;
9251+nla_put_failure:
9252+ return -ENOBUFS;
9253 }
9254
9255-/* callers should hold rtnl semaphore */
9256-
9257-static void rtmsg_rule(int event, struct fib_rule *r)
9258+int fib4_rules_dump(struct sk_buff *skb, struct netlink_callback *cb)
9259 {
9260- int size = NLMSG_SPACE(sizeof(struct rtmsg) + 128);
9261- struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
9262-
9263- if (!skb)
9264- netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, ENOBUFS);
9265- else if (inet_fill_rule(skb, r, 0, 0, event, 0) < 0) {
9266- kfree_skb(skb);
9267- netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, EINVAL);
9268- } else {
9269- netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_RULE, GFP_KERNEL);
9270- }
9271+ return fib_rules_dump(skb, cb, AF_INET);
9272 }
9273
9274-int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
9275+static u32 fib4_rule_default_pref(void)
9276 {
9277- int idx = 0;
9278- int s_idx = cb->args[0];
9279- struct fib_rule *r;
9280- struct hlist_node *node;
9281-
9282- rcu_read_lock();
9283- hlist_for_each_entry(r, node, &fib_rules, hlist) {
9284- if (idx < s_idx)
9285- goto next;
9286- if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid,
9287- cb->nlh->nlmsg_seq,
9288- RTM_NEWRULE, NLM_F_MULTI) < 0)
9289- break;
9290-next:
9291- idx++;
9292+ struct list_head *pos;
9293+ struct fib_rule *rule;
9294+
9295+ if (!list_empty(&fib4_rules)) {
9296+ pos = fib4_rules.next;
9297+ if (pos->next != &fib4_rules) {
9298+ rule = list_entry(pos->next, struct fib_rule, list);
9299+ if (rule->pref)
9300+ return rule->pref - 1;
9301+ }
9302 }
9303- rcu_read_unlock();
9304- cb->args[0] = idx;
9305
9306- return skb->len;
9307+ return 0;
9308 }
9309
9310-void __init fib_rules_init(void)
9311+static struct fib_rules_ops fib4_rules_ops = {
9312+ .family = AF_INET,
9313+ .rule_size = sizeof(struct fib4_rule),
9314+ .action = fib4_rule_action,
9315+ .match = fib4_rule_match,
9316+ .configure = fib4_rule_configure,
9317+ .compare = fib4_rule_compare,
9318+ .fill = fib4_rule_fill,
9319+ .default_pref = fib4_rule_default_pref,
9320+ .nlgroup = RTNLGRP_IPV4_RULE,
9321+ .policy = fib4_rule_policy,
9322+ .rules_list = &fib4_rules,
9323+ .owner = THIS_MODULE,
9324+};
9325+
9326+void __init fib4_rules_init(void)
9327 {
9328- INIT_HLIST_HEAD(&fib_rules);
9329- hlist_add_head(&local_rule.hlist, &fib_rules);
9330- hlist_add_after(&local_rule.hlist, &main_rule.hlist);
9331- hlist_add_after(&main_rule.hlist, &default_rule.hlist);
9332- register_netdevice_notifier(&fib_rules_notifier);
9333+ list_add_tail(&local_rule.common.list, &fib4_rules);
9334+ list_add_tail(&main_rule.common.list, &fib4_rules);
9335+ list_add_tail(&default_rule.common.list, &fib4_rules);
9336+
9337+ fib_rules_register(&fib4_rules_ops);
9338 }
9339diff -Nur linux-2.6.18-rc5/net/ipv4/fib_semantics.c linux-2.6.19/net/ipv4/fib_semantics.c
9340--- linux-2.6.18-rc5/net/ipv4/fib_semantics.c 2006-08-28 05:41:48.000000000 +0200
9341+++ linux-2.6.19/net/ipv4/fib_semantics.c 2006-09-22 10:04:58.000000000 +0200
9342@@ -33,7 +33,6 @@
9343 #include <linux/if_arp.h>
9344 #include <linux/proc_fs.h>
9345 #include <linux/skbuff.h>
9346-#include <linux/netlink.h>
9347 #include <linux/init.h>
9348
9349 #include <net/arp.h>
9350@@ -44,12 +43,14 @@
9351 #include <net/sock.h>
9352 #include <net/ip_fib.h>
9353 #include <net/ip_mp_alg.h>
9354+#include <net/netlink.h>
9355+#include <net/nexthop.h>
9356
9357 #include "fib_lookup.h"
9358
9359 #define FSprintk(a...)
9360
9361-static DEFINE_RWLOCK(fib_info_lock);
9362+static DEFINE_SPINLOCK(fib_info_lock);
9363 static struct hlist_head *fib_info_hash;
9364 static struct hlist_head *fib_info_laddrhash;
9365 static unsigned int fib_hash_size;
9366@@ -159,7 +160,7 @@
9367
9368 void fib_release_info(struct fib_info *fi)
9369 {
9370- write_lock_bh(&fib_info_lock);
9371+ spin_lock_bh(&fib_info_lock);
9372 if (fi && --fi->fib_treeref == 0) {
9373 hlist_del(&fi->fib_hash);
9374 if (fi->fib_prefsrc)
9375@@ -172,7 +173,7 @@
9376 fi->fib_dead = 1;
9377 fib_info_put(fi);
9378 }
9379- write_unlock_bh(&fib_info_lock);
9380+ spin_unlock_bh(&fib_info_lock);
9381 }
9382
9383 static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi)
9384@@ -254,7 +255,7 @@
9385 struct fib_nh *nh;
9386 unsigned int hash;
9387
9388- read_lock(&fib_info_lock);
9389+ spin_lock(&fib_info_lock);
9390
9391 hash = fib_devindex_hashfn(dev->ifindex);
9392 head = &fib_info_devhash[hash];
9393@@ -262,41 +263,41 @@
9394 if (nh->nh_dev == dev &&
9395 nh->nh_gw == gw &&
9396 !(nh->nh_flags&RTNH_F_DEAD)) {
9397- read_unlock(&fib_info_lock);
9398+ spin_unlock(&fib_info_lock);
9399 return 0;
9400 }
9401 }
9402
9403- read_unlock(&fib_info_lock);
9404+ spin_unlock(&fib_info_lock);
9405
9406 return -1;
9407 }
9408
9409 void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
9410- int z, int tb_id,
9411- struct nlmsghdr *n, struct netlink_skb_parms *req)
9412+ int dst_len, u32 tb_id, struct nl_info *info)
9413 {
9414 struct sk_buff *skb;
9415- u32 pid = req ? req->pid : n->nlmsg_pid;
9416- int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
9417-
9418- skb = alloc_skb(size, GFP_KERNEL);
9419- if (!skb)
9420- return;
9421-
9422- if (fib_dump_info(skb, pid, n->nlmsg_seq, event, tb_id,
9423- fa->fa_type, fa->fa_scope, &key, z,
9424- fa->fa_tos,
9425- fa->fa_info, 0) < 0) {
9426+ int payload = sizeof(struct rtmsg) + 256;
9427+ u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
9428+ int err = -ENOBUFS;
9429+
9430+ skb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL);
9431+ if (skb == NULL)
9432+ goto errout;
9433+
9434+ err = fib_dump_info(skb, info->pid, seq, event, tb_id,
9435+ fa->fa_type, fa->fa_scope, key, dst_len,
9436+ fa->fa_tos, fa->fa_info, 0);
9437+ if (err < 0) {
9438 kfree_skb(skb);
9439- return;
9440+ goto errout;
9441 }
9442- NETLINK_CB(skb).dst_group = RTNLGRP_IPV4_ROUTE;
9443- if (n->nlmsg_flags&NLM_F_ECHO)
9444- atomic_inc(&skb->users);
9445- netlink_broadcast(rtnl, skb, pid, RTNLGRP_IPV4_ROUTE, GFP_KERNEL);
9446- if (n->nlmsg_flags&NLM_F_ECHO)
9447- netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
9448+
9449+ err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
9450+ info->nlh, GFP_KERNEL);
9451+errout:
9452+ if (err < 0)
9453+ rtnl_set_sk_err(RTNLGRP_IPV4_ROUTE, err);
9454 }
9455
9456 /* Return the first fib alias matching TOS with
9457@@ -342,102 +343,100 @@
9458
9459 #ifdef CONFIG_IP_ROUTE_MULTIPATH
9460
9461-static u32 fib_get_attr32(struct rtattr *attr, int attrlen, int type)
9462-{
9463- while (RTA_OK(attr,attrlen)) {
9464- if (attr->rta_type == type)
9465- return *(u32*)RTA_DATA(attr);
9466- attr = RTA_NEXT(attr, attrlen);
9467- }
9468- return 0;
9469-}
9470-
9471-static int
9472-fib_count_nexthops(struct rtattr *rta)
9473+static int fib_count_nexthops(struct rtnexthop *rtnh, int remaining)
9474 {
9475 int nhs = 0;
9476- struct rtnexthop *nhp = RTA_DATA(rta);
9477- int nhlen = RTA_PAYLOAD(rta);
9478
9479- while (nhlen >= (int)sizeof(struct rtnexthop)) {
9480- if ((nhlen -= nhp->rtnh_len) < 0)
9481- return 0;
9482+ while (rtnh_ok(rtnh, remaining)) {
9483 nhs++;
9484- nhp = RTNH_NEXT(nhp);
9485- };
9486- return nhs;
9487+ rtnh = rtnh_next(rtnh, &remaining);
9488+ }
9489+
9490+ /* leftover implies invalid nexthop configuration, discard it */
9491+ return remaining > 0 ? 0 : nhs;
9492 }
9493
9494-static int
9495-fib_get_nhs(struct fib_info *fi, const struct rtattr *rta, const struct rtmsg *r)
9496+static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
9497+ int remaining, struct fib_config *cfg)
9498 {
9499- struct rtnexthop *nhp = RTA_DATA(rta);
9500- int nhlen = RTA_PAYLOAD(rta);
9501-
9502 change_nexthops(fi) {
9503- int attrlen = nhlen - sizeof(struct rtnexthop);
9504- if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
9505+ int attrlen;
9506+
9507+ if (!rtnh_ok(rtnh, remaining))
9508 return -EINVAL;
9509- nh->nh_flags = (r->rtm_flags&~0xFF) | nhp->rtnh_flags;
9510- nh->nh_oif = nhp->rtnh_ifindex;
9511- nh->nh_weight = nhp->rtnh_hops + 1;
9512- if (attrlen) {
9513- nh->nh_gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
9514+
9515+ nh->nh_flags = (cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags;
9516+ nh->nh_oif = rtnh->rtnh_ifindex;
9517+ nh->nh_weight = rtnh->rtnh_hops + 1;
9518+
9519+ attrlen = rtnh_attrlen(rtnh);
9520+ if (attrlen > 0) {
9521+ struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
9522+
9523+ nla = nla_find(attrs, attrlen, RTA_GATEWAY);
9524+ nh->nh_gw = nla ? nla_get_u32(nla) : 0;
9525 #ifdef CONFIG_NET_CLS_ROUTE
9526- nh->nh_tclassid = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_FLOW);
9527+ nla = nla_find(attrs, attrlen, RTA_FLOW);
9528+ nh->nh_tclassid = nla ? nla_get_u32(nla) : 0;
9529 #endif
9530 }
9531- nhp = RTNH_NEXT(nhp);
9532+
9533+ rtnh = rtnh_next(rtnh, &remaining);
9534 } endfor_nexthops(fi);
9535+
9536 return 0;
9537 }
9538
9539 #endif
9540
9541-int fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct kern_rta *rta,
9542- struct fib_info *fi)
9543+int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
9544 {
9545 #ifdef CONFIG_IP_ROUTE_MULTIPATH
9546- struct rtnexthop *nhp;
9547- int nhlen;
9548+ struct rtnexthop *rtnh;
9549+ int remaining;
9550 #endif
9551
9552- if (rta->rta_priority &&
9553- *rta->rta_priority != fi->fib_priority)
9554+ if (cfg->fc_priority && cfg->fc_priority != fi->fib_priority)
9555 return 1;
9556
9557- if (rta->rta_oif || rta->rta_gw) {
9558- if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) &&
9559- (!rta->rta_gw || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 4) == 0))
9560+ if (cfg->fc_oif || cfg->fc_gw) {
9561+ if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) &&
9562+ (!cfg->fc_gw || cfg->fc_gw == fi->fib_nh->nh_gw))
9563 return 0;
9564 return 1;
9565 }
9566
9567 #ifdef CONFIG_IP_ROUTE_MULTIPATH
9568- if (rta->rta_mp == NULL)
9569+ if (cfg->fc_mp == NULL)
9570 return 0;
9571- nhp = RTA_DATA(rta->rta_mp);
9572- nhlen = RTA_PAYLOAD(rta->rta_mp);
9573+
9574+ rtnh = cfg->fc_mp;
9575+ remaining = cfg->fc_mp_len;
9576
9577 for_nexthops(fi) {
9578- int attrlen = nhlen - sizeof(struct rtnexthop);
9579- u32 gw;
9580+ int attrlen;
9581
9582- if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
9583+ if (!rtnh_ok(rtnh, remaining))
9584 return -EINVAL;
9585- if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif)
9586+
9587+ if (rtnh->rtnh_ifindex && rtnh->rtnh_ifindex != nh->nh_oif)
9588 return 1;
9589- if (attrlen) {
9590- gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
9591- if (gw && gw != nh->nh_gw)
9592+
9593+ attrlen = rtnh_attrlen(rtnh);
9594+ if (attrlen < 0) {
9595+ struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
9596+
9597+ nla = nla_find(attrs, attrlen, RTA_GATEWAY);
9598+ if (nla && nla_get_u32(nla) != nh->nh_gw)
9599 return 1;
9600 #ifdef CONFIG_NET_CLS_ROUTE
9601- gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_FLOW);
9602- if (gw && gw != nh->nh_tclassid)
9603+ nla = nla_find(attrs, attrlen, RTA_FLOW);
9604+ if (nla && nla_get_u32(nla) != nh->nh_tclassid)
9605 return 1;
9606 #endif
9607 }
9608- nhp = RTNH_NEXT(nhp);
9609+
9610+ rtnh = rtnh_next(rtnh, &remaining);
9611 } endfor_nexthops(fi);
9612 #endif
9613 return 0;
9614@@ -488,7 +487,8 @@
9615 |-> {local prefix} (terminal node)
9616 */
9617
9618-static int fib_check_nh(const struct rtmsg *r, struct fib_info *fi, struct fib_nh *nh)
9619+static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
9620+ struct fib_nh *nh)
9621 {
9622 int err;
9623
9624@@ -502,7 +502,7 @@
9625 if (nh->nh_flags&RTNH_F_ONLINK) {
9626 struct net_device *dev;
9627
9628- if (r->rtm_scope >= RT_SCOPE_LINK)
9629+ if (cfg->fc_scope >= RT_SCOPE_LINK)
9630 return -EINVAL;
9631 if (inet_addr_type(nh->nh_gw) != RTN_UNICAST)
9632 return -EINVAL;
9633@@ -516,10 +516,15 @@
9634 return 0;
9635 }
9636 {
9637- struct flowi fl = { .nl_u = { .ip4_u =
9638- { .daddr = nh->nh_gw,
9639- .scope = r->rtm_scope + 1 } },
9640- .oif = nh->nh_oif };
9641+ struct flowi fl = {
9642+ .nl_u = {
9643+ .ip4_u = {
9644+ .daddr = nh->nh_gw,
9645+ .scope = cfg->fc_scope + 1,
9646+ },
9647+ },
9648+ .oif = nh->nh_oif,
9649+ };
9650
9651 /* It is not necessary, but requires a bit of thinking */
9652 if (fl.fl4_scope < RT_SCOPE_LINK)
9653@@ -598,7 +603,7 @@
9654 unsigned int old_size = fib_hash_size;
9655 unsigned int i, bytes;
9656
9657- write_lock_bh(&fib_info_lock);
9658+ spin_lock_bh(&fib_info_lock);
9659 old_info_hash = fib_info_hash;
9660 old_laddrhash = fib_info_laddrhash;
9661 fib_hash_size = new_size;
9662@@ -639,46 +644,35 @@
9663 }
9664 fib_info_laddrhash = new_laddrhash;
9665
9666- write_unlock_bh(&fib_info_lock);
9667+ spin_unlock_bh(&fib_info_lock);
9668
9669 bytes = old_size * sizeof(struct hlist_head *);
9670 fib_hash_free(old_info_hash, bytes);
9671 fib_hash_free(old_laddrhash, bytes);
9672 }
9673
9674-struct fib_info *
9675-fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
9676- const struct nlmsghdr *nlh, int *errp)
9677+struct fib_info *fib_create_info(struct fib_config *cfg)
9678 {
9679 int err;
9680 struct fib_info *fi = NULL;
9681 struct fib_info *ofi;
9682-#ifdef CONFIG_IP_ROUTE_MULTIPATH
9683 int nhs = 1;
9684-#else
9685- const int nhs = 1;
9686-#endif
9687-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
9688- u32 mp_alg = IP_MP_ALG_NONE;
9689-#endif
9690
9691 /* Fast check to catch the most weird cases */
9692- if (fib_props[r->rtm_type].scope > r->rtm_scope)
9693+ if (fib_props[cfg->fc_type].scope > cfg->fc_scope)
9694 goto err_inval;
9695
9696 #ifdef CONFIG_IP_ROUTE_MULTIPATH
9697- if (rta->rta_mp) {
9698- nhs = fib_count_nexthops(rta->rta_mp);
9699+ if (cfg->fc_mp) {
9700+ nhs = fib_count_nexthops(cfg->fc_mp, cfg->fc_mp_len);
9701 if (nhs == 0)
9702 goto err_inval;
9703 }
9704 #endif
9705 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
9706- if (rta->rta_mp_alg) {
9707- mp_alg = *rta->rta_mp_alg;
9708-
9709- if (mp_alg < IP_MP_ALG_NONE ||
9710- mp_alg > IP_MP_ALG_MAX)
9711+ if (cfg->fc_mp_alg) {
9712+ if (cfg->fc_mp_alg < IP_MP_ALG_NONE ||
9713+ cfg->fc_mp_alg > IP_MP_ALG_MAX)
9714 goto err_inval;
9715 }
9716 #endif
9717@@ -714,43 +708,42 @@
9718 goto failure;
9719 fib_info_cnt++;
9720
9721- fi->fib_protocol = r->rtm_protocol;
9722+ fi->fib_protocol = cfg->fc_protocol;
9723+ fi->fib_flags = cfg->fc_flags;
9724+ fi->fib_priority = cfg->fc_priority;
9725+ fi->fib_prefsrc = cfg->fc_prefsrc;
9726
9727 fi->fib_nhs = nhs;
9728 change_nexthops(fi) {
9729 nh->nh_parent = fi;
9730 } endfor_nexthops(fi)
9731
9732- fi->fib_flags = r->rtm_flags;
9733- if (rta->rta_priority)
9734- fi->fib_priority = *rta->rta_priority;
9735- if (rta->rta_mx) {
9736- int attrlen = RTA_PAYLOAD(rta->rta_mx);
9737- struct rtattr *attr = RTA_DATA(rta->rta_mx);
9738-
9739- while (RTA_OK(attr, attrlen)) {
9740- unsigned flavor = attr->rta_type;
9741- if (flavor) {
9742- if (flavor > RTAX_MAX)
9743+ if (cfg->fc_mx) {
9744+ struct nlattr *nla;
9745+ int remaining;
9746+
9747+ nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) {
9748+ int type = nla->nla_type;
9749+
9750+ if (type) {
9751+ if (type > RTAX_MAX)
9752 goto err_inval;
9753- fi->fib_metrics[flavor-1] = *(unsigned*)RTA_DATA(attr);
9754+ fi->fib_metrics[type - 1] = nla_get_u32(nla);
9755 }
9756- attr = RTA_NEXT(attr, attrlen);
9757 }
9758 }
9759- if (rta->rta_prefsrc)
9760- memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 4);
9761
9762- if (rta->rta_mp) {
9763+ if (cfg->fc_mp) {
9764 #ifdef CONFIG_IP_ROUTE_MULTIPATH
9765- if ((err = fib_get_nhs(fi, rta->rta_mp, r)) != 0)
9766+ err = fib_get_nhs(fi, cfg->fc_mp, cfg->fc_mp_len, cfg);
9767+ if (err != 0)
9768 goto failure;
9769- if (rta->rta_oif && fi->fib_nh->nh_oif != *rta->rta_oif)
9770+ if (cfg->fc_oif && fi->fib_nh->nh_oif != cfg->fc_oif)
9771 goto err_inval;
9772- if (rta->rta_gw && memcmp(&fi->fib_nh->nh_gw, rta->rta_gw, 4))
9773+ if (cfg->fc_gw && fi->fib_nh->nh_gw != cfg->fc_gw)
9774 goto err_inval;
9775 #ifdef CONFIG_NET_CLS_ROUTE
9776- if (rta->rta_flow && memcmp(&fi->fib_nh->nh_tclassid, rta->rta_flow, 4))
9777+ if (cfg->fc_flow && fi->fib_nh->nh_tclassid != cfg->fc_flow)
9778 goto err_inval;
9779 #endif
9780 #else
9781@@ -758,34 +751,32 @@
9782 #endif
9783 } else {
9784 struct fib_nh *nh = fi->fib_nh;
9785- if (rta->rta_oif)
9786- nh->nh_oif = *rta->rta_oif;
9787- if (rta->rta_gw)
9788- memcpy(&nh->nh_gw, rta->rta_gw, 4);
9789+
9790+ nh->nh_oif = cfg->fc_oif;
9791+ nh->nh_gw = cfg->fc_gw;
9792+ nh->nh_flags = cfg->fc_flags;
9793 #ifdef CONFIG_NET_CLS_ROUTE
9794- if (rta->rta_flow)
9795- memcpy(&nh->nh_tclassid, rta->rta_flow, 4);
9796+ nh->nh_tclassid = cfg->fc_flow;
9797 #endif
9798- nh->nh_flags = r->rtm_flags;
9799 #ifdef CONFIG_IP_ROUTE_MULTIPATH
9800 nh->nh_weight = 1;
9801 #endif
9802 }
9803
9804 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
9805- fi->fib_mp_alg = mp_alg;
9806+ fi->fib_mp_alg = cfg->fc_mp_alg;
9807 #endif
9808
9809- if (fib_props[r->rtm_type].error) {
9810- if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
9811+ if (fib_props[cfg->fc_type].error) {
9812+ if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
9813 goto err_inval;
9814 goto link_it;
9815 }
9816
9817- if (r->rtm_scope > RT_SCOPE_HOST)
9818+ if (cfg->fc_scope > RT_SCOPE_HOST)
9819 goto err_inval;
9820
9821- if (r->rtm_scope == RT_SCOPE_HOST) {
9822+ if (cfg->fc_scope == RT_SCOPE_HOST) {
9823 struct fib_nh *nh = fi->fib_nh;
9824
9825 /* Local address is added. */
9826@@ -798,14 +789,14 @@
9827 goto failure;
9828 } else {
9829 change_nexthops(fi) {
9830- if ((err = fib_check_nh(r, fi, nh)) != 0)
9831+ if ((err = fib_check_nh(cfg, fi, nh)) != 0)
9832 goto failure;
9833 } endfor_nexthops(fi)
9834 }
9835
9836 if (fi->fib_prefsrc) {
9837- if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
9838- memcmp(&fi->fib_prefsrc, rta->rta_dst, 4))
9839+ if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
9840+ fi->fib_prefsrc != cfg->fc_dst)
9841 if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
9842 goto err_inval;
9843 }
9844@@ -820,7 +811,7 @@
9845
9846 fi->fib_treeref++;
9847 atomic_inc(&fi->fib_clntref);
9848- write_lock_bh(&fib_info_lock);
9849+ spin_lock_bh(&fib_info_lock);
9850 hlist_add_head(&fi->fib_hash,
9851 &fib_info_hash[fib_info_hashfn(fi)]);
9852 if (fi->fib_prefsrc) {
9853@@ -839,19 +830,19 @@
9854 head = &fib_info_devhash[hash];
9855 hlist_add_head(&nh->nh_hash, head);
9856 } endfor_nexthops(fi)
9857- write_unlock_bh(&fib_info_lock);
9858+ spin_unlock_bh(&fib_info_lock);
9859 return fi;
9860
9861 err_inval:
9862 err = -EINVAL;
9863
9864 failure:
9865- *errp = err;
9866 if (fi) {
9867 fi->fib_dead = 1;
9868 free_fib_info(fi);
9869 }
9870- return NULL;
9871+
9872+ return ERR_PTR(err);
9873 }
9874
9875 /* Note! fib_semantic_match intentionally uses RCU list functions. */
9876@@ -937,224 +928,89 @@
9877 return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);
9878 }
9879
9880-int
9881-fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
9882- u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
9883- struct fib_info *fi, unsigned int flags)
9884+int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
9885+ u32 tb_id, u8 type, u8 scope, u32 dst, int dst_len, u8 tos,
9886+ struct fib_info *fi, unsigned int flags)
9887 {
9888+ struct nlmsghdr *nlh;
9889 struct rtmsg *rtm;
9890- struct nlmsghdr *nlh;
9891- unsigned char *b = skb->tail;
9892
9893- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
9894- rtm = NLMSG_DATA(nlh);
9895+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
9896+ if (nlh == NULL)
9897+ return -ENOBUFS;
9898+
9899+ rtm = nlmsg_data(nlh);
9900 rtm->rtm_family = AF_INET;
9901 rtm->rtm_dst_len = dst_len;
9902 rtm->rtm_src_len = 0;
9903 rtm->rtm_tos = tos;
9904 rtm->rtm_table = tb_id;
9905+ NLA_PUT_U32(skb, RTA_TABLE, tb_id);
9906 rtm->rtm_type = type;
9907 rtm->rtm_flags = fi->fib_flags;
9908 rtm->rtm_scope = scope;
9909- if (rtm->rtm_dst_len)
9910- RTA_PUT(skb, RTA_DST, 4, dst);
9911 rtm->rtm_protocol = fi->fib_protocol;
9912+
9913+ if (rtm->rtm_dst_len)
9914+ NLA_PUT_U32(skb, RTA_DST, dst);
9915+
9916 if (fi->fib_priority)
9917- RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority);
9918+ NLA_PUT_U32(skb, RTA_PRIORITY, fi->fib_priority);
9919+
9920 if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0)
9921- goto rtattr_failure;
9922+ goto nla_put_failure;
9923+
9924 if (fi->fib_prefsrc)
9925- RTA_PUT(skb, RTA_PREFSRC, 4, &fi->fib_prefsrc);
9926+ NLA_PUT_U32(skb, RTA_PREFSRC, fi->fib_prefsrc);
9927+
9928 if (fi->fib_nhs == 1) {
9929 if (fi->fib_nh->nh_gw)
9930- RTA_PUT(skb, RTA_GATEWAY, 4, &fi->fib_nh->nh_gw);
9931+ NLA_PUT_U32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw);
9932+
9933 if (fi->fib_nh->nh_oif)
9934- RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif);
9935+ NLA_PUT_U32(skb, RTA_OIF, fi->fib_nh->nh_oif);
9936 #ifdef CONFIG_NET_CLS_ROUTE
9937 if (fi->fib_nh[0].nh_tclassid)
9938- RTA_PUT(skb, RTA_FLOW, 4, &fi->fib_nh[0].nh_tclassid);
9939+ NLA_PUT_U32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid);
9940 #endif
9941 }
9942 #ifdef CONFIG_IP_ROUTE_MULTIPATH
9943 if (fi->fib_nhs > 1) {
9944- struct rtnexthop *nhp;
9945- struct rtattr *mp_head;
9946- if (skb_tailroom(skb) <= RTA_SPACE(0))
9947- goto rtattr_failure;
9948- mp_head = (struct rtattr*)skb_put(skb, RTA_SPACE(0));
9949+ struct rtnexthop *rtnh;
9950+ struct nlattr *mp;
9951+
9952+ mp = nla_nest_start(skb, RTA_MULTIPATH);
9953+ if (mp == NULL)
9954+ goto nla_put_failure;
9955
9956 for_nexthops(fi) {
9957- if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
9958- goto rtattr_failure;
9959- nhp = (struct rtnexthop*)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
9960- nhp->rtnh_flags = nh->nh_flags & 0xFF;
9961- nhp->rtnh_hops = nh->nh_weight-1;
9962- nhp->rtnh_ifindex = nh->nh_oif;
9963+ rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
9964+ if (rtnh == NULL)
9965+ goto nla_put_failure;
9966+
9967+ rtnh->rtnh_flags = nh->nh_flags & 0xFF;
9968+ rtnh->rtnh_hops = nh->nh_weight - 1;
9969+ rtnh->rtnh_ifindex = nh->nh_oif;
9970+
9971 if (nh->nh_gw)
9972- RTA_PUT(skb, RTA_GATEWAY, 4, &nh->nh_gw);
9973+ NLA_PUT_U32(skb, RTA_GATEWAY, nh->nh_gw);
9974 #ifdef CONFIG_NET_CLS_ROUTE
9975 if (nh->nh_tclassid)
9976- RTA_PUT(skb, RTA_FLOW, 4, &nh->nh_tclassid);
9977+ NLA_PUT_U32(skb, RTA_FLOW, nh->nh_tclassid);
9978 #endif
9979- nhp->rtnh_len = skb->tail - (unsigned char*)nhp;
9980+ /* length of rtnetlink header + attributes */
9981+ rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh;
9982 } endfor_nexthops(fi);
9983- mp_head->rta_type = RTA_MULTIPATH;
9984- mp_head->rta_len = skb->tail - (u8*)mp_head;
9985- }
9986-#endif
9987- nlh->nlmsg_len = skb->tail - b;
9988- return skb->len;
9989-
9990-nlmsg_failure:
9991-rtattr_failure:
9992- skb_trim(skb, b - skb->data);
9993- return -1;
9994-}
9995-
9996-#ifndef CONFIG_IP_NOSIOCRT
9997-
9998-int
9999-fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
10000- struct kern_rta *rta, struct rtentry *r)
10001-{
10002- int plen;
10003- u32 *ptr;
10004-
10005- memset(rtm, 0, sizeof(*rtm));
10006- memset(rta, 0, sizeof(*rta));
10007-
10008- if (r->rt_dst.sa_family != AF_INET)
10009- return -EAFNOSUPPORT;
10010-
10011- /* Check mask for validity:
10012- a) it must be contiguous.
10013- b) destination must have all host bits clear.
10014- c) if application forgot to set correct family (AF_INET),
10015- reject request unless it is absolutely clear i.e.
10016- both family and mask are zero.
10017- */
10018- plen = 32;
10019- ptr = &((struct sockaddr_in*)&r->rt_dst)->sin_addr.s_addr;
10020- if (!(r->rt_flags&RTF_HOST)) {
10021- u32 mask = ((struct sockaddr_in*)&r->rt_genmask)->sin_addr.s_addr;
10022- if (r->rt_genmask.sa_family != AF_INET) {
10023- if (mask || r->rt_genmask.sa_family)
10024- return -EAFNOSUPPORT;
10025- }
10026- if (bad_mask(mask, *ptr))
10027- return -EINVAL;
10028- plen = inet_mask_len(mask);
10029- }
10030-
10031- nl->nlmsg_flags = NLM_F_REQUEST;
10032- nl->nlmsg_pid = 0;
10033- nl->nlmsg_seq = 0;
10034- nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm));
10035- if (cmd == SIOCDELRT) {
10036- nl->nlmsg_type = RTM_DELROUTE;
10037- nl->nlmsg_flags = 0;
10038- } else {
10039- nl->nlmsg_type = RTM_NEWROUTE;
10040- nl->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE;
10041- rtm->rtm_protocol = RTPROT_BOOT;
10042- }
10043-
10044- rtm->rtm_dst_len = plen;
10045- rta->rta_dst = ptr;
10046-
10047- if (r->rt_metric) {
10048- *(u32*)&r->rt_pad3 = r->rt_metric - 1;
10049- rta->rta_priority = (u32*)&r->rt_pad3;
10050- }
10051- if (r->rt_flags&RTF_REJECT) {
10052- rtm->rtm_scope = RT_SCOPE_HOST;
10053- rtm->rtm_type = RTN_UNREACHABLE;
10054- return 0;
10055- }
10056- rtm->rtm_scope = RT_SCOPE_NOWHERE;
10057- rtm->rtm_type = RTN_UNICAST;
10058
10059- if (r->rt_dev) {
10060- char *colon;
10061- struct net_device *dev;
10062- char devname[IFNAMSIZ];
10063-
10064- if (copy_from_user(devname, r->rt_dev, IFNAMSIZ-1))
10065- return -EFAULT;
10066- devname[IFNAMSIZ-1] = 0;
10067- colon = strchr(devname, ':');
10068- if (colon)
10069- *colon = 0;
10070- dev = __dev_get_by_name(devname);
10071- if (!dev)
10072- return -ENODEV;
10073- rta->rta_oif = &dev->ifindex;
10074- if (colon) {
10075- struct in_ifaddr *ifa;
10076- struct in_device *in_dev = __in_dev_get_rtnl(dev);
10077- if (!in_dev)
10078- return -ENODEV;
10079- *colon = ':';
10080- for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next)
10081- if (strcmp(ifa->ifa_label, devname) == 0)
10082- break;
10083- if (ifa == NULL)
10084- return -ENODEV;
10085- rta->rta_prefsrc = &ifa->ifa_local;
10086- }
10087- }
10088-
10089- ptr = &((struct sockaddr_in*)&r->rt_gateway)->sin_addr.s_addr;
10090- if (r->rt_gateway.sa_family == AF_INET && *ptr) {
10091- rta->rta_gw = ptr;
10092- if (r->rt_flags&RTF_GATEWAY && inet_addr_type(*ptr) == RTN_UNICAST)
10093- rtm->rtm_scope = RT_SCOPE_UNIVERSE;
10094+ nla_nest_end(skb, mp);
10095 }
10096+#endif
10097+ return nlmsg_end(skb, nlh);
10098
10099- if (cmd == SIOCDELRT)
10100- return 0;
10101-
10102- if (r->rt_flags&RTF_GATEWAY && rta->rta_gw == NULL)
10103- return -EINVAL;
10104-
10105- if (rtm->rtm_scope == RT_SCOPE_NOWHERE)
10106- rtm->rtm_scope = RT_SCOPE_LINK;
10107-
10108- if (r->rt_flags&(RTF_MTU|RTF_WINDOW|RTF_IRTT)) {
10109- struct rtattr *rec;
10110- struct rtattr *mx = kmalloc(RTA_LENGTH(3*RTA_LENGTH(4)), GFP_KERNEL);
10111- if (mx == NULL)
10112- return -ENOMEM;
10113- rta->rta_mx = mx;
10114- mx->rta_type = RTA_METRICS;
10115- mx->rta_len = RTA_LENGTH(0);
10116- if (r->rt_flags&RTF_MTU) {
10117- rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len));
10118- rec->rta_type = RTAX_ADVMSS;
10119- rec->rta_len = RTA_LENGTH(4);
10120- mx->rta_len += RTA_LENGTH(4);
10121- *(u32*)RTA_DATA(rec) = r->rt_mtu - 40;
10122- }
10123- if (r->rt_flags&RTF_WINDOW) {
10124- rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len));
10125- rec->rta_type = RTAX_WINDOW;
10126- rec->rta_len = RTA_LENGTH(4);
10127- mx->rta_len += RTA_LENGTH(4);
10128- *(u32*)RTA_DATA(rec) = r->rt_window;
10129- }
10130- if (r->rt_flags&RTF_IRTT) {
10131- rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len));
10132- rec->rta_type = RTAX_RTT;
10133- rec->rta_len = RTA_LENGTH(4);
10134- mx->rta_len += RTA_LENGTH(4);
10135- *(u32*)RTA_DATA(rec) = r->rt_irtt<<3;
10136- }
10137- }
10138- return 0;
10139+nla_put_failure:
10140+ return nlmsg_cancel(skb, nlh);
10141 }
10142
10143-#endif
10144-
10145 /*
10146 Update FIB if:
10147 - local address disappeared -> we must delete all the entries
10148diff -Nur linux-2.6.18-rc5/net/ipv4/fib_trie.c linux-2.6.19/net/ipv4/fib_trie.c
10149--- linux-2.6.18-rc5/net/ipv4/fib_trie.c 2006-08-28 05:41:48.000000000 +0200
10150+++ linux-2.6.19/net/ipv4/fib_trie.c 2006-09-22 10:04:58.000000000 +0200
10151@@ -1124,17 +1124,14 @@
10152 return fa_head;
10153 }
10154
10155-static int
10156-fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
10157- struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
10158+static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
10159 {
10160 struct trie *t = (struct trie *) tb->tb_data;
10161 struct fib_alias *fa, *new_fa;
10162 struct list_head *fa_head = NULL;
10163 struct fib_info *fi;
10164- int plen = r->rtm_dst_len;
10165- int type = r->rtm_type;
10166- u8 tos = r->rtm_tos;
10167+ int plen = cfg->fc_dst_len;
10168+ u8 tos = cfg->fc_tos;
10169 u32 key, mask;
10170 int err;
10171 struct leaf *l;
10172@@ -1142,13 +1139,9 @@
10173 if (plen > 32)
10174 return -EINVAL;
10175
10176- key = 0;
10177- if (rta->rta_dst)
10178- memcpy(&key, rta->rta_dst, 4);
10179-
10180- key = ntohl(key);
10181+ key = ntohl(cfg->fc_dst);
10182
10183- pr_debug("Insert table=%d %08x/%d\n", tb->tb_id, key, plen);
10184+ pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
10185
10186 mask = ntohl(inet_make_mask(plen));
10187
10188@@ -1157,10 +1150,11 @@
10189
10190 key = key & mask;
10191
10192- fi = fib_create_info(r, rta, nlhdr, &err);
10193-
10194- if (!fi)
10195+ fi = fib_create_info(cfg);
10196+ if (IS_ERR(fi)) {
10197+ err = PTR_ERR(fi);
10198 goto err;
10199+ }
10200
10201 l = fib_find_node(t, key);
10202 fa = NULL;
10203@@ -1185,10 +1179,10 @@
10204 struct fib_alias *fa_orig;
10205
10206 err = -EEXIST;
10207- if (nlhdr->nlmsg_flags & NLM_F_EXCL)
10208+ if (cfg->fc_nlflags & NLM_F_EXCL)
10209 goto out;
10210
10211- if (nlhdr->nlmsg_flags & NLM_F_REPLACE) {
10212+ if (cfg->fc_nlflags & NLM_F_REPLACE) {
10213 struct fib_info *fi_drop;
10214 u8 state;
10215
10216@@ -1200,8 +1194,8 @@
10217 fi_drop = fa->fa_info;
10218 new_fa->fa_tos = fa->fa_tos;
10219 new_fa->fa_info = fi;
10220- new_fa->fa_type = type;
10221- new_fa->fa_scope = r->rtm_scope;
10222+ new_fa->fa_type = cfg->fc_type;
10223+ new_fa->fa_scope = cfg->fc_scope;
10224 state = fa->fa_state;
10225 new_fa->fa_state &= ~FA_S_ACCESSED;
10226
10227@@ -1224,17 +1218,17 @@
10228 break;
10229 if (fa->fa_info->fib_priority != fi->fib_priority)
10230 break;
10231- if (fa->fa_type == type &&
10232- fa->fa_scope == r->rtm_scope &&
10233+ if (fa->fa_type == cfg->fc_type &&
10234+ fa->fa_scope == cfg->fc_scope &&
10235 fa->fa_info == fi) {
10236 goto out;
10237 }
10238 }
10239- if (!(nlhdr->nlmsg_flags & NLM_F_APPEND))
10240+ if (!(cfg->fc_nlflags & NLM_F_APPEND))
10241 fa = fa_orig;
10242 }
10243 err = -ENOENT;
10244- if (!(nlhdr->nlmsg_flags & NLM_F_CREATE))
10245+ if (!(cfg->fc_nlflags & NLM_F_CREATE))
10246 goto out;
10247
10248 err = -ENOBUFS;
10249@@ -1244,8 +1238,8 @@
10250
10251 new_fa->fa_info = fi;
10252 new_fa->fa_tos = tos;
10253- new_fa->fa_type = type;
10254- new_fa->fa_scope = r->rtm_scope;
10255+ new_fa->fa_type = cfg->fc_type;
10256+ new_fa->fa_scope = cfg->fc_scope;
10257 new_fa->fa_state = 0;
10258 /*
10259 * Insert new entry to the list.
10260@@ -1262,7 +1256,8 @@
10261 (fa ? &fa->fa_list : fa_head));
10262
10263 rt_cache_flush(-1);
10264- rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req);
10265+ rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
10266+ &cfg->fc_nlinfo);
10267 succeeded:
10268 return 0;
10269
10270@@ -1548,28 +1543,21 @@
10271 return 1;
10272 }
10273
10274-static int
10275-fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
10276- struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
10277+static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
10278 {
10279 struct trie *t = (struct trie *) tb->tb_data;
10280 u32 key, mask;
10281- int plen = r->rtm_dst_len;
10282- u8 tos = r->rtm_tos;
10283+ int plen = cfg->fc_dst_len;
10284+ u8 tos = cfg->fc_tos;
10285 struct fib_alias *fa, *fa_to_delete;
10286 struct list_head *fa_head;
10287 struct leaf *l;
10288 struct leaf_info *li;
10289
10290-
10291 if (plen > 32)
10292 return -EINVAL;
10293
10294- key = 0;
10295- if (rta->rta_dst)
10296- memcpy(&key, rta->rta_dst, 4);
10297-
10298- key = ntohl(key);
10299+ key = ntohl(cfg->fc_dst);
10300 mask = ntohl(inet_make_mask(plen));
10301
10302 if (key & ~mask)
10303@@ -1598,13 +1586,12 @@
10304 if (fa->fa_tos != tos)
10305 break;
10306
10307- if ((!r->rtm_type ||
10308- fa->fa_type == r->rtm_type) &&
10309- (r->rtm_scope == RT_SCOPE_NOWHERE ||
10310- fa->fa_scope == r->rtm_scope) &&
10311- (!r->rtm_protocol ||
10312- fi->fib_protocol == r->rtm_protocol) &&
10313- fib_nh_match(r, nlhdr, rta, fi) == 0) {
10314+ if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
10315+ (cfg->fc_scope == RT_SCOPE_NOWHERE ||
10316+ fa->fa_scope == cfg->fc_scope) &&
10317+ (!cfg->fc_protocol ||
10318+ fi->fib_protocol == cfg->fc_protocol) &&
10319+ fib_nh_match(cfg, fi) == 0) {
10320 fa_to_delete = fa;
10321 break;
10322 }
10323@@ -1614,7 +1601,8 @@
10324 return -ESRCH;
10325
10326 fa = fa_to_delete;
10327- rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req);
10328+ rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id,
10329+ &cfg->fc_nlinfo);
10330
10331 l = fib_find_node(t, key);
10332 li = find_leaf_info(l, plen);
10333@@ -1848,7 +1836,7 @@
10334
10335 u32 xkey = htonl(key);
10336
10337- s_i = cb->args[3];
10338+ s_i = cb->args[4];
10339 i = 0;
10340
10341 /* rcu_read_lock is hold by caller */
10342@@ -1866,16 +1854,16 @@
10343 tb->tb_id,
10344 fa->fa_type,
10345 fa->fa_scope,
10346- &xkey,
10347+ xkey,
10348 plen,
10349 fa->fa_tos,
10350 fa->fa_info, 0) < 0) {
10351- cb->args[3] = i;
10352+ cb->args[4] = i;
10353 return -1;
10354 }
10355 i++;
10356 }
10357- cb->args[3] = i;
10358+ cb->args[4] = i;
10359 return skb->len;
10360 }
10361
10362@@ -1886,14 +1874,14 @@
10363 struct list_head *fa_head;
10364 struct leaf *l = NULL;
10365
10366- s_h = cb->args[2];
10367+ s_h = cb->args[3];
10368
10369 for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
10370 if (h < s_h)
10371 continue;
10372 if (h > s_h)
10373- memset(&cb->args[3], 0,
10374- sizeof(cb->args) - 3*sizeof(cb->args[0]));
10375+ memset(&cb->args[4], 0,
10376+ sizeof(cb->args) - 4*sizeof(cb->args[0]));
10377
10378 fa_head = get_fa_head(l, plen);
10379
10380@@ -1904,11 +1892,11 @@
10381 continue;
10382
10383 if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) {
10384- cb->args[2] = h;
10385+ cb->args[3] = h;
10386 return -1;
10387 }
10388 }
10389- cb->args[2] = h;
10390+ cb->args[3] = h;
10391 return skb->len;
10392 }
10393
10394@@ -1917,23 +1905,23 @@
10395 int m, s_m;
10396 struct trie *t = (struct trie *) tb->tb_data;
10397
10398- s_m = cb->args[1];
10399+ s_m = cb->args[2];
10400
10401 rcu_read_lock();
10402 for (m = 0; m <= 32; m++) {
10403 if (m < s_m)
10404 continue;
10405 if (m > s_m)
10406- memset(&cb->args[2], 0,
10407- sizeof(cb->args) - 2*sizeof(cb->args[0]));
10408+ memset(&cb->args[3], 0,
10409+ sizeof(cb->args) - 3*sizeof(cb->args[0]));
10410
10411 if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) {
10412- cb->args[1] = m;
10413+ cb->args[2] = m;
10414 goto out;
10415 }
10416 }
10417 rcu_read_unlock();
10418- cb->args[1] = m;
10419+ cb->args[2] = m;
10420 return skb->len;
10421 out:
10422 rcu_read_unlock();
10423@@ -1943,9 +1931,9 @@
10424 /* Fix more generic FIB names for init later */
10425
10426 #ifdef CONFIG_IP_MULTIPLE_TABLES
10427-struct fib_table * fib_hash_init(int id)
10428+struct fib_table * fib_hash_init(u32 id)
10429 #else
10430-struct fib_table * __init fib_hash_init(int id)
10431+struct fib_table * __init fib_hash_init(u32 id)
10432 #endif
10433 {
10434 struct fib_table *tb;
10435diff -Nur linux-2.6.18-rc5/net/ipv4/icmp.c linux-2.6.19/net/ipv4/icmp.c
10436--- linux-2.6.18-rc5/net/ipv4/icmp.c 2006-08-28 05:41:48.000000000 +0200
10437+++ linux-2.6.19/net/ipv4/icmp.c 2006-09-22 10:04:58.000000000 +0200
10438@@ -187,11 +187,11 @@
10439 };
10440
10441 /* Control parameters for ECHO replies. */
10442-int sysctl_icmp_echo_ignore_all;
10443-int sysctl_icmp_echo_ignore_broadcasts = 1;
10444+int sysctl_icmp_echo_ignore_all __read_mostly;
10445+int sysctl_icmp_echo_ignore_broadcasts __read_mostly = 1;
10446
10447 /* Control parameter - ignore bogus broadcast responses? */
10448-int sysctl_icmp_ignore_bogus_error_responses = 1;
10449+int sysctl_icmp_ignore_bogus_error_responses __read_mostly = 1;
10450
10451 /*
10452 * Configurable global rate limit.
10453@@ -205,9 +205,9 @@
10454 * time exceeded (11), parameter problem (12)
10455 */
10456
10457-int sysctl_icmp_ratelimit = 1 * HZ;
10458-int sysctl_icmp_ratemask = 0x1818;
10459-int sysctl_icmp_errors_use_inbound_ifaddr;
10460+int sysctl_icmp_ratelimit __read_mostly = 1 * HZ;
10461+int sysctl_icmp_ratemask __read_mostly = 0x1818;
10462+int sysctl_icmp_errors_use_inbound_ifaddr __read_mostly;
10463
10464 /*
10465 * ICMP control array. This specifies what to do with each ICMP.
10466@@ -406,6 +406,7 @@
10467 .saddr = rt->rt_spec_dst,
10468 .tos = RT_TOS(skb->nh.iph->tos) } },
10469 .proto = IPPROTO_ICMP };
10470+ security_skb_classify_flow(skb, &fl);
10471 if (ip_route_output_key(&rt, &fl))
10472 goto out_unlock;
10473 }
10474@@ -560,6 +561,7 @@
10475 }
10476 }
10477 };
10478+ security_skb_classify_flow(skb_in, &fl);
10479 if (ip_route_output_key(&rt, &fl))
10480 goto out_unlock;
10481 }
10482@@ -928,7 +930,7 @@
10483 ICMP_INC_STATS_BH(ICMP_MIB_INMSGS);
10484
10485 switch (skb->ip_summed) {
10486- case CHECKSUM_HW:
10487+ case CHECKSUM_COMPLETE:
10488 if (!(u16)csum_fold(skb->csum))
10489 break;
10490 /* fall through */
10491diff -Nur linux-2.6.18-rc5/net/ipv4/igmp.c linux-2.6.19/net/ipv4/igmp.c
10492--- linux-2.6.18-rc5/net/ipv4/igmp.c 2006-08-28 05:41:48.000000000 +0200
10493+++ linux-2.6.19/net/ipv4/igmp.c 2006-09-22 10:04:58.000000000 +0200
10494@@ -931,7 +931,7 @@
10495 goto drop;
10496
10497 switch (skb->ip_summed) {
10498- case CHECKSUM_HW:
10499+ case CHECKSUM_COMPLETE:
10500 if (!(u16)csum_fold(skb->csum))
10501 break;
10502 /* fall through */
10503@@ -1397,8 +1397,8 @@
10504 /*
10505 * Join a socket to a group
10506 */
10507-int sysctl_igmp_max_memberships = IP_MAX_MEMBERSHIPS;
10508-int sysctl_igmp_max_msf = IP_MAX_MSF;
10509+int sysctl_igmp_max_memberships __read_mostly = IP_MAX_MEMBERSHIPS;
10510+int sysctl_igmp_max_msf __read_mostly = IP_MAX_MSF;
10511
10512
10513 static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
10514diff -Nur linux-2.6.18-rc5/net/ipv4/inet_connection_sock.c linux-2.6.19/net/ipv4/inet_connection_sock.c
10515--- linux-2.6.18-rc5/net/ipv4/inet_connection_sock.c 2006-08-28 05:41:48.000000000 +0200
10516+++ linux-2.6.19/net/ipv4/inet_connection_sock.c 2006-09-22 10:04:58.000000000 +0200
10517@@ -327,6 +327,7 @@
10518 { .sport = inet_sk(sk)->sport,
10519 .dport = ireq->rmt_port } } };
10520
10521+ security_req_classify_flow(req, &fl);
10522 if (ip_route_output_flow(&rt, &fl, sk, 0)) {
10523 IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
10524 return NULL;
10525@@ -509,6 +510,8 @@
10526
10527 /* Deinitialize accept_queue to trap illegal accesses. */
10528 memset(&newicsk->icsk_accept_queue, 0, sizeof(newicsk->icsk_accept_queue));
10529+
10530+ security_inet_csk_clone(newsk, req);
10531 }
10532 return newsk;
10533 }
10534diff -Nur linux-2.6.18-rc5/net/ipv4/inet_hashtables.c linux-2.6.19/net/ipv4/inet_hashtables.c
10535--- linux-2.6.18-rc5/net/ipv4/inet_hashtables.c 2006-08-28 05:41:48.000000000 +0200
10536+++ linux-2.6.19/net/ipv4/inet_hashtables.c 2006-09-22 10:04:58.000000000 +0200
10537@@ -124,8 +124,10 @@
10538 * remote address for the connection. So always assume those are both
10539 * wildcarded during the search since they can never be otherwise.
10540 */
10541-struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 daddr,
10542- const unsigned short hnum, const int dif)
10543+static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
10544+ const u32 daddr,
10545+ const unsigned short hnum,
10546+ const int dif)
10547 {
10548 struct sock *result = NULL, *sk;
10549 const struct hlist_node *node;
10550@@ -159,6 +161,33 @@
10551 return result;
10552 }
10553
10554+/* Optimize the common listener case. */
10555+struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
10556+ const u32 daddr, const unsigned short hnum,
10557+ const int dif)
10558+{
10559+ struct sock *sk = NULL;
10560+ const struct hlist_head *head;
10561+
10562+ read_lock(&hashinfo->lhash_lock);
10563+ head = &hashinfo->listening_hash[inet_lhashfn(hnum)];
10564+ if (!hlist_empty(head)) {
10565+ const struct inet_sock *inet = inet_sk((sk = __sk_head(head)));
10566+
10567+ if (inet->num == hnum && !sk->sk_node.next &&
10568+ (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
10569+ (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
10570+ !sk->sk_bound_dev_if)
10571+ goto sherry_cache;
10572+ sk = inet_lookup_listener_slow(head, daddr, hnum, dif);
10573+ }
10574+ if (sk) {
10575+sherry_cache:
10576+ sock_hold(sk);
10577+ }
10578+ read_unlock(&hashinfo->lhash_lock);
10579+ return sk;
10580+}
10581 EXPORT_SYMBOL_GPL(__inet_lookup_listener);
10582
10583 /* called with local bh disabled */
10584diff -Nur linux-2.6.18-rc5/net/ipv4/inetpeer.c linux-2.6.19/net/ipv4/inetpeer.c
10585--- linux-2.6.18-rc5/net/ipv4/inetpeer.c 2006-08-28 05:41:48.000000000 +0200
10586+++ linux-2.6.19/net/ipv4/inetpeer.c 2006-09-22 10:04:58.000000000 +0200
10587@@ -126,12 +126,9 @@
10588
10589 peer_cachep = kmem_cache_create("inet_peer_cache",
10590 sizeof(struct inet_peer),
10591- 0, SLAB_HWCACHE_ALIGN,
10592+ 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
10593 NULL, NULL);
10594
10595- if (!peer_cachep)
10596- panic("cannot create inet_peer_cache");
10597-
10598 /* All the timers, started at system startup tend
10599 to synchronize. Perturb it a bit.
10600 */
10601diff -Nur linux-2.6.18-rc5/net/ipv4/ip_fragment.c linux-2.6.19/net/ipv4/ip_fragment.c
10602--- linux-2.6.18-rc5/net/ipv4/ip_fragment.c 2006-08-28 05:41:48.000000000 +0200
10603+++ linux-2.6.19/net/ipv4/ip_fragment.c 2006-09-22 10:04:58.000000000 +0200
10604@@ -54,15 +54,15 @@
10605 * even the most extreme cases without allowing an attacker to measurably
10606 * harm machine performance.
10607 */
10608-int sysctl_ipfrag_high_thresh = 256*1024;
10609-int sysctl_ipfrag_low_thresh = 192*1024;
10610+int sysctl_ipfrag_high_thresh __read_mostly = 256*1024;
10611+int sysctl_ipfrag_low_thresh __read_mostly = 192*1024;
10612
10613-int sysctl_ipfrag_max_dist = 64;
10614+int sysctl_ipfrag_max_dist __read_mostly = 64;
10615
10616 /* Important NOTE! Fragment queue must be destroyed before MSL expires.
10617 * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL.
10618 */
10619-int sysctl_ipfrag_time = IP_FRAG_TIME;
10620+int sysctl_ipfrag_time __read_mostly = IP_FRAG_TIME;
10621
10622 struct ipfrag_skb_cb
10623 {
10624@@ -130,7 +130,7 @@
10625 }
10626
10627 static struct timer_list ipfrag_secret_timer;
10628-int sysctl_ipfrag_secret_interval = 10 * 60 * HZ;
10629+int sysctl_ipfrag_secret_interval __read_mostly = 10 * 60 * HZ;
10630
10631 static void ipfrag_secret_rebuild(unsigned long dummy)
10632 {
10633@@ -665,7 +665,7 @@
10634 head->len += fp->len;
10635 if (head->ip_summed != fp->ip_summed)
10636 head->ip_summed = CHECKSUM_NONE;
10637- else if (head->ip_summed == CHECKSUM_HW)
10638+ else if (head->ip_summed == CHECKSUM_COMPLETE)
10639 head->csum = csum_add(head->csum, fp->csum);
10640 head->truesize += fp->truesize;
10641 atomic_sub(fp->truesize, &ip_frag_mem);
10642diff -Nur linux-2.6.18-rc5/net/ipv4/ip_gre.c linux-2.6.19/net/ipv4/ip_gre.c
10643--- linux-2.6.18-rc5/net/ipv4/ip_gre.c 2006-08-28 05:41:48.000000000 +0200
10644+++ linux-2.6.19/net/ipv4/ip_gre.c 2006-09-22 10:04:58.000000000 +0200
10645@@ -393,7 +393,8 @@
10646 int code = skb->h.icmph->code;
10647 int rel_type = 0;
10648 int rel_code = 0;
10649- int rel_info = 0;
10650+ __be32 rel_info = 0;
10651+ __u32 n = 0;
10652 u16 flags;
10653 int grehlen = (iph->ihl<<2) + 4;
10654 struct sk_buff *skb2;
10655@@ -422,14 +423,16 @@
10656 default:
10657 return;
10658 case ICMP_PARAMETERPROB:
10659- if (skb->h.icmph->un.gateway < (iph->ihl<<2))
10660+ n = ntohl(skb->h.icmph->un.gateway) >> 24;
10661+ if (n < (iph->ihl<<2))
10662 return;
10663
10664 /* So... This guy found something strange INSIDE encapsulated
10665 packet. Well, he is fool, but what can we do ?
10666 */
10667 rel_type = ICMP_PARAMETERPROB;
10668- rel_info = skb->h.icmph->un.gateway - grehlen;
10669+ n -= grehlen;
10670+ rel_info = htonl(n << 24);
10671 break;
10672
10673 case ICMP_DEST_UNREACH:
10674@@ -440,13 +443,14 @@
10675 return;
10676 case ICMP_FRAG_NEEDED:
10677 /* And it is the only really necessary thing :-) */
10678- rel_info = ntohs(skb->h.icmph->un.frag.mtu);
10679- if (rel_info < grehlen+68)
10680+ n = ntohs(skb->h.icmph->un.frag.mtu);
10681+ if (n < grehlen+68)
10682 return;
10683- rel_info -= grehlen;
10684+ n -= grehlen;
10685 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
10686- if (rel_info > ntohs(eiph->tot_len))
10687+ if (n > ntohs(eiph->tot_len))
10688 return;
10689+ rel_info = htonl(n);
10690 break;
10691 default:
10692 /* All others are translated to HOST_UNREACH.
10693@@ -508,12 +512,11 @@
10694
10695 /* change mtu on this route */
10696 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
10697- if (rel_info > dst_mtu(skb2->dst)) {
10698+ if (n > dst_mtu(skb2->dst)) {
10699 kfree_skb(skb2);
10700 return;
10701 }
10702- skb2->dst->ops->update_pmtu(skb2->dst, rel_info);
10703- rel_info = htonl(rel_info);
10704+ skb2->dst->ops->update_pmtu(skb2->dst, n);
10705 } else if (type == ICMP_TIME_EXCEEDED) {
10706 struct ip_tunnel *t = netdev_priv(skb2->dev);
10707 if (t->parms.iph.ttl) {
10708@@ -576,7 +579,7 @@
10709
10710 if (flags&GRE_CSUM) {
10711 switch (skb->ip_summed) {
10712- case CHECKSUM_HW:
10713+ case CHECKSUM_COMPLETE:
10714 csum = (u16)csum_fold(skb->csum);
10715 if (!csum)
10716 break;
10717@@ -584,7 +587,7 @@
10718 case CHECKSUM_NONE:
10719 skb->csum = 0;
10720 csum = __skb_checksum_complete(skb);
10721- skb->ip_summed = CHECKSUM_HW;
10722+ skb->ip_summed = CHECKSUM_COMPLETE;
10723 }
10724 offset += 4;
10725 }
10726diff -Nur linux-2.6.18-rc5/net/ipv4/ip_options.c linux-2.6.19/net/ipv4/ip_options.c
10727--- linux-2.6.18-rc5/net/ipv4/ip_options.c 2006-08-28 05:41:48.000000000 +0200
10728+++ linux-2.6.19/net/ipv4/ip_options.c 2006-09-22 10:04:58.000000000 +0200
10729@@ -24,6 +24,7 @@
10730 #include <net/ip.h>
10731 #include <net/icmp.h>
10732 #include <net/route.h>
10733+#include <net/cipso_ipv4.h>
10734
10735 /*
10736 * Write options to IP header, record destination address to
10737@@ -194,6 +195,13 @@
10738 dopt->is_strictroute = sopt->is_strictroute;
10739 }
10740 }
10741+ if (sopt->cipso) {
10742+ optlen = sptr[sopt->cipso+1];
10743+ dopt->cipso = dopt->optlen+sizeof(struct iphdr);
10744+ memcpy(dptr, sptr+sopt->cipso, optlen);
10745+ dptr += optlen;
10746+ dopt->optlen += optlen;
10747+ }
10748 while (dopt->optlen & 3) {
10749 *dptr++ = IPOPT_END;
10750 dopt->optlen++;
10751@@ -434,6 +442,17 @@
10752 if (optptr[2] == 0 && optptr[3] == 0)
10753 opt->router_alert = optptr - iph;
10754 break;
10755+ case IPOPT_CIPSO:
10756+ if (opt->cipso) {
10757+ pp_ptr = optptr;
10758+ goto error;
10759+ }
10760+ opt->cipso = optptr - iph;
10761+ if (cipso_v4_validate(&optptr)) {
10762+ pp_ptr = optptr;
10763+ goto error;
10764+ }
10765+ break;
10766 case IPOPT_SEC:
10767 case IPOPT_SID:
10768 default:
10769@@ -506,7 +525,6 @@
10770 opt->__data[optlen++] = IPOPT_END;
10771 opt->optlen = optlen;
10772 opt->is_data = 1;
10773- opt->is_setbyuser = 1;
10774 if (optlen && ip_options_compile(opt, NULL)) {
10775 kfree(opt);
10776 return -EINVAL;
10777diff -Nur linux-2.6.18-rc5/net/ipv4/ip_output.c linux-2.6.19/net/ipv4/ip_output.c
10778--- linux-2.6.18-rc5/net/ipv4/ip_output.c 2006-08-28 05:41:48.000000000 +0200
10779+++ linux-2.6.19/net/ipv4/ip_output.c 2006-09-22 10:04:58.000000000 +0200
10780@@ -83,7 +83,7 @@
10781 #include <linux/netlink.h>
10782 #include <linux/tcp.h>
10783
10784-int sysctl_ip_default_ttl = IPDEFTTL;
10785+int sysctl_ip_default_ttl __read_mostly = IPDEFTTL;
10786
10787 /* Generate a checksum for an outgoing IP datagram. */
10788 __inline__ void ip_send_check(struct iphdr *iph)
10789@@ -328,6 +328,7 @@
10790 * keep trying until route appears or the connection times
10791 * itself out.
10792 */
10793+ security_sk_classify_flow(sk, &fl);
10794 if (ip_route_output_flow(&rt, &fl, sk, 0))
10795 goto no_route;
10796 }
10797@@ -425,7 +426,7 @@
10798 int ptr;
10799 struct net_device *dev;
10800 struct sk_buff *skb2;
10801- unsigned int mtu, hlen, left, len, ll_rs;
10802+ unsigned int mtu, hlen, left, len, ll_rs, pad;
10803 int offset;
10804 __be16 not_last_frag;
10805 struct rtable *rt = (struct rtable*)skb->dst;
10806@@ -554,14 +556,13 @@
10807 left = skb->len - hlen; /* Space per frame */
10808 ptr = raw + hlen; /* Where to start from */
10809
10810-#ifdef CONFIG_BRIDGE_NETFILTER
10811 /* for bridged IP traffic encapsulated inside f.e. a vlan header,
10812- * we need to make room for the encapsulating header */
10813- ll_rs = LL_RESERVED_SPACE_EXTRA(rt->u.dst.dev, nf_bridge_pad(skb));
10814- mtu -= nf_bridge_pad(skb);
10815-#else
10816- ll_rs = LL_RESERVED_SPACE(rt->u.dst.dev);
10817-#endif
10818+ * we need to make room for the encapsulating header
10819+ */
10820+ pad = nf_bridge_pad(skb);
10821+ ll_rs = LL_RESERVED_SPACE_EXTRA(rt->u.dst.dev, pad);
10822+ mtu -= pad;
10823+
10824 /*
10825 * Fragment the datagram.
10826 */
10827@@ -678,7 +679,7 @@
10828 {
10829 struct iovec *iov = from;
10830
10831- if (skb->ip_summed == CHECKSUM_HW) {
10832+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
10833 if (memcpy_fromiovecend(to, iov, offset, len) < 0)
10834 return -EFAULT;
10835 } else {
10836@@ -734,7 +735,7 @@
10837 /* initialize protocol header pointer */
10838 skb->h.raw = skb->data + fragheaderlen;
10839
10840- skb->ip_summed = CHECKSUM_HW;
10841+ skb->ip_summed = CHECKSUM_PARTIAL;
10842 skb->csum = 0;
10843 sk->sk_sndmsg_off = 0;
10844 }
10845@@ -842,7 +843,7 @@
10846 length + fragheaderlen <= mtu &&
10847 rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
10848 !exthdrlen)
10849- csummode = CHECKSUM_HW;
10850+ csummode = CHECKSUM_PARTIAL;
10851
10852 inet->cork.length += length;
10853 if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
10854@@ -1365,6 +1366,7 @@
10855 { .sport = skb->h.th->dest,
10856 .dport = skb->h.th->source } },
10857 .proto = sk->sk_protocol };
10858+ security_skb_classify_flow(skb, &fl);
10859 if (ip_route_output_key(&rt, &fl))
10860 return;
10861 }
10862diff -Nur linux-2.6.18-rc5/net/ipv4/ipcomp.c linux-2.6.19/net/ipv4/ipcomp.c
10863--- linux-2.6.18-rc5/net/ipv4/ipcomp.c 2006-08-28 05:41:48.000000000 +0200
10864+++ linux-2.6.19/net/ipv4/ipcomp.c 2006-09-22 10:04:58.000000000 +0200
10865@@ -176,7 +176,7 @@
10866 return 0;
10867
10868 out_ok:
10869- if (x->props.mode)
10870+ if (x->props.mode == XFRM_MODE_TUNNEL)
10871 ip_send_check(iph);
10872 return 0;
10873 }
10874@@ -216,7 +216,7 @@
10875 t->id.daddr.a4 = x->id.daddr.a4;
10876 memcpy(&t->sel, &x->sel, sizeof(t->sel));
10877 t->props.family = AF_INET;
10878- t->props.mode = 1;
10879+ t->props.mode = XFRM_MODE_TUNNEL;
10880 t->props.saddr.a4 = x->props.saddr.a4;
10881 t->props.flags = x->props.flags;
10882
10883@@ -415,7 +415,7 @@
10884 goto out;
10885
10886 x->props.header_len = 0;
10887- if (x->props.mode)
10888+ if (x->props.mode == XFRM_MODE_TUNNEL)
10889 x->props.header_len += sizeof(struct iphdr);
10890
10891 mutex_lock(&ipcomp_resource_mutex);
10892@@ -427,7 +427,7 @@
10893 goto error;
10894 mutex_unlock(&ipcomp_resource_mutex);
10895
10896- if (x->props.mode) {
10897+ if (x->props.mode == XFRM_MODE_TUNNEL) {
10898 err = ipcomp_tunnel_attach(x);
10899 if (err)
10900 goto error_tunnel;
10901diff -Nur linux-2.6.18-rc5/net/ipv4/ipconfig.c linux-2.6.19/net/ipv4/ipconfig.c
10902--- linux-2.6.18-rc5/net/ipv4/ipconfig.c 2006-08-28 05:41:48.000000000 +0200
10903+++ linux-2.6.19/net/ipv4/ipconfig.c 2006-09-22 10:04:58.000000000 +0200
10904@@ -31,7 +31,6 @@
10905 * -- Josef Siemes <jsiemes@web.de>, Aug 2002
10906 */
10907
10908-#include <linux/config.h>
10909 #include <linux/types.h>
10910 #include <linux/string.h>
10911 #include <linux/kernel.h>
10912diff -Nur linux-2.6.18-rc5/net/ipv4/ipip.c linux-2.6.19/net/ipv4/ipip.c
10913--- linux-2.6.18-rc5/net/ipv4/ipip.c 2006-08-28 05:41:48.000000000 +0200
10914+++ linux-2.6.19/net/ipv4/ipip.c 2006-09-22 10:04:58.000000000 +0200
10915@@ -341,7 +341,8 @@
10916 int code = skb->h.icmph->code;
10917 int rel_type = 0;
10918 int rel_code = 0;
10919- int rel_info = 0;
10920+ __be32 rel_info = 0;
10921+ __u32 n = 0;
10922 struct sk_buff *skb2;
10923 struct flowi fl;
10924 struct rtable *rt;
10925@@ -354,14 +355,15 @@
10926 default:
10927 return 0;
10928 case ICMP_PARAMETERPROB:
10929- if (skb->h.icmph->un.gateway < hlen)
10930+ n = ntohl(skb->h.icmph->un.gateway) >> 24;
10931+ if (n < hlen)
10932 return 0;
10933
10934 /* So... This guy found something strange INSIDE encapsulated
10935 packet. Well, he is fool, but what can we do ?
10936 */
10937 rel_type = ICMP_PARAMETERPROB;
10938- rel_info = skb->h.icmph->un.gateway - hlen;
10939+ rel_info = htonl((n - hlen) << 24);
10940 break;
10941
10942 case ICMP_DEST_UNREACH:
10943@@ -372,13 +374,14 @@
10944 return 0;
10945 case ICMP_FRAG_NEEDED:
10946 /* And it is the only really necessary thing :-) */
10947- rel_info = ntohs(skb->h.icmph->un.frag.mtu);
10948- if (rel_info < hlen+68)
10949+ n = ntohs(skb->h.icmph->un.frag.mtu);
10950+ if (n < hlen+68)
10951 return 0;
10952- rel_info -= hlen;
10953+ n -= hlen;
10954 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
10955- if (rel_info > ntohs(eiph->tot_len))
10956+ if (n > ntohs(eiph->tot_len))
10957 return 0;
10958+ rel_info = htonl(n);
10959 break;
10960 default:
10961 /* All others are translated to HOST_UNREACH.
10962@@ -440,12 +443,11 @@
10963
10964 /* change mtu on this route */
10965 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
10966- if (rel_info > dst_mtu(skb2->dst)) {
10967+ if (n > dst_mtu(skb2->dst)) {
10968 kfree_skb(skb2);
10969 return 0;
10970 }
10971- skb2->dst->ops->update_pmtu(skb2->dst, rel_info);
10972- rel_info = htonl(rel_info);
10973+ skb2->dst->ops->update_pmtu(skb2->dst, n);
10974 } else if (type == ICMP_TIME_EXCEEDED) {
10975 struct ip_tunnel *t = netdev_priv(skb2->dev);
10976 if (t->parms.iph.ttl) {
10977diff -Nur linux-2.6.18-rc5/net/ipv4/ipmr.c linux-2.6.19/net/ipv4/ipmr.c
10978--- linux-2.6.18-rc5/net/ipv4/ipmr.c 2006-08-28 05:41:48.000000000 +0200
10979+++ linux-2.6.19/net/ipv4/ipmr.c 2006-09-22 10:04:58.000000000 +0200
10980@@ -312,7 +312,8 @@
10981 e = NLMSG_DATA(nlh);
10982 e->error = -ETIMEDOUT;
10983 memset(&e->msg, 0, sizeof(e->msg));
10984- netlink_unicast(rtnl, skb, NETLINK_CB(skb).dst_pid, MSG_DONTWAIT);
10985+
10986+ rtnl_unicast(skb, NETLINK_CB(skb).pid);
10987 } else
10988 kfree_skb(skb);
10989 }
10990@@ -512,7 +513,6 @@
10991
10992 while((skb=__skb_dequeue(&uc->mfc_un.unres.unresolved))) {
10993 if (skb->nh.iph->version == 0) {
10994- int err;
10995 struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
10996
10997 if (ipmr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) {
10998@@ -525,7 +525,8 @@
10999 e->error = -EMSGSIZE;
11000 memset(&e->msg, 0, sizeof(e->msg));
11001 }
11002- err = netlink_unicast(rtnl, skb, NETLINK_CB(skb).dst_pid, MSG_DONTWAIT);
11003+
11004+ rtnl_unicast(skb, NETLINK_CB(skb).pid);
11005 } else
11006 ip_mr_forward(skb, c, 0);
11007 }
11008@@ -1899,11 +1900,8 @@
11009 {
11010 mrt_cachep = kmem_cache_create("ip_mrt_cache",
11011 sizeof(struct mfc_cache),
11012- 0, SLAB_HWCACHE_ALIGN,
11013+ 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
11014 NULL, NULL);
11015- if (!mrt_cachep)
11016- panic("cannot allocate ip_mrt_cache");
11017-
11018 init_timer(&ipmr_expire_timer);
11019 ipmr_expire_timer.function=ipmr_expire_process;
11020 register_netdevice_notifier(&ip_mr_notifier);
11021diff -Nur linux-2.6.18-rc5/net/ipv4/ipvs/ip_vs_proto_tcp.c linux-2.6.19/net/ipv4/ipvs/ip_vs_proto_tcp.c
11022--- linux-2.6.18-rc5/net/ipv4/ipvs/ip_vs_proto_tcp.c 2006-08-28 05:41:48.000000000 +0200
11023+++ linux-2.6.19/net/ipv4/ipvs/ip_vs_proto_tcp.c 2006-09-22 10:04:58.000000000 +0200
11024@@ -151,7 +151,7 @@
11025 /* Only port and addr are changed, do fast csum update */
11026 tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr,
11027 cp->dport, cp->vport);
11028- if ((*pskb)->ip_summed == CHECKSUM_HW)
11029+ if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
11030 (*pskb)->ip_summed = CHECKSUM_NONE;
11031 } else {
11032 /* full checksum calculation */
11033@@ -204,7 +204,7 @@
11034 /* Only port and addr are changed, do fast csum update */
11035 tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr,
11036 cp->vport, cp->dport);
11037- if ((*pskb)->ip_summed == CHECKSUM_HW)
11038+ if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
11039 (*pskb)->ip_summed = CHECKSUM_NONE;
11040 } else {
11041 /* full checksum calculation */
11042@@ -229,7 +229,7 @@
11043 switch (skb->ip_summed) {
11044 case CHECKSUM_NONE:
11045 skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
11046- case CHECKSUM_HW:
11047+ case CHECKSUM_COMPLETE:
11048 if (csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
11049 skb->len - tcphoff,
11050 skb->nh.iph->protocol, skb->csum)) {
11051@@ -239,7 +239,7 @@
11052 }
11053 break;
11054 default:
11055- /* CHECKSUM_UNNECESSARY */
11056+ /* No need to checksum. */
11057 break;
11058 }
11059
11060diff -Nur linux-2.6.18-rc5/net/ipv4/ipvs/ip_vs_proto_udp.c linux-2.6.19/net/ipv4/ipvs/ip_vs_proto_udp.c
11061--- linux-2.6.18-rc5/net/ipv4/ipvs/ip_vs_proto_udp.c 2006-08-28 05:41:48.000000000 +0200
11062+++ linux-2.6.19/net/ipv4/ipvs/ip_vs_proto_udp.c 2006-09-22 10:04:58.000000000 +0200
11063@@ -161,7 +161,7 @@
11064 /* Only port and addr are changed, do fast csum update */
11065 udp_fast_csum_update(udph, cp->daddr, cp->vaddr,
11066 cp->dport, cp->vport);
11067- if ((*pskb)->ip_summed == CHECKSUM_HW)
11068+ if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
11069 (*pskb)->ip_summed = CHECKSUM_NONE;
11070 } else {
11071 /* full checksum calculation */
11072@@ -216,7 +216,7 @@
11073 /* Only port and addr are changed, do fast csum update */
11074 udp_fast_csum_update(udph, cp->vaddr, cp->daddr,
11075 cp->vport, cp->dport);
11076- if ((*pskb)->ip_summed == CHECKSUM_HW)
11077+ if ((*pskb)->ip_summed == CHECKSUM_COMPLETE)
11078 (*pskb)->ip_summed = CHECKSUM_NONE;
11079 } else {
11080 /* full checksum calculation */
11081@@ -250,7 +250,7 @@
11082 case CHECKSUM_NONE:
11083 skb->csum = skb_checksum(skb, udphoff,
11084 skb->len - udphoff, 0);
11085- case CHECKSUM_HW:
11086+ case CHECKSUM_COMPLETE:
11087 if (csum_tcpudp_magic(skb->nh.iph->saddr,
11088 skb->nh.iph->daddr,
11089 skb->len - udphoff,
11090@@ -262,7 +262,7 @@
11091 }
11092 break;
11093 default:
11094- /* CHECKSUM_UNNECESSARY */
11095+ /* No need to checksum. */
11096 break;
11097 }
11098 }
11099diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/Kconfig linux-2.6.19/net/ipv4/netfilter/Kconfig
11100--- linux-2.6.18-rc5/net/ipv4/netfilter/Kconfig 2006-08-28 05:41:48.000000000 +0200
11101+++ linux-2.6.19/net/ipv4/netfilter/Kconfig 2006-09-22 10:04:58.000000000 +0200
11102@@ -278,17 +278,6 @@
11103
11104 To compile it as a module, choose M here. If unsure, say N.
11105
11106-config IP_NF_MATCH_DSCP
11107- tristate "DSCP match support"
11108- depends on IP_NF_IPTABLES
11109- help
11110- This option adds a `DSCP' match, which allows you to match against
11111- the IPv4 header DSCP field (DSCP codepoint).
11112-
11113- The DSCP codepoint can have any value between 0x0 and 0x4f.
11114-
11115- To compile it as a module, choose M here. If unsure, say N.
11116-
11117 config IP_NF_MATCH_AH
11118 tristate "AH match support"
11119 depends on IP_NF_IPTABLES
11120@@ -568,17 +557,6 @@
11121
11122 To compile it as a module, choose M here. If unsure, say N.
11123
11124-config IP_NF_TARGET_DSCP
11125- tristate "DSCP target support"
11126- depends on IP_NF_MANGLE
11127- help
11128- This option adds a `DSCP' match, which allows you to match against
11129- the IPv4 header DSCP field (DSCP codepoint).
11130-
11131- The DSCP codepoint can have any value between 0x0 and 0x4f.
11132-
11133- To compile it as a module, choose M here. If unsure, say N.
11134-
11135 config IP_NF_TARGET_TTL
11136 tristate 'TTL target support'
11137 depends on IP_NF_MANGLE
11138diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/Makefile linux-2.6.19/net/ipv4/netfilter/Makefile
11139--- linux-2.6.18-rc5/net/ipv4/netfilter/Makefile 2006-08-28 05:41:48.000000000 +0200
11140+++ linux-2.6.19/net/ipv4/netfilter/Makefile 2006-09-22 10:04:58.000000000 +0200
11141@@ -59,7 +59,6 @@
11142 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
11143 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
11144 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
11145-obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
11146 obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
11147 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
11148 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
11149@@ -68,7 +67,6 @@
11150 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
11151 obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
11152 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
11153-obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
11154 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
11155 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
11156 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
11157diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/arp_tables.c linux-2.6.19/net/ipv4/netfilter/arp_tables.c
11158--- linux-2.6.18-rc5/net/ipv4/netfilter/arp_tables.c 2006-08-28 05:41:48.000000000 +0200
11159+++ linux-2.6.19/net/ipv4/netfilter/arp_tables.c 2006-09-22 10:04:58.000000000 +0200
11160@@ -208,8 +208,7 @@
11161 const struct net_device *out,
11162 unsigned int hooknum,
11163 const struct xt_target *target,
11164- const void *targinfo,
11165- void *userinfo)
11166+ const void *targinfo)
11167 {
11168 if (net_ratelimit())
11169 printk("arp_tables: error: '%s'\n", (char *)targinfo);
11170@@ -226,8 +225,7 @@
11171 unsigned int hook,
11172 const struct net_device *in,
11173 const struct net_device *out,
11174- struct arpt_table *table,
11175- void *userdata)
11176+ struct arpt_table *table)
11177 {
11178 static const char nulldevname[IFNAMSIZ];
11179 unsigned int verdict = NF_DROP;
11180@@ -302,8 +300,7 @@
11181 in, out,
11182 hook,
11183 t->u.kernel.target,
11184- t->data,
11185- userdata);
11186+ t->data);
11187
11188 /* Target might have changed stuff. */
11189 arp = (*pskb)->nh.arph;
11190@@ -494,8 +491,6 @@
11191 }
11192 } else if (t->u.kernel.target->checkentry
11193 && !t->u.kernel.target->checkentry(name, e, target, t->data,
11194- t->u.target_size
11195- - sizeof(*t),
11196 e->comefrom)) {
11197 duprintf("arp_tables: check failed for `%s'.\n",
11198 t->u.kernel.target->name);
11199@@ -562,8 +557,7 @@
11200
11201 t = arpt_get_target(e);
11202 if (t->u.kernel.target->destroy)
11203- t->u.kernel.target->destroy(t->u.kernel.target, t->data,
11204- t->u.target_size - sizeof(*t));
11205+ t->u.kernel.target->destroy(t->u.kernel.target, t->data);
11206 module_put(t->u.kernel.target->me);
11207 return 0;
11208 }
11209diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/arpt_mangle.c linux-2.6.19/net/ipv4/netfilter/arpt_mangle.c
11210--- linux-2.6.18-rc5/net/ipv4/netfilter/arpt_mangle.c 2006-08-28 05:41:48.000000000 +0200
11211+++ linux-2.6.19/net/ipv4/netfilter/arpt_mangle.c 2006-09-22 10:04:58.000000000 +0200
11212@@ -11,7 +11,7 @@
11213 target(struct sk_buff **pskb,
11214 const struct net_device *in, const struct net_device *out,
11215 unsigned int hooknum, const struct xt_target *target,
11216- const void *targinfo, void *userinfo)
11217+ const void *targinfo)
11218 {
11219 const struct arpt_mangle *mangle = targinfo;
11220 struct arphdr *arp;
11221@@ -67,7 +67,7 @@
11222
11223 static int
11224 checkentry(const char *tablename, const void *e, const struct xt_target *target,
11225- void *targinfo, unsigned int targinfosize, unsigned int hook_mask)
11226+ void *targinfo, unsigned int hook_mask)
11227 {
11228 const struct arpt_mangle *mangle = targinfo;
11229
11230diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/arptable_filter.c linux-2.6.19/net/ipv4/netfilter/arptable_filter.c
11231--- linux-2.6.18-rc5/net/ipv4/netfilter/arptable_filter.c 2006-08-28 05:41:48.000000000 +0200
11232+++ linux-2.6.19/net/ipv4/netfilter/arptable_filter.c 2006-09-22 10:04:58.000000000 +0200
11233@@ -155,7 +155,7 @@
11234 const struct net_device *out,
11235 int (*okfn)(struct sk_buff *))
11236 {
11237- return arpt_do_table(pskb, hook, in, out, &packet_filter, NULL);
11238+ return arpt_do_table(pskb, hook, in, out, &packet_filter);
11239 }
11240
11241 static struct nf_hook_ops arpt_ops[] = {
11242diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_core.c
11243--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_core.c 2006-08-28 05:41:48.000000000 +0200
11244+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_core.c 2006-09-22 10:04:58.000000000 +0200
11245@@ -66,13 +66,13 @@
11246 LIST_HEAD(ip_conntrack_expect_list);
11247 struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
11248 static LIST_HEAD(helpers);
11249-unsigned int ip_conntrack_htable_size = 0;
11250-int ip_conntrack_max;
11251+unsigned int ip_conntrack_htable_size __read_mostly = 0;
11252+int ip_conntrack_max __read_mostly;
11253 struct list_head *ip_conntrack_hash;
11254 static kmem_cache_t *ip_conntrack_cachep __read_mostly;
11255 static kmem_cache_t *ip_conntrack_expect_cachep __read_mostly;
11256 struct ip_conntrack ip_conntrack_untracked;
11257-unsigned int ip_ct_log_invalid;
11258+unsigned int ip_ct_log_invalid __read_mostly;
11259 static LIST_HEAD(unconfirmed);
11260 static int ip_conntrack_vmalloc;
11261
11262diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_netbios_ns.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
11263--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_netbios_ns.c 2006-08-28 05:41:48.000000000 +0200
11264+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_netbios_ns.c 2006-09-22 10:04:58.000000000 +0200
11265@@ -21,6 +21,7 @@
11266 #include <linux/skbuff.h>
11267 #include <linux/netdevice.h>
11268 #include <linux/inetdevice.h>
11269+#include <linux/if_addr.h>
11270 #include <linux/in.h>
11271 #include <linux/ip.h>
11272 #include <net/route.h>
11273diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_netlink.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_netlink.c
11274--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_netlink.c 2006-08-28 05:41:48.000000000 +0200
11275+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_netlink.c 2006-09-22 10:04:58.000000000 +0200
11276@@ -329,11 +329,7 @@
11277 /* dump everything */
11278 events = ~0UL;
11279 group = NFNLGRP_CONNTRACK_NEW;
11280- } else if (events & (IPCT_STATUS |
11281- IPCT_PROTOINFO |
11282- IPCT_HELPER |
11283- IPCT_HELPINFO |
11284- IPCT_NATINFO)) {
11285+ } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
11286 type = IPCTNL_MSG_CT_NEW;
11287 group = NFNLGRP_CONNTRACK_UPDATE;
11288 } else
11289@@ -385,6 +381,10 @@
11290 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
11291 goto nfattr_failure;
11292
11293+ if (events & IPCT_MARK
11294+ && ctnetlink_dump_mark(skb, ct) < 0)
11295+ goto nfattr_failure;
11296+
11297 nlh->nlmsg_len = skb->tail - b;
11298 nfnetlink_send(skb, 0, group, 0);
11299 return NOTIFY_DONE;
11300@@ -1253,6 +1253,9 @@
11301 } else
11302 return NOTIFY_DONE;
11303
11304+ if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW))
11305+ return NOTIFY_DONE;
11306+
11307 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
11308 if (!skb)
11309 return NOTIFY_DONE;
11310diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_generic.c
11311--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2006-08-28 05:41:48.000000000 +0200
11312+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2006-09-22 10:04:58.000000000 +0200
11313@@ -12,7 +12,7 @@
11314 #include <linux/netfilter.h>
11315 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
11316
11317-unsigned int ip_ct_generic_timeout = 600*HZ;
11318+unsigned int ip_ct_generic_timeout __read_mostly = 600*HZ;
11319
11320 static int generic_pkt_to_tuple(const struct sk_buff *skb,
11321 unsigned int dataoff,
11322diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
11323--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2006-08-28 05:41:48.000000000 +0200
11324+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2006-09-22 10:04:58.000000000 +0200
11325@@ -21,7 +21,7 @@
11326 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
11327 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
11328
11329-unsigned int ip_ct_icmp_timeout = 30*HZ;
11330+unsigned int ip_ct_icmp_timeout __read_mostly = 30*HZ;
11331
11332 #if 0
11333 #define DEBUGP printk
11334diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
11335--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2006-08-28 05:41:48.000000000 +0200
11336+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2006-09-22 10:04:58.000000000 +0200
11337@@ -58,13 +58,13 @@
11338 #define HOURS * 60 MINS
11339 #define DAYS * 24 HOURS
11340
11341-static unsigned int ip_ct_sctp_timeout_closed = 10 SECS;
11342-static unsigned int ip_ct_sctp_timeout_cookie_wait = 3 SECS;
11343-static unsigned int ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
11344-static unsigned int ip_ct_sctp_timeout_established = 5 DAYS;
11345-static unsigned int ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
11346-static unsigned int ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
11347-static unsigned int ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
11348+static unsigned int ip_ct_sctp_timeout_closed __read_mostly = 10 SECS;
11349+static unsigned int ip_ct_sctp_timeout_cookie_wait __read_mostly = 3 SECS;
11350+static unsigned int ip_ct_sctp_timeout_cookie_echoed __read_mostly = 3 SECS;
11351+static unsigned int ip_ct_sctp_timeout_established __read_mostly = 5 DAYS;
11352+static unsigned int ip_ct_sctp_timeout_shutdown_sent __read_mostly = 300 SECS / 1000;
11353+static unsigned int ip_ct_sctp_timeout_shutdown_recd __read_mostly = 300 SECS / 1000;
11354+static unsigned int ip_ct_sctp_timeout_shutdown_ack_sent __read_mostly = 3 SECS;
11355
11356 static const unsigned int * sctp_timeouts[]
11357 = { NULL, /* SCTP_CONNTRACK_NONE */
11358diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
11359--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2006-08-28 05:41:48.000000000 +0200
11360+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2006-09-22 10:04:58.000000000 +0200
11361@@ -48,19 +48,19 @@
11362 /* "Be conservative in what you do,
11363 be liberal in what you accept from others."
11364 If it's non-zero, we mark only out of window RST segments as INVALID. */
11365-int ip_ct_tcp_be_liberal = 0;
11366+int ip_ct_tcp_be_liberal __read_mostly = 0;
11367
11368 /* When connection is picked up from the middle, how many packets are required
11369 to pass in each direction when we assume we are in sync - if any side uses
11370 window scaling, we lost the game.
11371 If it is set to zero, we disable picking up already established
11372 connections. */
11373-int ip_ct_tcp_loose = 3;
11374+int ip_ct_tcp_loose __read_mostly = 3;
11375
11376 /* Max number of the retransmitted packets without receiving an (acceptable)
11377 ACK from the destination. If this number is reached, a shorter timer
11378 will be started. */
11379-int ip_ct_tcp_max_retrans = 3;
11380+int ip_ct_tcp_max_retrans __read_mostly = 3;
11381
11382 /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
11383 closely. They're more complex. --RR */
11384@@ -83,19 +83,19 @@
11385 #define HOURS * 60 MINS
11386 #define DAYS * 24 HOURS
11387
11388-unsigned int ip_ct_tcp_timeout_syn_sent = 2 MINS;
11389-unsigned int ip_ct_tcp_timeout_syn_recv = 60 SECS;
11390-unsigned int ip_ct_tcp_timeout_established = 5 DAYS;
11391-unsigned int ip_ct_tcp_timeout_fin_wait = 2 MINS;
11392-unsigned int ip_ct_tcp_timeout_close_wait = 60 SECS;
11393-unsigned int ip_ct_tcp_timeout_last_ack = 30 SECS;
11394-unsigned int ip_ct_tcp_timeout_time_wait = 2 MINS;
11395-unsigned int ip_ct_tcp_timeout_close = 10 SECS;
11396+unsigned int ip_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS;
11397+unsigned int ip_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS;
11398+unsigned int ip_ct_tcp_timeout_established __read_mostly = 5 DAYS;
11399+unsigned int ip_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS;
11400+unsigned int ip_ct_tcp_timeout_close_wait __read_mostly = 60 SECS;
11401+unsigned int ip_ct_tcp_timeout_last_ack __read_mostly = 30 SECS;
11402+unsigned int ip_ct_tcp_timeout_time_wait __read_mostly = 2 MINS;
11403+unsigned int ip_ct_tcp_timeout_close __read_mostly = 10 SECS;
11404
11405 /* RFC1122 says the R2 limit should be at least 100 seconds.
11406 Linux uses 15 packets as limit, which corresponds
11407 to ~13-30min depending on RTO. */
11408-unsigned int ip_ct_tcp_timeout_max_retrans = 5 MINS;
11409+unsigned int ip_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS;
11410
11411 static const unsigned int * tcp_timeouts[]
11412 = { NULL, /* TCP_CONNTRACK_NONE */
11413@@ -865,8 +865,7 @@
11414
11415 /* Checksum invalid? Ignore.
11416 * We skip checking packets on the outgoing path
11417- * because the semantic of CHECKSUM_HW is different there
11418- * and moreover root might send raw packets.
11419+ * because it is assumed to be correct.
11420 */
11421 /* FIXME: Source route IP option packets --RR */
11422 if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
11423diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_udp.c
11424--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2006-08-28 05:41:48.000000000 +0200
11425+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2006-09-22 10:04:58.000000000 +0200
11426@@ -18,8 +18,8 @@
11427 #include <linux/netfilter_ipv4.h>
11428 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
11429
11430-unsigned int ip_ct_udp_timeout = 30*HZ;
11431-unsigned int ip_ct_udp_timeout_stream = 180*HZ;
11432+unsigned int ip_ct_udp_timeout __read_mostly = 30*HZ;
11433+unsigned int ip_ct_udp_timeout_stream __read_mostly = 180*HZ;
11434
11435 static int udp_pkt_to_tuple(const struct sk_buff *skb,
11436 unsigned int dataoff,
11437@@ -117,8 +117,7 @@
11438
11439 /* Checksum invalid? Ignore.
11440 * We skip checking packets on the outgoing path
11441- * because the semantic of CHECKSUM_HW is different there
11442- * and moreover root might send raw packets.
11443+ * because the checksum is assumed to be correct.
11444 * FIXME: Source route IP option packets --RR */
11445 if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
11446 nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
11447diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_sip.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_sip.c
11448--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_sip.c 2006-08-28 05:41:48.000000000 +0200
11449+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_sip.c 2006-09-22 10:04:58.000000000 +0200
11450@@ -8,7 +8,6 @@
11451 * published by the Free Software Foundation.
11452 */
11453
11454-#include <linux/config.h>
11455 #include <linux/module.h>
11456 #include <linux/ctype.h>
11457 #include <linux/skbuff.h>
11458diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_standalone.c
11459--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_conntrack_standalone.c 2006-08-28 05:41:48.000000000 +0200
11460+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_standalone.c 2006-09-22 10:04:58.000000000 +0200
11461@@ -534,7 +534,7 @@
11462
11463 /* Sysctl support */
11464
11465-int ip_conntrack_checksum = 1;
11466+int ip_conntrack_checksum __read_mostly = 1;
11467
11468 #ifdef CONFIG_SYSCTL
11469
11470@@ -563,7 +563,7 @@
11471 /* From ip_conntrack_proto_icmp.c */
11472 extern unsigned int ip_ct_icmp_timeout;
11473
11474-/* From ip_conntrack_proto_icmp.c */
11475+/* From ip_conntrack_proto_generic.c */
11476 extern unsigned int ip_ct_generic_timeout;
11477
11478 /* Log invalid packets of a given protocol */
11479diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_core.c linux-2.6.19/net/ipv4/netfilter/ip_nat_core.c
11480--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_core.c 2006-08-28 05:41:48.000000000 +0200
11481+++ linux-2.6.19/net/ipv4/netfilter/ip_nat_core.c 2006-09-22 10:04:58.000000000 +0200
11482@@ -101,18 +101,6 @@
11483 write_unlock_bh(&ip_nat_lock);
11484 }
11485
11486-/* We do checksum mangling, so if they were wrong before they're still
11487- * wrong. Also works for incomplete packets (eg. ICMP dest
11488- * unreachables.) */
11489-u_int16_t
11490-ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
11491-{
11492- u_int32_t diffs[] = { oldvalinv, newval };
11493- return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
11494- oldcheck^0xFFFF));
11495-}
11496-EXPORT_SYMBOL(ip_nat_cheat_check);
11497-
11498 /* Is this tuple already taken? (not by us) */
11499 int
11500 ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
11501@@ -378,12 +366,12 @@
11502 iph = (void *)(*pskb)->data + iphdroff;
11503
11504 if (maniptype == IP_NAT_MANIP_SRC) {
11505- iph->check = ip_nat_cheat_check(~iph->saddr, target->src.ip,
11506- iph->check);
11507+ iph->check = nf_csum_update(~iph->saddr, target->src.ip,
11508+ iph->check);
11509 iph->saddr = target->src.ip;
11510 } else {
11511- iph->check = ip_nat_cheat_check(~iph->daddr, target->dst.ip,
11512- iph->check);
11513+ iph->check = nf_csum_update(~iph->daddr, target->dst.ip,
11514+ iph->check);
11515 iph->daddr = target->dst.ip;
11516 }
11517 return 1;
11518@@ -423,10 +411,10 @@
11519 EXPORT_SYMBOL_GPL(ip_nat_packet);
11520
11521 /* Dir is direction ICMP is coming from (opposite to packet it contains) */
11522-int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
11523- struct ip_conntrack *ct,
11524- enum ip_nat_manip_type manip,
11525- enum ip_conntrack_dir dir)
11526+int ip_nat_icmp_reply_translation(struct ip_conntrack *ct,
11527+ enum ip_conntrack_info ctinfo,
11528+ unsigned int hooknum,
11529+ struct sk_buff **pskb)
11530 {
11531 struct {
11532 struct icmphdr icmp;
11533@@ -434,7 +422,9 @@
11534 } *inside;
11535 struct ip_conntrack_tuple inner, target;
11536 int hdrlen = (*pskb)->nh.iph->ihl * 4;
11537+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
11538 unsigned long statusbit;
11539+ enum ip_nat_manip_type manip = HOOK2MANIP(hooknum);
11540
11541 if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
11542 return 0;
11543@@ -443,12 +433,8 @@
11544
11545 /* We're actually going to mangle it beyond trivial checksum
11546 adjustment, so make sure the current checksum is correct. */
11547- if ((*pskb)->ip_summed != CHECKSUM_UNNECESSARY) {
11548- hdrlen = (*pskb)->nh.iph->ihl * 4;
11549- if ((u16)csum_fold(skb_checksum(*pskb, hdrlen,
11550- (*pskb)->len - hdrlen, 0)))
11551- return 0;
11552- }
11553+ if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0))
11554+ return 0;
11555
11556 /* Must be RELATED */
11557 IP_NF_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||
11558@@ -487,12 +473,14 @@
11559 !manip))
11560 return 0;
11561
11562- /* Reloading "inside" here since manip_pkt inner. */
11563- inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
11564- inside->icmp.checksum = 0;
11565- inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen,
11566- (*pskb)->len - hdrlen,
11567- 0));
11568+ if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
11569+ /* Reloading "inside" here since manip_pkt inner. */
11570+ inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
11571+ inside->icmp.checksum = 0;
11572+ inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen,
11573+ (*pskb)->len - hdrlen,
11574+ 0));
11575+ }
11576
11577 /* Change outer to look the reply to an incoming packet
11578 * (proto 0 means don't invert per-proto part). */
11579diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_helper.c linux-2.6.19/net/ipv4/netfilter/ip_nat_helper.c
11580--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_helper.c 2006-08-28 05:41:48.000000000 +0200
11581+++ linux-2.6.19/net/ipv4/netfilter/ip_nat_helper.c 2006-09-22 10:04:58.000000000 +0200
11582@@ -165,7 +165,7 @@
11583 {
11584 struct iphdr *iph;
11585 struct tcphdr *tcph;
11586- int datalen;
11587+ int oldlen, datalen;
11588
11589 if (!skb_make_writable(pskb, (*pskb)->len))
11590 return 0;
11591@@ -180,13 +180,22 @@
11592 iph = (*pskb)->nh.iph;
11593 tcph = (void *)iph + iph->ihl*4;
11594
11595+ oldlen = (*pskb)->len - iph->ihl*4;
11596 mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
11597 match_offset, match_len, rep_buffer, rep_len);
11598
11599 datalen = (*pskb)->len - iph->ihl*4;
11600- tcph->check = 0;
11601- tcph->check = tcp_v4_check(tcph, datalen, iph->saddr, iph->daddr,
11602- csum_partial((char *)tcph, datalen, 0));
11603+ if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
11604+ tcph->check = 0;
11605+ tcph->check = tcp_v4_check(tcph, datalen,
11606+ iph->saddr, iph->daddr,
11607+ csum_partial((char *)tcph,
11608+ datalen, 0));
11609+ } else
11610+ tcph->check = nf_proto_csum_update(*pskb,
11611+ htons(oldlen) ^ 0xFFFF,
11612+ htons(datalen),
11613+ tcph->check, 1);
11614
11615 if (rep_len != match_len) {
11616 set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
11617@@ -221,6 +230,7 @@
11618 {
11619 struct iphdr *iph;
11620 struct udphdr *udph;
11621+ int datalen, oldlen;
11622
11623 /* UDP helpers might accidentally mangle the wrong packet */
11624 iph = (*pskb)->nh.iph;
11625@@ -238,22 +248,32 @@
11626
11627 iph = (*pskb)->nh.iph;
11628 udph = (void *)iph + iph->ihl*4;
11629+
11630+ oldlen = (*pskb)->len - iph->ihl*4;
11631 mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph),
11632 match_offset, match_len, rep_buffer, rep_len);
11633
11634 /* update the length of the UDP packet */
11635- udph->len = htons((*pskb)->len - iph->ihl*4);
11636+ datalen = (*pskb)->len - iph->ihl*4;
11637+ udph->len = htons(datalen);
11638
11639 /* fix udp checksum if udp checksum was previously calculated */
11640- if (udph->check) {
11641- int datalen = (*pskb)->len - iph->ihl * 4;
11642+ if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL)
11643+ return 1;
11644+
11645+ if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
11646 udph->check = 0;
11647 udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
11648 datalen, IPPROTO_UDP,
11649 csum_partial((char *)udph,
11650 datalen, 0));
11651- }
11652-
11653+ if (!udph->check)
11654+ udph->check = -1;
11655+ } else
11656+ udph->check = nf_proto_csum_update(*pskb,
11657+ htons(oldlen) ^ 0xFFFF,
11658+ htons(datalen),
11659+ udph->check, 1);
11660 return 1;
11661 }
11662 EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
11663@@ -293,11 +313,14 @@
11664 ntohl(sack->start_seq), new_start_seq,
11665 ntohl(sack->end_seq), new_end_seq);
11666
11667- tcph->check =
11668- ip_nat_cheat_check(~sack->start_seq, new_start_seq,
11669- ip_nat_cheat_check(~sack->end_seq,
11670- new_end_seq,
11671- tcph->check));
11672+ tcph->check = nf_proto_csum_update(skb,
11673+ ~sack->start_seq,
11674+ new_start_seq,
11675+ tcph->check, 0);
11676+ tcph->check = nf_proto_csum_update(skb,
11677+ ~sack->end_seq,
11678+ new_end_seq,
11679+ tcph->check, 0);
11680 sack->start_seq = new_start_seq;
11681 sack->end_seq = new_end_seq;
11682 sackoff += sizeof(*sack);
11683@@ -381,10 +404,10 @@
11684 newack = ntohl(tcph->ack_seq) - other_way->offset_before;
11685 newack = htonl(newack);
11686
11687- tcph->check = ip_nat_cheat_check(~tcph->seq, newseq,
11688- ip_nat_cheat_check(~tcph->ack_seq,
11689- newack,
11690- tcph->check));
11691+ tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq,
11692+ tcph->check, 0);
11693+ tcph->check = nf_proto_csum_update(*pskb, ~tcph->ack_seq, newack,
11694+ tcph->check, 0);
11695
11696 DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
11697 ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
11698diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_proto_gre.c linux-2.6.19/net/ipv4/netfilter/ip_nat_proto_gre.c
11699--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_proto_gre.c 2006-08-28 05:41:48.000000000 +0200
11700+++ linux-2.6.19/net/ipv4/netfilter/ip_nat_proto_gre.c 2006-09-22 10:04:58.000000000 +0200
11701@@ -130,9 +130,10 @@
11702 if (greh->csum) {
11703 /* FIXME: Never tested this code... */
11704 *(gre_csum(greh)) =
11705- ip_nat_cheat_check(~*(gre_key(greh)),
11706+ nf_proto_csum_update(*pskb,
11707+ ~*(gre_key(greh)),
11708 tuple->dst.u.gre.key,
11709- *(gre_csum(greh)));
11710+ *(gre_csum(greh)), 0);
11711 }
11712 *(gre_key(greh)) = tuple->dst.u.gre.key;
11713 break;
11714diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_proto_icmp.c linux-2.6.19/net/ipv4/netfilter/ip_nat_proto_icmp.c
11715--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_proto_icmp.c 2006-08-28 05:41:48.000000000 +0200
11716+++ linux-2.6.19/net/ipv4/netfilter/ip_nat_proto_icmp.c 2006-09-22 10:04:58.000000000 +0200
11717@@ -66,10 +66,10 @@
11718 return 0;
11719
11720 hdr = (struct icmphdr *)((*pskb)->data + hdroff);
11721-
11722- hdr->checksum = ip_nat_cheat_check(hdr->un.echo.id ^ 0xFFFF,
11723- tuple->src.u.icmp.id,
11724- hdr->checksum);
11725+ hdr->checksum = nf_proto_csum_update(*pskb,
11726+ hdr->un.echo.id ^ 0xFFFF,
11727+ tuple->src.u.icmp.id,
11728+ hdr->checksum, 0);
11729 hdr->un.echo.id = tuple->src.u.icmp.id;
11730 return 1;
11731 }
11732diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.6.19/net/ipv4/netfilter/ip_nat_proto_tcp.c
11733--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_proto_tcp.c 2006-08-28 05:41:48.000000000 +0200
11734+++ linux-2.6.19/net/ipv4/netfilter/ip_nat_proto_tcp.c 2006-09-22 10:04:58.000000000 +0200
11735@@ -129,10 +129,9 @@
11736 if (hdrsize < sizeof(*hdr))
11737 return 1;
11738
11739- hdr->check = ip_nat_cheat_check(~oldip, newip,
11740- ip_nat_cheat_check(oldport ^ 0xFFFF,
11741- newport,
11742- hdr->check));
11743+ hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, hdr->check, 1);
11744+ hdr->check = nf_proto_csum_update(*pskb, oldport ^ 0xFFFF, newport,
11745+ hdr->check, 0);
11746 return 1;
11747 }
11748
11749diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_proto_udp.c linux-2.6.19/net/ipv4/netfilter/ip_nat_proto_udp.c
11750--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_proto_udp.c 2006-08-28 05:41:48.000000000 +0200
11751+++ linux-2.6.19/net/ipv4/netfilter/ip_nat_proto_udp.c 2006-09-22 10:04:58.000000000 +0200
11752@@ -113,11 +113,16 @@
11753 newport = tuple->dst.u.udp.port;
11754 portptr = &hdr->dest;
11755 }
11756- if (hdr->check) /* 0 is a special case meaning no checksum */
11757- hdr->check = ip_nat_cheat_check(~oldip, newip,
11758- ip_nat_cheat_check(*portptr ^ 0xFFFF,
11759- newport,
11760- hdr->check));
11761+
11762+ if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
11763+ hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip,
11764+ hdr->check, 1);
11765+ hdr->check = nf_proto_csum_update(*pskb,
11766+ *portptr ^ 0xFFFF, newport,
11767+ hdr->check, 0);
11768+ if (!hdr->check)
11769+ hdr->check = -1;
11770+ }
11771 *portptr = newport;
11772 return 1;
11773 }
11774diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.19/net/ipv4/netfilter/ip_nat_rule.c
11775--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_rule.c 2006-08-28 05:41:48.000000000 +0200
11776+++ linux-2.6.19/net/ipv4/netfilter/ip_nat_rule.c 2006-09-22 10:04:58.000000000 +0200
11777@@ -104,8 +104,7 @@
11778 const struct net_device *out,
11779 unsigned int hooknum,
11780 const struct ipt_target *target,
11781- const void *targinfo,
11782- void *userinfo)
11783+ const void *targinfo)
11784 {
11785 struct ip_conntrack *ct;
11786 enum ip_conntrack_info ctinfo;
11787@@ -147,8 +146,7 @@
11788 const struct net_device *out,
11789 unsigned int hooknum,
11790 const struct ipt_target *target,
11791- const void *targinfo,
11792- void *userinfo)
11793+ const void *targinfo)
11794 {
11795 struct ip_conntrack *ct;
11796 enum ip_conntrack_info ctinfo;
11797@@ -174,7 +172,6 @@
11798 const void *entry,
11799 const struct ipt_target *target,
11800 void *targinfo,
11801- unsigned int targinfosize,
11802 unsigned int hook_mask)
11803 {
11804 struct ip_nat_multi_range_compat *mr = targinfo;
11805@@ -191,7 +188,6 @@
11806 const void *entry,
11807 const struct ipt_target *target,
11808 void *targinfo,
11809- unsigned int targinfosize,
11810 unsigned int hook_mask)
11811 {
11812 struct ip_nat_multi_range_compat *mr = targinfo;
11813@@ -255,7 +251,7 @@
11814 {
11815 int ret;
11816
11817- ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL);
11818+ ret = ipt_do_table(pskb, hooknum, in, out, &nat_table);
11819
11820 if (ret == NF_ACCEPT) {
11821 if (!ip_nat_initialized(ct, HOOK2MANIP(hooknum)))
11822diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.19/net/ipv4/netfilter/ip_nat_standalone.c
11823--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_nat_standalone.c 2006-08-28 05:41:48.000000000 +0200
11824+++ linux-2.6.19/net/ipv4/netfilter/ip_nat_standalone.c 2006-09-22 10:04:58.000000000 +0200
11825@@ -110,11 +110,6 @@
11826 IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
11827 & htons(IP_MF|IP_OFFSET)));
11828
11829- /* If we had a hardware checksum before, it's now invalid */
11830- if ((*pskb)->ip_summed == CHECKSUM_HW)
11831- if (skb_checksum_help(*pskb, (out == NULL)))
11832- return NF_DROP;
11833-
11834 ct = ip_conntrack_get(*pskb, &ctinfo);
11835 /* Can't track? It's not due to stress, or conntrack would
11836 have dropped it. Hence it's the user's responsibilty to
11837@@ -145,8 +140,8 @@
11838 case IP_CT_RELATED:
11839 case IP_CT_RELATED+IP_CT_IS_REPLY:
11840 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
11841- if (!ip_nat_icmp_reply_translation(pskb, ct, maniptype,
11842- CTINFO2DIR(ctinfo)))
11843+ if (!ip_nat_icmp_reply_translation(ct, ctinfo,
11844+ hooknum, pskb))
11845 return NF_DROP;
11846 else
11847 return NF_ACCEPT;
11848diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_queue.c linux-2.6.19/net/ipv4/netfilter/ip_queue.c
11849--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_queue.c 2006-08-28 05:41:48.000000000 +0200
11850+++ linux-2.6.19/net/ipv4/netfilter/ip_queue.c 2006-09-22 10:04:58.000000000 +0200
11851@@ -53,7 +53,7 @@
11852 typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
11853
11854 static unsigned char copy_mode = IPQ_COPY_NONE;
11855-static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT;
11856+static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT;
11857 static DEFINE_RWLOCK(queue_lock);
11858 static int peer_pid;
11859 static unsigned int copy_range;
11860@@ -208,9 +208,9 @@
11861 break;
11862
11863 case IPQ_COPY_PACKET:
11864- if (entry->skb->ip_summed == CHECKSUM_HW &&
11865- (*errp = skb_checksum_help(entry->skb,
11866- entry->info->outdev == NULL))) {
11867+ if ((entry->skb->ip_summed == CHECKSUM_PARTIAL ||
11868+ entry->skb->ip_summed == CHECKSUM_COMPLETE) &&
11869+ (*errp = skb_checksum_help(entry->skb))) {
11870 read_unlock_bh(&queue_lock);
11871 return NULL;
11872 }
11873diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ip_tables.c linux-2.6.19/net/ipv4/netfilter/ip_tables.c
11874--- linux-2.6.18-rc5/net/ipv4/netfilter/ip_tables.c 2006-08-28 05:41:48.000000000 +0200
11875+++ linux-2.6.19/net/ipv4/netfilter/ip_tables.c 2006-09-22 10:04:58.000000000 +0200
11876@@ -180,8 +180,7 @@
11877 const struct net_device *out,
11878 unsigned int hooknum,
11879 const struct xt_target *target,
11880- const void *targinfo,
11881- void *userinfo)
11882+ const void *targinfo)
11883 {
11884 if (net_ratelimit())
11885 printk("ip_tables: error: `%s'\n", (char *)targinfo);
11886@@ -217,8 +216,7 @@
11887 unsigned int hook,
11888 const struct net_device *in,
11889 const struct net_device *out,
11890- struct ipt_table *table,
11891- void *userdata)
11892+ struct ipt_table *table)
11893 {
11894 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
11895 u_int16_t offset;
11896@@ -308,8 +306,7 @@
11897 in, out,
11898 hook,
11899 t->u.kernel.target,
11900- t->data,
11901- userdata);
11902+ t->data);
11903
11904 #ifdef CONFIG_NETFILTER_DEBUG
11905 if (((struct ipt_entry *)table_base)->comefrom
11906@@ -467,8 +464,7 @@
11907 return 1;
11908
11909 if (m->u.kernel.match->destroy)
11910- m->u.kernel.match->destroy(m->u.kernel.match, m->data,
11911- m->u.match_size - sizeof(*m));
11912+ m->u.kernel.match->destroy(m->u.kernel.match, m->data);
11913 module_put(m->u.kernel.match->me);
11914 return 0;
11915 }
11916@@ -521,7 +517,6 @@
11917
11918 if (m->u.kernel.match->checkentry
11919 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
11920- m->u.match_size - sizeof(*m),
11921 hookmask)) {
11922 duprintf("ip_tables: check failed for `%s'.\n",
11923 m->u.kernel.match->name);
11924@@ -582,8 +577,6 @@
11925 }
11926 } else if (t->u.kernel.target->checkentry
11927 && !t->u.kernel.target->checkentry(name, e, target, t->data,
11928- t->u.target_size
11929- - sizeof(*t),
11930 e->comefrom)) {
11931 duprintf("ip_tables: check failed for `%s'.\n",
11932 t->u.kernel.target->name);
11933@@ -655,8 +648,7 @@
11934 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
11935 t = ipt_get_target(e);
11936 if (t->u.kernel.target->destroy)
11937- t->u.kernel.target->destroy(t->u.kernel.target, t->data,
11938- t->u.target_size - sizeof(*t));
11939+ t->u.kernel.target->destroy(t->u.kernel.target, t->data);
11940 module_put(t->u.kernel.target->me);
11941 return 0;
11942 }
11943@@ -1602,7 +1594,6 @@
11944
11945 if (m->u.kernel.match->checkentry
11946 && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
11947- dm->u.match_size - sizeof(*dm),
11948 hookmask)) {
11949 duprintf("ip_tables: check failed for `%s'.\n",
11950 m->u.kernel.match->name);
11951@@ -1661,8 +1652,7 @@
11952 goto out;
11953 } else if (t->u.kernel.target->checkentry
11954 && !t->u.kernel.target->checkentry(name, de, target,
11955- t->data, t->u.target_size - sizeof(*t),
11956- de->comefrom)) {
11957+ t->data, de->comefrom)) {
11958 duprintf("ip_tables: compat: check failed for `%s'.\n",
11959 t->u.kernel.target->name);
11960 goto out;
11961@@ -2185,7 +2175,6 @@
11962 const void *info,
11963 const struct xt_match *match,
11964 void *matchinfo,
11965- unsigned int matchsize,
11966 unsigned int hook_mask)
11967 {
11968 const struct ipt_icmp *icmpinfo = matchinfo;
11969diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_CLUSTERIP.c linux-2.6.19/net/ipv4/netfilter/ipt_CLUSTERIP.c
11970--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_CLUSTERIP.c 2006-08-28 05:41:48.000000000 +0200
11971+++ linux-2.6.19/net/ipv4/netfilter/ipt_CLUSTERIP.c 2006-09-22 10:04:58.000000000 +0200
11972@@ -302,8 +302,7 @@
11973 const struct net_device *out,
11974 unsigned int hooknum,
11975 const struct xt_target *target,
11976- const void *targinfo,
11977- void *userinfo)
11978+ const void *targinfo)
11979 {
11980 const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
11981 enum ip_conntrack_info ctinfo;
11982@@ -373,7 +372,6 @@
11983 const void *e_void,
11984 const struct xt_target *target,
11985 void *targinfo,
11986- unsigned int targinfosize,
11987 unsigned int hook_mask)
11988 {
11989 struct ipt_clusterip_tgt_info *cipinfo = targinfo;
11990@@ -450,8 +448,7 @@
11991 }
11992
11993 /* drop reference count of cluster config when rule is deleted */
11994-static void destroy(const struct xt_target *target, void *targinfo,
11995- unsigned int targinfosize)
11996+static void destroy(const struct xt_target *target, void *targinfo)
11997 {
11998 struct ipt_clusterip_tgt_info *cipinfo = targinfo;
11999
12000diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_DSCP.c linux-2.6.19/net/ipv4/netfilter/ipt_DSCP.c
12001--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_DSCP.c 2006-08-28 05:41:48.000000000 +0200
12002+++ linux-2.6.19/net/ipv4/netfilter/ipt_DSCP.c 1970-01-01 01:00:00.000000000 +0100
12003@@ -1,96 +0,0 @@
12004-/* iptables module for setting the IPv4 DSCP field, Version 1.8
12005- *
12006- * (C) 2002 by Harald Welte <laforge@netfilter.org>
12007- * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com>
12008- *
12009- * This program is free software; you can redistribute it and/or modify
12010- * it under the terms of the GNU General Public License version 2 as
12011- * published by the Free Software Foundation.
12012- *
12013- * See RFC2474 for a description of the DSCP field within the IP Header.
12014- *
12015- * ipt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp
12016-*/
12017-
12018-#include <linux/module.h>
12019-#include <linux/skbuff.h>
12020-#include <linux/ip.h>
12021-#include <net/checksum.h>
12022-
12023-#include <linux/netfilter_ipv4/ip_tables.h>
12024-#include <linux/netfilter_ipv4/ipt_DSCP.h>
12025-
12026-MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
12027-MODULE_DESCRIPTION("iptables DSCP modification module");
12028-MODULE_LICENSE("GPL");
12029-
12030-static unsigned int
12031-target(struct sk_buff **pskb,
12032- const struct net_device *in,
12033- const struct net_device *out,
12034- unsigned int hooknum,
12035- const struct xt_target *target,
12036- const void *targinfo,
12037- void *userinfo)
12038-{
12039- const struct ipt_DSCP_info *dinfo = targinfo;
12040- u_int8_t sh_dscp = ((dinfo->dscp << IPT_DSCP_SHIFT) & IPT_DSCP_MASK);
12041-
12042-
12043- if (((*pskb)->nh.iph->tos & IPT_DSCP_MASK) != sh_dscp) {
12044- u_int16_t diffs[2];
12045-
12046- if (!skb_make_writable(pskb, sizeof(struct iphdr)))
12047- return NF_DROP;
12048-
12049- diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF;
12050- (*pskb)->nh.iph->tos = ((*pskb)->nh.iph->tos & ~IPT_DSCP_MASK)
12051- | sh_dscp;
12052- diffs[1] = htons((*pskb)->nh.iph->tos);
12053- (*pskb)->nh.iph->check
12054- = csum_fold(csum_partial((char *)diffs,
12055- sizeof(diffs),
12056- (*pskb)->nh.iph->check
12057- ^ 0xFFFF));
12058- }
12059- return IPT_CONTINUE;
12060-}
12061-
12062-static int
12063-checkentry(const char *tablename,
12064- const void *e_void,
12065- const struct xt_target *target,
12066- void *targinfo,
12067- unsigned int targinfosize,
12068- unsigned int hook_mask)
12069-{
12070- const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp;
12071-
12072- if ((dscp > IPT_DSCP_MAX)) {
12073- printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
12074- return 0;
12075- }
12076- return 1;
12077-}
12078-
12079-static struct ipt_target ipt_dscp_reg = {
12080- .name = "DSCP",
12081- .target = target,
12082- .targetsize = sizeof(struct ipt_DSCP_info),
12083- .table = "mangle",
12084- .checkentry = checkentry,
12085- .me = THIS_MODULE,
12086-};
12087-
12088-static int __init ipt_dscp_init(void)
12089-{
12090- return ipt_register_target(&ipt_dscp_reg);
12091-}
12092-
12093-static void __exit ipt_dscp_fini(void)
12094-{
12095- ipt_unregister_target(&ipt_dscp_reg);
12096-}
12097-
12098-module_init(ipt_dscp_init);
12099-module_exit(ipt_dscp_fini);
12100diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_ECN.c linux-2.6.19/net/ipv4/netfilter/ipt_ECN.c
12101--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_ECN.c 2006-08-28 05:41:48.000000000 +0200
12102+++ linux-2.6.19/net/ipv4/netfilter/ipt_ECN.c 2006-09-22 10:04:58.000000000 +0200
12103@@ -27,32 +27,28 @@
12104 static inline int
12105 set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
12106 {
12107- if (((*pskb)->nh.iph->tos & IPT_ECN_IP_MASK)
12108- != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
12109- u_int16_t diffs[2];
12110+ struct iphdr *iph = (*pskb)->nh.iph;
12111+ u_int16_t oldtos;
12112
12113+ if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
12114 if (!skb_make_writable(pskb, sizeof(struct iphdr)))
12115 return 0;
12116-
12117- diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF;
12118- (*pskb)->nh.iph->tos &= ~IPT_ECN_IP_MASK;
12119- (*pskb)->nh.iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
12120- diffs[1] = htons((*pskb)->nh.iph->tos);
12121- (*pskb)->nh.iph->check
12122- = csum_fold(csum_partial((char *)diffs,
12123- sizeof(diffs),
12124- (*pskb)->nh.iph->check
12125- ^0xFFFF));
12126+ iph = (*pskb)->nh.iph;
12127+ oldtos = iph->tos;
12128+ iph->tos &= ~IPT_ECN_IP_MASK;
12129+ iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
12130+ iph->check = nf_csum_update(oldtos ^ 0xFFFF, iph->tos,
12131+ iph->check);
12132 }
12133 return 1;
12134 }
12135
12136 /* Return 0 if there was an error. */
12137 static inline int
12138-set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward)
12139+set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
12140 {
12141 struct tcphdr _tcph, *tcph;
12142- u_int16_t diffs[2];
12143+ u_int16_t oldval;
12144
12145 /* Not enought header? */
12146 tcph = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
12147@@ -70,22 +66,16 @@
12148 return 0;
12149 tcph = (void *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl*4;
12150
12151- if ((*pskb)->ip_summed == CHECKSUM_HW &&
12152- skb_checksum_help(*pskb, inward))
12153- return 0;
12154-
12155- diffs[0] = ((u_int16_t *)tcph)[6];
12156+ oldval = ((u_int16_t *)tcph)[6];
12157 if (einfo->operation & IPT_ECN_OP_SET_ECE)
12158 tcph->ece = einfo->proto.tcp.ece;
12159 if (einfo->operation & IPT_ECN_OP_SET_CWR)
12160 tcph->cwr = einfo->proto.tcp.cwr;
12161- diffs[1] = ((u_int16_t *)tcph)[6];
12162- diffs[0] = diffs[0] ^ 0xFFFF;
12163
12164- if ((*pskb)->ip_summed != CHECKSUM_UNNECESSARY)
12165- tcph->check = csum_fold(csum_partial((char *)diffs,
12166- sizeof(diffs),
12167- tcph->check^0xFFFF));
12168+ tcph->check = nf_proto_csum_update((*pskb),
12169+ oldval ^ 0xFFFF,
12170+ ((u_int16_t *)tcph)[6],
12171+ tcph->check, 0);
12172 return 1;
12173 }
12174
12175@@ -95,8 +85,7 @@
12176 const struct net_device *out,
12177 unsigned int hooknum,
12178 const struct xt_target *target,
12179- const void *targinfo,
12180- void *userinfo)
12181+ const void *targinfo)
12182 {
12183 const struct ipt_ECN_info *einfo = targinfo;
12184
12185@@ -106,7 +95,7 @@
12186
12187 if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR)
12188 && (*pskb)->nh.iph->protocol == IPPROTO_TCP)
12189- if (!set_ect_tcp(pskb, einfo, (out == NULL)))
12190+ if (!set_ect_tcp(pskb, einfo))
12191 return NF_DROP;
12192
12193 return IPT_CONTINUE;
12194@@ -117,7 +106,6 @@
12195 const void *e_void,
12196 const struct xt_target *target,
12197 void *targinfo,
12198- unsigned int targinfosize,
12199 unsigned int hook_mask)
12200 {
12201 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
12202diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_LOG.c linux-2.6.19/net/ipv4/netfilter/ipt_LOG.c
12203--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_LOG.c 2006-08-28 05:41:48.000000000 +0200
12204+++ linux-2.6.19/net/ipv4/netfilter/ipt_LOG.c 2006-09-22 10:04:58.000000000 +0200
12205@@ -416,8 +416,7 @@
12206 const struct net_device *out,
12207 unsigned int hooknum,
12208 const struct xt_target *target,
12209- const void *targinfo,
12210- void *userinfo)
12211+ const void *targinfo)
12212 {
12213 const struct ipt_log_info *loginfo = targinfo;
12214 struct nf_loginfo li;
12215@@ -440,7 +439,6 @@
12216 const void *e,
12217 const struct xt_target *target,
12218 void *targinfo,
12219- unsigned int targinfosize,
12220 unsigned int hook_mask)
12221 {
12222 const struct ipt_log_info *loginfo = targinfo;
12223diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_MASQUERADE.c linux-2.6.19/net/ipv4/netfilter/ipt_MASQUERADE.c
12224--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_MASQUERADE.c 2006-08-28 05:41:48.000000000 +0200
12225+++ linux-2.6.19/net/ipv4/netfilter/ipt_MASQUERADE.c 2006-09-22 10:04:58.000000000 +0200
12226@@ -42,7 +42,6 @@
12227 const void *e,
12228 const struct xt_target *target,
12229 void *targinfo,
12230- unsigned int targinfosize,
12231 unsigned int hook_mask)
12232 {
12233 const struct ip_nat_multi_range_compat *mr = targinfo;
12234@@ -64,8 +63,7 @@
12235 const struct net_device *out,
12236 unsigned int hooknum,
12237 const struct xt_target *target,
12238- const void *targinfo,
12239- void *userinfo)
12240+ const void *targinfo)
12241 {
12242 struct ip_conntrack *ct;
12243 enum ip_conntrack_info ctinfo;
12244diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_NETMAP.c linux-2.6.19/net/ipv4/netfilter/ipt_NETMAP.c
12245--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_NETMAP.c 2006-08-28 05:41:48.000000000 +0200
12246+++ linux-2.6.19/net/ipv4/netfilter/ipt_NETMAP.c 2006-09-22 10:04:58.000000000 +0200
12247@@ -33,7 +33,6 @@
12248 const void *e,
12249 const struct xt_target *target,
12250 void *targinfo,
12251- unsigned int targinfosize,
12252 unsigned int hook_mask)
12253 {
12254 const struct ip_nat_multi_range_compat *mr = targinfo;
12255@@ -55,8 +54,7 @@
12256 const struct net_device *out,
12257 unsigned int hooknum,
12258 const struct xt_target *target,
12259- const void *targinfo,
12260- void *userinfo)
12261+ const void *targinfo)
12262 {
12263 struct ip_conntrack *ct;
12264 enum ip_conntrack_info ctinfo;
12265diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_REDIRECT.c linux-2.6.19/net/ipv4/netfilter/ipt_REDIRECT.c
12266--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_REDIRECT.c 2006-08-28 05:41:48.000000000 +0200
12267+++ linux-2.6.19/net/ipv4/netfilter/ipt_REDIRECT.c 2006-09-22 10:04:58.000000000 +0200
12268@@ -36,7 +36,6 @@
12269 const void *e,
12270 const struct xt_target *target,
12271 void *targinfo,
12272- unsigned int targinfosize,
12273 unsigned int hook_mask)
12274 {
12275 const struct ip_nat_multi_range_compat *mr = targinfo;
12276@@ -58,8 +57,7 @@
12277 const struct net_device *out,
12278 unsigned int hooknum,
12279 const struct xt_target *target,
12280- const void *targinfo,
12281- void *userinfo)
12282+ const void *targinfo)
12283 {
12284 struct ip_conntrack *ct;
12285 enum ip_conntrack_info ctinfo;
12286diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_REJECT.c linux-2.6.19/net/ipv4/netfilter/ipt_REJECT.c
12287--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_REJECT.c 2006-08-28 05:41:48.000000000 +0200
12288+++ linux-2.6.19/net/ipv4/netfilter/ipt_REJECT.c 2006-09-22 10:04:58.000000000 +0200
12289@@ -90,6 +90,7 @@
12290 fl.proto = IPPROTO_TCP;
12291 fl.fl_ip_sport = tcph->dest;
12292 fl.fl_ip_dport = tcph->source;
12293+ security_skb_classify_flow(skb, &fl);
12294
12295 xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0);
12296
12297@@ -184,6 +185,7 @@
12298 tcph->urg_ptr = 0;
12299
12300 /* Adjust TCP checksum */
12301+ nskb->ip_summed = CHECKSUM_NONE;
12302 tcph->check = 0;
12303 tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
12304 nskb->nh.iph->saddr,
12305@@ -226,8 +228,7 @@
12306 const struct net_device *out,
12307 unsigned int hooknum,
12308 const struct xt_target *target,
12309- const void *targinfo,
12310- void *userinfo)
12311+ const void *targinfo)
12312 {
12313 const struct ipt_reject_info *reject = targinfo;
12314
12315@@ -275,7 +276,6 @@
12316 const void *e_void,
12317 const struct xt_target *target,
12318 void *targinfo,
12319- unsigned int targinfosize,
12320 unsigned int hook_mask)
12321 {
12322 const struct ipt_reject_info *rejinfo = targinfo;
12323diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_SAME.c linux-2.6.19/net/ipv4/netfilter/ipt_SAME.c
12324--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_SAME.c 2006-08-28 05:41:48.000000000 +0200
12325+++ linux-2.6.19/net/ipv4/netfilter/ipt_SAME.c 2006-09-22 10:04:58.000000000 +0200
12326@@ -52,7 +52,6 @@
12327 const void *e,
12328 const struct xt_target *target,
12329 void *targinfo,
12330- unsigned int targinfosize,
12331 unsigned int hook_mask)
12332 {
12333 unsigned int count, countess, rangeip, index = 0;
12334@@ -116,8 +115,7 @@
12335 }
12336
12337 static void
12338-same_destroy(const struct xt_target *target, void *targinfo,
12339- unsigned int targinfosize)
12340+same_destroy(const struct xt_target *target, void *targinfo)
12341 {
12342 struct ipt_same_info *mr = targinfo;
12343
12344@@ -133,8 +131,7 @@
12345 const struct net_device *out,
12346 unsigned int hooknum,
12347 const struct xt_target *target,
12348- const void *targinfo,
12349- void *userinfo)
12350+ const void *targinfo)
12351 {
12352 struct ip_conntrack *ct;
12353 enum ip_conntrack_info ctinfo;
12354diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_TCPMSS.c linux-2.6.19/net/ipv4/netfilter/ipt_TCPMSS.c
12355--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_TCPMSS.c 2006-08-28 05:41:48.000000000 +0200
12356+++ linux-2.6.19/net/ipv4/netfilter/ipt_TCPMSS.c 2006-09-22 10:04:58.000000000 +0200
12357@@ -27,14 +27,6 @@
12358 #define DEBUGP(format, args...)
12359 #endif
12360
12361-static u_int16_t
12362-cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
12363-{
12364- u_int32_t diffs[] = { oldvalinv, newval };
12365- return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
12366- oldcheck^0xFFFF));
12367-}
12368-
12369 static inline unsigned int
12370 optlen(const u_int8_t *opt, unsigned int offset)
12371 {
12372@@ -49,8 +41,7 @@
12373 const struct net_device *out,
12374 unsigned int hooknum,
12375 const struct xt_target *target,
12376- const void *targinfo,
12377- void *userinfo)
12378+ const void *targinfo)
12379 {
12380 const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
12381 struct tcphdr *tcph;
12382@@ -62,10 +53,6 @@
12383 if (!skb_make_writable(pskb, (*pskb)->len))
12384 return NF_DROP;
12385
12386- if ((*pskb)->ip_summed == CHECKSUM_HW &&
12387- skb_checksum_help(*pskb, out == NULL))
12388- return NF_DROP;
12389-
12390 iph = (*pskb)->nh.iph;
12391 tcplen = (*pskb)->len - iph->ihl*4;
12392
12393@@ -119,9 +106,10 @@
12394 opt[i+2] = (newmss & 0xff00) >> 8;
12395 opt[i+3] = (newmss & 0x00ff);
12396
12397- tcph->check = cheat_check(htons(oldmss)^0xFFFF,
12398- htons(newmss),
12399- tcph->check);
12400+ tcph->check = nf_proto_csum_update(*pskb,
12401+ htons(oldmss)^0xFFFF,
12402+ htons(newmss),
12403+ tcph->check, 0);
12404
12405 DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu"
12406 "->%u.%u.%u.%u:%hu changed TCP MSS option"
12407@@ -161,8 +149,10 @@
12408 opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
12409 memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
12410
12411- tcph->check = cheat_check(htons(tcplen) ^ 0xFFFF,
12412- htons(tcplen + TCPOLEN_MSS), tcph->check);
12413+ tcph->check = nf_proto_csum_update(*pskb,
12414+ htons(tcplen) ^ 0xFFFF,
12415+ htons(tcplen + TCPOLEN_MSS),
12416+ tcph->check, 1);
12417 tcplen += TCPOLEN_MSS;
12418
12419 opt[0] = TCPOPT_MSS;
12420@@ -170,16 +160,19 @@
12421 opt[2] = (newmss & 0xff00) >> 8;
12422 opt[3] = (newmss & 0x00ff);
12423
12424- tcph->check = cheat_check(~0, *((u_int32_t *)opt), tcph->check);
12425+ tcph->check = nf_proto_csum_update(*pskb, ~0, *((u_int32_t *)opt),
12426+ tcph->check, 0);
12427
12428 oldval = ((u_int16_t *)tcph)[6];
12429 tcph->doff += TCPOLEN_MSS/4;
12430- tcph->check = cheat_check(oldval ^ 0xFFFF,
12431- ((u_int16_t *)tcph)[6], tcph->check);
12432+ tcph->check = nf_proto_csum_update(*pskb,
12433+ oldval ^ 0xFFFF,
12434+ ((u_int16_t *)tcph)[6],
12435+ tcph->check, 0);
12436
12437 newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);
12438- iph->check = cheat_check(iph->tot_len ^ 0xFFFF,
12439- newtotlen, iph->check);
12440+ iph->check = nf_csum_update(iph->tot_len ^ 0xFFFF,
12441+ newtotlen, iph->check);
12442 iph->tot_len = newtotlen;
12443
12444 DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu"
12445@@ -214,7 +207,6 @@
12446 const void *e_void,
12447 const struct xt_target *target,
12448 void *targinfo,
12449- unsigned int targinfosize,
12450 unsigned int hook_mask)
12451 {
12452 const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
12453diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_TOS.c linux-2.6.19/net/ipv4/netfilter/ipt_TOS.c
12454--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_TOS.c 2006-08-28 05:41:48.000000000 +0200
12455+++ linux-2.6.19/net/ipv4/netfilter/ipt_TOS.c 2006-09-22 10:04:58.000000000 +0200
12456@@ -26,27 +26,20 @@
12457 const struct net_device *out,
12458 unsigned int hooknum,
12459 const struct xt_target *target,
12460- const void *targinfo,
12461- void *userinfo)
12462+ const void *targinfo)
12463 {
12464 const struct ipt_tos_target_info *tosinfo = targinfo;
12465+ struct iphdr *iph = (*pskb)->nh.iph;
12466+ u_int16_t oldtos;
12467
12468- if (((*pskb)->nh.iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
12469- u_int16_t diffs[2];
12470-
12471+ if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
12472 if (!skb_make_writable(pskb, sizeof(struct iphdr)))
12473 return NF_DROP;
12474-
12475- diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF;
12476- (*pskb)->nh.iph->tos
12477- = ((*pskb)->nh.iph->tos & IPTOS_PREC_MASK)
12478- | tosinfo->tos;
12479- diffs[1] = htons((*pskb)->nh.iph->tos);
12480- (*pskb)->nh.iph->check
12481- = csum_fold(csum_partial((char *)diffs,
12482- sizeof(diffs),
12483- (*pskb)->nh.iph->check
12484- ^0xFFFF));
12485+ iph = (*pskb)->nh.iph;
12486+ oldtos = iph->tos;
12487+ iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
12488+ iph->check = nf_csum_update(oldtos ^ 0xFFFF, iph->tos,
12489+ iph->check);
12490 }
12491 return IPT_CONTINUE;
12492 }
12493@@ -56,7 +49,6 @@
12494 const void *e_void,
12495 const struct xt_target *target,
12496 void *targinfo,
12497- unsigned int targinfosize,
12498 unsigned int hook_mask)
12499 {
12500 const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos;
12501diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_TTL.c linux-2.6.19/net/ipv4/netfilter/ipt_TTL.c
12502--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_TTL.c 2006-08-28 05:41:48.000000000 +0200
12503+++ linux-2.6.19/net/ipv4/netfilter/ipt_TTL.c 2006-09-22 10:04:58.000000000 +0200
12504@@ -23,11 +23,10 @@
12505 ipt_ttl_target(struct sk_buff **pskb,
12506 const struct net_device *in, const struct net_device *out,
12507 unsigned int hooknum, const struct xt_target *target,
12508- const void *targinfo, void *userinfo)
12509+ const void *targinfo)
12510 {
12511 struct iphdr *iph;
12512 const struct ipt_TTL_info *info = targinfo;
12513- u_int16_t diffs[2];
12514 int new_ttl;
12515
12516 if (!skb_make_writable(pskb, (*pskb)->len))
12517@@ -55,12 +54,10 @@
12518 }
12519
12520 if (new_ttl != iph->ttl) {
12521- diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
12522+ iph->check = nf_csum_update((iph->ttl << 8) ^ 0xFFFF,
12523+ new_ttl << 8,
12524+ iph->check);
12525 iph->ttl = new_ttl;
12526- diffs[1] = htons(((unsigned)iph->ttl) << 8);
12527- iph->check = csum_fold(csum_partial((char *)diffs,
12528- sizeof(diffs),
12529- iph->check^0xFFFF));
12530 }
12531
12532 return IPT_CONTINUE;
12533@@ -70,7 +67,6 @@
12534 const void *e,
12535 const struct xt_target *target,
12536 void *targinfo,
12537- unsigned int targinfosize,
12538 unsigned int hook_mask)
12539 {
12540 struct ipt_TTL_info *info = targinfo;
12541diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_ULOG.c linux-2.6.19/net/ipv4/netfilter/ipt_ULOG.c
12542--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_ULOG.c 2006-08-28 05:41:48.000000000 +0200
12543+++ linux-2.6.19/net/ipv4/netfilter/ipt_ULOG.c 2006-09-22 10:04:58.000000000 +0200
12544@@ -308,7 +308,7 @@
12545 const struct net_device *out,
12546 unsigned int hooknum,
12547 const struct xt_target *target,
12548- const void *targinfo, void *userinfo)
12549+ const void *targinfo)
12550 {
12551 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
12552
12553@@ -346,7 +346,6 @@
12554 const void *e,
12555 const struct xt_target *target,
12556 void *targinfo,
12557- unsigned int targinfosize,
12558 unsigned int hookmask)
12559 {
12560 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
12561diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_ah.c linux-2.6.19/net/ipv4/netfilter/ipt_ah.c
12562--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_ah.c 2006-08-28 05:41:48.000000000 +0200
12563+++ linux-2.6.19/net/ipv4/netfilter/ipt_ah.c 2006-09-22 10:04:58.000000000 +0200
12564@@ -74,7 +74,6 @@
12565 const void *ip_void,
12566 const struct xt_match *match,
12567 void *matchinfo,
12568- unsigned int matchinfosize,
12569 unsigned int hook_mask)
12570 {
12571 const struct ipt_ah *ahinfo = matchinfo;
12572diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_dscp.c linux-2.6.19/net/ipv4/netfilter/ipt_dscp.c
12573--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_dscp.c 2006-08-28 05:41:48.000000000 +0200
12574+++ linux-2.6.19/net/ipv4/netfilter/ipt_dscp.c 1970-01-01 01:00:00.000000000 +0100
12575@@ -1,54 +0,0 @@
12576-/* IP tables module for matching the value of the IPv4 DSCP field
12577- *
12578- * ipt_dscp.c,v 1.3 2002/08/05 19:00:21 laforge Exp
12579- *
12580- * (C) 2002 by Harald Welte <laforge@netfilter.org>
12581- *
12582- * This program is free software; you can redistribute it and/or modify
12583- * it under the terms of the GNU General Public License version 2 as
12584- * published by the Free Software Foundation.
12585- */
12586-
12587-#include <linux/module.h>
12588-#include <linux/skbuff.h>
12589-
12590-#include <linux/netfilter_ipv4/ipt_dscp.h>
12591-#include <linux/netfilter_ipv4/ip_tables.h>
12592-
12593-MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
12594-MODULE_DESCRIPTION("iptables DSCP matching module");
12595-MODULE_LICENSE("GPL");
12596-
12597-static int match(const struct sk_buff *skb,
12598- const struct net_device *in, const struct net_device *out,
12599- const struct xt_match *match, const void *matchinfo,
12600- int offset, unsigned int protoff, int *hotdrop)
12601-{
12602- const struct ipt_dscp_info *info = matchinfo;
12603- const struct iphdr *iph = skb->nh.iph;
12604-
12605- u_int8_t sh_dscp = ((info->dscp << IPT_DSCP_SHIFT) & IPT_DSCP_MASK);
12606-
12607- return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert;
12608-}
12609-
12610-static struct ipt_match dscp_match = {
12611- .name = "dscp",
12612- .match = match,
12613- .matchsize = sizeof(struct ipt_dscp_info),
12614- .me = THIS_MODULE,
12615-};
12616-
12617-static int __init ipt_dscp_init(void)
12618-{
12619- return ipt_register_match(&dscp_match);
12620-}
12621-
12622-static void __exit ipt_dscp_fini(void)
12623-{
12624- ipt_unregister_match(&dscp_match);
12625-
12626-}
12627-
12628-module_init(ipt_dscp_init);
12629-module_exit(ipt_dscp_fini);
12630diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_ecn.c linux-2.6.19/net/ipv4/netfilter/ipt_ecn.c
12631--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_ecn.c 2006-08-28 05:41:48.000000000 +0200
12632+++ linux-2.6.19/net/ipv4/netfilter/ipt_ecn.c 2006-09-22 10:04:58.000000000 +0200
12633@@ -88,8 +88,7 @@
12634
12635 static int checkentry(const char *tablename, const void *ip_void,
12636 const struct xt_match *match,
12637- void *matchinfo, unsigned int matchsize,
12638- unsigned int hook_mask)
12639+ void *matchinfo, unsigned int hook_mask)
12640 {
12641 const struct ipt_ecn_info *info = matchinfo;
12642 const struct ipt_ip *ip = ip_void;
12643diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_hashlimit.c linux-2.6.19/net/ipv4/netfilter/ipt_hashlimit.c
12644--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_hashlimit.c 2006-08-28 05:41:48.000000000 +0200
12645+++ linux-2.6.19/net/ipv4/netfilter/ipt_hashlimit.c 2006-09-22 10:04:58.000000000 +0200
12646@@ -478,7 +478,6 @@
12647 const void *inf,
12648 const struct xt_match *match,
12649 void *matchinfo,
12650- unsigned int matchsize,
12651 unsigned int hook_mask)
12652 {
12653 struct ipt_hashlimit_info *r = matchinfo;
12654@@ -529,8 +528,7 @@
12655 }
12656
12657 static void
12658-hashlimit_destroy(const struct xt_match *match, void *matchinfo,
12659- unsigned int matchsize)
12660+hashlimit_destroy(const struct xt_match *match, void *matchinfo)
12661 {
12662 struct ipt_hashlimit_info *r = matchinfo;
12663
12664diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_owner.c linux-2.6.19/net/ipv4/netfilter/ipt_owner.c
12665--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_owner.c 2006-08-28 05:41:48.000000000 +0200
12666+++ linux-2.6.19/net/ipv4/netfilter/ipt_owner.c 2006-09-22 10:04:58.000000000 +0200
12667@@ -56,7 +56,6 @@
12668 const void *ip,
12669 const struct xt_match *match,
12670 void *matchinfo,
12671- unsigned int matchsize,
12672 unsigned int hook_mask)
12673 {
12674 const struct ipt_owner_info *info = matchinfo;
12675diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/ipt_recent.c linux-2.6.19/net/ipv4/netfilter/ipt_recent.c
12676--- linux-2.6.18-rc5/net/ipv4/netfilter/ipt_recent.c 2006-08-28 05:41:48.000000000 +0200
12677+++ linux-2.6.19/net/ipv4/netfilter/ipt_recent.c 2006-09-22 10:04:58.000000000 +0200
12678@@ -35,14 +35,20 @@
12679 static unsigned int ip_pkt_list_tot = 20;
12680 static unsigned int ip_list_hash_size = 0;
12681 static unsigned int ip_list_perms = 0644;
12682+static unsigned int ip_list_uid = 0;
12683+static unsigned int ip_list_gid = 0;
12684 module_param(ip_list_tot, uint, 0400);
12685 module_param(ip_pkt_list_tot, uint, 0400);
12686 module_param(ip_list_hash_size, uint, 0400);
12687 module_param(ip_list_perms, uint, 0400);
12688+module_param(ip_list_uid, uint, 0400);
12689+module_param(ip_list_gid, uint, 0400);
12690 MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list");
12691 MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP to remember (max. 255)");
12692 MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs");
12693 MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/ipt_recent/* files");
12694+MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/ipt_recent/* files");
12695+MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/ipt_recent/* files");
12696
12697
12698 struct recent_entry {
12699@@ -232,7 +238,7 @@
12700 static int
12701 ipt_recent_checkentry(const char *tablename, const void *ip,
12702 const struct xt_match *match, void *matchinfo,
12703- unsigned int matchsize, unsigned int hook_mask)
12704+ unsigned int hook_mask)
12705 {
12706 const struct ipt_recent_info *info = matchinfo;
12707 struct recent_table *t;
12708@@ -274,6 +280,8 @@
12709 goto out;
12710 }
12711 t->proc->proc_fops = &recent_fops;
12712+ t->proc->uid = ip_list_uid;
12713+ t->proc->gid = ip_list_gid;
12714 t->proc->data = t;
12715 #endif
12716 spin_lock_bh(&recent_lock);
12717@@ -286,8 +294,7 @@
12718 }
12719
12720 static void
12721-ipt_recent_destroy(const struct xt_match *match, void *matchinfo,
12722- unsigned int matchsize)
12723+ipt_recent_destroy(const struct xt_match *match, void *matchinfo)
12724 {
12725 const struct ipt_recent_info *info = matchinfo;
12726 struct recent_table *t;
12727diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/iptable_filter.c linux-2.6.19/net/ipv4/netfilter/iptable_filter.c
12728--- linux-2.6.18-rc5/net/ipv4/netfilter/iptable_filter.c 2006-08-28 05:41:48.000000000 +0200
12729+++ linux-2.6.19/net/ipv4/netfilter/iptable_filter.c 2006-09-22 10:04:58.000000000 +0200
12730@@ -90,7 +90,7 @@
12731 const struct net_device *out,
12732 int (*okfn)(struct sk_buff *))
12733 {
12734- return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL);
12735+ return ipt_do_table(pskb, hook, in, out, &packet_filter);
12736 }
12737
12738 static unsigned int
12739@@ -108,7 +108,7 @@
12740 return NF_ACCEPT;
12741 }
12742
12743- return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL);
12744+ return ipt_do_table(pskb, hook, in, out, &packet_filter);
12745 }
12746
12747 static struct nf_hook_ops ipt_ops[] = {
12748diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/iptable_mangle.c linux-2.6.19/net/ipv4/netfilter/iptable_mangle.c
12749--- linux-2.6.18-rc5/net/ipv4/netfilter/iptable_mangle.c 2006-08-28 05:41:48.000000000 +0200
12750+++ linux-2.6.19/net/ipv4/netfilter/iptable_mangle.c 2006-09-22 10:04:58.000000000 +0200
12751@@ -119,7 +119,7 @@
12752 const struct net_device *out,
12753 int (*okfn)(struct sk_buff *))
12754 {
12755- return ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL);
12756+ return ipt_do_table(pskb, hook, in, out, &packet_mangler);
12757 }
12758
12759 static unsigned int
12760@@ -148,7 +148,7 @@
12761 daddr = (*pskb)->nh.iph->daddr;
12762 tos = (*pskb)->nh.iph->tos;
12763
12764- ret = ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL);
12765+ ret = ipt_do_table(pskb, hook, in, out, &packet_mangler);
12766 /* Reroute for ANY change. */
12767 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
12768 && ((*pskb)->nh.iph->saddr != saddr
12769diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/iptable_raw.c linux-2.6.19/net/ipv4/netfilter/iptable_raw.c
12770--- linux-2.6.18-rc5/net/ipv4/netfilter/iptable_raw.c 2006-08-28 05:41:48.000000000 +0200
12771+++ linux-2.6.19/net/ipv4/netfilter/iptable_raw.c 2006-09-22 10:04:58.000000000 +0200
12772@@ -95,7 +95,7 @@
12773 const struct net_device *out,
12774 int (*okfn)(struct sk_buff *))
12775 {
12776- return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
12777+ return ipt_do_table(pskb, hook, in, out, &packet_raw);
12778 }
12779
12780 /* 'raw' is the very first table. */
12781diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter/nf_conntrack_proto_icmp.c linux-2.6.19/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
12782--- linux-2.6.18-rc5/net/ipv4/netfilter/nf_conntrack_proto_icmp.c 2006-08-28 05:41:48.000000000 +0200
12783+++ linux-2.6.19/net/ipv4/netfilter/nf_conntrack_proto_icmp.c 2006-09-22 10:04:58.000000000 +0200
12784@@ -25,7 +25,7 @@
12785 #include <net/netfilter/nf_conntrack_protocol.h>
12786 #include <net/netfilter/nf_conntrack_core.h>
12787
12788-unsigned long nf_ct_icmp_timeout = 30*HZ;
12789+unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
12790
12791 #if 0
12792 #define DEBUGP printk
12793diff -Nur linux-2.6.18-rc5/net/ipv4/netfilter.c linux-2.6.19/net/ipv4/netfilter.c
12794--- linux-2.6.18-rc5/net/ipv4/netfilter.c 2006-08-28 05:41:48.000000000 +0200
12795+++ linux-2.6.19/net/ipv4/netfilter.c 2006-09-22 10:04:58.000000000 +0200
12796@@ -168,7 +168,7 @@
12797 unsigned int csum = 0;
12798
12799 switch (skb->ip_summed) {
12800- case CHECKSUM_HW:
12801+ case CHECKSUM_COMPLETE:
12802 if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
12803 break;
12804 if ((protocol == 0 && !(u16)csum_fold(skb->csum)) ||
12805diff -Nur linux-2.6.18-rc5/net/ipv4/proc.c linux-2.6.19/net/ipv4/proc.c
12806--- linux-2.6.18-rc5/net/ipv4/proc.c 2006-08-28 05:41:48.000000000 +0200
12807+++ linux-2.6.19/net/ipv4/proc.c 2006-09-22 10:04:58.000000000 +0200
12808@@ -173,6 +173,8 @@
12809 SNMP_MIB_ITEM("NoPorts", UDP_MIB_NOPORTS),
12810 SNMP_MIB_ITEM("InErrors", UDP_MIB_INERRORS),
12811 SNMP_MIB_ITEM("OutDatagrams", UDP_MIB_OUTDATAGRAMS),
12812+ SNMP_MIB_ITEM("RcvbufErrors", UDP_MIB_RCVBUFERRORS),
12813+ SNMP_MIB_ITEM("SndbufErrors", UDP_MIB_SNDBUFERRORS),
12814 SNMP_MIB_SENTINEL
12815 };
12816
12817diff -Nur linux-2.6.18-rc5/net/ipv4/raw.c linux-2.6.19/net/ipv4/raw.c
12818--- linux-2.6.18-rc5/net/ipv4/raw.c 2006-08-28 05:41:48.000000000 +0200
12819+++ linux-2.6.19/net/ipv4/raw.c 2006-09-22 10:04:58.000000000 +0200
12820@@ -38,8 +38,7 @@
12821 * as published by the Free Software Foundation; either version
12822 * 2 of the License, or (at your option) any later version.
12823 */
12824-
12825-#include <linux/config.h>
12826+
12827 #include <linux/types.h>
12828 #include <asm/atomic.h>
12829 #include <asm/byteorder.h>
12830@@ -484,6 +483,7 @@
12831 if (!inet->hdrincl)
12832 raw_probe_proto_opt(&fl, msg);
12833
12834+ security_sk_classify_flow(sk, &fl);
12835 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
12836 }
12837 if (err)
12838diff -Nur linux-2.6.18-rc5/net/ipv4/route.c linux-2.6.19/net/ipv4/route.c
12839--- linux-2.6.18-rc5/net/ipv4/route.c 2006-08-28 05:41:48.000000000 +0200
12840+++ linux-2.6.19/net/ipv4/route.c 2006-09-22 10:04:58.000000000 +0200
12841@@ -2639,51 +2639,54 @@
12842 {
12843 struct rtable *rt = (struct rtable*)skb->dst;
12844 struct rtmsg *r;
12845- struct nlmsghdr *nlh;
12846- unsigned char *b = skb->tail;
12847+ struct nlmsghdr *nlh;
12848 struct rta_cacheinfo ci;
12849-#ifdef CONFIG_IP_MROUTE
12850- struct rtattr *eptr;
12851-#endif
12852- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
12853- r = NLMSG_DATA(nlh);
12854+
12855+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
12856+ if (nlh == NULL)
12857+ return -ENOBUFS;
12858+
12859+ r = nlmsg_data(nlh);
12860 r->rtm_family = AF_INET;
12861 r->rtm_dst_len = 32;
12862 r->rtm_src_len = 0;
12863 r->rtm_tos = rt->fl.fl4_tos;
12864 r->rtm_table = RT_TABLE_MAIN;
12865+ NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
12866 r->rtm_type = rt->rt_type;
12867 r->rtm_scope = RT_SCOPE_UNIVERSE;
12868 r->rtm_protocol = RTPROT_UNSPEC;
12869 r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
12870 if (rt->rt_flags & RTCF_NOTIFY)
12871 r->rtm_flags |= RTM_F_NOTIFY;
12872- RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst);
12873+
12874+ NLA_PUT_U32(skb, RTA_DST, rt->rt_dst);
12875+
12876 if (rt->fl.fl4_src) {
12877 r->rtm_src_len = 32;
12878- RTA_PUT(skb, RTA_SRC, 4, &rt->fl.fl4_src);
12879+ NLA_PUT_U32(skb, RTA_SRC, rt->fl.fl4_src);
12880 }
12881 if (rt->u.dst.dev)
12882- RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex);
12883+ NLA_PUT_U32(skb, RTA_OIF, rt->u.dst.dev->ifindex);
12884 #ifdef CONFIG_NET_CLS_ROUTE
12885 if (rt->u.dst.tclassid)
12886- RTA_PUT(skb, RTA_FLOW, 4, &rt->u.dst.tclassid);
12887+ NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid);
12888 #endif
12889 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
12890- if (rt->rt_multipath_alg != IP_MP_ALG_NONE) {
12891- __u32 alg = rt->rt_multipath_alg;
12892-
12893- RTA_PUT(skb, RTA_MP_ALGO, 4, &alg);
12894- }
12895+ if (rt->rt_multipath_alg != IP_MP_ALG_NONE)
12896+ NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
12897 #endif
12898 if (rt->fl.iif)
12899- RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_spec_dst);
12900+ NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_spec_dst);
12901 else if (rt->rt_src != rt->fl.fl4_src)
12902- RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_src);
12903+ NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_src);
12904+
12905 if (rt->rt_dst != rt->rt_gateway)
12906- RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway);
12907+ NLA_PUT_U32(skb, RTA_GATEWAY, rt->rt_gateway);
12908+
12909 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
12910- goto rtattr_failure;
12911+ goto nla_put_failure;
12912+
12913 ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
12914 ci.rta_used = rt->u.dst.__use;
12915 ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
12916@@ -2700,10 +2703,7 @@
12917 ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;
12918 }
12919 }
12920-#ifdef CONFIG_IP_MROUTE
12921- eptr = (struct rtattr*)skb->tail;
12922-#endif
12923- RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
12924+
12925 if (rt->fl.iif) {
12926 #ifdef CONFIG_IP_MROUTE
12927 u32 dst = rt->rt_dst;
12928@@ -2715,41 +2715,46 @@
12929 if (!nowait) {
12930 if (err == 0)
12931 return 0;
12932- goto nlmsg_failure;
12933+ goto nla_put_failure;
12934 } else {
12935 if (err == -EMSGSIZE)
12936- goto nlmsg_failure;
12937- ((struct rta_cacheinfo*)RTA_DATA(eptr))->rta_error = err;
12938+ goto nla_put_failure;
12939+ ci.rta_error = err;
12940 }
12941 }
12942 } else
12943 #endif
12944- RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif);
12945+ NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif);
12946 }
12947
12948- nlh->nlmsg_len = skb->tail - b;
12949- return skb->len;
12950+ NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
12951+
12952+ return nlmsg_end(skb, nlh);
12953
12954-nlmsg_failure:
12955-rtattr_failure:
12956- skb_trim(skb, b - skb->data);
12957- return -1;
12958+nla_put_failure:
12959+ return nlmsg_cancel(skb, nlh);
12960 }
12961
12962 int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
12963 {
12964- struct rtattr **rta = arg;
12965- struct rtmsg *rtm = NLMSG_DATA(nlh);
12966+ struct rtmsg *rtm;
12967+ struct nlattr *tb[RTA_MAX+1];
12968 struct rtable *rt = NULL;
12969- u32 dst = 0;
12970- u32 src = 0;
12971- int iif = 0;
12972- int err = -ENOBUFS;
12973+ u32 dst, src, iif;
12974+ int err;
12975 struct sk_buff *skb;
12976
12977+ err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
12978+ if (err < 0)
12979+ goto errout;
12980+
12981+ rtm = nlmsg_data(nlh);
12982+
12983 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
12984- if (!skb)
12985- goto out;
12986+ if (skb == NULL) {
12987+ err = -ENOBUFS;
12988+ goto errout;
12989+ }
12990
12991 /* Reserve room for dummy headers, this skb can pass
12992 through good chunk of routing engine.
12993@@ -2760,62 +2765,61 @@
12994 skb->nh.iph->protocol = IPPROTO_ICMP;
12995 skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
12996
12997- if (rta[RTA_SRC - 1])
12998- memcpy(&src, RTA_DATA(rta[RTA_SRC - 1]), 4);
12999- if (rta[RTA_DST - 1])
13000- memcpy(&dst, RTA_DATA(rta[RTA_DST - 1]), 4);
13001- if (rta[RTA_IIF - 1])
13002- memcpy(&iif, RTA_DATA(rta[RTA_IIF - 1]), sizeof(int));
13003+ src = tb[RTA_SRC] ? nla_get_u32(tb[RTA_SRC]) : 0;
13004+ dst = tb[RTA_DST] ? nla_get_u32(tb[RTA_DST]) : 0;
13005+ iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
13006
13007 if (iif) {
13008- struct net_device *dev = __dev_get_by_index(iif);
13009- err = -ENODEV;
13010- if (!dev)
13011- goto out_free;
13012+ struct net_device *dev;
13013+
13014+ dev = __dev_get_by_index(iif);
13015+ if (dev == NULL) {
13016+ err = -ENODEV;
13017+ goto errout_free;
13018+ }
13019+
13020 skb->protocol = htons(ETH_P_IP);
13021 skb->dev = dev;
13022 local_bh_disable();
13023 err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
13024 local_bh_enable();
13025- rt = (struct rtable*)skb->dst;
13026- if (!err && rt->u.dst.error)
13027+
13028+ rt = (struct rtable*) skb->dst;
13029+ if (err == 0 && rt->u.dst.error)
13030 err = -rt->u.dst.error;
13031 } else {
13032- struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst,
13033- .saddr = src,
13034- .tos = rtm->rtm_tos } } };
13035- int oif = 0;
13036- if (rta[RTA_OIF - 1])
13037- memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));
13038- fl.oif = oif;
13039+ struct flowi fl = {
13040+ .nl_u = {
13041+ .ip4_u = {
13042+ .daddr = dst,
13043+ .saddr = src,
13044+ .tos = rtm->rtm_tos,
13045+ },
13046+ },
13047+ .oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0,
13048+ };
13049 err = ip_route_output_key(&rt, &fl);
13050 }
13051+
13052 if (err)
13053- goto out_free;
13054+ goto errout_free;
13055
13056 skb->dst = &rt->u.dst;
13057 if (rtm->rtm_flags & RTM_F_NOTIFY)
13058 rt->rt_flags |= RTCF_NOTIFY;
13059
13060- NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
13061-
13062 err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
13063 RTM_NEWROUTE, 0, 0);
13064- if (!err)
13065- goto out_free;
13066- if (err < 0) {
13067- err = -EMSGSIZE;
13068- goto out_free;
13069- }
13070+ if (err <= 0)
13071+ goto errout_free;
13072
13073- err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
13074- if (err > 0)
13075- err = 0;
13076-out: return err;
13077+ err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
13078+errout:
13079+ return err;
13080
13081-out_free:
13082+errout_free:
13083 kfree_skb(skb);
13084- goto out;
13085+ goto errout;
13086 }
13087
13088 int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
13089@@ -3143,13 +3147,9 @@
13090 }
13091 #endif
13092
13093- ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",
13094- sizeof(struct rtable),
13095- 0, SLAB_HWCACHE_ALIGN,
13096- NULL, NULL);
13097-
13098- if (!ipv4_dst_ops.kmem_cachep)
13099- panic("IP: failed to allocate ip_dst_cache\n");
13100+ ipv4_dst_ops.kmem_cachep =
13101+ kmem_cache_create("ip_dst_cache", sizeof(struct rtable), 0,
13102+ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
13103
13104 rt_hash_table = (struct rt_hash_bucket *)
13105 alloc_large_system_hash("IP route cache",
13106diff -Nur linux-2.6.18-rc5/net/ipv4/syncookies.c linux-2.6.19/net/ipv4/syncookies.c
13107--- linux-2.6.18-rc5/net/ipv4/syncookies.c 2006-08-28 05:41:48.000000000 +0200
13108+++ linux-2.6.19/net/ipv4/syncookies.c 2006-09-22 10:04:58.000000000 +0200
13109@@ -214,6 +214,10 @@
13110 if (!req)
13111 goto out;
13112
13113+ if (security_inet_conn_request(sk, skb, req)) {
13114+ reqsk_free(req);
13115+ goto out;
13116+ }
13117 ireq = inet_rsk(req);
13118 treq = tcp_rsk(req);
13119 treq->rcv_isn = htonl(skb->h.th->seq) - 1;
13120@@ -259,6 +263,7 @@
13121 .uli_u = { .ports =
13122 { .sport = skb->h.th->dest,
13123 .dport = skb->h.th->source } } };
13124+ security_req_classify_flow(req, &fl);
13125 if (ip_route_output_key(&rt, &fl)) {
13126 reqsk_free(req);
13127 goto out;
13128diff -Nur linux-2.6.18-rc5/net/ipv4/sysctl_net_ipv4.c linux-2.6.19/net/ipv4/sysctl_net_ipv4.c
13129--- linux-2.6.18-rc5/net/ipv4/sysctl_net_ipv4.c 2006-08-28 05:41:48.000000000 +0200
13130+++ linux-2.6.19/net/ipv4/sysctl_net_ipv4.c 2006-09-22 10:04:58.000000000 +0200
13131@@ -17,6 +17,7 @@
13132 #include <net/ip.h>
13133 #include <net/route.h>
13134 #include <net/tcp.h>
13135+#include <net/cipso_ipv4.h>
13136
13137 /* From af_inet.c */
13138 extern int sysctl_ip_nonlocal_bind;
13139@@ -697,6 +698,40 @@
13140 .mode = 0644,
13141 .proc_handler = &proc_dointvec
13142 },
13143+#ifdef CONFIG_NETLABEL
13144+ {
13145+ .ctl_name = NET_CIPSOV4_CACHE_ENABLE,
13146+ .procname = "cipso_cache_enable",
13147+ .data = &cipso_v4_cache_enabled,
13148+ .maxlen = sizeof(int),
13149+ .mode = 0644,
13150+ .proc_handler = &proc_dointvec,
13151+ },
13152+ {
13153+ .ctl_name = NET_CIPSOV4_CACHE_BUCKET_SIZE,
13154+ .procname = "cipso_cache_bucket_size",
13155+ .data = &cipso_v4_cache_bucketsize,
13156+ .maxlen = sizeof(int),
13157+ .mode = 0644,
13158+ .proc_handler = &proc_dointvec,
13159+ },
13160+ {
13161+ .ctl_name = NET_CIPSOV4_RBM_OPTFMT,
13162+ .procname = "cipso_rbm_optfmt",
13163+ .data = &cipso_v4_rbm_optfmt,
13164+ .maxlen = sizeof(int),
13165+ .mode = 0644,
13166+ .proc_handler = &proc_dointvec,
13167+ },
13168+ {
13169+ .ctl_name = NET_CIPSOV4_RBM_STRICTVALID,
13170+ .procname = "cipso_rbm_strictvalid",
13171+ .data = &cipso_v4_rbm_strictvalid,
13172+ .maxlen = sizeof(int),
13173+ .mode = 0644,
13174+ .proc_handler = &proc_dointvec,
13175+ },
13176+#endif /* CONFIG_NETLABEL */
13177 { .ctl_name = 0 }
13178 };
13179
13180diff -Nur linux-2.6.18-rc5/net/ipv4/tcp.c linux-2.6.19/net/ipv4/tcp.c
13181--- linux-2.6.18-rc5/net/ipv4/tcp.c 2006-08-28 05:41:48.000000000 +0200
13182+++ linux-2.6.19/net/ipv4/tcp.c 2006-09-22 10:04:58.000000000 +0200
13183@@ -268,7 +268,7 @@
13184 #include <asm/uaccess.h>
13185 #include <asm/ioctls.h>
13186
13187-int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
13188+int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT;
13189
13190 DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics) __read_mostly;
13191
13192@@ -568,7 +568,7 @@
13193 skb->truesize += copy;
13194 sk->sk_wmem_queued += copy;
13195 sk->sk_forward_alloc -= copy;
13196- skb->ip_summed = CHECKSUM_HW;
13197+ skb->ip_summed = CHECKSUM_PARTIAL;
13198 tp->write_seq += copy;
13199 TCP_SKB_CB(skb)->end_seq += copy;
13200 skb_shinfo(skb)->gso_segs = 0;
13201@@ -723,7 +723,7 @@
13202 * Check whether we can use HW checksum.
13203 */
13204 if (sk->sk_route_caps & NETIF_F_ALL_CSUM)
13205- skb->ip_summed = CHECKSUM_HW;
13206+ skb->ip_summed = CHECKSUM_PARTIAL;
13207
13208 skb_entail(sk, tp, skb);
13209 copy = size_goal;
13210@@ -955,8 +955,11 @@
13211 * receive buffer and there was a small segment
13212 * in queue.
13213 */
13214- (copied > 0 && (icsk->icsk_ack.pending & ICSK_ACK_PUSHED) &&
13215- !icsk->icsk_ack.pingpong && !atomic_read(&sk->sk_rmem_alloc)))
13216+ (copied > 0 &&
13217+ ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED2) ||
13218+ ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED) &&
13219+ !icsk->icsk_ack.pingpong)) &&
13220+ !atomic_read(&sk->sk_rmem_alloc)))
13221 time_to_ack = 1;
13222 }
13223
13224@@ -2205,7 +2208,7 @@
13225 th->fin = th->psh = 0;
13226
13227 th->check = ~csum_fold(th->check + delta);
13228- if (skb->ip_summed != CHECKSUM_HW)
13229+ if (skb->ip_summed != CHECKSUM_PARTIAL)
13230 th->check = csum_fold(csum_partial(skb->h.raw, thlen,
13231 skb->csum));
13232
13233@@ -2219,7 +2222,7 @@
13234
13235 delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len);
13236 th->check = ~csum_fold(th->check + delta);
13237- if (skb->ip_summed != CHECKSUM_HW)
13238+ if (skb->ip_summed != CHECKSUM_PARTIAL)
13239 th->check = csum_fold(csum_partial(skb->h.raw, thlen,
13240 skb->csum));
13241
13242@@ -2254,9 +2257,7 @@
13243 tcp_hashinfo.bind_bucket_cachep =
13244 kmem_cache_create("tcp_bind_bucket",
13245 sizeof(struct inet_bind_bucket), 0,
13246- SLAB_HWCACHE_ALIGN, NULL, NULL);
13247- if (!tcp_hashinfo.bind_bucket_cachep)
13248- panic("tcp_init: Cannot alloc tcp_bind_bucket cache.");
13249+ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
13250
13251 /* Size and allocate the main established and bind bucket
13252 * hash tables.
13253diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_bic.c linux-2.6.19/net/ipv4/tcp_bic.c
13254--- linux-2.6.18-rc5/net/ipv4/tcp_bic.c 2006-08-28 05:41:48.000000000 +0200
13255+++ linux-2.6.19/net/ipv4/tcp_bic.c 2006-09-22 10:04:58.000000000 +0200
13256@@ -231,7 +231,7 @@
13257
13258 static int __init bictcp_register(void)
13259 {
13260- BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
13261+ BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
13262 return tcp_register_congestion_control(&bictcp);
13263 }
13264
13265diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_cubic.c linux-2.6.19/net/ipv4/tcp_cubic.c
13266--- linux-2.6.18-rc5/net/ipv4/tcp_cubic.c 2006-08-28 05:41:48.000000000 +0200
13267+++ linux-2.6.19/net/ipv4/tcp_cubic.c 2006-09-22 10:04:58.000000000 +0200
13268@@ -358,7 +358,7 @@
13269
13270 static int __init cubictcp_register(void)
13271 {
13272- BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
13273+ BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
13274
13275 /* Precompute a bunch of the scaling factors that are used per-packet
13276 * based on SRTT of 100ms
13277diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_highspeed.c linux-2.6.19/net/ipv4/tcp_highspeed.c
13278--- linux-2.6.18-rc5/net/ipv4/tcp_highspeed.c 2006-08-28 05:41:48.000000000 +0200
13279+++ linux-2.6.19/net/ipv4/tcp_highspeed.c 2006-09-22 10:04:58.000000000 +0200
13280@@ -189,7 +189,7 @@
13281
13282 static int __init hstcp_register(void)
13283 {
13284- BUG_ON(sizeof(struct hstcp) > ICSK_CA_PRIV_SIZE);
13285+ BUILD_BUG_ON(sizeof(struct hstcp) > ICSK_CA_PRIV_SIZE);
13286 return tcp_register_congestion_control(&tcp_highspeed);
13287 }
13288
13289diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_htcp.c linux-2.6.19/net/ipv4/tcp_htcp.c
13290--- linux-2.6.18-rc5/net/ipv4/tcp_htcp.c 2006-08-28 05:41:48.000000000 +0200
13291+++ linux-2.6.19/net/ipv4/tcp_htcp.c 2006-09-22 10:04:58.000000000 +0200
13292@@ -286,7 +286,7 @@
13293
13294 static int __init htcp_register(void)
13295 {
13296- BUG_ON(sizeof(struct htcp) > ICSK_CA_PRIV_SIZE);
13297+ BUILD_BUG_ON(sizeof(struct htcp) > ICSK_CA_PRIV_SIZE);
13298 BUILD_BUG_ON(BETA_MIN >= BETA_MAX);
13299 return tcp_register_congestion_control(&htcp);
13300 }
13301diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_hybla.c linux-2.6.19/net/ipv4/tcp_hybla.c
13302--- linux-2.6.18-rc5/net/ipv4/tcp_hybla.c 2006-08-28 05:41:48.000000000 +0200
13303+++ linux-2.6.19/net/ipv4/tcp_hybla.c 2006-09-22 10:04:58.000000000 +0200
13304@@ -170,7 +170,7 @@
13305
13306 static int __init hybla_register(void)
13307 {
13308- BUG_ON(sizeof(struct hybla) > ICSK_CA_PRIV_SIZE);
13309+ BUILD_BUG_ON(sizeof(struct hybla) > ICSK_CA_PRIV_SIZE);
13310 return tcp_register_congestion_control(&tcp_hybla);
13311 }
13312
13313diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_input.c linux-2.6.19/net/ipv4/tcp_input.c
13314--- linux-2.6.18-rc5/net/ipv4/tcp_input.c 2006-08-28 05:41:48.000000000 +0200
13315+++ linux-2.6.19/net/ipv4/tcp_input.c 2006-09-22 10:04:58.000000000 +0200
13316@@ -72,24 +72,24 @@
13317 #include <asm/unaligned.h>
13318 #include <net/netdma.h>
13319
13320-int sysctl_tcp_timestamps = 1;
13321-int sysctl_tcp_window_scaling = 1;
13322-int sysctl_tcp_sack = 1;
13323-int sysctl_tcp_fack = 1;
13324-int sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH;
13325-int sysctl_tcp_ecn;
13326-int sysctl_tcp_dsack = 1;
13327-int sysctl_tcp_app_win = 31;
13328-int sysctl_tcp_adv_win_scale = 2;
13329-
13330-int sysctl_tcp_stdurg;
13331-int sysctl_tcp_rfc1337;
13332-int sysctl_tcp_max_orphans = NR_FILE;
13333-int sysctl_tcp_frto;
13334-int sysctl_tcp_nometrics_save;
13335+int sysctl_tcp_timestamps __read_mostly = 1;
13336+int sysctl_tcp_window_scaling __read_mostly = 1;
13337+int sysctl_tcp_sack __read_mostly = 1;
13338+int sysctl_tcp_fack __read_mostly = 1;
13339+int sysctl_tcp_reordering __read_mostly = TCP_FASTRETRANS_THRESH;
13340+int sysctl_tcp_ecn __read_mostly;
13341+int sysctl_tcp_dsack __read_mostly = 1;
13342+int sysctl_tcp_app_win __read_mostly = 31;
13343+int sysctl_tcp_adv_win_scale __read_mostly = 2;
13344+
13345+int sysctl_tcp_stdurg __read_mostly;
13346+int sysctl_tcp_rfc1337 __read_mostly;
13347+int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
13348+int sysctl_tcp_frto __read_mostly;
13349+int sysctl_tcp_nometrics_save __read_mostly;
13350
13351-int sysctl_tcp_moderate_rcvbuf = 1;
07f72ae0 13352-int sysctl_tcp_abc;
6b10f65d 13353+int sysctl_tcp_moderate_rcvbuf __read_mostly = 1;
13354+int sysctl_tcp_abc __read_mostly = 1;
13355
13356 #define FLAG_DATA 0x01 /* Incoming frame contained data. */
13357 #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
13358@@ -127,7 +127,7 @@
13359 /* skb->len may jitter because of SACKs, even if peer
13360 * sends good full-sized frames.
13361 */
13362- len = skb->len;
13363+ len = skb_shinfo(skb)->gso_size ?: skb->len;
13364 if (len >= icsk->icsk_ack.rcv_mss) {
13365 icsk->icsk_ack.rcv_mss = len;
13366 } else {
13367@@ -156,6 +156,8 @@
13368 return;
13369 }
13370 }
13371+ if (icsk->icsk_ack.pending & ICSK_ACK_PUSHED)
13372+ icsk->icsk_ack.pending |= ICSK_ACK_PUSHED2;
13373 icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
13374 }
13375 }
6b10f65d 13376diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_ipv4.c linux-2.6.19/net/ipv4/tcp_ipv4.c
13377--- linux-2.6.18-rc5/net/ipv4/tcp_ipv4.c 2006-08-28 05:41:48.000000000 +0200
13378+++ linux-2.6.19/net/ipv4/tcp_ipv4.c 2006-09-22 10:04:58.000000000 +0200
13379@@ -78,8 +78,8 @@
13380 #include <linux/proc_fs.h>
13381 #include <linux/seq_file.h>
13382
13383-int sysctl_tcp_tw_reuse;
13384-int sysctl_tcp_low_latency;
13385+int sysctl_tcp_tw_reuse __read_mostly;
13386+int sysctl_tcp_low_latency __read_mostly;
13387
13388 /* Check TCP sequence numbers in ICMP packets. */
13389 #define ICMP_MIN_LENGTH 8
13390@@ -484,7 +484,7 @@
13391 struct inet_sock *inet = inet_sk(sk);
13392 struct tcphdr *th = skb->h.th;
13393
13394- if (skb->ip_summed == CHECKSUM_HW) {
13395+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
13396 th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0);
13397 skb->csum = offsetof(struct tcphdr, check);
13398 } else {
13399@@ -509,7 +509,7 @@
13400 th->check = 0;
13401 th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
13402 skb->csum = offsetof(struct tcphdr, check);
13403- skb->ip_summed = CHECKSUM_HW;
13404+ skb->ip_summed = CHECKSUM_PARTIAL;
13405 return 0;
13406 }
13407
13408@@ -798,6 +798,9 @@
13409
13410 tcp_openreq_init(req, &tmp_opt, skb);
13411
13412+ if (security_inet_conn_request(sk, skb, req))
13413+ goto drop_and_free;
13414+
13415 ireq = inet_rsk(req);
13416 ireq->loc_addr = daddr;
13417 ireq->rmt_addr = saddr;
13418@@ -948,9 +951,9 @@
13419 if (req)
13420 return tcp_check_req(sk, skb, req, prev);
13421
13422- nsk = __inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr,
13423- th->source, skb->nh.iph->daddr,
13424- ntohs(th->dest), inet_iif(skb));
13425+ nsk = inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr,
13426+ th->source, skb->nh.iph->daddr,
13427+ th->dest, inet_iif(skb));
13428
13429 if (nsk) {
13430 if (nsk->sk_state != TCP_TIME_WAIT) {
13431@@ -970,7 +973,7 @@
13432
13433 static int tcp_v4_checksum_init(struct sk_buff *skb)
13434 {
13435- if (skb->ip_summed == CHECKSUM_HW) {
13436+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
13437 if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,
13438 skb->nh.iph->daddr, skb->csum)) {
13439 skb->ip_summed = CHECKSUM_UNNECESSARY;
13440@@ -1087,7 +1090,7 @@
13441 TCP_SKB_CB(skb)->sacked = 0;
13442
13443 sk = __inet_lookup(&tcp_hashinfo, skb->nh.iph->saddr, th->source,
13444- skb->nh.iph->daddr, ntohs(th->dest),
13445+ skb->nh.iph->daddr, th->dest,
13446 inet_iif(skb));
13447
13448 if (!sk)
13449@@ -1101,7 +1104,7 @@
13450 goto discard_and_relse;
13451 nf_reset(skb);
13452
13453- if (sk_filter(sk, skb, 0))
13454+ if (sk_filter(sk, skb))
13455 goto discard_and_relse;
13456
13457 skb->dev = NULL;
13458@@ -1165,7 +1168,7 @@
13459 case TCP_TW_SYN: {
13460 struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
13461 skb->nh.iph->daddr,
13462- ntohs(th->dest),
13463+ th->dest,
13464 inet_iif(skb));
13465 if (sk2) {
13466 inet_twsk_deschedule((struct inet_timewait_sock *)sk,
13467diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_lp.c linux-2.6.19/net/ipv4/tcp_lp.c
13468--- linux-2.6.18-rc5/net/ipv4/tcp_lp.c 2006-08-28 05:41:48.000000000 +0200
13469+++ linux-2.6.19/net/ipv4/tcp_lp.c 2006-09-22 10:04:58.000000000 +0200
13470@@ -31,7 +31,6 @@
13471 * Version: $Id$
13472 */
13473
13474-#include <linux/config.h>
13475 #include <linux/module.h>
13476 #include <net/tcp.h>
13477
13478@@ -321,7 +320,7 @@
13479
13480 static int __init tcp_lp_register(void)
13481 {
13482- BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE);
13483+ BUILD_BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE);
13484 return tcp_register_congestion_control(&tcp_lp);
13485 }
13486
13487diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_minisocks.c linux-2.6.19/net/ipv4/tcp_minisocks.c
13488--- linux-2.6.18-rc5/net/ipv4/tcp_minisocks.c 2006-08-28 05:41:48.000000000 +0200
13489+++ linux-2.6.19/net/ipv4/tcp_minisocks.c 2006-09-22 10:04:58.000000000 +0200
13490@@ -34,8 +34,8 @@
13491 #define SYNC_INIT 1
13492 #endif
13493
13494-int sysctl_tcp_syncookies = SYNC_INIT;
13495-int sysctl_tcp_abort_on_overflow;
13496+int sysctl_tcp_syncookies __read_mostly = SYNC_INIT;
13497+int sysctl_tcp_abort_on_overflow __read_mostly;
13498
13499 struct inet_timewait_death_row tcp_death_row = {
13500 .sysctl_max_tw_buckets = NR_FILE * 2,
13501diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_output.c linux-2.6.19/net/ipv4/tcp_output.c
13502--- linux-2.6.18-rc5/net/ipv4/tcp_output.c 2006-08-28 05:41:48.000000000 +0200
13503+++ linux-2.6.19/net/ipv4/tcp_output.c 2006-09-22 10:04:58.000000000 +0200
13504@@ -43,24 +43,24 @@
13505 #include <linux/smp_lock.h>
13506
13507 /* People can turn this off for buggy TCP's found in printers etc. */
13508-int sysctl_tcp_retrans_collapse = 1;
13509+int sysctl_tcp_retrans_collapse __read_mostly = 1;
13510
13511 /* People can turn this on to work with those rare, broken TCPs that
13512 * interpret the window field as a signed quantity.
13513 */
13514-int sysctl_tcp_workaround_signed_windows = 0;
13515+int sysctl_tcp_workaround_signed_windows __read_mostly = 0;
13516
13517 /* This limits the percentage of the congestion window which we
13518 * will allow a single TSO frame to consume. Building TSO frames
13519 * which are too large can cause TCP streams to be bursty.
13520 */
13521-int sysctl_tcp_tso_win_divisor = 3;
13522+int sysctl_tcp_tso_win_divisor __read_mostly = 3;
13523
13524-int sysctl_tcp_mtu_probing = 0;
13525-int sysctl_tcp_base_mss = 512;
13526+int sysctl_tcp_mtu_probing __read_mostly = 0;
13527+int sysctl_tcp_base_mss __read_mostly = 512;
13528
13529 /* By default, RFC2861 behavior. */
13530-int sysctl_tcp_slow_start_after_idle = 1;
13531+int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
13532
13533 static void update_send_head(struct sock *sk, struct tcp_sock *tp,
13534 struct sk_buff *skb)
13535@@ -577,7 +577,7 @@
13536 TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked;
13537 TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL;
13538
13539- if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) {
13540+ if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_PARTIAL) {
13541 /* Copy and checksum data tail into the new buffer. */
13542 buff->csum = csum_partial_copy_nocheck(skb->data + len, skb_put(buff, nsize),
13543 nsize, 0);
13544@@ -586,7 +586,7 @@
13545
13546 skb->csum = csum_block_sub(skb->csum, buff->csum, len);
13547 } else {
13548- skb->ip_summed = CHECKSUM_HW;
13549+ skb->ip_summed = CHECKSUM_PARTIAL;
13550 skb_split(skb, buff, len);
13551 }
13552
13553@@ -689,7 +689,7 @@
13554 __pskb_trim_head(skb, len - skb_headlen(skb));
13555
13556 TCP_SKB_CB(skb)->seq += len;
13557- skb->ip_summed = CHECKSUM_HW;
13558+ skb->ip_summed = CHECKSUM_PARTIAL;
13559
13560 skb->truesize -= len;
13561 sk->sk_wmem_queued -= len;
13562@@ -1062,7 +1062,7 @@
13563 /* This packet was never sent out yet, so no SACK bits. */
13564 TCP_SKB_CB(buff)->sacked = 0;
13565
13566- buff->ip_summed = skb->ip_summed = CHECKSUM_HW;
13567+ buff->ip_summed = skb->ip_summed = CHECKSUM_PARTIAL;
13568 skb_split(skb, buff, len);
13569
13570 /* Fix up tso_factor for both original and new SKB. */
13571@@ -1206,8 +1206,7 @@
13572 TCP_SKB_CB(nskb)->flags = TCPCB_FLAG_ACK;
13573 TCP_SKB_CB(nskb)->sacked = 0;
13574 nskb->csum = 0;
13575- if (skb->ip_summed == CHECKSUM_HW)
13576- nskb->ip_summed = CHECKSUM_HW;
13577+ nskb->ip_summed = skb->ip_summed;
13578
13579 len = 0;
13580 while (len < probe_size) {
13581@@ -1231,7 +1230,7 @@
13582 ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
13583 if (!skb_shinfo(skb)->nr_frags) {
13584 skb_pull(skb, copy);
13585- if (skb->ip_summed != CHECKSUM_HW)
13586+ if (skb->ip_summed != CHECKSUM_PARTIAL)
13587 skb->csum = csum_partial(skb->data, skb->len, 0);
13588 } else {
13589 __pskb_trim_head(skb, copy);
13590@@ -1572,10 +1571,9 @@
13591
13592 memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size);
13593
13594- if (next_skb->ip_summed == CHECKSUM_HW)
13595- skb->ip_summed = CHECKSUM_HW;
13596+ skb->ip_summed = next_skb->ip_summed;
13597
13598- if (skb->ip_summed != CHECKSUM_HW)
13599+ if (skb->ip_summed != CHECKSUM_PARTIAL)
13600 skb->csum = csum_block_add(skb->csum, next_skb->csum, skb_size);
13601
13602 /* Update sequence range on original skb. */
13603diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_timer.c linux-2.6.19/net/ipv4/tcp_timer.c
13604--- linux-2.6.18-rc5/net/ipv4/tcp_timer.c 2006-08-28 05:41:48.000000000 +0200
13605+++ linux-2.6.19/net/ipv4/tcp_timer.c 2006-09-22 10:04:58.000000000 +0200
13606@@ -23,14 +23,14 @@
13607 #include <linux/module.h>
13608 #include <net/tcp.h>
13609
13610-int sysctl_tcp_syn_retries = TCP_SYN_RETRIES;
13611-int sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES;
13612-int sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME;
13613-int sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES;
13614-int sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL;
13615-int sysctl_tcp_retries1 = TCP_RETR1;
13616-int sysctl_tcp_retries2 = TCP_RETR2;
13617-int sysctl_tcp_orphan_retries;
13618+int sysctl_tcp_syn_retries __read_mostly = TCP_SYN_RETRIES;
13619+int sysctl_tcp_synack_retries __read_mostly = TCP_SYNACK_RETRIES;
13620+int sysctl_tcp_keepalive_time __read_mostly = TCP_KEEPALIVE_TIME;
13621+int sysctl_tcp_keepalive_probes __read_mostly = TCP_KEEPALIVE_PROBES;
13622+int sysctl_tcp_keepalive_intvl __read_mostly = TCP_KEEPALIVE_INTVL;
13623+int sysctl_tcp_retries1 __read_mostly = TCP_RETR1;
13624+int sysctl_tcp_retries2 __read_mostly = TCP_RETR2;
13625+int sysctl_tcp_orphan_retries __read_mostly;
13626
13627 static void tcp_write_timer(unsigned long);
13628 static void tcp_delack_timer(unsigned long);
13629diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_vegas.c linux-2.6.19/net/ipv4/tcp_vegas.c
13630--- linux-2.6.18-rc5/net/ipv4/tcp_vegas.c 2006-08-28 05:41:48.000000000 +0200
13631+++ linux-2.6.19/net/ipv4/tcp_vegas.c 2006-09-22 10:04:58.000000000 +0200
13632@@ -370,7 +370,7 @@
13633
13634 static int __init tcp_vegas_register(void)
13635 {
13636- BUG_ON(sizeof(struct vegas) > ICSK_CA_PRIV_SIZE);
13637+ BUILD_BUG_ON(sizeof(struct vegas) > ICSK_CA_PRIV_SIZE);
13638 tcp_register_congestion_control(&tcp_vegas);
13639 return 0;
13640 }
13641diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_veno.c linux-2.6.19/net/ipv4/tcp_veno.c
13642--- linux-2.6.18-rc5/net/ipv4/tcp_veno.c 2006-08-28 05:41:48.000000000 +0200
13643+++ linux-2.6.19/net/ipv4/tcp_veno.c 2006-09-22 10:04:58.000000000 +0200
13644@@ -9,7 +9,6 @@
13645 * See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
13646 */
13647
13648-#include <linux/config.h>
13649 #include <linux/mm.h>
13650 #include <linux/module.h>
13651 #include <linux/skbuff.h>
13652@@ -213,7 +212,7 @@
13653
13654 static int __init tcp_veno_register(void)
13655 {
13656- BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE);
13657+ BUILD_BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE);
13658 tcp_register_congestion_control(&tcp_veno);
13659 return 0;
13660 }
13661diff -Nur linux-2.6.18-rc5/net/ipv4/tcp_westwood.c linux-2.6.19/net/ipv4/tcp_westwood.c
13662--- linux-2.6.18-rc5/net/ipv4/tcp_westwood.c 2006-08-28 05:41:48.000000000 +0200
13663+++ linux-2.6.19/net/ipv4/tcp_westwood.c 2006-09-22 10:04:58.000000000 +0200
13664@@ -289,7 +289,7 @@
13665
13666 static int __init tcp_westwood_register(void)
13667 {
13668- BUG_ON(sizeof(struct westwood) > ICSK_CA_PRIV_SIZE);
13669+ BUILD_BUG_ON(sizeof(struct westwood) > ICSK_CA_PRIV_SIZE);
13670 return tcp_register_congestion_control(&tcp_westwood);
13671 }
13672
13673diff -Nur linux-2.6.18-rc5/net/ipv4/udp.c linux-2.6.19/net/ipv4/udp.c
13674--- linux-2.6.18-rc5/net/ipv4/udp.c 2006-08-28 05:41:48.000000000 +0200
13675+++ linux-2.6.19/net/ipv4/udp.c 2006-09-22 10:04:58.000000000 +0200
13676@@ -118,14 +118,33 @@
13677 struct hlist_head udp_hash[UDP_HTABLE_SIZE];
13678 DEFINE_RWLOCK(udp_hash_lock);
13679
13680-/* Shared by v4/v6 udp. */
13681-int udp_port_rover;
13682+static int udp_port_rover;
13683
13684-static int udp_v4_get_port(struct sock *sk, unsigned short snum)
13685+static inline int udp_lport_inuse(u16 num)
13686 {
13687+ struct sock *sk;
13688 struct hlist_node *node;
13689+
13690+ sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)])
13691+ if (inet_sk(sk)->num == num)
13692+ return 1;
13693+ return 0;
13694+}
13695+
13696+/**
13697+ * udp_get_port - common port lookup for IPv4 and IPv6
13698+ *
13699+ * @sk: socket struct in question
13700+ * @snum: port number to look up
13701+ * @saddr_comp: AF-dependent comparison of bound local IP addresses
13702+ */
13703+int udp_get_port(struct sock *sk, unsigned short snum,
13704+ int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2))
13705+{
13706+ struct hlist_node *node;
13707+ struct hlist_head *head;
13708 struct sock *sk2;
13709- struct inet_sock *inet = inet_sk(sk);
13710+ int error = 1;
13711
13712 write_lock_bh(&udp_hash_lock);
13713 if (snum == 0) {
13714@@ -137,11 +156,10 @@
13715 best_size_so_far = 32767;
13716 best = result = udp_port_rover;
13717 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
13718- struct hlist_head *list;
13719 int size;
13720
13721- list = &udp_hash[result & (UDP_HTABLE_SIZE - 1)];
13722- if (hlist_empty(list)) {
13723+ head = &udp_hash[result & (UDP_HTABLE_SIZE - 1)];
13724+ if (hlist_empty(head)) {
13725 if (result > sysctl_local_port_range[1])
13726 result = sysctl_local_port_range[0] +
13727 ((result - sysctl_local_port_range[0]) &
13728@@ -149,12 +167,11 @@
13729 goto gotit;
13730 }
13731 size = 0;
13732- sk_for_each(sk2, node, list)
13733- if (++size >= best_size_so_far)
13734- goto next;
13735- best_size_so_far = size;
13736- best = result;
13737- next:;
13738+ sk_for_each(sk2, node, head)
13739+ if (++size < best_size_so_far) {
13740+ best_size_so_far = size;
13741+ best = result;
13742+ }
13743 }
13744 result = best;
13745 for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) {
13746@@ -170,38 +187,44 @@
13747 gotit:
13748 udp_port_rover = snum = result;
13749 } else {
13750- sk_for_each(sk2, node,
13751- &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]) {
13752- struct inet_sock *inet2 = inet_sk(sk2);
13753-
13754- if (inet2->num == snum &&
13755- sk2 != sk &&
13756- !ipv6_only_sock(sk2) &&
13757- (!sk2->sk_bound_dev_if ||
13758- !sk->sk_bound_dev_if ||
13759- sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
13760- (!inet2->rcv_saddr ||
13761- !inet->rcv_saddr ||
13762- inet2->rcv_saddr == inet->rcv_saddr) &&
13763- (!sk2->sk_reuse || !sk->sk_reuse))
13764+ head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
13765+
13766+ sk_for_each(sk2, node, head)
13767+ if (inet_sk(sk2)->num == snum &&
13768+ sk2 != sk &&
13769+ (!sk2->sk_reuse || !sk->sk_reuse) &&
13770+ (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
13771+ || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
13772+ (*saddr_cmp)(sk, sk2) )
13773 goto fail;
13774- }
13775 }
13776- inet->num = snum;
13777+ inet_sk(sk)->num = snum;
13778 if (sk_unhashed(sk)) {
13779- struct hlist_head *h = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
13780-
13781- sk_add_node(sk, h);
13782+ head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
13783+ sk_add_node(sk, head);
13784 sock_prot_inc_use(sk->sk_prot);
13785 }
13786- write_unlock_bh(&udp_hash_lock);
13787- return 0;
13788-
13789+ error = 0;
13790 fail:
13791 write_unlock_bh(&udp_hash_lock);
13792- return 1;
13793+ return error;
13794+}
13795+
13796+static inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
13797+{
13798+ struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
13799+
13800+ return ( !ipv6_only_sock(sk2) &&
13801+ (!inet1->rcv_saddr || !inet2->rcv_saddr ||
13802+ inet1->rcv_saddr == inet2->rcv_saddr ));
13803 }
13804
13805+static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
13806+{
13807+ return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
13808+}
13809+
13810+
13811 static void udp_v4_hash(struct sock *sk)
13812 {
13813 BUG();
13814@@ -429,7 +452,7 @@
13815 /*
13816 * Only one fragment on the socket.
13817 */
13818- if (skb->ip_summed == CHECKSUM_HW) {
13819+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
13820 skb->csum = offsetof(struct udphdr, check);
13821 uh->check = ~csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
13822 up->len, IPPROTO_UDP, 0);
13823@@ -448,7 +471,7 @@
13824 * fragments on the socket so that all csums of sk_buffs
13825 * should be together.
13826 */
13827- if (skb->ip_summed == CHECKSUM_HW) {
13828+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
13829 int offset = (unsigned char *)uh - skb->data;
13830 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
13831
13832@@ -603,6 +626,7 @@
13833 .uli_u = { .ports =
13834 { .sport = inet->sport,
13835 .dport = dport } } };
13836+ security_sk_classify_flow(sk, &fl);
13837 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
13838 if (err)
13839 goto out;
13840@@ -661,6 +685,16 @@
13841 UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS);
13842 return len;
13843 }
13844+ /*
13845+ * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space. Reporting
13846+ * ENOBUFS might not be good (it's not tunable per se), but otherwise
13847+ * we don't have a good statistic (IpOutDiscards but it can be too many
13848+ * things). We could add another new stat but at least for now that
13849+ * seems like overkill.
13850+ */
13851+ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
13852+ UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS);
13853+ }
13854 return err;
13855
13856 do_confirm:
13857@@ -980,6 +1014,7 @@
13858 static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
13859 {
13860 struct udp_sock *up = udp_sk(sk);
13861+ int rc;
13862
13863 /*
13864 * Charge it to the socket, dropping if the queue is full.
13865@@ -1026,7 +1061,10 @@
13866 skb->ip_summed = CHECKSUM_UNNECESSARY;
13867 }
13868
13869- if (sock_queue_rcv_skb(sk,skb)<0) {
13870+ if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
13871+ /* Note that an ENOMEM error is charged twice */
13872+ if (rc == -ENOMEM)
13873+ UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS);
13874 UDP_INC_STATS_BH(UDP_MIB_INERRORS);
13875 kfree_skb(skb);
13876 return -1;
13877@@ -1087,7 +1125,7 @@
13878 {
13879 if (uh->check == 0) {
13880 skb->ip_summed = CHECKSUM_UNNECESSARY;
13881- } else if (skb->ip_summed == CHECKSUM_HW) {
13882+ } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
13883 if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
13884 skb->ip_summed = CHECKSUM_UNNECESSARY;
13885 }
13886@@ -1581,7 +1619,7 @@
13887 EXPORT_SYMBOL(udp_hash);
13888 EXPORT_SYMBOL(udp_hash_lock);
13889 EXPORT_SYMBOL(udp_ioctl);
13890-EXPORT_SYMBOL(udp_port_rover);
13891+EXPORT_SYMBOL(udp_get_port);
13892 EXPORT_SYMBOL(udp_prot);
13893 EXPORT_SYMBOL(udp_sendmsg);
13894 EXPORT_SYMBOL(udp_poll);
13895diff -Nur linux-2.6.18-rc5/net/ipv4/xfrm4_input.c linux-2.6.19/net/ipv4/xfrm4_input.c
13896--- linux-2.6.18-rc5/net/ipv4/xfrm4_input.c 2006-08-28 05:41:48.000000000 +0200
13897+++ linux-2.6.19/net/ipv4/xfrm4_input.c 2006-09-22 10:04:58.000000000 +0200
13898@@ -106,7 +106,7 @@
13899 if (x->mode->input(x, skb))
13900 goto drop;
13901
13902- if (x->props.mode) {
13903+ if (x->props.mode == XFRM_MODE_TUNNEL) {
13904 decaps = 1;
13905 break;
13906 }
13907diff -Nur linux-2.6.18-rc5/net/ipv4/xfrm4_mode_transport.c linux-2.6.19/net/ipv4/xfrm4_mode_transport.c
13908--- linux-2.6.18-rc5/net/ipv4/xfrm4_mode_transport.c 2006-08-28 05:41:48.000000000 +0200
13909+++ linux-2.6.19/net/ipv4/xfrm4_mode_transport.c 2006-09-22 10:04:58.000000000 +0200
13910@@ -21,9 +21,8 @@
13911 * On exit, skb->h will be set to the start of the payload to be processed
13912 * by x->type->output and skb->nh will be set to the top IP header.
13913 */
13914-static int xfrm4_transport_output(struct sk_buff *skb)
13915+static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
13916 {
13917- struct xfrm_state *x;
13918 struct iphdr *iph;
13919 int ihl;
13920
13921@@ -33,7 +32,6 @@
13922 ihl = iph->ihl * 4;
13923 skb->h.raw += ihl;
13924
13925- x = skb->dst->xfrm;
13926 skb->nh.raw = memmove(skb_push(skb, x->props.header_len), iph, ihl);
13927 return 0;
13928 }
13929diff -Nur linux-2.6.18-rc5/net/ipv4/xfrm4_mode_tunnel.c linux-2.6.19/net/ipv4/xfrm4_mode_tunnel.c
13930--- linux-2.6.18-rc5/net/ipv4/xfrm4_mode_tunnel.c 2006-08-28 05:41:48.000000000 +0200
13931+++ linux-2.6.19/net/ipv4/xfrm4_mode_tunnel.c 2006-09-22 10:04:58.000000000 +0200
13932@@ -33,10 +33,9 @@
13933 * On exit, skb->h will be set to the start of the payload to be processed
13934 * by x->type->output and skb->nh will be set to the top IP header.
13935 */
13936-static int xfrm4_tunnel_output(struct sk_buff *skb)
13937+static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
13938 {
13939 struct dst_entry *dst = skb->dst;
13940- struct xfrm_state *x = dst->xfrm;
13941 struct iphdr *iph, *top_iph;
13942 int flags;
13943
13944diff -Nur linux-2.6.18-rc5/net/ipv4/xfrm4_output.c linux-2.6.19/net/ipv4/xfrm4_output.c
13945--- linux-2.6.18-rc5/net/ipv4/xfrm4_output.c 2006-08-28 05:41:48.000000000 +0200
13946+++ linux-2.6.19/net/ipv4/xfrm4_output.c 2006-09-22 10:04:58.000000000 +0200
13947@@ -48,13 +48,13 @@
13948 struct xfrm_state *x = dst->xfrm;
13949 int err;
13950
13951- if (skb->ip_summed == CHECKSUM_HW) {
13952- err = skb_checksum_help(skb, 0);
13953+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
13954+ err = skb_checksum_help(skb);
13955 if (err)
13956 goto error_nolock;
13957 }
13958
13959- if (x->props.mode) {
13960+ if (x->props.mode == XFRM_MODE_TUNNEL) {
13961 err = xfrm4_tunnel_check_size(skb);
13962 if (err)
13963 goto error_nolock;
13964@@ -66,7 +66,7 @@
13965 if (err)
13966 goto error;
13967
13968- err = x->mode->output(skb);
13969+ err = x->mode->output(x, skb);
13970 if (err)
13971 goto error;
13972
13973@@ -85,7 +85,7 @@
13974 }
13975 dst = skb->dst;
13976 x = dst->xfrm;
13977- } while (x && !x->props.mode);
13978+ } while (x && (x->props.mode != XFRM_MODE_TUNNEL));
13979
13980 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
13981 err = 0;
13982diff -Nur linux-2.6.18-rc5/net/ipv4/xfrm4_policy.c linux-2.6.19/net/ipv4/xfrm4_policy.c
13983--- linux-2.6.18-rc5/net/ipv4/xfrm4_policy.c 2006-08-28 05:41:48.000000000 +0200
13984+++ linux-2.6.19/net/ipv4/xfrm4_policy.c 2006-09-22 10:04:58.000000000 +0200
13985@@ -21,6 +21,25 @@
13986 return __ip_route_output_key((struct rtable**)dst, fl);
13987 }
13988
13989+static int xfrm4_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
13990+{
13991+ struct rtable *rt;
13992+ struct flowi fl_tunnel = {
13993+ .nl_u = {
13994+ .ip4_u = {
13995+ .daddr = daddr->a4,
13996+ },
13997+ },
13998+ };
13999+
14000+ if (!xfrm4_dst_lookup((struct xfrm_dst **)&rt, &fl_tunnel)) {
14001+ saddr->a4 = rt->rt_src;
14002+ dst_release(&rt->u.dst);
14003+ return 0;
14004+ }
14005+ return -EHOSTUNREACH;
14006+}
14007+
14008 static struct dst_entry *
14009 __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
14010 {
14011@@ -33,7 +52,7 @@
14012 xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
14013 xdst->u.rt.fl.fl4_src == fl->fl4_src &&
14014 xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
14015- xfrm_bundle_ok(xdst, fl, AF_INET)) {
14016+ xfrm_bundle_ok(xdst, fl, AF_INET, 0)) {
14017 dst_clone(dst);
14018 break;
14019 }
14020@@ -93,10 +112,11 @@
14021
14022 xdst = (struct xfrm_dst *)dst1;
14023 xdst->route = &rt->u.dst;
14024+ xdst->genid = xfrm[i]->genid;
14025
14026 dst1->next = dst_prev;
14027 dst_prev = dst1;
14028- if (xfrm[i]->props.mode) {
14029+ if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
14030 remote = xfrm[i]->id.daddr.a4;
14031 local = xfrm[i]->props.saddr.a4;
14032 tunnel = 1;
14033@@ -135,6 +155,7 @@
14034 dst_prev->flags |= DST_HOST;
14035 dst_prev->lastuse = jiffies;
14036 dst_prev->header_len = header_len;
14037+ dst_prev->nfheader_len = 0;
14038 dst_prev->trailer_len = trailer_len;
14039 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
14040
14041@@ -296,6 +317,7 @@
14042 .family = AF_INET,
14043 .dst_ops = &xfrm4_dst_ops,
14044 .dst_lookup = xfrm4_dst_lookup,
14045+ .get_saddr = xfrm4_get_saddr,
14046 .find_bundle = __xfrm4_find_bundle,
14047 .bundle_create = __xfrm4_bundle_create,
14048 .decode_session = _decode_session4,
14049diff -Nur linux-2.6.18-rc5/net/ipv4/xfrm4_state.c linux-2.6.19/net/ipv4/xfrm4_state.c
14050--- linux-2.6.18-rc5/net/ipv4/xfrm4_state.c 2006-08-28 05:41:48.000000000 +0200
14051+++ linux-2.6.19/net/ipv4/xfrm4_state.c 2006-09-22 10:04:58.000000000 +0200
14052@@ -42,99 +42,15 @@
14053 x->props.saddr = tmpl->saddr;
14054 if (x->props.saddr.a4 == 0)
14055 x->props.saddr.a4 = saddr->a4;
14056- if (tmpl->mode && x->props.saddr.a4 == 0) {
14057- struct rtable *rt;
14058- struct flowi fl_tunnel = {
14059- .nl_u = {
14060- .ip4_u = {
14061- .daddr = x->id.daddr.a4,
14062- }
14063- }
14064- };
14065- if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
14066- &fl_tunnel, AF_INET)) {
14067- x->props.saddr.a4 = rt->rt_src;
14068- dst_release(&rt->u.dst);
14069- }
14070- }
14071 x->props.mode = tmpl->mode;
14072 x->props.reqid = tmpl->reqid;
14073 x->props.family = AF_INET;
14074 }
14075
14076-static struct xfrm_state *
14077-__xfrm4_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
14078-{
14079- unsigned h = __xfrm4_spi_hash(daddr, spi, proto);
14080- struct xfrm_state *x;
14081-
14082- list_for_each_entry(x, xfrm4_state_afinfo.state_byspi+h, byspi) {
14083- if (x->props.family == AF_INET &&
14084- spi == x->id.spi &&
14085- daddr->a4 == x->id.daddr.a4 &&
14086- proto == x->id.proto) {
14087- xfrm_state_hold(x);
14088- return x;
14089- }
14090- }
14091- return NULL;
14092-}
14093-
14094-static struct xfrm_state *
14095-__xfrm4_find_acq(u8 mode, u32 reqid, u8 proto,
14096- xfrm_address_t *daddr, xfrm_address_t *saddr,
14097- int create)
14098-{
14099- struct xfrm_state *x, *x0;
14100- unsigned h = __xfrm4_dst_hash(daddr);
14101-
14102- x0 = NULL;
14103-
14104- list_for_each_entry(x, xfrm4_state_afinfo.state_bydst+h, bydst) {
14105- if (x->props.family == AF_INET &&
14106- daddr->a4 == x->id.daddr.a4 &&
14107- mode == x->props.mode &&
14108- proto == x->id.proto &&
14109- saddr->a4 == x->props.saddr.a4 &&
14110- reqid == x->props.reqid &&
14111- x->km.state == XFRM_STATE_ACQ &&
14112- !x->id.spi) {
14113- x0 = x;
14114- break;
14115- }
14116- }
14117- if (!x0 && create && (x0 = xfrm_state_alloc()) != NULL) {
14118- x0->sel.daddr.a4 = daddr->a4;
14119- x0->sel.saddr.a4 = saddr->a4;
14120- x0->sel.prefixlen_d = 32;
14121- x0->sel.prefixlen_s = 32;
14122- x0->props.saddr.a4 = saddr->a4;
14123- x0->km.state = XFRM_STATE_ACQ;
14124- x0->id.daddr.a4 = daddr->a4;
14125- x0->id.proto = proto;
14126- x0->props.family = AF_INET;
14127- x0->props.mode = mode;
14128- x0->props.reqid = reqid;
14129- x0->props.family = AF_INET;
14130- x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
14131- xfrm_state_hold(x0);
14132- x0->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
14133- add_timer(&x0->timer);
14134- xfrm_state_hold(x0);
14135- list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h);
14136- wake_up(&km_waitq);
14137- }
14138- if (x0)
14139- xfrm_state_hold(x0);
14140- return x0;
14141-}
14142-
14143 static struct xfrm_state_afinfo xfrm4_state_afinfo = {
14144 .family = AF_INET,
14145 .init_flags = xfrm4_init_flags,
14146 .init_tempsel = __xfrm4_init_tempsel,
14147- .state_lookup = __xfrm4_state_lookup,
14148- .find_acq = __xfrm4_find_acq,
14149 };
14150
14151 void __init xfrm4_state_init(void)
14152diff -Nur linux-2.6.18-rc5/net/ipv4/xfrm4_tunnel.c linux-2.6.19/net/ipv4/xfrm4_tunnel.c
14153--- linux-2.6.18-rc5/net/ipv4/xfrm4_tunnel.c 2006-08-28 05:41:48.000000000 +0200
14154+++ linux-2.6.19/net/ipv4/xfrm4_tunnel.c 2006-09-22 10:04:58.000000000 +0200
14155@@ -28,7 +28,7 @@
14156
14157 static int ipip_init_state(struct xfrm_state *x)
14158 {
14159- if (!x->props.mode)
14160+ if (x->props.mode != XFRM_MODE_TUNNEL)
14161 return -EINVAL;
14162
14163 if (x->encap)
14164diff -Nur linux-2.6.18-rc5/net/ipv6/Kconfig linux-2.6.19/net/ipv6/Kconfig
14165--- linux-2.6.18-rc5/net/ipv6/Kconfig 2006-08-28 05:41:48.000000000 +0200
14166+++ linux-2.6.19/net/ipv6/Kconfig 2006-09-22 10:04:58.000000000 +0200
14167@@ -97,6 +97,15 @@
14168
14169 If unsure, say Y.
14170
14171+config IPV6_MIP6
14172+ bool "IPv6: Mobility (EXPERIMENTAL)"
14173+ depends on IPV6 && EXPERIMENTAL
14174+ select XFRM
14175+ ---help---
14176+ Support for IPv6 Mobility described in RFC 3775.
14177+
14178+ If unsure, say N.
14179+
14180 config INET6_XFRM_TUNNEL
14181 tristate
14182 select INET6_TUNNEL
14183@@ -126,6 +135,13 @@
14184
14185 If unsure, say Y.
14186
14187+config INET6_XFRM_MODE_ROUTEOPTIMIZATION
14188+ tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)"
14189+ depends on IPV6 && EXPERIMENTAL
14190+ select XFRM
14191+ ---help---
14192+ Support for MIPv6 route optimization mode.
14193+
14194 config IPV6_TUNNEL
14195 tristate "IPv6: IPv6-in-IPv6 tunnel"
14196 select INET6_TUNNEL
14197@@ -135,3 +151,31 @@
14198
14199 If unsure, say N.
14200
14201+config IPV6_SUBTREES
14202+ bool "IPv6: source address based routing"
14203+ depends on IPV6 && EXPERIMENTAL
14204+ ---help---
14205+ Enable routing by source address or prefix.
14206+
14207+ The destination address is still the primary routing key, so mixing
14208+ normal and source prefix specific routes in the same routing table
14209+ may sometimes lead to unintended routing behavior. This can be
14210+ avoided by defining different routing tables for the normal and
14211+ source prefix specific routes.
14212+
14213+ If unsure, say N.
14214+
14215+config IPV6_MULTIPLE_TABLES
14216+ bool "IPv6: Multiple Routing Tables"
14217+ depends on IPV6 && EXPERIMENTAL
14218+ select FIB_RULES
14219+ ---help---
14220+ Support multiple routing tables.
14221+
14222+config IPV6_ROUTE_FWMARK
14223+ bool "IPv6: use netfilter MARK value as routing key"
14224+ depends on IPV6_MULTIPLE_TABLES && NETFILTER
14225+ ---help---
14226+ If you say Y here, you will be able to specify different routes for
14227+ packets with different mark values (see iptables(8), MARK target).
14228+
14229diff -Nur linux-2.6.18-rc5/net/ipv6/Makefile linux-2.6.19/net/ipv6/Makefile
14230--- linux-2.6.18-rc5/net/ipv6/Makefile 2006-08-28 05:41:48.000000000 +0200
14231+++ linux-2.6.19/net/ipv6/Makefile 2006-09-22 10:04:58.000000000 +0200
14232@@ -13,6 +13,9 @@
14233 ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
14234 xfrm6_output.o
14235 ipv6-$(CONFIG_NETFILTER) += netfilter.o
14236+ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
14237+ipv6-$(CONFIG_IPV6_MIP6) += mip6.o
14238+
14239 ipv6-objs += $(ipv6-y)
14240
14241 obj-$(CONFIG_INET6_AH) += ah6.o
14242@@ -22,6 +25,7 @@
14243 obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
14244 obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
14245 obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
14246+obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
14247 obj-$(CONFIG_NETFILTER) += netfilter/
14248
14249 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
14250diff -Nur linux-2.6.18-rc5/net/ipv6/addrconf.c linux-2.6.19/net/ipv6/addrconf.c
14251--- linux-2.6.18-rc5/net/ipv6/addrconf.c 2006-08-28 05:41:48.000000000 +0200
14252+++ linux-2.6.19/net/ipv6/addrconf.c 2006-09-22 10:04:58.000000000 +0200
14253@@ -48,6 +48,7 @@
14254 #include <linux/net.h>
14255 #include <linux/in6.h>
14256 #include <linux/netdevice.h>
14257+#include <linux/if_addr.h>
14258 #include <linux/if_arp.h>
14259 #include <linux/if_arcnet.h>
14260 #include <linux/if_infiniband.h>
14261@@ -72,6 +73,7 @@
14262 #include <net/addrconf.h>
14263 #include <net/tcp.h>
14264 #include <net/ip.h>
14265+#include <net/netlink.h>
14266 #include <linux/if_tunnel.h>
14267 #include <linux/rtnetlink.h>
14268
14269@@ -144,7 +146,7 @@
14270
14271 static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
14272
14273-struct ipv6_devconf ipv6_devconf = {
14274+struct ipv6_devconf ipv6_devconf __read_mostly = {
14275 .forwarding = 0,
14276 .hop_limit = IPV6_DEFAULT_HOPLIMIT,
14277 .mtu6 = IPV6_MIN_MTU,
14278@@ -175,7 +177,7 @@
14279 #endif
14280 };
14281
14282-static struct ipv6_devconf ipv6_devconf_dflt = {
14283+static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
14284 .forwarding = 0,
14285 .hop_limit = IPV6_DEFAULT_HOPLIMIT,
14286 .mtu6 = IPV6_MIN_MTU,
14287@@ -578,6 +580,8 @@
14288 ifa->flags = flags | IFA_F_TENTATIVE;
14289 ifa->cstamp = ifa->tstamp = jiffies;
14290
14291+ ifa->rt = rt;
14292+
14293 ifa->idev = idev;
14294 in6_dev_hold(idev);
14295 /* For caller */
14296@@ -734,7 +736,7 @@
14297
14298 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
14299 if (onlink == 0) {
14300- ip6_del_rt(rt, NULL, NULL, NULL);
14301+ ip6_del_rt(rt);
14302 rt = NULL;
14303 } else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
14304 rt->rt6i_expires = expires;
14305@@ -1507,59 +1509,56 @@
14306 addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
14307 unsigned long expires, u32 flags)
14308 {
14309- struct in6_rtmsg rtmsg;
14310+ struct fib6_config cfg = {
14311+ .fc_table = RT6_TABLE_PREFIX,
14312+ .fc_metric = IP6_RT_PRIO_ADDRCONF,
14313+ .fc_ifindex = dev->ifindex,
14314+ .fc_expires = expires,
14315+ .fc_dst_len = plen,
14316+ .fc_flags = RTF_UP | flags,
14317+ };
14318
14319- memset(&rtmsg, 0, sizeof(rtmsg));
14320- ipv6_addr_copy(&rtmsg.rtmsg_dst, pfx);
14321- rtmsg.rtmsg_dst_len = plen;
14322- rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
14323- rtmsg.rtmsg_ifindex = dev->ifindex;
14324- rtmsg.rtmsg_info = expires;
14325- rtmsg.rtmsg_flags = RTF_UP|flags;
14326- rtmsg.rtmsg_type = RTMSG_NEWROUTE;
14327+ ipv6_addr_copy(&cfg.fc_dst, pfx);
14328
14329 /* Prevent useless cloning on PtP SIT.
14330 This thing is done here expecting that the whole
14331 class of non-broadcast devices need not cloning.
14332 */
14333- if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
14334- rtmsg.rtmsg_flags |= RTF_NONEXTHOP;
14335+ if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
14336+ cfg.fc_flags |= RTF_NONEXTHOP;
14337
14338- ip6_route_add(&rtmsg, NULL, NULL, NULL);
14339+ ip6_route_add(&cfg);
14340 }
14341
14342 /* Create "default" multicast route to the interface */
14343
14344 static void addrconf_add_mroute(struct net_device *dev)
14345 {
14346- struct in6_rtmsg rtmsg;
14347+ struct fib6_config cfg = {
14348+ .fc_table = RT6_TABLE_LOCAL,
14349+ .fc_metric = IP6_RT_PRIO_ADDRCONF,
14350+ .fc_ifindex = dev->ifindex,
14351+ .fc_dst_len = 8,
14352+ .fc_flags = RTF_UP,
14353+ };
14354+
14355+ ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
14356
14357- memset(&rtmsg, 0, sizeof(rtmsg));
14358- ipv6_addr_set(&rtmsg.rtmsg_dst,
14359- htonl(0xFF000000), 0, 0, 0);
14360- rtmsg.rtmsg_dst_len = 8;
14361- rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
14362- rtmsg.rtmsg_ifindex = dev->ifindex;
14363- rtmsg.rtmsg_flags = RTF_UP;
14364- rtmsg.rtmsg_type = RTMSG_NEWROUTE;
14365- ip6_route_add(&rtmsg, NULL, NULL, NULL);
14366+ ip6_route_add(&cfg);
14367 }
14368
14369 static void sit_route_add(struct net_device *dev)
14370 {
14371- struct in6_rtmsg rtmsg;
14372-
14373- memset(&rtmsg, 0, sizeof(rtmsg));
14374-
14375- rtmsg.rtmsg_type = RTMSG_NEWROUTE;
14376- rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
14377+ struct fib6_config cfg = {
14378+ .fc_table = RT6_TABLE_MAIN,
14379+ .fc_metric = IP6_RT_PRIO_ADDRCONF,
14380+ .fc_ifindex = dev->ifindex,
14381+ .fc_dst_len = 96,
14382+ .fc_flags = RTF_UP | RTF_NONEXTHOP,
14383+ };
14384
14385 /* prefix length - 96 bits "::d.d.d.d" */
14386- rtmsg.rtmsg_dst_len = 96;
14387- rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP;
14388- rtmsg.rtmsg_ifindex = dev->ifindex;
14389-
14390- ip6_route_add(&rtmsg, NULL, NULL, NULL);
14391+ ip6_route_add(&cfg);
14392 }
14393
14394 static void addrconf_add_lroute(struct net_device *dev)
14395@@ -1660,7 +1659,7 @@
14396 if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
14397 if (rt->rt6i_flags&RTF_EXPIRES) {
14398 if (valid_lft == 0) {
14399- ip6_del_rt(rt, NULL, NULL, NULL);
14400+ ip6_del_rt(rt);
14401 rt = NULL;
14402 } else {
14403 rt->rt6i_expires = jiffies + rt_expires;
14404@@ -1887,9 +1886,6 @@
14405 if ((dev = __dev_get_by_index(ifindex)) == NULL)
14406 return -ENODEV;
14407
14408- if (!(dev->flags&IFF_UP))
14409- return -ENETDOWN;
14410-
14411 if ((idev = addrconf_add_dev(dev)) == NULL)
14412 return -ENOBUFS;
14413
14414@@ -2869,52 +2865,57 @@
14415 spin_unlock_bh(&addrconf_verify_lock);
14416 }
14417
14418+static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
14419+{
14420+ struct in6_addr *pfx = NULL;
14421+
14422+ if (addr)
14423+ pfx = nla_data(addr);
14424+
14425+ if (local) {
14426+ if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
14427+ pfx = NULL;
14428+ else
14429+ pfx = nla_data(local);
14430+ }
14431+
14432+ return pfx;
14433+}
14434+
14435+static struct nla_policy ifa_ipv6_policy[IFA_MAX+1] __read_mostly = {
14436+ [IFA_ADDRESS] = { .len = sizeof(struct in6_addr) },
14437+ [IFA_LOCAL] = { .len = sizeof(struct in6_addr) },
14438+ [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },
14439+};
14440+
14441 static int
14442 inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
14443 {
14444- struct rtattr **rta = arg;
14445- struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
14446+ struct ifaddrmsg *ifm;
14447+ struct nlattr *tb[IFA_MAX+1];
14448 struct in6_addr *pfx;
14449+ int err;
14450
14451- pfx = NULL;
14452- if (rta[IFA_ADDRESS-1]) {
14453- if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx))
14454- return -EINVAL;
14455- pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
14456- }
14457- if (rta[IFA_LOCAL-1]) {
14458- if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
14459- (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
14460- return -EINVAL;
14461- pfx = RTA_DATA(rta[IFA_LOCAL-1]);
14462- }
14463+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
14464+ if (err < 0)
14465+ return err;
14466+
14467+ ifm = nlmsg_data(nlh);
14468+ pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
14469 if (pfx == NULL)
14470 return -EINVAL;
14471
14472 return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
14473 }
14474
14475-static int
14476-inet6_addr_modify(int ifindex, struct in6_addr *pfx,
14477- __u32 prefered_lft, __u32 valid_lft)
14478+static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 prefered_lft,
14479+ u32 valid_lft)
14480 {
14481- struct inet6_ifaddr *ifp = NULL;
14482- struct net_device *dev;
14483 int ifa_flags = 0;
14484
14485- if ((dev = __dev_get_by_index(ifindex)) == NULL)
14486- return -ENODEV;
14487-
14488- if (!(dev->flags&IFF_UP))
14489- return -ENETDOWN;
14490-
14491 if (!valid_lft || (prefered_lft > valid_lft))
14492 return -EINVAL;
14493
14494- ifp = ipv6_get_ifaddr(pfx, dev, 1);
14495- if (ifp == NULL)
14496- return -ENOENT;
14497-
14498 if (valid_lft == INFINITY_LIFE_TIME)
14499 ifa_flags = IFA_F_PERMANENT;
14500 else if (valid_lft >= 0x7FFFFFFF/HZ)
14501@@ -2936,7 +2937,6 @@
14502 spin_unlock_bh(&ifp->lock);
14503 if (!(ifp->flags&IFA_F_TENTATIVE))
14504 ipv6_ifa_notify(0, ifp);
14505- in6_ifa_put(ifp);
14506
14507 addrconf_verify(0);
14508
14509@@ -2946,172 +2946,185 @@
14510 static int
14511 inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
14512 {
14513- struct rtattr **rta = arg;
14514- struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
14515+ struct ifaddrmsg *ifm;
14516+ struct nlattr *tb[IFA_MAX+1];
14517 struct in6_addr *pfx;
14518- __u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME;
14519+ struct inet6_ifaddr *ifa;
14520+ struct net_device *dev;
14521+ u32 valid_lft, preferred_lft;
14522+ int err;
14523
14524- pfx = NULL;
14525- if (rta[IFA_ADDRESS-1]) {
14526- if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx))
14527- return -EINVAL;
14528- pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
14529- }
14530- if (rta[IFA_LOCAL-1]) {
14531- if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
14532- (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
14533- return -EINVAL;
14534- pfx = RTA_DATA(rta[IFA_LOCAL-1]);
14535- }
14536+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
14537+ if (err < 0)
14538+ return err;
14539+
14540+ ifm = nlmsg_data(nlh);
14541+ pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
14542 if (pfx == NULL)
14543 return -EINVAL;
14544
14545- if (rta[IFA_CACHEINFO-1]) {
14546+ if (tb[IFA_CACHEINFO]) {
14547 struct ifa_cacheinfo *ci;
14548- if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci))
14549- return -EINVAL;
14550- ci = RTA_DATA(rta[IFA_CACHEINFO-1]);
14551+
14552+ ci = nla_data(tb[IFA_CACHEINFO]);
14553 valid_lft = ci->ifa_valid;
14554- prefered_lft = ci->ifa_prefered;
14555+ preferred_lft = ci->ifa_prefered;
14556+ } else {
14557+ preferred_lft = INFINITY_LIFE_TIME;
14558+ valid_lft = INFINITY_LIFE_TIME;
14559 }
14560
14561- if (nlh->nlmsg_flags & NLM_F_REPLACE) {
14562- int ret;
14563- ret = inet6_addr_modify(ifm->ifa_index, pfx,
14564- prefered_lft, valid_lft);
14565- if (ret == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE))
14566- return ret;
14567+ dev = __dev_get_by_index(ifm->ifa_index);
14568+ if (dev == NULL)
14569+ return -ENODEV;
14570+
14571+ ifa = ipv6_get_ifaddr(pfx, dev, 1);
14572+ if (ifa == NULL) {
14573+ /*
14574+ * It would be best to check for !NLM_F_CREATE here but
14575+ * userspace alreay relies on not having to provide this.
14576+ */
14577+ return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
14578+ preferred_lft, valid_lft);
14579 }
14580
14581- return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
14582- prefered_lft, valid_lft);
14583+ if (nlh->nlmsg_flags & NLM_F_EXCL ||
14584+ !(nlh->nlmsg_flags & NLM_F_REPLACE))
14585+ err = -EEXIST;
14586+ else
14587+ err = inet6_addr_modify(ifa, preferred_lft, valid_lft);
14588+
14589+ in6_ifa_put(ifa);
14590+
14591+ return err;
14592+}
14593+
14594+static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags,
14595+ u8 scope, int ifindex)
14596+{
14597+ struct ifaddrmsg *ifm;
14598
14599+ ifm = nlmsg_data(nlh);
14600+ ifm->ifa_family = AF_INET6;
14601+ ifm->ifa_prefixlen = prefixlen;
14602+ ifm->ifa_flags = flags;
14603+ ifm->ifa_scope = scope;
14604+ ifm->ifa_index = ifindex;
14605 }
14606
14607-/* Maximum length of ifa_cacheinfo attributes */
14608-#define INET6_IFADDR_RTA_SPACE \
14609- RTA_SPACE(16) /* IFA_ADDRESS */ + \
14610- RTA_SPACE(sizeof(struct ifa_cacheinfo)) /* CACHEINFO */
14611+static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
14612+ unsigned long tstamp, u32 preferred, u32 valid)
14613+{
14614+ struct ifa_cacheinfo ci;
14615+
14616+ ci.cstamp = (u32)(TIME_DELTA(cstamp, INITIAL_JIFFIES) / HZ * 100
14617+ + TIME_DELTA(cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
14618+ ci.tstamp = (u32)(TIME_DELTA(tstamp, INITIAL_JIFFIES) / HZ * 100
14619+ + TIME_DELTA(tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
14620+ ci.ifa_prefered = preferred;
14621+ ci.ifa_valid = valid;
14622+
14623+ return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci);
14624+}
14625+
14626+static inline int rt_scope(int ifa_scope)
14627+{
14628+ if (ifa_scope & IFA_HOST)
14629+ return RT_SCOPE_HOST;
14630+ else if (ifa_scope & IFA_LINK)
14631+ return RT_SCOPE_LINK;
14632+ else if (ifa_scope & IFA_SITE)
14633+ return RT_SCOPE_SITE;
14634+ else
14635+ return RT_SCOPE_UNIVERSE;
14636+}
14637+
14638+static inline int inet6_ifaddr_msgsize(void)
14639+{
14640+ return nlmsg_total_size(sizeof(struct ifaddrmsg) +
14641+ nla_total_size(16) +
14642+ nla_total_size(sizeof(struct ifa_cacheinfo)) +
14643+ 128);
14644+}
14645
14646 static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
14647 u32 pid, u32 seq, int event, unsigned int flags)
14648 {
14649- struct ifaddrmsg *ifm;
14650 struct nlmsghdr *nlh;
14651- struct ifa_cacheinfo ci;
14652- unsigned char *b = skb->tail;
14653+ u32 preferred, valid;
14654+
14655+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
14656+ if (nlh == NULL)
14657+ return -ENOBUFS;
14658+
14659+ put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
14660+ ifa->idev->dev->ifindex);
14661
14662- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
14663- ifm = NLMSG_DATA(nlh);
14664- ifm->ifa_family = AF_INET6;
14665- ifm->ifa_prefixlen = ifa->prefix_len;
14666- ifm->ifa_flags = ifa->flags;
14667- ifm->ifa_scope = RT_SCOPE_UNIVERSE;
14668- if (ifa->scope&IFA_HOST)
14669- ifm->ifa_scope = RT_SCOPE_HOST;
14670- else if (ifa->scope&IFA_LINK)
14671- ifm->ifa_scope = RT_SCOPE_LINK;
14672- else if (ifa->scope&IFA_SITE)
14673- ifm->ifa_scope = RT_SCOPE_SITE;
14674- ifm->ifa_index = ifa->idev->dev->ifindex;
14675- RTA_PUT(skb, IFA_ADDRESS, 16, &ifa->addr);
14676 if (!(ifa->flags&IFA_F_PERMANENT)) {
14677- ci.ifa_prefered = ifa->prefered_lft;
14678- ci.ifa_valid = ifa->valid_lft;
14679- if (ci.ifa_prefered != INFINITY_LIFE_TIME) {
14680+ preferred = ifa->prefered_lft;
14681+ valid = ifa->valid_lft;
14682+ if (preferred != INFINITY_LIFE_TIME) {
14683 long tval = (jiffies - ifa->tstamp)/HZ;
14684- ci.ifa_prefered -= tval;
14685- if (ci.ifa_valid != INFINITY_LIFE_TIME)
14686- ci.ifa_valid -= tval;
14687+ preferred -= tval;
14688+ if (valid != INFINITY_LIFE_TIME)
14689+ valid -= tval;
14690 }
14691 } else {
14692- ci.ifa_prefered = INFINITY_LIFE_TIME;
14693- ci.ifa_valid = INFINITY_LIFE_TIME;
14694+ preferred = INFINITY_LIFE_TIME;
14695+ valid = INFINITY_LIFE_TIME;
14696 }
14697- ci.cstamp = (__u32)(TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) / HZ * 100
14698- + TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
14699- ci.tstamp = (__u32)(TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) / HZ * 100
14700- + TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
14701- RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
14702- nlh->nlmsg_len = skb->tail - b;
14703- return skb->len;
14704
14705-nlmsg_failure:
14706-rtattr_failure:
14707- skb_trim(skb, b - skb->data);
14708- return -1;
14709+ if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 ||
14710+ put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
14711+ return nlmsg_cancel(skb, nlh);
14712+
14713+ return nlmsg_end(skb, nlh);
14714 }
14715
14716 static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
14717 u32 pid, u32 seq, int event, u16 flags)
14718 {
14719- struct ifaddrmsg *ifm;
14720 struct nlmsghdr *nlh;
14721- struct ifa_cacheinfo ci;
14722- unsigned char *b = skb->tail;
14723+ u8 scope = RT_SCOPE_UNIVERSE;
14724+ int ifindex = ifmca->idev->dev->ifindex;
14725
14726- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
14727- ifm = NLMSG_DATA(nlh);
14728- ifm->ifa_family = AF_INET6;
14729- ifm->ifa_prefixlen = 128;
14730- ifm->ifa_flags = IFA_F_PERMANENT;
14731- ifm->ifa_scope = RT_SCOPE_UNIVERSE;
14732- if (ipv6_addr_scope(&ifmca->mca_addr)&IFA_SITE)
14733- ifm->ifa_scope = RT_SCOPE_SITE;
14734- ifm->ifa_index = ifmca->idev->dev->ifindex;
14735- RTA_PUT(skb, IFA_MULTICAST, 16, &ifmca->mca_addr);
14736- ci.cstamp = (__u32)(TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) / HZ
14737- * 100 + TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) % HZ
14738- * 100 / HZ);
14739- ci.tstamp = (__u32)(TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) / HZ
14740- * 100 + TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) % HZ
14741- * 100 / HZ);
14742- ci.ifa_prefered = INFINITY_LIFE_TIME;
14743- ci.ifa_valid = INFINITY_LIFE_TIME;
14744- RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
14745- nlh->nlmsg_len = skb->tail - b;
14746- return skb->len;
14747+ if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
14748+ scope = RT_SCOPE_SITE;
14749
14750-nlmsg_failure:
14751-rtattr_failure:
14752- skb_trim(skb, b - skb->data);
14753- return -1;
14754+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
14755+ if (nlh == NULL)
14756+ return -ENOBUFS;
14757+
14758+ put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
14759+ if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 ||
14760+ put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
14761+ INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
14762+ return nlmsg_cancel(skb, nlh);
14763+
14764+ return nlmsg_end(skb, nlh);
14765 }
14766
14767 static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
14768 u32 pid, u32 seq, int event, unsigned int flags)
14769 {
14770- struct ifaddrmsg *ifm;
14771 struct nlmsghdr *nlh;
14772- struct ifa_cacheinfo ci;
14773- unsigned char *b = skb->tail;
14774+ u8 scope = RT_SCOPE_UNIVERSE;
14775+ int ifindex = ifaca->aca_idev->dev->ifindex;
14776
14777- nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
14778- ifm = NLMSG_DATA(nlh);
14779- ifm->ifa_family = AF_INET6;
14780- ifm->ifa_prefixlen = 128;
14781- ifm->ifa_flags = IFA_F_PERMANENT;
14782- ifm->ifa_scope = RT_SCOPE_UNIVERSE;
14783- if (ipv6_addr_scope(&ifaca->aca_addr)&IFA_SITE)
14784- ifm->ifa_scope = RT_SCOPE_SITE;
14785- ifm->ifa_index = ifaca->aca_idev->dev->ifindex;
14786- RTA_PUT(skb, IFA_ANYCAST, 16, &ifaca->aca_addr);
14787- ci.cstamp = (__u32)(TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) / HZ
14788- * 100 + TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) % HZ
14789- * 100 / HZ);
14790- ci.tstamp = (__u32)(TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) / HZ
14791- * 100 + TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) % HZ
14792- * 100 / HZ);
14793- ci.ifa_prefered = INFINITY_LIFE_TIME;
14794- ci.ifa_valid = INFINITY_LIFE_TIME;
14795- RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
14796- nlh->nlmsg_len = skb->tail - b;
14797- return skb->len;
14798+ if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE)
14799+ scope = RT_SCOPE_SITE;
14800
14801-nlmsg_failure:
14802-rtattr_failure:
14803- skb_trim(skb, b - skb->data);
14804- return -1;
14805+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
14806+ if (nlh == NULL)
14807+ return -ENOBUFS;
14808+
14809+ put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
14810+ if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 ||
14811+ put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
14812+ INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
14813+ return nlmsg_cancel(skb, nlh);
14814+
14815+ return nlmsg_end(skb, nlh);
14816 }
14817
14818 enum addr_type_t
14819@@ -3222,79 +3235,74 @@
14820 return inet6_dump_addr(skb, cb, type);
14821 }
14822
14823-static int inet6_rtm_getaddr(struct sk_buff *in_skb,
14824- struct nlmsghdr* nlh, void *arg)
14825+static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
14826+ void *arg)
14827 {
14828- struct rtattr **rta = arg;
14829- struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
14830+ struct ifaddrmsg *ifm;
14831+ struct nlattr *tb[IFA_MAX+1];
14832 struct in6_addr *addr = NULL;
14833 struct net_device *dev = NULL;
14834 struct inet6_ifaddr *ifa;
14835 struct sk_buff *skb;
14836- int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
14837 int err;
14838
14839- if (rta[IFA_ADDRESS-1]) {
14840- if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*addr))
14841- return -EINVAL;
14842- addr = RTA_DATA(rta[IFA_ADDRESS-1]);
14843- }
14844- if (rta[IFA_LOCAL-1]) {
14845- if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*addr) ||
14846- (addr && memcmp(addr, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*addr))))
14847- return -EINVAL;
14848- addr = RTA_DATA(rta[IFA_LOCAL-1]);
14849+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
14850+ if (err < 0)
14851+ goto errout;
14852+
14853+ addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
14854+ if (addr == NULL) {
14855+ err = -EINVAL;
14856+ goto errout;
14857 }
14858- if (addr == NULL)
14859- return -EINVAL;
14860
14861+ ifm = nlmsg_data(nlh);
14862 if (ifm->ifa_index)
14863 dev = __dev_get_by_index(ifm->ifa_index);
14864
14865- if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL)
14866- return -EADDRNOTAVAIL;
14867+ if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) {
14868+ err = -EADDRNOTAVAIL;
14869+ goto errout;
14870+ }
14871
14872- if ((skb = alloc_skb(size, GFP_KERNEL)) == NULL) {
14873+ if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) {
14874 err = -ENOBUFS;
14875- goto out;
14876+ goto errout_ifa;
14877 }
14878
14879- NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
14880 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
14881 nlh->nlmsg_seq, RTM_NEWADDR, 0);
14882 if (err < 0) {
14883- err = -EMSGSIZE;
14884- goto out_free;
14885+ kfree_skb(skb);
14886+ goto errout_ifa;
14887 }
14888
14889- err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
14890- if (err > 0)
14891- err = 0;
14892-out:
14893+ err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
14894+errout_ifa:
14895 in6_ifa_put(ifa);
14896+errout:
14897 return err;
14898-out_free:
14899- kfree_skb(skb);
14900- goto out;
14901 }
14902
14903 static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
14904 {
14905 struct sk_buff *skb;
14906- int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
14907+ int err = -ENOBUFS;
14908
14909- skb = alloc_skb(size, GFP_ATOMIC);
14910- if (!skb) {
14911- netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, ENOBUFS);
14912- return;
14913- }
14914- if (inet6_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) {
14915+ skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC);
14916+ if (skb == NULL)
14917+ goto errout;
14918+
14919+ err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
14920+ if (err < 0) {
14921 kfree_skb(skb);
14922- netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, EINVAL);
14923- return;
14924+ goto errout;
14925 }
14926- NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFADDR;
14927- netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFADDR, GFP_ATOMIC);
14928+
14929+ err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
14930+errout:
14931+ if (err < 0)
14932+ rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
14933 }
14934
14935 static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
14936@@ -3435,20 +3443,23 @@
14937 void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
14938 {
14939 struct sk_buff *skb;
14940- int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE);
14941+ int payload = sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE;
14942+ int err = -ENOBUFS;
14943
14944- skb = alloc_skb(size, GFP_ATOMIC);
14945- if (!skb) {
14946- netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, ENOBUFS);
14947- return;
14948- }
14949- if (inet6_fill_ifinfo(skb, idev, current->pid, 0, event, 0) < 0) {
14950+ skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
14951+ if (skb == NULL)
14952+ goto errout;
14953+
14954+ err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
14955+ if (err < 0) {
14956 kfree_skb(skb);
14957- netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, EINVAL);
14958- return;
14959+ goto errout;
14960 }
14961- NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFINFO;
14962- netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC);
14963+
14964+ err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
14965+errout:
14966+ if (err < 0)
14967+ rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
14968 }
14969
14970 /* Maximum length of prefix_cacheinfo attributes */
14971@@ -3500,20 +3511,23 @@
14972 struct prefix_info *pinfo)
14973 {
14974 struct sk_buff *skb;
14975- int size = NLMSG_SPACE(sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE);
14976+ int payload = sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE;
14977+ int err = -ENOBUFS;
14978
14979- skb = alloc_skb(size, GFP_ATOMIC);
14980- if (!skb) {
14981- netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, ENOBUFS);
14982- return;
14983- }
14984- if (inet6_fill_prefix(skb, idev, pinfo, current->pid, 0, event, 0) < 0) {
14985+ skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
14986+ if (skb == NULL)
14987+ goto errout;
14988+
14989+ err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
14990+ if (err < 0) {
14991 kfree_skb(skb);
14992- netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, EINVAL);
14993- return;
14994+ goto errout;
14995 }
14996- NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_PREFIX;
14997- netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_PREFIX, GFP_ATOMIC);
14998+
14999+ err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
15000+errout:
15001+ if (err < 0)
15002+ rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err);
15003 }
15004
15005 static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = {
15006@@ -3528,6 +3542,9 @@
15007 [RTM_DELROUTE - RTM_BASE] = { .doit = inet6_rtm_delroute, },
15008 [RTM_GETROUTE - RTM_BASE] = { .doit = inet6_rtm_getroute,
15009 .dumpit = inet6_dump_fib, },
15010+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
15011+ [RTM_GETRULE - RTM_BASE] = { .dumpit = fib6_rules_dump, },
15012+#endif
15013 };
15014
15015 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
15016@@ -3536,7 +3553,7 @@
15017
15018 switch (event) {
15019 case RTM_NEWADDR:
15020- ip6_ins_rt(ifp->rt, NULL, NULL, NULL);
15021+ ip6_ins_rt(ifp->rt);
15022 if (ifp->idev->cnf.forwarding)
15023 addrconf_join_anycast(ifp);
15024 break;
15025@@ -3545,7 +3562,7 @@
15026 addrconf_leave_anycast(ifp);
15027 addrconf_leave_solict(ifp->idev, &ifp->addr);
15028 dst_hold(&ifp->rt->u.dst);
15029- if (ip6_del_rt(ifp->rt, NULL, NULL, NULL))
15030+ if (ip6_del_rt(ifp->rt))
15031 dst_free(&ifp->rt->u.dst);
15032 break;
15033 }
15034@@ -3653,7 +3670,7 @@
15035 ctl_table addrconf_conf_dir[2];
15036 ctl_table addrconf_proto_dir[2];
15037 ctl_table addrconf_root_dir[2];
15038-} addrconf_sysctl = {
15039+} addrconf_sysctl __read_mostly = {
15040 .sysctl_header = NULL,
15041 .addrconf_vars = {
15042 {
15043diff -Nur linux-2.6.18-rc5/net/ipv6/af_inet6.c linux-2.6.19/net/ipv6/af_inet6.c
15044--- linux-2.6.18-rc5/net/ipv6/af_inet6.c 2006-08-28 05:41:48.000000000 +0200
15045+++ linux-2.6.19/net/ipv6/af_inet6.c 2006-09-22 10:04:58.000000000 +0200
15046@@ -59,6 +59,9 @@
15047 #ifdef CONFIG_IPV6_TUNNEL
15048 #include <net/ip6_tunnel.h>
15049 #endif
15050+#ifdef CONFIG_IPV6_MIP6
15051+#include <net/mip6.h>
15052+#endif
15053
15054 #include <asm/uaccess.h>
15055 #include <asm/system.h>
15056@@ -67,7 +70,7 @@
15057 MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
15058 MODULE_LICENSE("GPL");
15059
15060-int sysctl_ipv6_bindv6only;
15061+int sysctl_ipv6_bindv6only __read_mostly;
15062
15063 /* The inetsw table contains everything that inet_create needs to
15064 * build a new socket.
15065@@ -637,6 +640,7 @@
15066 fl.oif = sk->sk_bound_dev_if;
15067 fl.fl_ip_dport = inet->dport;
15068 fl.fl_ip_sport = inet->sport;
15069+ security_sk_classify_flow(sk, &fl);
15070
15071 if (np->opt && np->opt->srcrt) {
15072 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
15073@@ -658,7 +662,7 @@
15074 return err;
15075 }
15076
15077- __ip6_dst_store(sk, dst, NULL);
15078+ __ip6_dst_store(sk, dst, NULL, NULL);
15079 }
15080
15081 return 0;
15082@@ -757,6 +761,8 @@
15083 struct list_head *r;
15084 int err;
15085
15086+ BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb));
15087+
15088 #ifdef MODULE
15089 #if 0 /* FIXME --RR */
15090 if (!mod_member_present(&__this_module, can_unload))
15091@@ -766,11 +772,6 @@
15092 #endif
15093 #endif
15094
15095- if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) {
15096- printk(KERN_CRIT "inet6_proto_init: size fault\n");
15097- return -EINVAL;
15098- }
15099-
15100 err = proto_register(&tcpv6_prot, 1);
15101 if (err)
15102 goto out;
15103@@ -856,6 +857,9 @@
15104 ipv6_frag_init();
15105 ipv6_nodata_init();
15106 ipv6_destopt_init();
15107+#ifdef CONFIG_IPV6_MIP6
15108+ mip6_init();
15109+#endif
15110
15111 /* Init v6 transport protocols. */
15112 udpv6_init();
15113@@ -919,6 +923,9 @@
15114 tcp6_proc_exit();
15115 raw6_proc_exit();
15116 #endif
15117+#ifdef CONFIG_IPV6_MIP6
15118+ mip6_fini();
15119+#endif
15120 /* Cleanup code parts. */
15121 sit_cleanup();
15122 ip6_flowlabel_cleanup();
15123diff -Nur linux-2.6.18-rc5/net/ipv6/ah6.c linux-2.6.19/net/ipv6/ah6.c
15124--- linux-2.6.18-rc5/net/ipv6/ah6.c 2006-08-28 05:41:48.000000000 +0200
15125+++ linux-2.6.19/net/ipv6/ah6.c 2006-09-22 10:04:58.000000000 +0200
15126@@ -74,6 +74,66 @@
15127 return 0;
15128 }
15129
15130+#ifdef CONFIG_IPV6_MIP6
15131+/**
15132+ * ipv6_rearrange_destopt - rearrange IPv6 destination options header
15133+ * @iph: IPv6 header
15134+ * @destopt: destionation options header
15135+ */
15136+static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt)
15137+{
15138+ u8 *opt = (u8 *)destopt;
15139+ int len = ipv6_optlen(destopt);
15140+ int off = 0;
15141+ int optlen = 0;
15142+
15143+ off += 2;
15144+ len -= 2;
15145+
15146+ while (len > 0) {
15147+
15148+ switch (opt[off]) {
15149+
15150+ case IPV6_TLV_PAD0:
15151+ optlen = 1;
15152+ break;
15153+ default:
15154+ if (len < 2)
15155+ goto bad;
15156+ optlen = opt[off+1]+2;
15157+ if (len < optlen)
15158+ goto bad;
15159+
15160+ /* Rearrange the source address in @iph and the
15161+ * addresses in home address option for final source.
15162+ * See 11.3.2 of RFC 3775 for details.
15163+ */
15164+ if (opt[off] == IPV6_TLV_HAO) {
15165+ struct in6_addr final_addr;
15166+ struct ipv6_destopt_hao *hao;
15167+
15168+ hao = (struct ipv6_destopt_hao *)&opt[off];
15169+ if (hao->length != sizeof(hao->addr)) {
15170+ if (net_ratelimit())
15171+ printk(KERN_WARNING "destopt hao: invalid header length: %u\n", hao->length);
15172+ goto bad;
15173+ }
15174+ ipv6_addr_copy(&final_addr, &hao->addr);
15175+ ipv6_addr_copy(&hao->addr, &iph->saddr);
15176+ ipv6_addr_copy(&iph->saddr, &final_addr);
15177+ }
15178+ break;
15179+ }
15180+
15181+ off += optlen;
15182+ len -= optlen;
15183+ }
15184+ /* Note: ok if len == 0 */
15185+bad:
15186+ return;
15187+}
15188+#endif
15189+
15190 /**
15191 * ipv6_rearrange_rthdr - rearrange IPv6 routing header
15192 * @iph: IPv6 header
15193@@ -113,7 +173,7 @@
15194 ipv6_addr_copy(&iph->daddr, &final_addr);
15195 }
15196
15197-static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len)
15198+static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
15199 {
15200 union {
15201 struct ipv6hdr *iph;
15202@@ -128,8 +188,12 @@
15203
15204 while (exthdr.raw < end) {
15205 switch (nexthdr) {
15206- case NEXTHDR_HOP:
15207 case NEXTHDR_DEST:
15208+#ifdef CONFIG_IPV6_MIP6
15209+ if (dir == XFRM_POLICY_OUT)
15210+ ipv6_rearrange_destopt(iph, exthdr.opth);
15211+#endif
15212+ case NEXTHDR_HOP:
15213 if (!zero_out_mutable_opts(exthdr.opth)) {
15214 LIMIT_NETDEBUG(
15215 KERN_WARNING "overrun %sopts\n",
15216@@ -164,6 +228,9 @@
15217 u8 nexthdr;
15218 char tmp_base[8];
15219 struct {
15220+#ifdef CONFIG_IPV6_MIP6
15221+ struct in6_addr saddr;
15222+#endif
15223 struct in6_addr daddr;
15224 char hdrs[0];
15225 } *tmp_ext;
15226@@ -188,10 +255,15 @@
15227 err = -ENOMEM;
15228 goto error;
15229 }
15230+#ifdef CONFIG_IPV6_MIP6
15231+ memcpy(tmp_ext, &top_iph->saddr, extlen);
15232+#else
15233 memcpy(tmp_ext, &top_iph->daddr, extlen);
15234+#endif
15235 err = ipv6_clear_mutable_options(top_iph,
15236 extlen - sizeof(*tmp_ext) +
15237- sizeof(*top_iph));
15238+ sizeof(*top_iph),
15239+ XFRM_POLICY_OUT);
15240 if (err)
15241 goto error_free_iph;
15242 }
15243@@ -219,7 +291,11 @@
15244
15245 memcpy(top_iph, tmp_base, sizeof(tmp_base));
15246 if (tmp_ext) {
15247+#ifdef CONFIG_IPV6_MIP6
15248+ memcpy(&top_iph->saddr, tmp_ext, extlen);
15249+#else
15250 memcpy(&top_iph->daddr, tmp_ext, extlen);
15251+#endif
15252 error_free_iph:
15253 kfree(tmp_ext);
15254 }
15255@@ -278,7 +354,7 @@
15256 if (!tmp_hdr)
15257 goto out;
15258 memcpy(tmp_hdr, skb->nh.raw, hdr_len);
15259- if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len))
15260+ if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN))
15261 goto free_out;
15262 skb->nh.ipv6h->priority = 0;
15263 skb->nh.ipv6h->flow_lbl[0] = 0;
15264@@ -387,7 +463,7 @@
15265 goto error;
15266
15267 x->props.header_len = XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len);
15268- if (x->props.mode)
15269+ if (x->props.mode == XFRM_MODE_TUNNEL)
15270 x->props.header_len += sizeof(struct ipv6hdr);
15271 x->data = ahp;
15272
15273@@ -424,7 +500,8 @@
15274 .init_state = ah6_init_state,
15275 .destructor = ah6_destroy,
15276 .input = ah6_input,
15277- .output = ah6_output
15278+ .output = ah6_output,
15279+ .hdr_offset = xfrm6_find_1stfragopt,
15280 };
15281
15282 static struct inet6_protocol ah6_protocol = {
15283diff -Nur linux-2.6.18-rc5/net/ipv6/anycast.c linux-2.6.19/net/ipv6/anycast.c
15284--- linux-2.6.18-rc5/net/ipv6/anycast.c 2006-08-28 05:41:48.000000000 +0200
15285+++ linux-2.6.19/net/ipv6/anycast.c 2006-09-22 10:04:58.000000000 +0200
15286@@ -335,7 +335,7 @@
15287 write_unlock_bh(&idev->lock);
15288
15289 dst_hold(&rt->u.dst);
15290- if (ip6_ins_rt(rt, NULL, NULL, NULL))
15291+ if (ip6_ins_rt(rt))
15292 dst_release(&rt->u.dst);
15293
15294 addrconf_join_solict(dev, &aca->aca_addr);
15295@@ -378,7 +378,7 @@
15296 addrconf_leave_solict(idev, &aca->aca_addr);
15297
15298 dst_hold(&aca->aca_rt->u.dst);
15299- if (ip6_del_rt(aca->aca_rt, NULL, NULL, NULL))
15300+ if (ip6_del_rt(aca->aca_rt))
15301 dst_free(&aca->aca_rt->u.dst);
15302 else
15303 dst_release(&aca->aca_rt->u.dst);
15304diff -Nur linux-2.6.18-rc5/net/ipv6/datagram.c linux-2.6.19/net/ipv6/datagram.c
15305--- linux-2.6.18-rc5/net/ipv6/datagram.c 2006-08-28 05:41:48.000000000 +0200
15306+++ linux-2.6.19/net/ipv6/datagram.c 2006-09-22 10:04:58.000000000 +0200
15307@@ -156,6 +156,8 @@
15308 if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST))
15309 fl.oif = np->mcast_oif;
15310
15311+ security_sk_classify_flow(sk, &fl);
15312+
15313 if (flowlabel) {
15314 if (flowlabel->opt && flowlabel->opt->srcrt) {
15315 struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
15316@@ -191,7 +193,12 @@
15317
15318 ip6_dst_store(sk, dst,
15319 ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ?
15320- &np->daddr : NULL);
15321+ &np->daddr : NULL,
15322+#ifdef CONFIG_IPV6_SUBTREES
15323+ ipv6_addr_equal(&fl.fl6_src, &np->saddr) ?
15324+ &np->saddr :
15325+#endif
15326+ NULL);
15327
15328 sk->sk_state = TCP_ESTABLISHED;
15329 out:
15330@@ -641,10 +648,13 @@
15331
15332 rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg);
15333
15334- /*
15335- * TYPE 0
15336- */
15337- if (rthdr->type) {
15338+ switch (rthdr->type) {
15339+ case IPV6_SRCRT_TYPE_0:
15340+#ifdef CONFIG_IPV6_MIP6
15341+ case IPV6_SRCRT_TYPE_2:
15342+#endif
15343+ break;
15344+ default:
15345 err = -EINVAL;
15346 goto exit_f;
15347 }
15348diff -Nur linux-2.6.18-rc5/net/ipv6/esp6.c linux-2.6.19/net/ipv6/esp6.c
15349--- linux-2.6.18-rc5/net/ipv6/esp6.c 2006-08-28 05:41:48.000000000 +0200
15350+++ linux-2.6.19/net/ipv6/esp6.c 2006-09-22 10:04:58.000000000 +0200
15351@@ -95,8 +95,13 @@
15352 esph->seq_no = htonl(++x->replay.oseq);
15353 xfrm_aevent_doreplay(x);
15354
15355- if (esp->conf.ivlen)
15356+ if (esp->conf.ivlen) {
15357+ if (unlikely(!esp->conf.ivinitted)) {
15358+ get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
15359+ esp->conf.ivinitted = 1;
15360+ }
15361 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
15362+ }
15363
15364 do {
15365 struct scatterlist *sg = &esp->sgbuf[0];
15366@@ -227,7 +232,7 @@
15367 struct esp_data *esp = x->data;
15368 u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
15369
15370- if (x->props.mode) {
15371+ if (x->props.mode == XFRM_MODE_TUNNEL) {
15372 mtu = ALIGN(mtu + 2, blksize);
15373 } else {
15374 /* The worst case. */
15375@@ -339,12 +344,12 @@
15376 esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
15377 if (unlikely(esp->conf.ivec == NULL))
15378 goto error;
15379- get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
15380+ esp->conf.ivinitted = 0;
15381 }
15382 if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len))
15383 goto error;
15384 x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
15385- if (x->props.mode)
15386+ if (x->props.mode == XFRM_MODE_TUNNEL)
15387 x->props.header_len += sizeof(struct ipv6hdr);
15388 x->data = esp;
15389 return 0;
15390@@ -365,7 +370,8 @@
15391 .destructor = esp6_destroy,
15392 .get_max_size = esp6_get_max_size,
15393 .input = esp6_input,
15394- .output = esp6_output
15395+ .output = esp6_output,
15396+ .hdr_offset = xfrm6_find_1stfragopt,
15397 };
15398
15399 static struct inet6_protocol esp6_protocol = {
15400diff -Nur linux-2.6.18-rc5/net/ipv6/exthdrs.c linux-2.6.19/net/ipv6/exthdrs.c
15401--- linux-2.6.18-rc5/net/ipv6/exthdrs.c 2006-08-28 05:41:48.000000000 +0200
15402+++ linux-2.6.19/net/ipv6/exthdrs.c 2006-09-22 10:04:58.000000000 +0200
15403@@ -43,9 +43,54 @@
15404 #include <net/ndisc.h>
15405 #include <net/ip6_route.h>
15406 #include <net/addrconf.h>
15407+#ifdef CONFIG_IPV6_MIP6
15408+#include <net/xfrm.h>
15409+#endif
15410
15411 #include <asm/uaccess.h>
15412
15413+int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
15414+{
15415+ int packet_len = skb->tail - skb->nh.raw;
15416+ struct ipv6_opt_hdr *hdr;
15417+ int len;
15418+
15419+ if (offset + 2 > packet_len)
15420+ goto bad;
15421+ hdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
15422+ len = ((hdr->hdrlen + 1) << 3);
15423+
15424+ if (offset + len > packet_len)
15425+ goto bad;
15426+
15427+ offset += 2;
15428+ len -= 2;
15429+
15430+ while (len > 0) {
15431+ int opttype = skb->nh.raw[offset];
15432+ int optlen;
15433+
15434+ if (opttype == type)
15435+ return offset;
15436+
15437+ switch (opttype) {
15438+ case IPV6_TLV_PAD0:
15439+ optlen = 1;
15440+ break;
15441+ default:
15442+ optlen = skb->nh.raw[offset + 1] + 2;
15443+ if (optlen > len)
15444+ goto bad;
15445+ break;
15446+ }
15447+ offset += optlen;
15448+ len -= optlen;
15449+ }
15450+ /* not_found */
15451+ bad:
15452+ return -1;
15453+}
15454+
15455 /*
15456 * Parsing tlv encoded headers.
15457 *
15458@@ -56,7 +101,7 @@
15459
15460 struct tlvtype_proc {
15461 int type;
15462- int (*func)(struct sk_buff *skb, int offset);
15463+ int (*func)(struct sk_buff **skbp, int offset);
15464 };
15465
15466 /*********************
15467@@ -65,8 +110,10 @@
15468
15469 /* An unknown option is detected, decide what to do */
15470
15471-static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
15472+static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
15473 {
15474+ struct sk_buff *skb = *skbp;
15475+
15476 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
15477 case 0: /* ignore */
15478 return 1;
15479@@ -91,8 +138,9 @@
15480
15481 /* Parse tlv encoded option header (hop-by-hop or destination) */
15482
15483-static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
15484+static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
15485 {
15486+ struct sk_buff *skb = *skbp;
15487 struct tlvtype_proc *curr;
15488 int off = skb->h.raw - skb->nh.raw;
15489 int len = ((skb->h.raw[1]+1)<<3);
15490@@ -122,13 +170,13 @@
15491 /* type specific length/alignment
15492 checks will be performed in the
15493 func(). */
15494- if (curr->func(skb, off) == 0)
15495+ if (curr->func(skbp, off) == 0)
15496 return 0;
15497 break;
15498 }
15499 }
15500 if (curr->type < 0) {
15501- if (ip6_tlvopt_unknown(skb, off) == 0)
15502+ if (ip6_tlvopt_unknown(skbp, off) == 0)
15503 return 0;
15504 }
15505 break;
15506@@ -147,8 +195,85 @@
15507 Destination options header.
15508 *****************************/
15509
15510+#ifdef CONFIG_IPV6_MIP6
15511+static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
15512+{
15513+ struct sk_buff *skb = *skbp;
15514+ struct ipv6_destopt_hao *hao;
15515+ struct inet6_skb_parm *opt = IP6CB(skb);
15516+ struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->nh.raw;
15517+ struct in6_addr tmp_addr;
15518+ int ret;
15519+
15520+ if (opt->dsthao) {
15521+ LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
15522+ goto discard;
15523+ }
15524+ opt->dsthao = opt->dst1;
15525+ opt->dst1 = 0;
15526+
15527+ hao = (struct ipv6_destopt_hao *)(skb->nh.raw + optoff);
15528+
15529+ if (hao->length != 16) {
15530+ LIMIT_NETDEBUG(
15531+ KERN_DEBUG "hao invalid option length = %d\n", hao->length);
15532+ goto discard;
15533+ }
15534+
15535+ if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
15536+ LIMIT_NETDEBUG(
15537+ KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
15538+ goto discard;
15539+ }
15540+
15541+ ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
15542+ (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
15543+ if (unlikely(ret < 0))
15544+ goto discard;
15545+
15546+ if (skb_cloned(skb)) {
15547+ struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
15548+ struct inet6_skb_parm *opt2;
15549+
15550+ if (skb2 == NULL)
15551+ goto discard;
15552+
15553+ opt2 = IP6CB(skb2);
15554+ memcpy(opt2, opt, sizeof(*opt2));
15555+
15556+ kfree_skb(skb);
15557+
15558+ /* update all variable using below by copied skbuff */
15559+ *skbp = skb = skb2;
15560+ hao = (struct ipv6_destopt_hao *)(skb2->nh.raw + optoff);
15561+ ipv6h = (struct ipv6hdr *)skb2->nh.raw;
15562+ }
15563+
15564+ if (skb->ip_summed == CHECKSUM_COMPLETE)
15565+ skb->ip_summed = CHECKSUM_NONE;
15566+
15567+ ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
15568+ ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
15569+ ipv6_addr_copy(&hao->addr, &tmp_addr);
15570+
15571+ if (skb->tstamp.off_sec == 0)
15572+ __net_timestamp(skb);
15573+
15574+ return 1;
15575+
15576+ discard:
15577+ kfree_skb(skb);
15578+ return 0;
15579+}
15580+#endif
15581+
15582 static struct tlvtype_proc tlvprocdestopt_lst[] = {
15583- /* No destination options are defined now */
15584+#ifdef CONFIG_IPV6_MIP6
15585+ {
15586+ .type = IPV6_TLV_HAO,
15587+ .func = ipv6_dest_hao,
15588+ },
15589+#endif
15590 {-1, NULL}
15591 };
15592
15593@@ -156,6 +281,9 @@
15594 {
15595 struct sk_buff *skb = *skbp;
15596 struct inet6_skb_parm *opt = IP6CB(skb);
15597+#ifdef CONFIG_IPV6_MIP6
15598+ __u16 dstbuf;
15599+#endif
15600
15601 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
15602 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
15603@@ -166,10 +294,19 @@
15604
15605 opt->lastopt = skb->h.raw - skb->nh.raw;
15606 opt->dst1 = skb->h.raw - skb->nh.raw;
15607+#ifdef CONFIG_IPV6_MIP6
15608+ dstbuf = opt->dst1;
15609+#endif
15610
15611- if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
15612+ if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
15613+ skb = *skbp;
15614 skb->h.raw += ((skb->h.raw[1]+1)<<3);
15615+ opt = IP6CB(skb);
15616+#ifdef CONFIG_IPV6_MIP6
15617+ opt->nhoff = dstbuf;
15618+#else
15619 opt->nhoff = opt->dst1;
15620+#endif
15621 return 1;
15622 }
15623
15624@@ -219,7 +356,7 @@
15625 {
15626 struct sk_buff *skb = *skbp;
15627 struct inet6_skb_parm *opt = IP6CB(skb);
15628- struct in6_addr *addr;
15629+ struct in6_addr *addr = NULL;
15630 struct in6_addr daddr;
15631 int n, i;
15632
15633@@ -244,6 +381,23 @@
15634
15635 looped_back:
15636 if (hdr->segments_left == 0) {
15637+ switch (hdr->type) {
15638+#ifdef CONFIG_IPV6_MIP6
15639+ case IPV6_SRCRT_TYPE_2:
15640+ /* Silently discard type 2 header unless it was
15641+ * processed by own
15642+ */
15643+ if (!addr) {
15644+ IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
15645+ kfree_skb(skb);
15646+ return -1;
15647+ }
15648+ break;
15649+#endif
15650+ default:
15651+ break;
15652+ }
15653+
15654 opt->lastopt = skb->h.raw - skb->nh.raw;
15655 opt->srcrt = skb->h.raw - skb->nh.raw;
15656 skb->h.raw += (hdr->hdrlen + 1) << 3;
15657@@ -253,17 +407,29 @@
15658 return 1;
15659 }
15660
15661- if (hdr->type != IPV6_SRCRT_TYPE_0) {
15662+ switch (hdr->type) {
15663+ case IPV6_SRCRT_TYPE_0:
15664+ if (hdr->hdrlen & 0x01) {
15665+ IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
15666+ icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
15667+ return -1;
15668+ }
15669+ break;
15670+#ifdef CONFIG_IPV6_MIP6
15671+ case IPV6_SRCRT_TYPE_2:
15672+ /* Silently discard invalid RTH type 2 */
15673+ if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
15674+ IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
15675+ kfree_skb(skb);
15676+ return -1;
15677+ }
15678+ break;
15679+#endif
15680+ default:
15681 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
15682 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
15683 return -1;
15684 }
15685-
15686- if (hdr->hdrlen & 0x01) {
15687- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
15688- icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
15689- return -1;
15690- }
15691
15692 /*
15693 * This is the routing header forwarding algorithm from
15694@@ -294,7 +460,7 @@
15695 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
15696 }
15697
15698- if (skb->ip_summed == CHECKSUM_HW)
15699+ if (skb->ip_summed == CHECKSUM_COMPLETE)
15700 skb->ip_summed = CHECKSUM_NONE;
15701
15702 i = n - --hdr->segments_left;
15703@@ -303,6 +469,27 @@
15704 addr = rthdr->addr;
15705 addr += i - 1;
15706
15707+ switch (hdr->type) {
15708+#ifdef CONFIG_IPV6_MIP6
15709+ case IPV6_SRCRT_TYPE_2:
15710+ if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
15711+ (xfrm_address_t *)&skb->nh.ipv6h->saddr,
15712+ IPPROTO_ROUTING) < 0) {
15713+ IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
15714+ kfree_skb(skb);
15715+ return -1;
15716+ }
15717+ if (!ipv6_chk_home_addr(addr)) {
15718+ IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
15719+ kfree_skb(skb);
15720+ return -1;
15721+ }
15722+ break;
15723+#endif
15724+ default:
15725+ break;
15726+ }
15727+
15728 if (ipv6_addr_is_multicast(addr)) {
15729 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
15730 kfree_skb(skb);
15731@@ -421,8 +608,10 @@
15732
15733 /* Router Alert as of RFC 2711 */
15734
15735-static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
15736+static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
15737 {
15738+ struct sk_buff *skb = *skbp;
15739+
15740 if (skb->nh.raw[optoff+1] == 2) {
15741 IP6CB(skb)->ra = optoff;
15742 return 1;
15743@@ -435,8 +624,9 @@
15744
15745 /* Jumbo payload */
15746
15747-static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
15748+static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
15749 {
15750+ struct sk_buff *skb = *skbp;
15751 u32 pkt_len;
15752
15753 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
15754@@ -485,8 +675,9 @@
15755 { -1, }
15756 };
15757
15758-int ipv6_parse_hopopts(struct sk_buff *skb)
15759+int ipv6_parse_hopopts(struct sk_buff **skbp)
15760 {
15761+ struct sk_buff *skb = *skbp;
15762 struct inet6_skb_parm *opt = IP6CB(skb);
15763
15764 /*
15765@@ -502,8 +693,10 @@
15766 }
15767
15768 opt->hop = sizeof(struct ipv6hdr);
15769- if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
15770+ if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
15771+ skb = *skbp;
15772 skb->h.raw += (skb->h.raw[1]+1)<<3;
15773+ opt = IP6CB(skb);
15774 opt->nhoff = sizeof(struct ipv6hdr);
15775 return 1;
15776 }
15777diff -Nur linux-2.6.18-rc5/net/ipv6/fib6_rules.c linux-2.6.19/net/ipv6/fib6_rules.c
15778--- linux-2.6.18-rc5/net/ipv6/fib6_rules.c 1970-01-01 01:00:00.000000000 +0100
15779+++ linux-2.6.19/net/ipv6/fib6_rules.c 2006-09-22 10:04:58.000000000 +0200
15780@@ -0,0 +1,305 @@
15781+/*
15782+ * net/ipv6/fib6_rules.c IPv6 Routing Policy Rules
15783+ *
15784+ * Copyright (C)2003-2006 Helsinki University of Technology
15785+ * Copyright (C)2003-2006 USAGI/WIDE Project
15786+ *
15787+ * This program is free software; you can redistribute it and/or
15788+ * modify it under the terms of the GNU General Public License as
15789+ * published by the Free Software Foundation, version 2.
15790+ *
15791+ * Authors
15792+ * Thomas Graf <tgraf@suug.ch>
15793+ * Ville Nuorvala <vnuorval@tcs.hut.fi>
15794+ */
15795+
15796+#include <linux/config.h>
15797+#include <linux/netdevice.h>
15798+
15799+#include <net/fib_rules.h>
15800+#include <net/ipv6.h>
15801+#include <net/ip6_route.h>
15802+#include <net/netlink.h>
15803+
15804+struct fib6_rule
15805+{
15806+ struct fib_rule common;
15807+ struct rt6key src;
15808+ struct rt6key dst;
15809+#ifdef CONFIG_IPV6_ROUTE_FWMARK
15810+ u32 fwmark;
15811+ u32 fwmask;
15812+#endif
15813+ u8 tclass;
15814+};
15815+
15816+static struct fib_rules_ops fib6_rules_ops;
15817+
15818+static struct fib6_rule main_rule = {
15819+ .common = {
15820+ .refcnt = ATOMIC_INIT(2),
15821+ .pref = 0x7FFE,
15822+ .action = FR_ACT_TO_TBL,
15823+ .table = RT6_TABLE_MAIN,
15824+ },
15825+};
15826+
15827+static struct fib6_rule local_rule = {
15828+ .common = {
15829+ .refcnt = ATOMIC_INIT(2),
15830+ .pref = 0,
15831+ .action = FR_ACT_TO_TBL,
15832+ .table = RT6_TABLE_LOCAL,
15833+ .flags = FIB_RULE_PERMANENT,
15834+ },
15835+};
15836+
15837+static LIST_HEAD(fib6_rules);
15838+
15839+struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
15840+ pol_lookup_t lookup)
15841+{
15842+ struct fib_lookup_arg arg = {
15843+ .lookup_ptr = lookup,
15844+ };
15845+
15846+ fib_rules_lookup(&fib6_rules_ops, fl, flags, &arg);
15847+ if (arg.rule)
15848+ fib_rule_put(arg.rule);
15849+
15850+ if (arg.result)
15851+ return (struct dst_entry *) arg.result;
15852+
15853+ dst_hold(&ip6_null_entry.u.dst);
15854+ return &ip6_null_entry.u.dst;
15855+}
15856+
15857+static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
15858+ int flags, struct fib_lookup_arg *arg)
15859+{
15860+ struct rt6_info *rt = NULL;
15861+ struct fib6_table *table;
15862+ pol_lookup_t lookup = arg->lookup_ptr;
15863+
15864+ switch (rule->action) {
15865+ case FR_ACT_TO_TBL:
15866+ break;
15867+ case FR_ACT_UNREACHABLE:
15868+ rt = &ip6_null_entry;
15869+ goto discard_pkt;
15870+ default:
15871+ case FR_ACT_BLACKHOLE:
15872+ rt = &ip6_blk_hole_entry;
15873+ goto discard_pkt;
15874+ case FR_ACT_PROHIBIT:
15875+ rt = &ip6_prohibit_entry;
15876+ goto discard_pkt;
15877+ }
15878+
15879+ table = fib6_get_table(rule->table);
15880+ if (table)
15881+ rt = lookup(table, flp, flags);
15882+
15883+ if (rt != &ip6_null_entry)
15884+ goto out;
15885+ dst_release(&rt->u.dst);
15886+ rt = NULL;
15887+ goto out;
15888+
15889+discard_pkt:
15890+ dst_hold(&rt->u.dst);
15891+out:
15892+ arg->result = rt;
15893+ return rt == NULL ? -EAGAIN : 0;
15894+}
15895+
15896+
15897+static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
15898+{
15899+ struct fib6_rule *r = (struct fib6_rule *) rule;
15900+
15901+ if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
15902+ return 0;
15903+
15904+ if ((flags & RT6_LOOKUP_F_HAS_SADDR) &&
15905+ !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen))
15906+ return 0;
15907+
15908+ if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff))
15909+ return 0;
15910+
15911+#ifdef CONFIG_IPV6_ROUTE_FWMARK
15912+ if ((r->fwmark ^ fl->fl6_fwmark) & r->fwmask)
15913+ return 0;
15914+#endif
15915+
15916+ return 1;
15917+}
15918+
15919+static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
15920+ [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
15921+ [FRA_PRIORITY] = { .type = NLA_U32 },
15922+ [FRA_SRC] = { .len = sizeof(struct in6_addr) },
15923+ [FRA_DST] = { .len = sizeof(struct in6_addr) },
15924+ [FRA_FWMARK] = { .type = NLA_U32 },
15925+ [FRA_FWMASK] = { .type = NLA_U32 },
15926+ [FRA_TABLE] = { .type = NLA_U32 },
15927+};
15928+
15929+static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
15930+ struct nlmsghdr *nlh, struct fib_rule_hdr *frh,
15931+ struct nlattr **tb)
15932+{
15933+ int err = -EINVAL;
15934+ struct fib6_rule *rule6 = (struct fib6_rule *) rule;
15935+
15936+ if (frh->src_len > 128 || frh->dst_len > 128 ||
15937+ (frh->tos & ~IPV6_FLOWINFO_MASK))
15938+ goto errout;
15939+
15940+ if (rule->action == FR_ACT_TO_TBL) {
15941+ if (rule->table == RT6_TABLE_UNSPEC)
15942+ goto errout;
15943+
15944+ if (fib6_new_table(rule->table) == NULL) {
15945+ err = -ENOBUFS;
15946+ goto errout;
15947+ }
15948+ }
15949+
15950+ if (tb[FRA_SRC])
15951+ nla_memcpy(&rule6->src.addr, tb[FRA_SRC],
15952+ sizeof(struct in6_addr));
15953+
15954+ if (tb[FRA_DST])
15955+ nla_memcpy(&rule6->dst.addr, tb[FRA_DST],
15956+ sizeof(struct in6_addr));
15957+
15958+#ifdef CONFIG_IPV6_ROUTE_FWMARK
15959+ if (tb[FRA_FWMARK]) {
15960+ rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]);
15961+ if (rule6->fwmark) {
15962+ /*
15963+ * if the mark value is non-zero,
15964+ * all bits are compared by default
15965+ * unless a mask is explicitly specified.
15966+ */
15967+ rule6->fwmask = 0xFFFFFFFF;
15968+ }
15969+ }
15970+
15971+ if (tb[FRA_FWMASK])
15972+ rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]);
15973+#endif
15974+
15975+ rule6->src.plen = frh->src_len;
15976+ rule6->dst.plen = frh->dst_len;
15977+ rule6->tclass = frh->tos;
15978+
15979+ err = 0;
15980+errout:
15981+ return err;
15982+}
15983+
15984+static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
15985+ struct nlattr **tb)
15986+{
15987+ struct fib6_rule *rule6 = (struct fib6_rule *) rule;
15988+
15989+ if (frh->src_len && (rule6->src.plen != frh->src_len))
15990+ return 0;
15991+
15992+ if (frh->dst_len && (rule6->dst.plen != frh->dst_len))
15993+ return 0;
15994+
15995+ if (frh->tos && (rule6->tclass != frh->tos))
15996+ return 0;
15997+
15998+ if (tb[FRA_SRC] &&
15999+ nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr)))
16000+ return 0;
16001+
16002+ if (tb[FRA_DST] &&
16003+ nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
16004+ return 0;
16005+
16006+#ifdef CONFIG_IPV6_ROUTE_FWMARK
16007+ if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK])))
16008+ return 0;
16009+
16010+ if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK])))
16011+ return 0;
16012+#endif
16013+
16014+ return 1;
16015+}
16016+
16017+static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
16018+ struct nlmsghdr *nlh, struct fib_rule_hdr *frh)
16019+{
16020+ struct fib6_rule *rule6 = (struct fib6_rule *) rule;
16021+
16022+ frh->family = AF_INET6;
16023+ frh->dst_len = rule6->dst.plen;
16024+ frh->src_len = rule6->src.plen;
16025+ frh->tos = rule6->tclass;
16026+
16027+ if (rule6->dst.plen)
16028+ NLA_PUT(skb, FRA_DST, sizeof(struct in6_addr),
16029+ &rule6->dst.addr);
16030+
16031+ if (rule6->src.plen)
16032+ NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr),
16033+ &rule6->src.addr);
16034+
16035+#ifdef CONFIG_IPV6_ROUTE_FWMARK
16036+ if (rule6->fwmark)
16037+ NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark);
16038+
16039+ if (rule6->fwmask || rule6->fwmark)
16040+ NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask);
16041+#endif
16042+
16043+ return 0;
16044+
16045+nla_put_failure:
16046+ return -ENOBUFS;
16047+}
16048+
16049+int fib6_rules_dump(struct sk_buff *skb, struct netlink_callback *cb)
16050+{
16051+ return fib_rules_dump(skb, cb, AF_INET6);
16052+}
16053+
16054+static u32 fib6_rule_default_pref(void)
16055+{
16056+ return 0x3FFF;
16057+}
16058+
16059+static struct fib_rules_ops fib6_rules_ops = {
16060+ .family = AF_INET6,
16061+ .rule_size = sizeof(struct fib6_rule),
16062+ .action = fib6_rule_action,
16063+ .match = fib6_rule_match,
16064+ .configure = fib6_rule_configure,
16065+ .compare = fib6_rule_compare,
16066+ .fill = fib6_rule_fill,
16067+ .default_pref = fib6_rule_default_pref,
16068+ .nlgroup = RTNLGRP_IPV6_RULE,
16069+ .policy = fib6_rule_policy,
16070+ .rules_list = &fib6_rules,
16071+ .owner = THIS_MODULE,
16072+};
16073+
16074+void __init fib6_rules_init(void)
16075+{
16076+ list_add_tail(&local_rule.common.list, &fib6_rules);
16077+ list_add_tail(&main_rule.common.list, &fib6_rules);
16078+
16079+ fib_rules_register(&fib6_rules_ops);
16080+}
16081+
16082+void fib6_rules_cleanup(void)
16083+{
16084+ fib_rules_unregister(&fib6_rules_ops);
16085+}
16086diff -Nur linux-2.6.18-rc5/net/ipv6/icmp.c linux-2.6.19/net/ipv6/icmp.c
16087--- linux-2.6.18-rc5/net/ipv6/icmp.c 2006-08-28 05:41:48.000000000 +0200
16088+++ linux-2.6.19/net/ipv6/icmp.c 2006-09-22 10:04:58.000000000 +0200
16089@@ -151,7 +151,7 @@
16090 return 0;
16091 }
16092
16093-static int sysctl_icmpv6_time = 1*HZ;
16094+static int sysctl_icmpv6_time __read_mostly = 1*HZ;
16095
16096 /*
16097 * Check the ICMP output rate limit
16098@@ -273,6 +273,29 @@
16099 return 0;
16100 }
16101
16102+#ifdef CONFIG_IPV6_MIP6
16103+static void mip6_addr_swap(struct sk_buff *skb)
16104+{
16105+ struct ipv6hdr *iph = skb->nh.ipv6h;
16106+ struct inet6_skb_parm *opt = IP6CB(skb);
16107+ struct ipv6_destopt_hao *hao;
16108+ struct in6_addr tmp;
16109+ int off;
16110+
16111+ if (opt->dsthao) {
16112+ off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO);
16113+ if (likely(off >= 0)) {
16114+ hao = (struct ipv6_destopt_hao *)(skb->nh.raw + off);
16115+ ipv6_addr_copy(&tmp, &iph->saddr);
16116+ ipv6_addr_copy(&iph->saddr, &hao->addr);
16117+ ipv6_addr_copy(&hao->addr, &tmp);
16118+ }
16119+ }
16120+}
16121+#else
16122+static inline void mip6_addr_swap(struct sk_buff *skb) {}
16123+#endif
16124+
16125 /*
16126 * Send an ICMP message in response to a packet in error
16127 */
16128@@ -350,6 +373,8 @@
16129 return;
16130 }
16131
16132+ mip6_addr_swap(skb);
16133+
16134 memset(&fl, 0, sizeof(fl));
16135 fl.proto = IPPROTO_ICMPV6;
16136 ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
16137@@ -358,6 +383,7 @@
16138 fl.oif = iif;
16139 fl.fl_icmp_type = type;
16140 fl.fl_icmp_code = code;
16141+ security_skb_classify_flow(skb, &fl);
16142
16143 if (icmpv6_xmit_lock())
16144 return;
16145@@ -472,6 +498,7 @@
16146 ipv6_addr_copy(&fl.fl6_src, saddr);
16147 fl.oif = skb->dev->ifindex;
16148 fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
16149+ security_skb_classify_flow(skb, &fl);
16150
16151 if (icmpv6_xmit_lock())
16152 return;
16153@@ -604,7 +631,7 @@
16154
16155 /* Perform checksum. */
16156 switch (skb->ip_summed) {
16157- case CHECKSUM_HW:
16158+ case CHECKSUM_COMPLETE:
16159 if (!csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6,
16160 skb->csum))
16161 break;
16162diff -Nur linux-2.6.18-rc5/net/ipv6/inet6_connection_sock.c linux-2.6.19/net/ipv6/inet6_connection_sock.c
16163--- linux-2.6.18-rc5/net/ipv6/inet6_connection_sock.c 2006-08-28 05:41:48.000000000 +0200
16164+++ linux-2.6.19/net/ipv6/inet6_connection_sock.c 2006-09-22 10:04:58.000000000 +0200
16165@@ -157,6 +157,7 @@
16166 fl.oif = sk->sk_bound_dev_if;
16167 fl.fl_ip_sport = inet->sport;
16168 fl.fl_ip_dport = inet->dport;
16169+ security_sk_classify_flow(sk, &fl);
16170
16171 if (np->opt && np->opt->srcrt) {
16172 struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
16173@@ -185,7 +186,7 @@
16174 return err;
16175 }
16176
16177- __ip6_dst_store(sk, dst, NULL);
16178+ __ip6_dst_store(sk, dst, NULL, NULL);
16179 }
16180
16181 skb->dst = dst_clone(dst);
16182diff -Nur linux-2.6.18-rc5/net/ipv6/ip6_fib.c linux-2.6.19/net/ipv6/ip6_fib.c
16183--- linux-2.6.18-rc5/net/ipv6/ip6_fib.c 2006-08-28 05:41:48.000000000 +0200
16184+++ linux-2.6.19/net/ipv6/ip6_fib.c 2006-09-22 10:04:58.000000000 +0200
16185@@ -18,6 +18,7 @@
16186 * Yuji SEKIYA @USAGI: Support default route on router node;
16187 * remove ip6_null_entry from the top of
16188 * routing table.
16189+ * Ville Nuorvala: Fixed routing subtrees.
16190 */
16191 #include <linux/errno.h>
16192 #include <linux/types.h>
16193@@ -26,6 +27,7 @@
16194 #include <linux/netdevice.h>
16195 #include <linux/in6.h>
16196 #include <linux/init.h>
16197+#include <linux/list.h>
16198
16199 #ifdef CONFIG_PROC_FS
16200 #include <linux/proc_fs.h>
16201@@ -68,19 +70,19 @@
16202 void *arg;
16203 };
16204
16205-DEFINE_RWLOCK(fib6_walker_lock);
16206-
16207+static DEFINE_RWLOCK(fib6_walker_lock);
16208
16209 #ifdef CONFIG_IPV6_SUBTREES
16210 #define FWS_INIT FWS_S
16211-#define SUBTREE(fn) ((fn)->subtree)
16212 #else
16213 #define FWS_INIT FWS_L
16214-#define SUBTREE(fn) NULL
16215 #endif
16216
16217 static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt);
16218+static struct rt6_info * fib6_find_prefix(struct fib6_node *fn);
16219 static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
16220+static int fib6_walk(struct fib6_walker_t *w);
16221+static int fib6_walk_continue(struct fib6_walker_t *w);
16222
16223 /*
16224 * A routing update causes an increase of the serial number on the
16225@@ -93,13 +95,31 @@
16226
16227 static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0);
16228
16229-struct fib6_walker_t fib6_walker_list = {
16230+static struct fib6_walker_t fib6_walker_list = {
16231 .prev = &fib6_walker_list,
16232 .next = &fib6_walker_list,
16233 };
16234
16235 #define FOR_WALKERS(w) for ((w)=fib6_walker_list.next; (w) != &fib6_walker_list; (w)=(w)->next)
16236
16237+static inline void fib6_walker_link(struct fib6_walker_t *w)
16238+{
16239+ write_lock_bh(&fib6_walker_lock);
16240+ w->next = fib6_walker_list.next;
16241+ w->prev = &fib6_walker_list;
16242+ w->next->prev = w;
16243+ w->prev->next = w;
16244+ write_unlock_bh(&fib6_walker_lock);
16245+}
16246+
16247+static inline void fib6_walker_unlink(struct fib6_walker_t *w)
16248+{
16249+ write_lock_bh(&fib6_walker_lock);
16250+ w->next->prev = w->prev;
16251+ w->prev->next = w->next;
16252+ w->prev = w->next = w;
16253+ write_unlock_bh(&fib6_walker_lock);
16254+}
16255 static __inline__ u32 fib6_new_sernum(void)
16256 {
16257 u32 n = ++rt_sernum;
16258@@ -147,6 +167,253 @@
16259 dst_free(&rt->u.dst);
16260 }
16261
16262+static struct fib6_table fib6_main_tbl = {
16263+ .tb6_id = RT6_TABLE_MAIN,
16264+ .tb6_lock = RW_LOCK_UNLOCKED,
16265+ .tb6_root = {
16266+ .leaf = &ip6_null_entry,
16267+ .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
16268+ },
16269+};
16270+
16271+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
16272+#define FIB_TABLE_HASHSZ 256
16273+#else
16274+#define FIB_TABLE_HASHSZ 1
16275+#endif
16276+static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];
16277+
16278+static void fib6_link_table(struct fib6_table *tb)
16279+{
16280+ unsigned int h;
16281+
16282+ h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);
16283+
16284+ /*
16285+ * No protection necessary, this is the only list mutatation
16286+ * operation, tables never disappear once they exist.
16287+ */
16288+ hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]);
16289+}
16290+
16291+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
16292+static struct fib6_table fib6_local_tbl = {
16293+ .tb6_id = RT6_TABLE_LOCAL,
16294+ .tb6_lock = RW_LOCK_UNLOCKED,
16295+ .tb6_root = {
16296+ .leaf = &ip6_null_entry,
16297+ .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
16298+ },
16299+};
16300+
16301+static struct fib6_table *fib6_alloc_table(u32 id)
16302+{
16303+ struct fib6_table *table;
16304+
16305+ table = kzalloc(sizeof(*table), GFP_ATOMIC);
16306+ if (table != NULL) {
16307+ table->tb6_id = id;
16308+ table->tb6_lock = RW_LOCK_UNLOCKED;
16309+ table->tb6_root.leaf = &ip6_null_entry;
16310+ table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
16311+ }
16312+
16313+ return table;
16314+}
16315+
16316+struct fib6_table *fib6_new_table(u32 id)
16317+{
16318+ struct fib6_table *tb;
16319+
16320+ if (id == 0)
16321+ id = RT6_TABLE_MAIN;
16322+ tb = fib6_get_table(id);
16323+ if (tb)
16324+ return tb;
16325+
16326+ tb = fib6_alloc_table(id);
16327+ if (tb != NULL)
16328+ fib6_link_table(tb);
16329+
16330+ return tb;
16331+}
16332+
16333+struct fib6_table *fib6_get_table(u32 id)
16334+{
16335+ struct fib6_table *tb;
16336+ struct hlist_node *node;
16337+ unsigned int h;
16338+
16339+ if (id == 0)
16340+ id = RT6_TABLE_MAIN;
16341+ h = id & (FIB_TABLE_HASHSZ - 1);
16342+ rcu_read_lock();
16343+ hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) {
16344+ if (tb->tb6_id == id) {
16345+ rcu_read_unlock();
16346+ return tb;
16347+ }
16348+ }
16349+ rcu_read_unlock();
16350+
16351+ return NULL;
16352+}
16353+
16354+static void __init fib6_tables_init(void)
16355+{
16356+ fib6_link_table(&fib6_main_tbl);
16357+ fib6_link_table(&fib6_local_tbl);
16358+}
16359+
16360+#else
16361+
16362+struct fib6_table *fib6_new_table(u32 id)
16363+{
16364+ return fib6_get_table(id);
16365+}
16366+
16367+struct fib6_table *fib6_get_table(u32 id)
16368+{
16369+ return &fib6_main_tbl;
16370+}
16371+
16372+struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
16373+ pol_lookup_t lookup)
16374+{
16375+ return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags);
16376+}
16377+
16378+static void __init fib6_tables_init(void)
16379+{
16380+ fib6_link_table(&fib6_main_tbl);
16381+}
16382+
16383+#endif
16384+
16385+static int fib6_dump_node(struct fib6_walker_t *w)
16386+{
16387+ int res;
16388+ struct rt6_info *rt;
16389+
16390+ for (rt = w->leaf; rt; rt = rt->u.next) {
16391+ res = rt6_dump_route(rt, w->args);
16392+ if (res < 0) {
16393+ /* Frame is full, suspend walking */
16394+ w->leaf = rt;
16395+ return 1;
16396+ }
16397+ BUG_TRAP(res!=0);
16398+ }
16399+ w->leaf = NULL;
16400+ return 0;
16401+}
16402+
16403+static void fib6_dump_end(struct netlink_callback *cb)
16404+{
16405+ struct fib6_walker_t *w = (void*)cb->args[2];
16406+
16407+ if (w) {
16408+ cb->args[2] = 0;
16409+ kfree(w);
16410+ }
16411+ cb->done = (void*)cb->args[3];
16412+ cb->args[1] = 3;
16413+}
16414+
16415+static int fib6_dump_done(struct netlink_callback *cb)
16416+{
16417+ fib6_dump_end(cb);
16418+ return cb->done ? cb->done(cb) : 0;
16419+}
16420+
16421+static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,
16422+ struct netlink_callback *cb)
16423+{
16424+ struct fib6_walker_t *w;
16425+ int res;
16426+
16427+ w = (void *)cb->args[2];
16428+ w->root = &table->tb6_root;
16429+
16430+ if (cb->args[4] == 0) {
16431+ read_lock_bh(&table->tb6_lock);
16432+ res = fib6_walk(w);
16433+ read_unlock_bh(&table->tb6_lock);
16434+ if (res > 0)
16435+ cb->args[4] = 1;
16436+ } else {
16437+ read_lock_bh(&table->tb6_lock);
16438+ res = fib6_walk_continue(w);
16439+ read_unlock_bh(&table->tb6_lock);
16440+ if (res != 0) {
16441+ if (res < 0)
16442+ fib6_walker_unlink(w);
16443+ goto end;
16444+ }
16445+ fib6_walker_unlink(w);
16446+ cb->args[4] = 0;
16447+ }
16448+end:
16449+ return res;
16450+}
16451+
16452+int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
16453+{
16454+ unsigned int h, s_h;
16455+ unsigned int e = 0, s_e;
16456+ struct rt6_rtnl_dump_arg arg;
16457+ struct fib6_walker_t *w;
16458+ struct fib6_table *tb;
16459+ struct hlist_node *node;
16460+ int res = 0;
16461+
16462+ s_h = cb->args[0];
16463+ s_e = cb->args[1];
16464+
16465+ w = (void *)cb->args[2];
16466+ if (w == NULL) {
16467+ /* New dump:
16468+ *
16469+ * 1. hook callback destructor.
16470+ */
16471+ cb->args[3] = (long)cb->done;
16472+ cb->done = fib6_dump_done;
16473+
16474+ /*
16475+ * 2. allocate and initialize walker.
16476+ */
16477+ w = kzalloc(sizeof(*w), GFP_ATOMIC);
16478+ if (w == NULL)
16479+ return -ENOMEM;
16480+ w->func = fib6_dump_node;
16481+ cb->args[2] = (long)w;
16482+ }
16483+
16484+ arg.skb = skb;
16485+ arg.cb = cb;
16486+ w->args = &arg;
16487+
16488+ for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
16489+ e = 0;
16490+ hlist_for_each_entry(tb, node, &fib_table_hash[h], tb6_hlist) {
16491+ if (e < s_e)
16492+ goto next;
16493+ res = fib6_dump_table(tb, skb, cb);
16494+ if (res != 0)
16495+ goto out;
16496+next:
16497+ e++;
16498+ }
16499+ }
16500+out:
16501+ cb->args[1] = e;
16502+ cb->args[0] = h;
16503+
16504+ res = res < 0 ? res : skb->len;
16505+ if (res <= 0)
16506+ fib6_dump_end(cb);
16507+ return res;
16508+}
16509
16510 /*
16511 * Routing Table
16512@@ -343,7 +610,7 @@
16513 */
16514
16515 static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
16516- struct nlmsghdr *nlh, struct netlink_skb_parms *req)
16517+ struct nl_info *info)
16518 {
16519 struct rt6_info *iter = NULL;
16520 struct rt6_info **ins;
16521@@ -398,7 +665,7 @@
16522 *ins = rt;
16523 rt->rt6i_node = fn;
16524 atomic_inc(&rt->rt6i_ref);
16525- inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req);
16526+ inet6_rt_notify(RTM_NEWROUTE, rt, info);
16527 rt6_stats.fib_rt_entries++;
16528
16529 if ((fn->fn_flags & RTN_RTINFO) == 0) {
16530@@ -428,10 +695,9 @@
16531 * with source addr info in sub-trees
16532 */
16533
16534-int fib6_add(struct fib6_node *root, struct rt6_info *rt,
16535- struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
16536+int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
16537 {
16538- struct fib6_node *fn;
16539+ struct fib6_node *fn, *pn = NULL;
16540 int err = -ENOMEM;
16541
16542 fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
16543@@ -440,6 +706,8 @@
16544 if (fn == NULL)
16545 goto out;
16546
16547+ pn = fn;
16548+
16549 #ifdef CONFIG_IPV6_SUBTREES
16550 if (rt->rt6i_src.plen) {
16551 struct fib6_node *sn;
16552@@ -485,10 +753,6 @@
16553 /* Now link new subtree to main tree */
16554 sfn->parent = fn;
16555 fn->subtree = sfn;
16556- if (fn->leaf == NULL) {
16557- fn->leaf = rt;
16558- atomic_inc(&rt->rt6i_ref);
16559- }
16560 } else {
16561 sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
16562 sizeof(struct in6_addr), rt->rt6i_src.plen,
16563@@ -498,21 +762,42 @@
16564 goto st_failure;
16565 }
16566
16567+ if (fn->leaf == NULL) {
16568+ fn->leaf = rt;
16569+ atomic_inc(&rt->rt6i_ref);
16570+ }
16571 fn = sn;
16572 }
16573 #endif
16574
16575- err = fib6_add_rt2node(fn, rt, nlh, req);
16576+ err = fib6_add_rt2node(fn, rt, info);
16577
16578 if (err == 0) {
16579 fib6_start_gc(rt);
16580 if (!(rt->rt6i_flags&RTF_CACHE))
16581- fib6_prune_clones(fn, rt);
16582+ fib6_prune_clones(pn, rt);
16583 }
16584
16585 out:
16586- if (err)
16587+ if (err) {
16588+#ifdef CONFIG_IPV6_SUBTREES
16589+ /*
16590+ * If fib6_add_1 has cleared the old leaf pointer in the
16591+ * super-tree leaf node we have to find a new one for it.
16592+ */
16593+ if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) {
16594+ pn->leaf = fib6_find_prefix(pn);
16595+#if RT6_DEBUG >= 2
16596+ if (!pn->leaf) {
16597+ BUG_TRAP(pn->leaf != NULL);
16598+ pn->leaf = &ip6_null_entry;
16599+ }
16600+#endif
16601+ atomic_inc(&pn->leaf->rt6i_ref);
16602+ }
16603+#endif
16604 dst_free(&rt->u.dst);
16605+ }
16606 return err;
16607
16608 #ifdef CONFIG_IPV6_SUBTREES
16609@@ -543,6 +828,9 @@
16610 struct fib6_node *fn;
16611 int dir;
16612
16613+ if (unlikely(args->offset == 0))
16614+ return NULL;
16615+
16616 /*
16617 * Descend on a tree
16618 */
16619@@ -564,33 +852,26 @@
16620 break;
16621 }
16622
16623- while ((fn->fn_flags & RTN_ROOT) == 0) {
16624-#ifdef CONFIG_IPV6_SUBTREES
16625- if (fn->subtree) {
16626- struct fib6_node *st;
16627- struct lookup_args *narg;
16628-
16629- narg = args + 1;
16630-
16631- if (narg->addr) {
16632- st = fib6_lookup_1(fn->subtree, narg);
16633-
16634- if (st && !(st->fn_flags & RTN_ROOT))
16635- return st;
16636- }
16637- }
16638-#endif
16639-
16640- if (fn->fn_flags & RTN_RTINFO) {
16641+ while(fn) {
16642+ if (FIB6_SUBTREE(fn) || fn->fn_flags & RTN_RTINFO) {
16643 struct rt6key *key;
16644
16645 key = (struct rt6key *) ((u8 *) fn->leaf +
16646 args->offset);
16647
16648- if (ipv6_prefix_equal(&key->addr, args->addr, key->plen))
16649- return fn;
16650+ if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) {
16651+#ifdef CONFIG_IPV6_SUBTREES
16652+ if (fn->subtree)
16653+ fn = fib6_lookup_1(fn->subtree, args + 1);
16654+#endif
16655+ if (!fn || fn->fn_flags & RTN_RTINFO)
16656+ return fn;
16657+ }
16658 }
16659
16660+ if (fn->fn_flags & RTN_ROOT)
16661+ break;
16662+
16663 fn = fn->parent;
16664 }
16665
16666@@ -600,18 +881,24 @@
16667 struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr,
16668 struct in6_addr *saddr)
16669 {
16670- struct lookup_args args[2];
16671 struct fib6_node *fn;
16672-
16673- args[0].offset = offsetof(struct rt6_info, rt6i_dst);
16674- args[0].addr = daddr;
16675-
16676+ struct lookup_args args[] = {
16677+ {
16678+ .offset = offsetof(struct rt6_info, rt6i_dst),
16679+ .addr = daddr,
16680+ },
16681 #ifdef CONFIG_IPV6_SUBTREES
16682- args[1].offset = offsetof(struct rt6_info, rt6i_src);
16683- args[1].addr = saddr;
16684+ {
16685+ .offset = offsetof(struct rt6_info, rt6i_src),
16686+ .addr = saddr,
16687+ },
16688 #endif
16689+ {
16690+ .offset = 0, /* sentinel */
16691+ }
16692+ };
16693
16694- fn = fib6_lookup_1(root, args);
16695+ fn = fib6_lookup_1(root, daddr ? args : args + 1);
16696
16697 if (fn == NULL || fn->fn_flags & RTN_TL_ROOT)
16698 fn = root;
16699@@ -667,10 +954,8 @@
16700 #ifdef CONFIG_IPV6_SUBTREES
16701 if (src_len) {
16702 BUG_TRAP(saddr!=NULL);
16703- if (fn == NULL)
16704- fn = fn->subtree;
16705- if (fn)
16706- fn = fib6_locate_1(fn, saddr, src_len,
16707+ if (fn && fn->subtree)
16708+ fn = fib6_locate_1(fn->subtree, saddr, src_len,
16709 offsetof(struct rt6_info, rt6i_src));
16710 }
16711 #endif
16712@@ -699,7 +984,7 @@
16713 if(fn->right)
16714 return fn->right->leaf;
16715
16716- fn = SUBTREE(fn);
16717+ fn = FIB6_SUBTREE(fn);
16718 }
16719 return NULL;
16720 }
16721@@ -730,7 +1015,7 @@
16722 if (fn->right) child = fn->right, children |= 1;
16723 if (fn->left) child = fn->left, children |= 2;
16724
16725- if (children == 3 || SUBTREE(fn)
16726+ if (children == 3 || FIB6_SUBTREE(fn)
16727 #ifdef CONFIG_IPV6_SUBTREES
16728 /* Subtree root (i.e. fn) may have one child */
16729 || (children && fn->fn_flags&RTN_ROOT)
16730@@ -749,9 +1034,9 @@
16731
16732 pn = fn->parent;
16733 #ifdef CONFIG_IPV6_SUBTREES
16734- if (SUBTREE(pn) == fn) {
16735+ if (FIB6_SUBTREE(pn) == fn) {
16736 BUG_TRAP(fn->fn_flags&RTN_ROOT);
16737- SUBTREE(pn) = NULL;
16738+ FIB6_SUBTREE(pn) = NULL;
16739 nstate = FWS_L;
16740 } else {
16741 BUG_TRAP(!(fn->fn_flags&RTN_ROOT));
16742@@ -799,7 +1084,7 @@
16743 read_unlock(&fib6_walker_lock);
16744
16745 node_free(fn);
16746- if (pn->fn_flags&RTN_RTINFO || SUBTREE(pn))
16747+ if (pn->fn_flags&RTN_RTINFO || FIB6_SUBTREE(pn))
16748 return pn;
16749
16750 rt6_release(pn->leaf);
16751@@ -809,7 +1094,7 @@
16752 }
16753
16754 static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
16755- struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
16756+ struct nl_info *info)
16757 {
16758 struct fib6_walker_t *w;
16759 struct rt6_info *rt = *rtp;
16760@@ -865,11 +1150,11 @@
16761 if (atomic_read(&rt->rt6i_ref) != 1) BUG();
16762 }
16763
16764- inet6_rt_notify(RTM_DELROUTE, rt, nlh, req);
16765+ inet6_rt_notify(RTM_DELROUTE, rt, info);
16766 rt6_release(rt);
16767 }
16768
16769-int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
16770+int fib6_del(struct rt6_info *rt, struct nl_info *info)
16771 {
16772 struct fib6_node *fn = rt->rt6i_node;
16773 struct rt6_info **rtp;
16774@@ -885,8 +1170,18 @@
16775
16776 BUG_TRAP(fn->fn_flags&RTN_RTINFO);
16777
16778- if (!(rt->rt6i_flags&RTF_CACHE))
16779- fib6_prune_clones(fn, rt);
16780+ if (!(rt->rt6i_flags&RTF_CACHE)) {
16781+ struct fib6_node *pn = fn;
16782+#ifdef CONFIG_IPV6_SUBTREES
16783+ /* clones of this route might be in another subtree */
16784+ if (rt->rt6i_src.plen) {
16785+ while (!(pn->fn_flags&RTN_ROOT))
16786+ pn = pn->parent;
16787+ pn = pn->parent;
16788+ }
16789+#endif
16790+ fib6_prune_clones(pn, rt);
16791+ }
16792
16793 /*
16794 * Walk the leaf entries looking for ourself
16795@@ -894,7 +1189,7 @@
16796
16797 for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
16798 if (*rtp == rt) {
16799- fib6_del_route(fn, rtp, nlh, _rtattr, req);
16800+ fib6_del_route(fn, rtp, info);
16801 return 0;
16802 }
16803 }
16804@@ -925,7 +1220,7 @@
16805 * <0 -> walk is terminated by an error.
16806 */
16807
16808-int fib6_walk_continue(struct fib6_walker_t *w)
16809+static int fib6_walk_continue(struct fib6_walker_t *w)
16810 {
16811 struct fib6_node *fn, *pn;
16812
16813@@ -942,8 +1237,8 @@
16814 switch (w->state) {
16815 #ifdef CONFIG_IPV6_SUBTREES
16816 case FWS_S:
16817- if (SUBTREE(fn)) {
16818- w->node = SUBTREE(fn);
16819+ if (FIB6_SUBTREE(fn)) {
16820+ w->node = FIB6_SUBTREE(fn);
16821 continue;
16822 }
16823 w->state = FWS_L;
16824@@ -977,7 +1272,7 @@
16825 pn = fn->parent;
16826 w->node = pn;
16827 #ifdef CONFIG_IPV6_SUBTREES
16828- if (SUBTREE(pn) == fn) {
16829+ if (FIB6_SUBTREE(pn) == fn) {
16830 BUG_TRAP(fn->fn_flags&RTN_ROOT);
16831 w->state = FWS_L;
16832 continue;
16833@@ -999,7 +1294,7 @@
16834 }
16835 }
16836
16837-int fib6_walk(struct fib6_walker_t *w)
16838+static int fib6_walk(struct fib6_walker_t *w)
16839 {
16840 int res;
16841
16842@@ -1023,7 +1318,7 @@
16843 res = c->func(rt, c->arg);
16844 if (res < 0) {
16845 w->leaf = rt;
16846- res = fib6_del(rt, NULL, NULL, NULL);
16847+ res = fib6_del(rt, NULL);
16848 if (res) {
16849 #if RT6_DEBUG >= 2
16850 printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
16851@@ -1049,9 +1344,9 @@
16852 * ignoring pure split nodes) will be scanned.
16853 */
16854
16855-void fib6_clean_tree(struct fib6_node *root,
16856- int (*func)(struct rt6_info *, void *arg),
16857- int prune, void *arg)
16858+static void fib6_clean_tree(struct fib6_node *root,
16859+ int (*func)(struct rt6_info *, void *arg),
16860+ int prune, void *arg)
16861 {
16862 struct fib6_cleaner_t c;
16863
16864@@ -1064,6 +1359,25 @@
16865 fib6_walk(&c.w);
16866 }
16867
16868+void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
16869+ int prune, void *arg)
16870+{
16871+ struct fib6_table *table;
16872+ struct hlist_node *node;
16873+ unsigned int h;
16874+
16875+ rcu_read_lock();
16876+ for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
16877+ hlist_for_each_entry_rcu(table, node, &fib_table_hash[h],
16878+ tb6_hlist) {
16879+ write_lock_bh(&table->tb6_lock);
16880+ fib6_clean_tree(&table->tb6_root, func, prune, arg);
16881+ write_unlock_bh(&table->tb6_lock);
16882+ }
16883+ }
16884+ rcu_read_unlock();
16885+}
16886+
16887 static int fib6_prune_clone(struct rt6_info *rt, void *arg)
16888 {
16889 if (rt->rt6i_flags & RTF_CACHE) {
16890@@ -1142,11 +1456,8 @@
16891 }
16892 gc_args.more = 0;
16893
16894-
16895- write_lock_bh(&rt6_lock);
16896 ndisc_dst_gc(&gc_args.more);
16897- fib6_clean_tree(&ip6_routing_table, fib6_age, 0, NULL);
16898- write_unlock_bh(&rt6_lock);
16899+ fib6_clean_all(fib6_age, 0, NULL);
16900
16901 if (gc_args.more)
16902 mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval);
16903@@ -1161,10 +1472,10 @@
16904 {
16905 fib6_node_kmem = kmem_cache_create("fib6_nodes",
16906 sizeof(struct fib6_node),
16907- 0, SLAB_HWCACHE_ALIGN,
16908+ 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
16909 NULL, NULL);
16910- if (!fib6_node_kmem)
16911- panic("cannot create fib6_nodes cache");
16912+
16913+ fib6_tables_init();
16914 }
16915
16916 void fib6_gc_cleanup(void)
16917diff -Nur linux-2.6.18-rc5/net/ipv6/ip6_input.c linux-2.6.19/net/ipv6/ip6_input.c
16918--- linux-2.6.18-rc5/net/ipv6/ip6_input.c 2006-08-28 05:41:48.000000000 +0200
16919+++ linux-2.6.19/net/ipv6/ip6_input.c 2006-09-22 10:04:58.000000000 +0200
16920@@ -111,7 +111,7 @@
16921 }
16922
16923 if (hdr->nexthdr == NEXTHDR_HOP) {
16924- if (ipv6_parse_hopopts(skb) < 0) {
16925+ if (ipv6_parse_hopopts(&skb) < 0) {
16926 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
16927 return 0;
16928 }
16929diff -Nur linux-2.6.18-rc5/net/ipv6/ip6_output.c linux-2.6.19/net/ipv6/ip6_output.c
16930--- linux-2.6.18-rc5/net/ipv6/ip6_output.c 2006-08-28 05:41:48.000000000 +0200
16931+++ linux-2.6.19/net/ipv6/ip6_output.c 2006-09-22 10:04:58.000000000 +0200
16932@@ -475,17 +475,25 @@
16933 switch (**nexthdr) {
16934
16935 case NEXTHDR_HOP:
16936+ break;
16937 case NEXTHDR_ROUTING:
16938+ found_rhdr = 1;
16939+ break;
16940 case NEXTHDR_DEST:
16941- if (**nexthdr == NEXTHDR_ROUTING) found_rhdr = 1;
16942- if (**nexthdr == NEXTHDR_DEST && found_rhdr) return offset;
16943- offset += ipv6_optlen(exthdr);
16944- *nexthdr = &exthdr->nexthdr;
16945- exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
16946+#ifdef CONFIG_IPV6_MIP6
16947+ if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
16948+ break;
16949+#endif
16950+ if (found_rhdr)
16951+ return offset;
16952 break;
16953 default :
16954 return offset;
16955 }
16956+
16957+ offset += ipv6_optlen(exthdr);
16958+ *nexthdr = &exthdr->nexthdr;
16959+ exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
16960 }
16961
16962 return offset;
16963@@ -726,6 +734,14 @@
16964 return err;
16965 }
16966
16967+static inline int ip6_rt_check(struct rt6key *rt_key,
16968+ struct in6_addr *fl_addr,
16969+ struct in6_addr *addr_cache)
16970+{
16971+ return ((rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) &&
16972+ (addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache)));
16973+}
16974+
16975 static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
16976 struct dst_entry *dst,
16977 struct flowi *fl)
16978@@ -741,8 +757,8 @@
16979 * that we do not support routing by source, TOS,
16980 * and MSG_DONTROUTE --ANK (980726)
16981 *
16982- * 1. If route was host route, check that
16983- * cached destination is current.
16984+ * 1. ip6_rt_check(): If route was host route,
16985+ * check that cached destination is current.
16986 * If it is network route, we still may
16987 * check its validity using saved pointer
16988 * to the last used address: daddr_cache.
16989@@ -753,11 +769,11 @@
16990 * sockets.
16991 * 2. oif also should be the same.
16992 */
16993- if (((rt->rt6i_dst.plen != 128 ||
16994- !ipv6_addr_equal(&fl->fl6_dst, &rt->rt6i_dst.addr))
16995- && (np->daddr_cache == NULL ||
16996- !ipv6_addr_equal(&fl->fl6_dst, np->daddr_cache)))
16997- || (fl->oif && fl->oif != dst->dev->ifindex)) {
16998+ if (ip6_rt_check(&rt->rt6i_dst, &fl->fl6_dst, np->daddr_cache) ||
16999+#ifdef CONFIG_IPV6_SUBTREES
17000+ ip6_rt_check(&rt->rt6i_src, &fl->fl6_src, np->saddr_cache) ||
17001+#endif
17002+ (fl->oif && fl->oif != dst->dev->ifindex)) {
17003 dst_release(dst);
17004 dst = NULL;
17005 }
17006@@ -866,7 +882,7 @@
17007 /* initialize protocol header pointer */
17008 skb->h.raw = skb->data + fragheaderlen;
17009
17010- skb->ip_summed = CHECKSUM_HW;
17011+ skb->ip_summed = CHECKSUM_PARTIAL;
17012 skb->csum = 0;
17013 sk->sk_sndmsg_off = 0;
17014 }
17015@@ -963,7 +979,7 @@
17016
17017 hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
17018
17019- fragheaderlen = sizeof(struct ipv6hdr) + (opt ? opt->opt_nflen : 0);
17020+ fragheaderlen = sizeof(struct ipv6hdr) + rt->u.dst.nfheader_len + (opt ? opt->opt_nflen : 0);
17021 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
17022
17023 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
17024diff -Nur linux-2.6.18-rc5/net/ipv6/ipcomp6.c linux-2.6.19/net/ipv6/ipcomp6.c
17025--- linux-2.6.18-rc5/net/ipv6/ipcomp6.c 2006-08-28 05:41:48.000000000 +0200
17026+++ linux-2.6.19/net/ipv6/ipcomp6.c 2006-09-22 10:04:58.000000000 +0200
17027@@ -212,7 +212,7 @@
17028 memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr));
17029 memcpy(&t->sel, &x->sel, sizeof(t->sel));
17030 t->props.family = AF_INET6;
17031- t->props.mode = 1;
17032+ t->props.mode = XFRM_MODE_TUNNEL;
17033 memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
17034
17035 if (xfrm_init_state(t))
17036@@ -416,7 +416,7 @@
17037 goto out;
17038
17039 x->props.header_len = 0;
17040- if (x->props.mode)
17041+ if (x->props.mode == XFRM_MODE_TUNNEL)
17042 x->props.header_len += sizeof(struct ipv6hdr);
17043
17044 mutex_lock(&ipcomp6_resource_mutex);
17045@@ -428,7 +428,7 @@
17046 goto error;
17047 mutex_unlock(&ipcomp6_resource_mutex);
17048
17049- if (x->props.mode) {
17050+ if (x->props.mode == XFRM_MODE_TUNNEL) {
17051 err = ipcomp6_tunnel_attach(x);
17052 if (err)
17053 goto error_tunnel;
17054@@ -460,6 +460,7 @@
17055 .destructor = ipcomp6_destroy,
17056 .input = ipcomp6_input,
17057 .output = ipcomp6_output,
17058+ .hdr_offset = xfrm6_find_1stfragopt,
17059 };
17060
17061 static struct inet6_protocol ipcomp6_protocol =
17062diff -Nur linux-2.6.18-rc5/net/ipv6/ipv6_sockglue.c linux-2.6.19/net/ipv6/ipv6_sockglue.c
17063--- linux-2.6.18-rc5/net/ipv6/ipv6_sockglue.c 2006-08-28 05:41:48.000000000 +0200
17064+++ linux-2.6.19/net/ipv6/ipv6_sockglue.c 2006-09-22 10:04:58.000000000 +0200
17065@@ -407,8 +407,16 @@
17066 /* routing header option needs extra check */
17067 if (optname == IPV6_RTHDR && opt->srcrt) {
17068 struct ipv6_rt_hdr *rthdr = opt->srcrt;
17069- if (rthdr->type)
17070+ switch (rthdr->type) {
17071+ case IPV6_SRCRT_TYPE_0:
17072+#ifdef CONFIG_IPV6_MIP6
17073+ case IPV6_SRCRT_TYPE_2:
17074+#endif
17075+ break;
17076+ default:
17077 goto sticky_done;
17078+ }
17079+
17080 if ((rthdr->hdrlen & 1) ||
17081 (rthdr->hdrlen >> 1) != rthdr->segments_left)
17082 goto sticky_done;
17083diff -Nur linux-2.6.18-rc5/net/ipv6/ipv6_syms.c linux-2.6.19/net/ipv6/ipv6_syms.c
17084--- linux-2.6.18-rc5/net/ipv6/ipv6_syms.c 2006-08-28 05:41:48.000000000 +0200
17085+++ linux-2.6.19/net/ipv6/ipv6_syms.c 2006-09-22 10:04:58.000000000 +0200
17086@@ -31,6 +31,8 @@
17087 EXPORT_SYMBOL(in6_dev_finish_destroy);
17088 #ifdef CONFIG_XFRM
17089 EXPORT_SYMBOL(xfrm6_rcv);
17090+EXPORT_SYMBOL(xfrm6_input_addr);
17091+EXPORT_SYMBOL(xfrm6_find_1stfragopt);
17092 #endif
17093 EXPORT_SYMBOL(rt6_lookup);
17094 EXPORT_SYMBOL(ipv6_push_nfrag_opts);
17095diff -Nur linux-2.6.18-rc5/net/ipv6/mcast.c linux-2.6.19/net/ipv6/mcast.c
17096--- linux-2.6.18-rc5/net/ipv6/mcast.c 2006-08-28 05:41:48.000000000 +0200
17097+++ linux-2.6.19/net/ipv6/mcast.c 2006-09-22 10:04:58.000000000 +0200
17098@@ -171,7 +171,7 @@
17099
17100 #define IPV6_MLD_MAX_MSF 64
17101
17102-int sysctl_mld_max_msf = IPV6_MLD_MAX_MSF;
17103+int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
17104
17105 /*
17106 * socket join on multicast group
17107diff -Nur linux-2.6.18-rc5/net/ipv6/mip6.c linux-2.6.19/net/ipv6/mip6.c
17108--- linux-2.6.18-rc5/net/ipv6/mip6.c 1970-01-01 01:00:00.000000000 +0100
17109+++ linux-2.6.19/net/ipv6/mip6.c 2006-09-22 10:04:58.000000000 +0200
17110@@ -0,0 +1,519 @@
17111+/*
17112+ * Copyright (C)2003-2006 Helsinki University of Technology
17113+ * Copyright (C)2003-2006 USAGI/WIDE Project
17114+ *
17115+ * This program is free software; you can redistribute it and/or modify
17116+ * it under the terms of the GNU General Public License as published by
17117+ * the Free Software Foundation; either version 2 of the License, or
17118+ * (at your option) any later version.
17119+ *
17120+ * This program is distributed in the hope that it will be useful,
17121+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17122+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17123+ * GNU General Public License for more details.
17124+ *
17125+ * You should have received a copy of the GNU General Public License
17126+ * along with this program; if not, write to the Free Software
17127+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17128+ */
17129+/*
17130+ * Authors:
17131+ * Noriaki TAKAMIYA @USAGI
17132+ * Masahide NAKAMURA @USAGI
17133+ */
17134+
17135+#include <linux/config.h>
17136+#include <linux/module.h>
17137+#include <linux/skbuff.h>
17138+#include <linux/time.h>
17139+#include <linux/ipv6.h>
17140+#include <linux/icmpv6.h>
17141+#include <net/sock.h>
17142+#include <net/ipv6.h>
17143+#include <net/ip6_checksum.h>
17144+#include <net/xfrm.h>
17145+#include <net/mip6.h>
17146+
17147+static xfrm_address_t *mip6_xfrm_addr(struct xfrm_state *x, xfrm_address_t *addr)
17148+{
17149+ return x->coaddr;
17150+}
17151+
17152+static inline unsigned int calc_padlen(unsigned int len, unsigned int n)
17153+{
17154+ return (n - len + 16) & 0x7;
17155+}
17156+
17157+static inline void *mip6_padn(__u8 *data, __u8 padlen)
17158+{
17159+ if (!data)
17160+ return NULL;
17161+ if (padlen == 1) {
17162+ data[0] = MIP6_OPT_PAD_1;
17163+ } else if (padlen > 1) {
17164+ data[0] = MIP6_OPT_PAD_N;
17165+ data[1] = padlen - 2;
17166+ if (padlen > 2)
17167+ memset(data+2, 0, data[1]);
17168+ }
17169+ return data + padlen;
17170+}
17171+
17172+static inline void mip6_param_prob(struct sk_buff *skb, int code, int pos)
17173+{
17174+ icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev);
17175+}
17176+
17177+static int mip6_mh_len(int type)
17178+{
17179+ int len = 0;
17180+
17181+ switch (type) {
17182+ case IP6_MH_TYPE_BRR:
17183+ len = 0;
17184+ break;
17185+ case IP6_MH_TYPE_HOTI:
17186+ case IP6_MH_TYPE_COTI:
17187+ case IP6_MH_TYPE_BU:
17188+ case IP6_MH_TYPE_BACK:
17189+ len = 1;
17190+ break;
17191+ case IP6_MH_TYPE_HOT:
17192+ case IP6_MH_TYPE_COT:
17193+ case IP6_MH_TYPE_BERROR:
17194+ len = 2;
17195+ break;
17196+ }
17197+ return len;
17198+}
17199+
17200+int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
17201+{
17202+ struct ip6_mh *mh;
17203+ int mhlen;
17204+
17205+ if (!pskb_may_pull(skb, (skb->h.raw - skb->data) + 8) ||
17206+ !pskb_may_pull(skb, (skb->h.raw - skb->data) + ((skb->h.raw[1] + 1) << 3)))
17207+ return -1;
17208+
17209+ mh = (struct ip6_mh *)skb->h.raw;
17210+
17211+ if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
17212+ LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
17213+ mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
17214+ mip6_param_prob(skb, 0, (&mh->ip6mh_hdrlen) - skb->nh.raw);
17215+ return -1;
17216+ }
17217+ mhlen = (mh->ip6mh_hdrlen + 1) << 3;
17218+
17219+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
17220+ skb->ip_summed = CHECKSUM_UNNECESSARY;
17221+ if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
17222+ &skb->nh.ipv6h->daddr,
17223+ mhlen, IPPROTO_MH,
17224+ skb->csum)) {
17225+ LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH hw checksum failed\n");
17226+ skb->ip_summed = CHECKSUM_NONE;
17227+ }
17228+ }
17229+ if (skb->ip_summed == CHECKSUM_NONE) {
17230+ if (csum_ipv6_magic(&skb->nh.ipv6h->saddr,
17231+ &skb->nh.ipv6h->daddr,
17232+ mhlen, IPPROTO_MH,
17233+ skb_checksum(skb, 0, mhlen, 0))) {
17234+ LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH checksum failed "
17235+ "[" NIP6_FMT " > " NIP6_FMT "]\n",
17236+ NIP6(skb->nh.ipv6h->saddr),
17237+ NIP6(skb->nh.ipv6h->daddr));
17238+ return -1;
17239+ }
17240+ skb->ip_summed = CHECKSUM_UNNECESSARY;
17241+ }
17242+
17243+ if (mh->ip6mh_proto != IPPROTO_NONE) {
17244+ LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
17245+ mh->ip6mh_proto);
17246+ mip6_param_prob(skb, 0, (&mh->ip6mh_proto) - skb->nh.raw);
17247+ return -1;
17248+ }
17249+
17250+ return 0;
17251+}
17252+
17253+struct mip6_report_rate_limiter {
17254+ spinlock_t lock;
17255+ struct timeval stamp;
17256+ int iif;
17257+ struct in6_addr src;
17258+ struct in6_addr dst;
17259+};
17260+
17261+static struct mip6_report_rate_limiter mip6_report_rl = {
17262+ .lock = SPIN_LOCK_UNLOCKED
17263+};
17264+
17265+static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb)
17266+{
17267+ struct ipv6hdr *iph = skb->nh.ipv6h;
17268+ struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data;
17269+
17270+ if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) &&
17271+ !ipv6_addr_any((struct in6_addr *)x->coaddr))
17272+ return -ENOENT;
17273+
17274+ return destopt->nexthdr;
17275+}
17276+
17277+/* Destination Option Header is inserted.
17278+ * IP Header's src address is replaced with Home Address Option in
17279+ * Destination Option Header.
17280+ */
17281+static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb)
17282+{
17283+ struct ipv6hdr *iph;
17284+ struct ipv6_destopt_hdr *dstopt;
17285+ struct ipv6_destopt_hao *hao;
17286+ u8 nexthdr;
17287+ int len;
17288+
17289+ iph = (struct ipv6hdr *)skb->data;
17290+ iph->payload_len = htons(skb->len - sizeof(*iph));
17291+
17292+ nexthdr = *skb->nh.raw;
17293+ *skb->nh.raw = IPPROTO_DSTOPTS;
17294+
17295+ dstopt = (struct ipv6_destopt_hdr *)skb->h.raw;
17296+ dstopt->nexthdr = nexthdr;
17297+
17298+ hao = mip6_padn((char *)(dstopt + 1),
17299+ calc_padlen(sizeof(*dstopt), 6));
17300+
17301+ hao->type = IPV6_TLV_HAO;
17302+ hao->length = sizeof(*hao) - 2;
17303+ BUG_TRAP(hao->length == 16);
17304+
17305+ len = ((char *)hao - (char *)dstopt) + sizeof(*hao);
17306+
17307+ memcpy(&hao->addr, &iph->saddr, sizeof(hao->addr));
17308+ memcpy(&iph->saddr, x->coaddr, sizeof(iph->saddr));
17309+
17310+ BUG_TRAP(len == x->props.header_len);
17311+ dstopt->hdrlen = (x->props.header_len >> 3) - 1;
17312+
17313+ return 0;
17314+}
17315+
17316+static inline int mip6_report_rl_allow(struct timeval *stamp,
17317+ struct in6_addr *dst,
17318+ struct in6_addr *src, int iif)
17319+{
17320+ int allow = 0;
17321+
17322+ spin_lock_bh(&mip6_report_rl.lock);
17323+ if (mip6_report_rl.stamp.tv_sec != stamp->tv_sec ||
17324+ mip6_report_rl.stamp.tv_usec != stamp->tv_usec ||
17325+ mip6_report_rl.iif != iif ||
17326+ !ipv6_addr_equal(&mip6_report_rl.src, src) ||
17327+ !ipv6_addr_equal(&mip6_report_rl.dst, dst)) {
17328+ mip6_report_rl.stamp.tv_sec = stamp->tv_sec;
17329+ mip6_report_rl.stamp.tv_usec = stamp->tv_usec;
17330+ mip6_report_rl.iif = iif;
17331+ ipv6_addr_copy(&mip6_report_rl.src, src);
17332+ ipv6_addr_copy(&mip6_report_rl.dst, dst);
17333+ allow = 1;
17334+ }
17335+ spin_unlock_bh(&mip6_report_rl.lock);
17336+ return allow;
17337+}
17338+
17339+static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl)
17340+{
17341+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
17342+ struct ipv6_destopt_hao *hao = NULL;
17343+ struct xfrm_selector sel;
17344+ int offset;
17345+ struct timeval stamp;
17346+ int err = 0;
17347+
17348+ if (unlikely(fl->proto == IPPROTO_MH &&
17349+ fl->fl_mh_type <= IP6_MH_TYPE_MAX))
17350+ goto out;
17351+
17352+ if (likely(opt->dsthao)) {
17353+ offset = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO);
17354+ if (likely(offset >= 0))
17355+ hao = (struct ipv6_destopt_hao *)(skb->nh.raw + offset);
17356+ }
17357+
17358+ skb_get_timestamp(skb, &stamp);
17359+
17360+ if (!mip6_report_rl_allow(&stamp, &skb->nh.ipv6h->daddr,
17361+ hao ? &hao->addr : &skb->nh.ipv6h->saddr,
17362+ opt->iif))
17363+ goto out;
17364+
17365+ memset(&sel, 0, sizeof(sel));
17366+ memcpy(&sel.daddr, (xfrm_address_t *)&skb->nh.ipv6h->daddr,
17367+ sizeof(sel.daddr));
17368+ sel.prefixlen_d = 128;
17369+ memcpy(&sel.saddr, (xfrm_address_t *)&skb->nh.ipv6h->saddr,
17370+ sizeof(sel.saddr));
17371+ sel.prefixlen_s = 128;
17372+ sel.family = AF_INET6;
17373+ sel.proto = fl->proto;
17374+ sel.dport = xfrm_flowi_dport(fl);
17375+ if (sel.dport)
17376+ sel.dport_mask = ~((__u16)0);
17377+ sel.sport = xfrm_flowi_sport(fl);
17378+ if (sel.sport)
17379+ sel.sport_mask = ~((__u16)0);
17380+ sel.ifindex = fl->oif;
17381+
17382+ err = km_report(IPPROTO_DSTOPTS, &sel,
17383+ (hao ? (xfrm_address_t *)&hao->addr : NULL));
17384+
17385+ out:
17386+ return err;
17387+}
17388+
17389+static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
17390+ u8 **nexthdr)
17391+{
17392+ u16 offset = sizeof(struct ipv6hdr);
17393+ struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1);
17394+ unsigned int packet_len = skb->tail - skb->nh.raw;
17395+ int found_rhdr = 0;
17396+
17397+ *nexthdr = &skb->nh.ipv6h->nexthdr;
17398+
17399+ while (offset + 1 <= packet_len) {
17400+
17401+ switch (**nexthdr) {
17402+ case NEXTHDR_HOP:
17403+ break;
17404+ case NEXTHDR_ROUTING:
17405+ found_rhdr = 1;
17406+ break;
17407+ case NEXTHDR_DEST:
17408+ /*
17409+ * HAO MUST NOT appear more than once.
17410+ * XXX: It is better to try to find by the end of
17411+ * XXX: packet if HAO exists.
17412+ */
17413+ if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) {
17414+ LIMIT_NETDEBUG(KERN_WARNING "mip6: hao exists already, override\n");
17415+ return offset;
17416+ }
17417+
17418+ if (found_rhdr)
17419+ return offset;
17420+
17421+ break;
17422+ default:
17423+ return offset;
17424+ }
17425+
17426+ offset += ipv6_optlen(exthdr);
17427+ *nexthdr = &exthdr->nexthdr;
17428+ exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
17429+ }
17430+
17431+ return offset;
17432+}
17433+
17434+static int mip6_destopt_init_state(struct xfrm_state *x)
17435+{
17436+ if (x->id.spi) {
17437+ printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
17438+ x->id.spi);
17439+ return -EINVAL;
17440+ }
17441+ if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
17442+ printk(KERN_INFO "%s: state's mode is not %u: %u\n",
17443+ __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
17444+ return -EINVAL;
17445+ }
17446+
17447+ x->props.header_len = sizeof(struct ipv6_destopt_hdr) +
17448+ calc_padlen(sizeof(struct ipv6_destopt_hdr), 6) +
17449+ sizeof(struct ipv6_destopt_hao);
17450+ BUG_TRAP(x->props.header_len == 24);
17451+
17452+ return 0;
17453+}
17454+
17455+/*
17456+ * Do nothing about destroying since it has no specific operation for
17457+ * destination options header unlike IPsec protocols.
17458+ */
17459+static void mip6_destopt_destroy(struct xfrm_state *x)
17460+{
17461+}
17462+
17463+static struct xfrm_type mip6_destopt_type =
17464+{
17465+ .description = "MIP6DESTOPT",
17466+ .owner = THIS_MODULE,
17467+ .proto = IPPROTO_DSTOPTS,
17468+ .flags = XFRM_TYPE_NON_FRAGMENT,
17469+ .init_state = mip6_destopt_init_state,
17470+ .destructor = mip6_destopt_destroy,
17471+ .input = mip6_destopt_input,
17472+ .output = mip6_destopt_output,
17473+ .reject = mip6_destopt_reject,
17474+ .hdr_offset = mip6_destopt_offset,
17475+ .local_addr = mip6_xfrm_addr,
17476+};
17477+
17478+static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb)
17479+{
17480+ struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data;
17481+
17482+ if (!ipv6_addr_equal(&rt2->addr, (struct in6_addr *)x->coaddr) &&
17483+ !ipv6_addr_any((struct in6_addr *)x->coaddr))
17484+ return -ENOENT;
17485+
17486+ return rt2->rt_hdr.nexthdr;
17487+}
17488+
17489+/* Routing Header type 2 is inserted.
17490+ * IP Header's dst address is replaced with Routing Header's Home Address.
17491+ */
17492+static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb)
17493+{
17494+ struct ipv6hdr *iph;
17495+ struct rt2_hdr *rt2;
17496+ u8 nexthdr;
17497+
17498+ iph = (struct ipv6hdr *)skb->data;
17499+ iph->payload_len = htons(skb->len - sizeof(*iph));
17500+
17501+ nexthdr = *skb->nh.raw;
17502+ *skb->nh.raw = IPPROTO_ROUTING;
17503+
17504+ rt2 = (struct rt2_hdr *)skb->h.raw;
17505+ rt2->rt_hdr.nexthdr = nexthdr;
17506+ rt2->rt_hdr.hdrlen = (x->props.header_len >> 3) - 1;
17507+ rt2->rt_hdr.type = IPV6_SRCRT_TYPE_2;
17508+ rt2->rt_hdr.segments_left = 1;
17509+ memset(&rt2->reserved, 0, sizeof(rt2->reserved));
17510+
17511+ BUG_TRAP(rt2->rt_hdr.hdrlen == 2);
17512+
17513+ memcpy(&rt2->addr, &iph->daddr, sizeof(rt2->addr));
17514+ memcpy(&iph->daddr, x->coaddr, sizeof(iph->daddr));
17515+
17516+ return 0;
17517+}
17518+
17519+static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
17520+ u8 **nexthdr)
17521+{
17522+ u16 offset = sizeof(struct ipv6hdr);
17523+ struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1);
17524+ unsigned int packet_len = skb->tail - skb->nh.raw;
17525+ int found_rhdr = 0;
17526+
17527+ *nexthdr = &skb->nh.ipv6h->nexthdr;
17528+
17529+ while (offset + 1 <= packet_len) {
17530+
17531+ switch (**nexthdr) {
17532+ case NEXTHDR_HOP:
17533+ break;
17534+ case NEXTHDR_ROUTING:
17535+ if (offset + 3 <= packet_len) {
17536+ struct ipv6_rt_hdr *rt;
17537+ rt = (struct ipv6_rt_hdr *)(skb->nh.raw + offset);
17538+ if (rt->type != 0)
17539+ return offset;
17540+ }
17541+ found_rhdr = 1;
17542+ break;
17543+ case NEXTHDR_DEST:
17544+ if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
17545+ return offset;
17546+
17547+ if (found_rhdr)
17548+ return offset;
17549+
17550+ break;
17551+ default:
17552+ return offset;
17553+ }
17554+
17555+ offset += ipv6_optlen(exthdr);
17556+ *nexthdr = &exthdr->nexthdr;
17557+ exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
17558+ }
17559+
17560+ return offset;
17561+}
17562+
17563+static int mip6_rthdr_init_state(struct xfrm_state *x)
17564+{
17565+ if (x->id.spi) {
17566+ printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__,
17567+ x->id.spi);
17568+ return -EINVAL;
17569+ }
17570+ if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
17571+ printk(KERN_INFO "%s: state's mode is not %u: %u\n",
17572+ __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
17573+ return -EINVAL;
17574+ }
17575+
17576+ x->props.header_len = sizeof(struct rt2_hdr);
17577+
17578+ return 0;
17579+}
17580+
17581+/*
17582+ * Do nothing about destroying since it has no specific operation for routing
17583+ * header type 2 unlike IPsec protocols.
17584+ */
17585+static void mip6_rthdr_destroy(struct xfrm_state *x)
17586+{
17587+}
17588+
17589+static struct xfrm_type mip6_rthdr_type =
17590+{
17591+ .description = "MIP6RT",
17592+ .owner = THIS_MODULE,
17593+ .proto = IPPROTO_ROUTING,
17594+ .flags = XFRM_TYPE_NON_FRAGMENT,
17595+ .init_state = mip6_rthdr_init_state,
17596+ .destructor = mip6_rthdr_destroy,
17597+ .input = mip6_rthdr_input,
17598+ .output = mip6_rthdr_output,
17599+ .hdr_offset = mip6_rthdr_offset,
17600+ .remote_addr = mip6_xfrm_addr,
17601+};
17602+
17603+int __init mip6_init(void)
17604+{
17605+ printk(KERN_INFO "Mobile IPv6\n");
17606+
17607+ if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) {
17608+ printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __FUNCTION__);
17609+ goto mip6_destopt_xfrm_fail;
17610+ }
17611+ if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) {
17612+ printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
17613+ goto mip6_rthdr_xfrm_fail;
17614+ }
17615+ return 0;
17616+
17617+ mip6_rthdr_xfrm_fail:
17618+ xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
17619+ mip6_destopt_xfrm_fail:
17620+ return -EAGAIN;
17621+}
17622+
17623+void __exit mip6_fini(void)
17624+{
17625+ if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
17626+ printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
17627+ if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
17628+ printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
17629+}
17630diff -Nur linux-2.6.18-rc5/net/ipv6/ndisc.c linux-2.6.19/net/ipv6/ndisc.c
17631--- linux-2.6.18-rc5/net/ipv6/ndisc.c 2006-08-28 05:41:48.000000000 +0200
17632+++ linux-2.6.19/net/ipv6/ndisc.c 2006-09-22 10:04:58.000000000 +0200
17633@@ -62,6 +62,7 @@
17634 #include <linux/sysctl.h>
17635 #endif
17636
17637+#include <linux/if_addr.h>
17638 #include <linux/if_arp.h>
17639 #include <linux/ipv6.h>
17640 #include <linux/icmpv6.h>
17641@@ -411,7 +412,8 @@
17642 */
17643
17644 static inline void ndisc_flow_init(struct flowi *fl, u8 type,
17645- struct in6_addr *saddr, struct in6_addr *daddr)
17646+ struct in6_addr *saddr, struct in6_addr *daddr,
17647+ int oif)
17648 {
17649 memset(fl, 0, sizeof(*fl));
17650 ipv6_addr_copy(&fl->fl6_src, saddr);
17651@@ -419,6 +421,8 @@
17652 fl->proto = IPPROTO_ICMPV6;
17653 fl->fl_icmp_type = type;
17654 fl->fl_icmp_code = 0;
17655+ fl->oif = oif;
17656+ security_sk_classify_flow(ndisc_socket->sk, fl);
17657 }
17658
17659 static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
17660@@ -450,7 +454,8 @@
17661 src_addr = &tmpaddr;
17662 }
17663
17664- ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr);
17665+ ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr,
17666+ dev->ifindex);
17667
17668 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
17669 if (!dst)
17670@@ -540,7 +545,8 @@
17671 saddr = &addr_buf;
17672 }
17673
17674- ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr);
17675+ ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr,
17676+ dev->ifindex);
17677
17678 dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
17679 if (!dst)
17680@@ -615,7 +621,8 @@
17681 int len;
17682 int err;
17683
17684- ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr);
17685+ ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr,
17686+ dev->ifindex);
17687
17688 dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output);
17689 if (!dst)
17690@@ -959,7 +966,7 @@
17691 struct rt6_info *rt;
17692 rt = rt6_get_dflt_router(saddr, dev);
17693 if (rt)
17694- ip6_del_rt(rt, NULL, NULL, NULL);
17695+ ip6_del_rt(rt);
17696 }
17697
17698 out:
17699@@ -1112,7 +1119,7 @@
17700
17701 if (rt && lifetime == 0) {
17702 neigh_clone(neigh);
17703- ip6_del_rt(rt, NULL, NULL, NULL);
17704+ ip6_del_rt(rt);
17705 rt = NULL;
17706 }
17707
17708@@ -1344,7 +1351,8 @@
17709
17710 neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
17711 if (neigh) {
17712- rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, lladdr,
17713+ rt6_redirect(dest, &skb->nh.ipv6h->daddr,
17714+ &skb->nh.ipv6h->saddr, neigh, lladdr,
17715 on_link);
17716 neigh_release(neigh);
17717 }
17718@@ -1380,7 +1388,8 @@
17719 return;
17720 }
17721
17722- ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
17723+ ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr,
17724+ dev->ifindex);
17725
17726 dst = ip6_route_output(NULL, &fl);
17727 if (dst == NULL)
17728diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/Makefile linux-2.6.19/net/ipv6/netfilter/Makefile
17729--- linux-2.6.18-rc5/net/ipv6/netfilter/Makefile 2006-08-28 05:41:48.000000000 +0200
17730+++ linux-2.6.19/net/ipv6/netfilter/Makefile 2006-09-22 10:04:58.000000000 +0200
17731@@ -5,7 +5,7 @@
17732 # Link order matters here.
17733 obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
17734 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
17735-obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
17736+obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
17737 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
17738 obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
17739 obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
17740diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6_queue.c linux-2.6.19/net/ipv6/netfilter/ip6_queue.c
17741--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6_queue.c 2006-08-28 05:41:48.000000000 +0200
17742+++ linux-2.6.19/net/ipv6/netfilter/ip6_queue.c 2006-09-22 10:04:58.000000000 +0200
17743@@ -57,7 +57,7 @@
17744 typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
17745
17746 static unsigned char copy_mode = IPQ_COPY_NONE;
17747-static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT;
17748+static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT;
17749 static DEFINE_RWLOCK(queue_lock);
17750 static int peer_pid;
17751 static unsigned int copy_range;
17752@@ -206,9 +206,9 @@
17753 break;
17754
17755 case IPQ_COPY_PACKET:
17756- if (entry->skb->ip_summed == CHECKSUM_HW &&
17757- (*errp = skb_checksum_help(entry->skb,
17758- entry->info->outdev == NULL))) {
17759+ if ((entry->skb->ip_summed == CHECKSUM_PARTIAL ||
17760+ entry->skb->ip_summed == CHECKSUM_COMPLETE) &&
17761+ (*errp = skb_checksum_help(entry->skb))) {
17762 read_unlock_bh(&queue_lock);
17763 return NULL;
17764 }
17765diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6_tables.c linux-2.6.19/net/ipv6/netfilter/ip6_tables.c
17766--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6_tables.c 2006-08-28 05:41:48.000000000 +0200
17767+++ linux-2.6.19/net/ipv6/netfilter/ip6_tables.c 2006-09-22 10:04:58.000000000 +0200
17768@@ -220,8 +220,7 @@
17769 const struct net_device *out,
17770 unsigned int hooknum,
17771 const struct xt_target *target,
17772- const void *targinfo,
17773- void *userinfo)
17774+ const void *targinfo)
17775 {
17776 if (net_ratelimit())
17777 printk("ip6_tables: error: `%s'\n", (char *)targinfo);
17778@@ -258,8 +257,7 @@
17779 unsigned int hook,
17780 const struct net_device *in,
17781 const struct net_device *out,
17782- struct xt_table *table,
17783- void *userdata)
17784+ struct xt_table *table)
17785 {
17786 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
17787 int offset = 0;
17788@@ -349,8 +347,7 @@
17789 in, out,
17790 hook,
17791 t->u.kernel.target,
17792- t->data,
17793- userdata);
17794+ t->data);
17795
17796 #ifdef CONFIG_NETFILTER_DEBUG
17797 if (((struct ip6t_entry *)table_base)->comefrom
17798@@ -507,8 +504,7 @@
17799 return 1;
17800
17801 if (m->u.kernel.match->destroy)
17802- m->u.kernel.match->destroy(m->u.kernel.match, m->data,
17803- m->u.match_size - sizeof(*m));
17804+ m->u.kernel.match->destroy(m->u.kernel.match, m->data);
17805 module_put(m->u.kernel.match->me);
17806 return 0;
17807 }
17808@@ -561,7 +557,6 @@
17809
17810 if (m->u.kernel.match->checkentry
17811 && !m->u.kernel.match->checkentry(name, ipv6, match, m->data,
17812- m->u.match_size - sizeof(*m),
17813 hookmask)) {
17814 duprintf("ip_tables: check failed for `%s'.\n",
17815 m->u.kernel.match->name);
17816@@ -622,8 +617,6 @@
17817 }
17818 } else if (t->u.kernel.target->checkentry
17819 && !t->u.kernel.target->checkentry(name, e, target, t->data,
17820- t->u.target_size
17821- - sizeof(*t),
17822 e->comefrom)) {
17823 duprintf("ip_tables: check failed for `%s'.\n",
17824 t->u.kernel.target->name);
17825@@ -695,8 +688,7 @@
17826 IP6T_MATCH_ITERATE(e, cleanup_match, NULL);
17827 t = ip6t_get_target(e);
17828 if (t->u.kernel.target->destroy)
17829- t->u.kernel.target->destroy(t->u.kernel.target, t->data,
17830- t->u.target_size - sizeof(*t));
17831+ t->u.kernel.target->destroy(t->u.kernel.target, t->data);
17832 module_put(t->u.kernel.target->me);
17833 return 0;
17834 }
17835@@ -1352,7 +1344,6 @@
17836 const void *entry,
17837 const struct xt_match *match,
17838 void *matchinfo,
17839- unsigned int matchsize,
17840 unsigned int hook_mask)
17841 {
17842 const struct ip6t_icmp *icmpinfo = matchinfo;
17843diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_HL.c linux-2.6.19/net/ipv6/netfilter/ip6t_HL.c
17844--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_HL.c 2006-08-28 05:41:48.000000000 +0200
17845+++ linux-2.6.19/net/ipv6/netfilter/ip6t_HL.c 2006-09-22 10:04:58.000000000 +0200
17846@@ -22,7 +22,7 @@
17847 const struct net_device *out,
17848 unsigned int hooknum,
17849 const struct xt_target *target,
17850- const void *targinfo, void *userinfo)
17851+ const void *targinfo)
17852 {
17853 struct ipv6hdr *ip6h;
17854 const struct ip6t_HL_info *info = targinfo;
17855@@ -66,7 +66,6 @@
17856 const void *entry,
17857 const struct xt_target *target,
17858 void *targinfo,
17859- unsigned int targinfosize,
17860 unsigned int hook_mask)
17861 {
17862 struct ip6t_HL_info *info = targinfo;
17863diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_LOG.c linux-2.6.19/net/ipv6/netfilter/ip6t_LOG.c
17864--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_LOG.c 2006-08-28 05:41:48.000000000 +0200
17865+++ linux-2.6.19/net/ipv6/netfilter/ip6t_LOG.c 2006-09-22 10:04:58.000000000 +0200
17866@@ -427,8 +427,7 @@
17867 const struct net_device *out,
17868 unsigned int hooknum,
17869 const struct xt_target *target,
17870- const void *targinfo,
17871- void *userinfo)
17872+ const void *targinfo)
17873 {
17874 const struct ip6t_log_info *loginfo = targinfo;
17875 struct nf_loginfo li;
17876@@ -452,7 +451,6 @@
17877 const void *entry,
17878 const struct xt_target *target,
17879 void *targinfo,
17880- unsigned int targinfosize,
17881 unsigned int hook_mask)
17882 {
17883 const struct ip6t_log_info *loginfo = targinfo;
17884diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.19/net/ipv6/netfilter/ip6t_REJECT.c
17885--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_REJECT.c 2006-08-28 05:41:48.000000000 +0200
17886+++ linux-2.6.19/net/ipv6/netfilter/ip6t_REJECT.c 2006-09-22 10:04:58.000000000 +0200
17887@@ -96,6 +96,7 @@
17888 ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
17889 fl.fl_ip_sport = otcph.dest;
17890 fl.fl_ip_dport = otcph.source;
17891+ security_skb_classify_flow(oldskb, &fl);
17892 dst = ip6_route_output(NULL, &fl);
17893 if (dst == NULL)
17894 return;
17895@@ -179,8 +180,7 @@
17896 const struct net_device *out,
17897 unsigned int hooknum,
17898 const struct xt_target *target,
17899- const void *targinfo,
17900- void *userinfo)
17901+ const void *targinfo)
17902 {
17903 const struct ip6t_reject_info *reject = targinfo;
17904
17905@@ -223,7 +223,6 @@
17906 const void *entry,
17907 const struct xt_target *target,
17908 void *targinfo,
17909- unsigned int targinfosize,
17910 unsigned int hook_mask)
17911 {
17912 const struct ip6t_reject_info *rejinfo = targinfo;
17913@@ -256,9 +255,7 @@
17914
17915 static int __init ip6t_reject_init(void)
17916 {
17917- if (ip6t_register_target(&ip6t_reject_reg))
17918- return -EINVAL;
17919- return 0;
17920+ return ip6t_register_target(&ip6t_reject_reg);
17921 }
17922
17923 static void __exit ip6t_reject_fini(void)
17924diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_ah.c linux-2.6.19/net/ipv6/netfilter/ip6t_ah.c
17925--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_ah.c 2006-08-28 05:41:48.000000000 +0200
17926+++ linux-2.6.19/net/ipv6/netfilter/ip6t_ah.c 2006-09-22 10:04:58.000000000 +0200
17927@@ -102,7 +102,6 @@
17928 const void *entry,
17929 const struct xt_match *match,
17930 void *matchinfo,
17931- unsigned int matchinfosize,
17932 unsigned int hook_mask)
17933 {
17934 const struct ip6t_ah *ahinfo = matchinfo;
17935diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_dst.c linux-2.6.19/net/ipv6/netfilter/ip6t_dst.c
17936--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_dst.c 2006-08-28 05:41:48.000000000 +0200
17937+++ linux-2.6.19/net/ipv6/netfilter/ip6t_dst.c 1970-01-01 01:00:00.000000000 +0100
17938@@ -1,220 +0,0 @@
17939-/* Kernel module to match Hop-by-Hop and Destination parameters. */
17940-
17941-/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
17942- *
17943- * This program is free software; you can redistribute it and/or modify
17944- * it under the terms of the GNU General Public License version 2 as
17945- * published by the Free Software Foundation.
17946- */
17947-
17948-#include <linux/module.h>
17949-#include <linux/skbuff.h>
17950-#include <linux/ipv6.h>
17951-#include <linux/types.h>
17952-#include <net/checksum.h>
17953-#include <net/ipv6.h>
17954-
17955-#include <asm/byteorder.h>
17956-
17957-#include <linux/netfilter_ipv6/ip6_tables.h>
17958-#include <linux/netfilter_ipv6/ip6t_opts.h>
17959-
17960-#define HOPBYHOP 0
17961-
17962-MODULE_LICENSE("GPL");
17963-#if HOPBYHOP
17964-MODULE_DESCRIPTION("IPv6 HbH match");
17965-#else
17966-MODULE_DESCRIPTION("IPv6 DST match");
17967-#endif
17968-MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
17969-
17970-#if 0
17971-#define DEBUGP printk
17972-#else
17973-#define DEBUGP(format, args...)
17974-#endif
17975-
17976-/*
17977- * (Type & 0xC0) >> 6
17978- * 0 -> ignorable
17979- * 1 -> must drop the packet
17980- * 2 -> send ICMP PARM PROB regardless and drop packet
17981- * 3 -> Send ICMP if not a multicast address and drop packet
17982- * (Type & 0x20) >> 5
17983- * 0 -> invariant
17984- * 1 -> can change the routing
17985- * (Type & 0x1F) Type
17986- * 0 -> Pad1 (only 1 byte!)
17987- * 1 -> PadN LENGTH info (total length = length + 2)
17988- * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
17989- * 5 -> RTALERT 2 x x
17990- */
17991-
17992-static int
17993-match(const struct sk_buff *skb,
17994- const struct net_device *in,
17995- const struct net_device *out,
17996- const struct xt_match *match,
17997- const void *matchinfo,
17998- int offset,
17999- unsigned int protoff,
18000- int *hotdrop)
18001-{
18002- struct ipv6_opt_hdr _optsh, *oh;
18003- const struct ip6t_opts *optinfo = matchinfo;
18004- unsigned int temp;
18005- unsigned int ptr;
18006- unsigned int hdrlen = 0;
18007- unsigned int ret = 0;
18008- u8 _opttype, *tp = NULL;
18009- u8 _optlen, *lp = NULL;
18010- unsigned int optlen;
18011-
18012-#if HOPBYHOP
18013- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0)
18014-#else
18015- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0)
18016-#endif
18017- return 0;
18018-
18019- oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
18020- if (oh == NULL) {
18021- *hotdrop = 1;
18022- return 0;
18023- }
18024-
18025- hdrlen = ipv6_optlen(oh);
18026- if (skb->len - ptr < hdrlen) {
18027- /* Packet smaller than it's length field */
18028- return 0;
18029- }
18030-
18031- DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
18032-
18033- DEBUGP("len %02X %04X %02X ",
18034- optinfo->hdrlen, hdrlen,
18035- (!(optinfo->flags & IP6T_OPTS_LEN) ||
18036- ((optinfo->hdrlen == hdrlen) ^
18037- !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
18038-
18039- ret = (oh != NULL) &&
18040- (!(optinfo->flags & IP6T_OPTS_LEN) ||
18041- ((optinfo->hdrlen == hdrlen) ^
18042- !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
18043-
18044- ptr += 2;
18045- hdrlen -= 2;
18046- if (!(optinfo->flags & IP6T_OPTS_OPTS)) {
18047- return ret;
18048- } else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
18049- DEBUGP("Not strict - not implemented");
18050- } else {
18051- DEBUGP("Strict ");
18052- DEBUGP("#%d ", optinfo->optsnr);
18053- for (temp = 0; temp < optinfo->optsnr; temp++) {
18054- /* type field exists ? */
18055- if (hdrlen < 1)
18056- break;
18057- tp = skb_header_pointer(skb, ptr, sizeof(_opttype),
18058- &_opttype);
18059- if (tp == NULL)
18060- break;
18061-
18062- /* Type check */
18063- if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) {
18064- DEBUGP("Tbad %02X %02X\n",
18065- *tp,
18066- (optinfo->opts[temp] & 0xFF00) >> 8);
18067- return 0;
18068- } else {
18069- DEBUGP("Tok ");
18070- }
18071- /* Length check */
18072- if (*tp) {
18073- u16 spec_len;
18074-
18075- /* length field exists ? */
18076- if (hdrlen < 2)
18077- break;
18078- lp = skb_header_pointer(skb, ptr + 1,
18079- sizeof(_optlen),
18080- &_optlen);
18081- if (lp == NULL)
18082- break;
18083- spec_len = optinfo->opts[temp] & 0x00FF;
18084-
18085- if (spec_len != 0x00FF && spec_len != *lp) {
18086- DEBUGP("Lbad %02X %04X\n", *lp,
18087- spec_len);
18088- return 0;
18089- }
18090- DEBUGP("Lok ");
18091- optlen = *lp + 2;
18092- } else {
18093- DEBUGP("Pad1\n");
18094- optlen = 1;
18095- }
18096-
18097- /* Step to the next */
18098- DEBUGP("len%04X \n", optlen);
18099-
18100- if ((ptr > skb->len - optlen || hdrlen < optlen) &&
18101- (temp < optinfo->optsnr - 1)) {
18102- DEBUGP("new pointer is too large! \n");
18103- break;
18104- }
18105- ptr += optlen;
18106- hdrlen -= optlen;
18107- }
18108- if (temp == optinfo->optsnr)
18109- return ret;
18110- else
18111- return 0;
18112- }
18113-
18114- return 0;
18115-}
18116-
18117-/* Called when user tries to insert an entry of this type. */
18118-static int
18119-checkentry(const char *tablename,
18120- const void *info,
18121- const struct xt_match *match,
18122- void *matchinfo,
18123- unsigned int matchinfosize,
18124- unsigned int hook_mask)
18125-{
18126- const struct ip6t_opts *optsinfo = matchinfo;
18127-
18128- if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
18129- DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
18130- return 0;
18131- }
18132- return 1;
18133-}
18134-
18135-static struct ip6t_match opts_match = {
18136-#if HOPBYHOP
18137- .name = "hbh",
18138-#else
18139- .name = "dst",
18140-#endif
18141- .match = match,
18142- .matchsize = sizeof(struct ip6t_opts),
18143- .checkentry = checkentry,
18144- .me = THIS_MODULE,
18145-};
18146-
18147-static int __init ip6t_dst_init(void)
18148-{
18149- return ip6t_register_match(&opts_match);
18150-}
18151-
18152-static void __exit ip6t_dst_fini(void)
18153-{
18154- ip6t_unregister_match(&opts_match);
18155-}
18156-
18157-module_init(ip6t_dst_init);
18158-module_exit(ip6t_dst_fini);
18159diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_frag.c linux-2.6.19/net/ipv6/netfilter/ip6t_frag.c
18160--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_frag.c 2006-08-28 05:41:48.000000000 +0200
18161+++ linux-2.6.19/net/ipv6/netfilter/ip6t_frag.c 2006-09-22 10:04:59.000000000 +0200
18162@@ -119,7 +119,6 @@
18163 const void *ip,
18164 const struct xt_match *match,
18165 void *matchinfo,
18166- unsigned int matchinfosize,
18167 unsigned int hook_mask)
18168 {
18169 const struct ip6t_frag *fraginfo = matchinfo;
18170diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_hbh.c linux-2.6.19/net/ipv6/netfilter/ip6t_hbh.c
18171--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_hbh.c 2006-08-28 05:41:48.000000000 +0200
18172+++ linux-2.6.19/net/ipv6/netfilter/ip6t_hbh.c 2006-09-22 10:04:59.000000000 +0200
18173@@ -19,15 +19,10 @@
18174 #include <linux/netfilter_ipv6/ip6_tables.h>
18175 #include <linux/netfilter_ipv6/ip6t_opts.h>
18176
18177-#define HOPBYHOP 1
18178-
18179 MODULE_LICENSE("GPL");
18180-#if HOPBYHOP
18181-MODULE_DESCRIPTION("IPv6 HbH match");
18182-#else
18183-MODULE_DESCRIPTION("IPv6 DST match");
18184-#endif
18185+MODULE_DESCRIPTION("IPv6 opts match");
18186 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
18187+MODULE_ALIAS("ip6t_dst");
18188
18189 #if 0
18190 #define DEBUGP printk
18191@@ -71,11 +66,7 @@
18192 u8 _optlen, *lp = NULL;
18193 unsigned int optlen;
18194
18195-#if HOPBYHOP
18196- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0)
18197-#else
18198- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0)
18199-#endif
18200+ if (ipv6_find_hdr(skb, &ptr, match->data, NULL) < 0)
18201 return 0;
18202
18203 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
18204@@ -182,7 +173,6 @@
18205 const void *entry,
18206 const struct xt_match *match,
18207 void *matchinfo,
18208- unsigned int matchinfosize,
18209 unsigned int hook_mask)
18210 {
18211 const struct ip6t_opts *optsinfo = matchinfo;
18212@@ -194,26 +184,35 @@
18213 return 1;
18214 }
18215
18216-static struct ip6t_match opts_match = {
18217-#if HOPBYHOP
18218- .name = "hbh",
18219-#else
18220- .name = "dst",
18221-#endif
18222- .match = match,
18223- .matchsize = sizeof(struct ip6t_opts),
18224- .checkentry = checkentry,
18225- .me = THIS_MODULE,
18226+static struct xt_match opts_match[] = {
18227+ {
18228+ .name = "hbh",
18229+ .family = AF_INET6,
18230+ .match = match,
18231+ .matchsize = sizeof(struct ip6t_opts),
18232+ .checkentry = checkentry,
18233+ .me = THIS_MODULE,
18234+ .data = NEXTHDR_HOP,
18235+ },
18236+ {
18237+ .name = "dst",
18238+ .family = AF_INET6,
18239+ .match = match,
18240+ .matchsize = sizeof(struct ip6t_opts),
18241+ .checkentry = checkentry,
18242+ .me = THIS_MODULE,
18243+ .data = NEXTHDR_DEST,
18244+ },
18245 };
18246
18247 static int __init ip6t_hbh_init(void)
18248 {
18249- return ip6t_register_match(&opts_match);
18250+ return xt_register_matches(opts_match, ARRAY_SIZE(opts_match));
18251 }
18252
18253 static void __exit ip6t_hbh_fini(void)
18254 {
18255- ip6t_unregister_match(&opts_match);
18256+ xt_unregister_matches(opts_match, ARRAY_SIZE(opts_match));
18257 }
18258
18259 module_init(ip6t_hbh_init);
18260diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_ipv6header.c linux-2.6.19/net/ipv6/netfilter/ip6t_ipv6header.c
18261--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_ipv6header.c 2006-08-28 05:41:48.000000000 +0200
18262+++ linux-2.6.19/net/ipv6/netfilter/ip6t_ipv6header.c 2006-09-22 10:04:59.000000000 +0200
18263@@ -128,7 +128,6 @@
18264 const void *ip,
18265 const struct xt_match *match,
18266 void *matchinfo,
18267- unsigned int matchsize,
18268 unsigned int hook_mask)
18269 {
18270 const struct ip6t_ipv6header_info *info = matchinfo;
18271diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_owner.c linux-2.6.19/net/ipv6/netfilter/ip6t_owner.c
18272--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_owner.c 2006-08-28 05:41:48.000000000 +0200
18273+++ linux-2.6.19/net/ipv6/netfilter/ip6t_owner.c 2006-09-22 10:04:59.000000000 +0200
18274@@ -57,7 +57,6 @@
18275 const void *ip,
18276 const struct xt_match *match,
18277 void *matchinfo,
18278- unsigned int matchsize,
18279 unsigned int hook_mask)
18280 {
18281 const struct ip6t_owner_info *info = matchinfo;
18282diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_rt.c linux-2.6.19/net/ipv6/netfilter/ip6t_rt.c
18283--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6t_rt.c 2006-08-28 05:41:48.000000000 +0200
18284+++ linux-2.6.19/net/ipv6/netfilter/ip6t_rt.c 2006-09-22 10:04:59.000000000 +0200
18285@@ -197,7 +197,6 @@
18286 const void *entry,
18287 const struct xt_match *match,
18288 void *matchinfo,
18289- unsigned int matchinfosize,
18290 unsigned int hook_mask)
18291 {
18292 const struct ip6t_rt *rtinfo = matchinfo;
18293diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6table_filter.c linux-2.6.19/net/ipv6/netfilter/ip6table_filter.c
18294--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6table_filter.c 2006-08-28 05:41:48.000000000 +0200
18295+++ linux-2.6.19/net/ipv6/netfilter/ip6table_filter.c 2006-09-22 10:04:59.000000000 +0200
18296@@ -108,7 +108,7 @@
18297 const struct net_device *out,
18298 int (*okfn)(struct sk_buff *))
18299 {
18300- return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL);
18301+ return ip6t_do_table(pskb, hook, in, out, &packet_filter);
18302 }
18303
18304 static unsigned int
18305@@ -128,7 +128,7 @@
18306 }
18307 #endif
18308
18309- return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL);
18310+ return ip6t_do_table(pskb, hook, in, out, &packet_filter);
18311 }
18312
18313 static struct nf_hook_ops ip6t_ops[] = {
18314diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.19/net/ipv6/netfilter/ip6table_mangle.c
18315--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6table_mangle.c 2006-08-28 05:41:48.000000000 +0200
18316+++ linux-2.6.19/net/ipv6/netfilter/ip6table_mangle.c 2006-09-22 10:04:59.000000000 +0200
18317@@ -138,7 +138,7 @@
18318 const struct net_device *out,
18319 int (*okfn)(struct sk_buff *))
18320 {
18321- return ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL);
18322+ return ip6t_do_table(pskb, hook, in, out, &packet_mangler);
18323 }
18324
18325 static unsigned int
18326@@ -174,7 +174,7 @@
18327 /* flowlabel and prio (includes version, which shouldn't change either */
18328 flowlabel = *((u_int32_t *) (*pskb)->nh.ipv6h);
18329
18330- ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL);
18331+ ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler);
18332
18333 if (ret != NF_DROP && ret != NF_STOLEN
18334 && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr))
18335diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/ip6table_raw.c linux-2.6.19/net/ipv6/netfilter/ip6table_raw.c
18336--- linux-2.6.18-rc5/net/ipv6/netfilter/ip6table_raw.c 2006-08-28 05:41:48.000000000 +0200
18337+++ linux-2.6.19/net/ipv6/netfilter/ip6table_raw.c 2006-09-22 10:04:59.000000000 +0200
18338@@ -122,7 +122,7 @@
18339 const struct net_device *out,
18340 int (*okfn)(struct sk_buff *))
18341 {
18342- return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
18343+ return ip6t_do_table(pskb, hook, in, out, &packet_raw);
18344 }
18345
18346 static struct nf_hook_ops ip6t_ops[] = {
18347diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c linux-2.6.19/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
18348--- linux-2.6.18-rc5/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c 2006-08-28 05:41:48.000000000 +0200
18349+++ linux-2.6.19/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c 2006-09-22 10:04:59.000000000 +0200
18350@@ -335,7 +335,7 @@
18351 /* From nf_conntrack_proto_icmpv6.c */
18352 extern unsigned int nf_ct_icmpv6_timeout;
18353
18354-/* From nf_conntrack_frag6.c */
18355+/* From nf_conntrack_reasm.c */
18356 extern unsigned int nf_ct_frag6_timeout;
18357 extern unsigned int nf_ct_frag6_low_thresh;
18358 extern unsigned int nf_ct_frag6_high_thresh;
18359diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c linux-2.6.19/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
18360--- linux-2.6.18-rc5/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c 2006-08-28 05:41:48.000000000 +0200
18361+++ linux-2.6.19/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c 2006-09-22 10:04:59.000000000 +0200
18362@@ -33,7 +33,7 @@
18363 #include <net/netfilter/nf_conntrack_core.h>
18364 #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
18365
18366-unsigned long nf_ct_icmpv6_timeout = 30*HZ;
18367+unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
18368
18369 #if 0
18370 #define DEBUGP printk
18371diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter/nf_conntrack_reasm.c linux-2.6.19/net/ipv6/netfilter/nf_conntrack_reasm.c
18372--- linux-2.6.18-rc5/net/ipv6/netfilter/nf_conntrack_reasm.c 2006-08-28 05:41:48.000000000 +0200
18373+++ linux-2.6.19/net/ipv6/netfilter/nf_conntrack_reasm.c 2006-09-22 10:04:59.000000000 +0200
18374@@ -54,9 +54,9 @@
18375 #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */
18376 #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT
18377
18378-unsigned int nf_ct_frag6_high_thresh = 256*1024;
18379-unsigned int nf_ct_frag6_low_thresh = 192*1024;
18380-unsigned long nf_ct_frag6_timeout = IPV6_FRAG_TIMEOUT;
18381+unsigned int nf_ct_frag6_high_thresh __read_mostly = 256*1024;
18382+unsigned int nf_ct_frag6_low_thresh __read_mostly = 192*1024;
18383+unsigned long nf_ct_frag6_timeout __read_mostly = IPV6_FRAG_TIMEOUT;
18384
18385 struct nf_ct_frag6_skb_cb
18386 {
18387@@ -408,7 +408,7 @@
18388 return -1;
18389 }
18390
18391- if (skb->ip_summed == CHECKSUM_HW)
18392+ if (skb->ip_summed == CHECKSUM_COMPLETE)
18393 skb->csum = csum_sub(skb->csum,
18394 csum_partial(skb->nh.raw,
18395 (u8*)(fhdr + 1) - skb->nh.raw,
18396@@ -640,7 +640,7 @@
18397 head->len += fp->len;
18398 if (head->ip_summed != fp->ip_summed)
18399 head->ip_summed = CHECKSUM_NONE;
18400- else if (head->ip_summed == CHECKSUM_HW)
18401+ else if (head->ip_summed == CHECKSUM_COMPLETE)
18402 head->csum = csum_add(head->csum, fp->csum);
18403 head->truesize += fp->truesize;
18404 atomic_sub(fp->truesize, &nf_ct_frag6_mem);
18405@@ -652,7 +652,7 @@
18406 head->nh.ipv6h->payload_len = htons(payload_len);
18407
18408 /* Yes, and fold redundant checksum back. 8) */
18409- if (head->ip_summed == CHECKSUM_HW)
18410+ if (head->ip_summed == CHECKSUM_COMPLETE)
18411 head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum);
18412
18413 fq->fragments = NULL;
18414diff -Nur linux-2.6.18-rc5/net/ipv6/netfilter.c linux-2.6.19/net/ipv6/netfilter.c
18415--- linux-2.6.18-rc5/net/ipv6/netfilter.c 2006-08-28 05:41:48.000000000 +0200
18416+++ linux-2.6.19/net/ipv6/netfilter.c 2006-09-22 10:04:58.000000000 +0200
18417@@ -87,7 +87,7 @@
18418 unsigned int csum = 0;
18419
18420 switch (skb->ip_summed) {
18421- case CHECKSUM_HW:
18422+ case CHECKSUM_COMPLETE:
18423 if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
18424 break;
18425 if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
18426diff -Nur linux-2.6.18-rc5/net/ipv6/raw.c linux-2.6.19/net/ipv6/raw.c
18427--- linux-2.6.18-rc5/net/ipv6/raw.c 2006-08-28 05:41:48.000000000 +0200
18428+++ linux-2.6.19/net/ipv6/raw.c 2006-09-22 10:04:59.000000000 +0200
18429@@ -50,6 +50,9 @@
18430 #include <net/udp.h>
18431 #include <net/inet_common.h>
18432 #include <net/tcp_states.h>
18433+#ifdef CONFIG_IPV6_MIP6
18434+#include <net/mip6.h>
18435+#endif
18436
18437 #include <net/rawv6.h>
18438 #include <net/xfrm.h>
18439@@ -169,8 +172,32 @@
18440 sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
18441
18442 while (sk) {
18443+ int filtered;
18444+
18445 delivered = 1;
18446- if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) {
18447+ switch (nexthdr) {
18448+ case IPPROTO_ICMPV6:
18449+ filtered = icmpv6_filter(sk, skb);
18450+ break;
18451+#ifdef CONFIG_IPV6_MIP6
18452+ case IPPROTO_MH:
18453+ /* XXX: To validate MH only once for each packet,
18454+ * this is placed here. It should be after checking
18455+ * xfrm policy, however it doesn't. The checking xfrm
18456+ * policy is placed in rawv6_rcv() because it is
18457+ * required for each socket.
18458+ */
18459+ filtered = mip6_mh_filter(sk, skb);
18460+ break;
18461+#endif
18462+ default:
18463+ filtered = 0;
18464+ break;
18465+ }
18466+
18467+ if (filtered < 0)
18468+ break;
18469+ if (filtered == 0) {
18470 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
18471
18472 /* Not releasing hash table! */
18473@@ -334,7 +361,7 @@
18474 if (!rp->checksum)
18475 skb->ip_summed = CHECKSUM_UNNECESSARY;
18476
18477- if (skb->ip_summed == CHECKSUM_HW) {
18478+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
18479 skb_postpull_rcsum(skb, skb->nh.raw,
18480 skb->h.raw - skb->nh.raw);
18481 if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr,
18482@@ -582,6 +609,9 @@
18483 struct iovec *iov;
18484 u8 __user *type = NULL;
18485 u8 __user *code = NULL;
18486+#ifdef CONFIG_IPV6_MIP6
18487+ u8 len = 0;
18488+#endif
18489 int probed = 0;
18490 int i;
18491
18492@@ -613,6 +643,20 @@
18493 probed = 1;
18494 }
18495 break;
18496+#ifdef CONFIG_IPV6_MIP6
18497+ case IPPROTO_MH:
18498+ if (iov->iov_base && iov->iov_len < 1)
18499+ break;
18500+ /* check if type field is readable or not. */
18501+ if (iov->iov_len > 2 - len) {
18502+ u8 __user *p = iov->iov_base;
18503+ get_user(fl->fl_mh_type, &p[2 - len]);
18504+ probed = 1;
18505+ } else
18506+ len += iov->iov_len;
18507+
18508+ break;
18509+#endif
18510 default:
18511 probed = 1;
18512 break;
18513@@ -759,6 +803,7 @@
18514
18515 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
18516 fl.oif = np->mcast_oif;
18517+ security_sk_classify_flow(sk, &fl);
18518
18519 err = ip6_dst_lookup(sk, &dst, &fl);
18520 if (err)
18521diff -Nur linux-2.6.18-rc5/net/ipv6/reassembly.c linux-2.6.19/net/ipv6/reassembly.c
18522--- linux-2.6.18-rc5/net/ipv6/reassembly.c 2006-08-28 05:41:48.000000000 +0200
18523+++ linux-2.6.19/net/ipv6/reassembly.c 2006-09-22 10:04:59.000000000 +0200
18524@@ -53,10 +53,10 @@
18525 #include <net/ndisc.h>
18526 #include <net/addrconf.h>
18527
18528-int sysctl_ip6frag_high_thresh = 256*1024;
18529-int sysctl_ip6frag_low_thresh = 192*1024;
18530+int sysctl_ip6frag_high_thresh __read_mostly = 256*1024;
18531+int sysctl_ip6frag_low_thresh __read_mostly = 192*1024;
18532
18533-int sysctl_ip6frag_time = IPV6_FRAG_TIMEOUT;
18534+int sysctl_ip6frag_time __read_mostly = IPV6_FRAG_TIMEOUT;
18535
18536 struct ip6frag_skb_cb
18537 {
18538@@ -152,7 +152,7 @@
18539 }
18540
18541 static struct timer_list ip6_frag_secret_timer;
18542-int sysctl_ip6frag_secret_interval = 10 * 60 * HZ;
18543+int sysctl_ip6frag_secret_interval __read_mostly = 10 * 60 * HZ;
18544
18545 static void ip6_frag_secret_rebuild(unsigned long dummy)
18546 {
18547@@ -433,7 +433,7 @@
18548 return;
18549 }
18550
18551- if (skb->ip_summed == CHECKSUM_HW)
18552+ if (skb->ip_summed == CHECKSUM_COMPLETE)
18553 skb->csum = csum_sub(skb->csum,
18554 csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0));
18555
18556@@ -647,7 +647,7 @@
18557 head->len += fp->len;
18558 if (head->ip_summed != fp->ip_summed)
18559 head->ip_summed = CHECKSUM_NONE;
18560- else if (head->ip_summed == CHECKSUM_HW)
18561+ else if (head->ip_summed == CHECKSUM_COMPLETE)
18562 head->csum = csum_add(head->csum, fp->csum);
18563 head->truesize += fp->truesize;
18564 atomic_sub(fp->truesize, &ip6_frag_mem);
18565@@ -662,7 +662,7 @@
18566 *skb_in = head;
18567
18568 /* Yes, and fold redundant checksum back. 8) */
18569- if (head->ip_summed == CHECKSUM_HW)
18570+ if (head->ip_summed == CHECKSUM_COMPLETE)
18571 head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum);
18572
18573 IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
18574diff -Nur linux-2.6.18-rc5/net/ipv6/route.c linux-2.6.19/net/ipv6/route.c
18575--- linux-2.6.18-rc5/net/ipv6/route.c 2006-08-28 05:41:48.000000000 +0200
18576+++ linux-2.6.19/net/ipv6/route.c 2006-09-22 10:04:59.000000000 +0200
18577@@ -22,6 +22,8 @@
18578 * routers in REACHABLE, STALE, DELAY or PROBE states).
18579 * - always select the same router if it is (probably)
18580 * reachable. otherwise, round-robin the list.
18581+ * Ville Nuorvala
18582+ * Fixed routing subtrees.
18583 */
18584
18585 #include <linux/capability.h>
18586@@ -35,7 +37,6 @@
18587 #include <linux/netdevice.h>
18588 #include <linux/in6.h>
18589 #include <linux/init.h>
18590-#include <linux/netlink.h>
18591 #include <linux/if_arp.h>
18592
18593 #ifdef CONFIG_PROC_FS
18594@@ -54,6 +55,7 @@
18595 #include <net/dst.h>
18596 #include <net/xfrm.h>
18597 #include <net/netevent.h>
18598+#include <net/netlink.h>
18599
18600 #include <asm/uaccess.h>
18601
18602@@ -74,9 +76,6 @@
18603
18604 #define CLONE_OFFLINK_ROUTE 0
18605
18606-#define RT6_SELECT_F_IFACE 0x1
18607-#define RT6_SELECT_F_REACHABLE 0x2
18608-
18609 static int ip6_rt_max_size = 4096;
18610 static int ip6_rt_gc_min_interval = HZ / 2;
18611 static int ip6_rt_gc_timeout = 60*HZ;
18612@@ -140,15 +139,49 @@
18613 .rt6i_ref = ATOMIC_INIT(1),
18614 };
18615
18616-struct fib6_node ip6_routing_table = {
18617- .leaf = &ip6_null_entry,
18618- .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
18619-};
18620+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
18621
18622-/* Protects all the ip6 fib */
18623+struct rt6_info ip6_prohibit_entry = {
18624+ .u = {
18625+ .dst = {
18626+ .__refcnt = ATOMIC_INIT(1),
18627+ .__use = 1,
18628+ .dev = &loopback_dev,
18629+ .obsolete = -1,
18630+ .error = -EACCES,
18631+ .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
18632+ .input = ip6_pkt_discard,
18633+ .output = ip6_pkt_discard_out,
18634+ .ops = &ip6_dst_ops,
18635+ .path = (struct dst_entry*)&ip6_prohibit_entry,
18636+ }
18637+ },
18638+ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
18639+ .rt6i_metric = ~(u32) 0,
18640+ .rt6i_ref = ATOMIC_INIT(1),
18641+};
18642
18643-DEFINE_RWLOCK(rt6_lock);
18644+struct rt6_info ip6_blk_hole_entry = {
18645+ .u = {
18646+ .dst = {
18647+ .__refcnt = ATOMIC_INIT(1),
18648+ .__use = 1,
18649+ .dev = &loopback_dev,
18650+ .obsolete = -1,
18651+ .error = -EINVAL,
18652+ .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
18653+ .input = ip6_pkt_discard,
18654+ .output = ip6_pkt_discard_out,
18655+ .ops = &ip6_dst_ops,
18656+ .path = (struct dst_entry*)&ip6_blk_hole_entry,
18657+ }
18658+ },
18659+ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
18660+ .rt6i_metric = ~(u32) 0,
18661+ .rt6i_ref = ATOMIC_INIT(1),
18662+};
18663
18664+#endif
18665
18666 /* allocate dst with ip6_dst_ops */
18667 static __inline__ struct rt6_info *ip6_dst_alloc(void)
18668@@ -188,8 +221,14 @@
18669 time_after(jiffies, rt->rt6i_expires));
18670 }
18671
18672+static inline int rt6_need_strict(struct in6_addr *daddr)
18673+{
18674+ return (ipv6_addr_type(daddr) &
18675+ (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
18676+}
18677+
18678 /*
18679- * Route lookup. Any rt6_lock is implied.
18680+ * Route lookup. Any table->tb6_lock is implied.
18681 */
18682
18683 static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
18684@@ -298,7 +337,7 @@
18685 int m, n;
18686
18687 m = rt6_check_dev(rt, oif);
18688- if (!m && (strict & RT6_SELECT_F_IFACE))
18689+ if (!m && (strict & RT6_LOOKUP_F_IFACE))
18690 return -1;
18691 #ifdef CONFIG_IPV6_ROUTER_PREF
18692 m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
18693@@ -306,7 +345,7 @@
18694 n = rt6_check_neigh(rt);
18695 if (n > 1)
18696 m |= 16;
18697- else if (!n && strict & RT6_SELECT_F_REACHABLE)
18698+ else if (!n && strict & RT6_LOOKUP_F_REACHABLE)
18699 return -1;
18700 return m;
18701 }
18702@@ -346,7 +385,7 @@
18703 }
18704
18705 if (!match &&
18706- (strict & RT6_SELECT_F_REACHABLE) &&
18707+ (strict & RT6_LOOKUP_F_REACHABLE) &&
18708 last && last != rt0) {
18709 /* no entries matched; do round-robin */
18710 static DEFINE_SPINLOCK(lock);
18711@@ -417,7 +456,7 @@
18712 rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex);
18713
18714 if (rt && !lifetime) {
18715- ip6_del_rt(rt, NULL, NULL, NULL);
18716+ ip6_del_rt(rt);
18717 rt = NULL;
18718 }
18719
18720@@ -441,44 +480,95 @@
18721 }
18722 #endif
18723
18724-struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
18725- int oif, int strict)
18726+#define BACKTRACK(saddr) \
18727+do { \
18728+ if (rt == &ip6_null_entry) { \
18729+ struct fib6_node *pn; \
18730+ while (fn) { \
18731+ if (fn->fn_flags & RTN_TL_ROOT) \
18732+ goto out; \
18733+ pn = fn->parent; \
18734+ if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) \
18735+ fn = fib6_lookup(pn->subtree, NULL, saddr); \
18736+ else \
18737+ fn = pn; \
18738+ if (fn->fn_flags & RTN_RTINFO) \
18739+ goto restart; \
18740+ } \
18741+ } \
18742+} while(0)
18743+
18744+static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table,
18745+ struct flowi *fl, int flags)
18746 {
18747 struct fib6_node *fn;
18748 struct rt6_info *rt;
18749
18750- read_lock_bh(&rt6_lock);
18751- fn = fib6_lookup(&ip6_routing_table, daddr, saddr);
18752- rt = rt6_device_match(fn->leaf, oif, strict);
18753+ read_lock_bh(&table->tb6_lock);
18754+ fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
18755+restart:
18756+ rt = fn->leaf;
18757+ rt = rt6_device_match(rt, fl->oif, flags);
18758+ BACKTRACK(&fl->fl6_src);
18759+out:
18760 dst_hold(&rt->u.dst);
18761- rt->u.dst.__use++;
18762- read_unlock_bh(&rt6_lock);
18763+ read_unlock_bh(&table->tb6_lock);
18764
18765 rt->u.dst.lastuse = jiffies;
18766- if (rt->u.dst.error == 0)
18767- return rt;
18768- dst_release(&rt->u.dst);
18769+ rt->u.dst.__use++;
18770+
18771+ return rt;
18772+
18773+}
18774+
18775+struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
18776+ int oif, int strict)
18777+{
18778+ struct flowi fl = {
18779+ .oif = oif,
18780+ .nl_u = {
18781+ .ip6_u = {
18782+ .daddr = *daddr,
18783+ /* TODO: saddr */
18784+ },
18785+ },
18786+ };
18787+ struct dst_entry *dst;
18788+ int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
18789+
18790+ dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
18791+ if (dst->error == 0)
18792+ return (struct rt6_info *) dst;
18793+
18794+ dst_release(dst);
18795+
18796 return NULL;
18797 }
18798
18799-/* ip6_ins_rt is called with FREE rt6_lock.
18800+/* ip6_ins_rt is called with FREE table->tb6_lock.
18801 It takes new route entry, the addition fails by any reason the
18802 route is freed. In any case, if caller does not hold it, it may
18803 be destroyed.
18804 */
18805
18806-int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh,
18807- void *_rtattr, struct netlink_skb_parms *req)
18808+static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info)
18809 {
18810 int err;
18811+ struct fib6_table *table;
18812
18813- write_lock_bh(&rt6_lock);
18814- err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr, req);
18815- write_unlock_bh(&rt6_lock);
18816+ table = rt->rt6i_table;
18817+ write_lock_bh(&table->tb6_lock);
18818+ err = fib6_add(&table->tb6_root, rt, info);
18819+ write_unlock_bh(&table->tb6_lock);
18820
18821 return err;
18822 }
18823
18824+int ip6_ins_rt(struct rt6_info *rt)
18825+{
18826+ return __ip6_ins_rt(rt, NULL);
18827+}
18828+
18829 static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr,
18830 struct in6_addr *saddr)
18831 {
18832@@ -532,51 +622,39 @@
18833 return rt;
18834 }
18835
18836-#define BACKTRACK() \
18837-if (rt == &ip6_null_entry) { \
18838- while ((fn = fn->parent) != NULL) { \
18839- if (fn->fn_flags & RTN_ROOT) { \
18840- goto out; \
18841- } \
18842- if (fn->fn_flags & RTN_RTINFO) \
18843- goto restart; \
18844- } \
18845-}
18846-
18847-
18848-void ip6_route_input(struct sk_buff *skb)
18849+static struct rt6_info *ip6_pol_route_input(struct fib6_table *table,
18850+ struct flowi *fl, int flags)
18851 {
18852 struct fib6_node *fn;
18853 struct rt6_info *rt, *nrt;
18854- int strict;
18855+ int strict = 0;
18856 int attempts = 3;
18857 int err;
18858- int reachable = RT6_SELECT_F_REACHABLE;
18859+ int reachable = RT6_LOOKUP_F_REACHABLE;
18860
18861- strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0;
18862+ strict |= flags & RT6_LOOKUP_F_IFACE;
18863
18864 relookup:
18865- read_lock_bh(&rt6_lock);
18866+ read_lock_bh(&table->tb6_lock);
18867
18868 restart_2:
18869- fn = fib6_lookup(&ip6_routing_table, &skb->nh.ipv6h->daddr,
18870- &skb->nh.ipv6h->saddr);
18871+ fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
18872
18873 restart:
18874- rt = rt6_select(&fn->leaf, skb->dev->ifindex, strict | reachable);
18875- BACKTRACK();
18876+ rt = rt6_select(&fn->leaf, fl->iif, strict | reachable);
18877+ BACKTRACK(&fl->fl6_src);
18878 if (rt == &ip6_null_entry ||
18879 rt->rt6i_flags & RTF_CACHE)
18880 goto out;
18881
18882 dst_hold(&rt->u.dst);
18883- read_unlock_bh(&rt6_lock);
18884+ read_unlock_bh(&table->tb6_lock);
18885
18886 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
18887- nrt = rt6_alloc_cow(rt, &skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr);
18888+ nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
18889 else {
18890 #if CLONE_OFFLINK_ROUTE
18891- nrt = rt6_alloc_clone(rt, &skb->nh.ipv6h->daddr);
18892+ nrt = rt6_alloc_clone(rt, &fl->fl6_dst);
18893 #else
18894 goto out2;
18895 #endif
18896@@ -587,7 +665,7 @@
18897
18898 dst_hold(&rt->u.dst);
18899 if (nrt) {
18900- err = ip6_ins_rt(nrt, NULL, NULL, &NETLINK_CB(skb));
18901+ err = ip6_ins_rt(nrt);
18902 if (!err)
18903 goto out2;
18904 }
18905@@ -596,7 +674,7 @@
18906 goto out2;
18907
18908 /*
18909- * Race condition! In the gap, when rt6_lock was
18910+ * Race condition! In the gap, when table->tb6_lock was
18911 * released someone could insert this route. Relookup.
18912 */
18913 dst_release(&rt->u.dst);
18914@@ -608,40 +686,63 @@
18915 goto restart_2;
18916 }
18917 dst_hold(&rt->u.dst);
18918- read_unlock_bh(&rt6_lock);
18919+ read_unlock_bh(&table->tb6_lock);
18920 out2:
18921 rt->u.dst.lastuse = jiffies;
18922 rt->u.dst.__use++;
18923- skb->dst = (struct dst_entry *) rt;
18924- return;
18925+
18926+ return rt;
18927 }
18928
18929-struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
18930+void ip6_route_input(struct sk_buff *skb)
18931+{
18932+ struct ipv6hdr *iph = skb->nh.ipv6h;
18933+ struct flowi fl = {
18934+ .iif = skb->dev->ifindex,
18935+ .nl_u = {
18936+ .ip6_u = {
18937+ .daddr = iph->daddr,
18938+ .saddr = iph->saddr,
18939+#ifdef CONFIG_IPV6_ROUTE_FWMARK
18940+ .fwmark = skb->nfmark,
18941+#endif
18942+ .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK,
18943+ },
18944+ },
18945+ .proto = iph->nexthdr,
18946+ };
18947+ int flags = rt6_need_strict(&iph->daddr) ? RT6_LOOKUP_F_IFACE : 0;
18948+
18949+ skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input);
18950+}
18951+
18952+static struct rt6_info *ip6_pol_route_output(struct fib6_table *table,
18953+ struct flowi *fl, int flags)
18954 {
18955 struct fib6_node *fn;
18956 struct rt6_info *rt, *nrt;
18957- int strict;
18958+ int strict = 0;
18959 int attempts = 3;
18960 int err;
18961- int reachable = RT6_SELECT_F_REACHABLE;
18962+ int reachable = RT6_LOOKUP_F_REACHABLE;
18963
18964- strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0;
18965+ strict |= flags & RT6_LOOKUP_F_IFACE;
18966
18967 relookup:
18968- read_lock_bh(&rt6_lock);
18969+ read_lock_bh(&table->tb6_lock);
18970
18971 restart_2:
18972- fn = fib6_lookup(&ip6_routing_table, &fl->fl6_dst, &fl->fl6_src);
18973+ fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
18974
18975 restart:
18976 rt = rt6_select(&fn->leaf, fl->oif, strict | reachable);
18977- BACKTRACK();
18978+ BACKTRACK(&fl->fl6_src);
18979 if (rt == &ip6_null_entry ||
18980 rt->rt6i_flags & RTF_CACHE)
18981 goto out;
18982
18983 dst_hold(&rt->u.dst);
18984- read_unlock_bh(&rt6_lock);
18985+ read_unlock_bh(&table->tb6_lock);
18986
18987 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
18988 nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
18989@@ -658,7 +759,7 @@
18990
18991 dst_hold(&rt->u.dst);
18992 if (nrt) {
18993- err = ip6_ins_rt(nrt, NULL, NULL, NULL);
18994+ err = ip6_ins_rt(nrt);
18995 if (!err)
18996 goto out2;
18997 }
18998@@ -667,7 +768,7 @@
18999 goto out2;
19000
19001 /*
19002- * Race condition! In the gap, when rt6_lock was
19003+ * Race condition! In the gap, when table->tb6_lock was
19004 * released someone could insert this route. Relookup.
19005 */
19006 dst_release(&rt->u.dst);
19007@@ -679,11 +780,21 @@
19008 goto restart_2;
19009 }
19010 dst_hold(&rt->u.dst);
19011- read_unlock_bh(&rt6_lock);
19012+ read_unlock_bh(&table->tb6_lock);
19013 out2:
19014 rt->u.dst.lastuse = jiffies;
19015 rt->u.dst.__use++;
19016- return &rt->u.dst;
19017+ return rt;
19018+}
19019+
19020+struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
19021+{
19022+ int flags = 0;
19023+
19024+ if (rt6_need_strict(&fl->fl6_dst))
19025+ flags |= RT6_LOOKUP_F_IFACE;
19026+
19027+ return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
19028 }
19029
19030
19031@@ -709,7 +820,7 @@
19032
19033 if (rt) {
19034 if (rt->rt6i_flags & RTF_CACHE)
19035- ip6_del_rt(rt, NULL, NULL, NULL);
19036+ ip6_del_rt(rt);
19037 else
19038 dst_release(dst);
19039 }
19040@@ -747,8 +858,6 @@
19041 }
19042 }
19043
19044-/* Protected by rt6_lock. */
19045-static struct dst_entry *ndisc_dst_gc_list;
19046 static int ipv6_get_mtu(struct net_device *dev);
19047
19048 static inline unsigned int ipv6_advmss(unsigned int mtu)
19049@@ -769,6 +878,9 @@
19050 return mtu;
19051 }
19052
19053+static struct dst_entry *ndisc_dst_gc_list;
19054+static DEFINE_SPINLOCK(ndisc_lock);
19055+
19056 struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
19057 struct neighbour *neigh,
19058 struct in6_addr *addr,
19059@@ -809,10 +921,10 @@
19060 rt->rt6i_dst.plen = 128;
19061 #endif
19062
19063- write_lock_bh(&rt6_lock);
19064+ spin_lock_bh(&ndisc_lock);
19065 rt->u.dst.next = ndisc_dst_gc_list;
19066 ndisc_dst_gc_list = &rt->u.dst;
19067- write_unlock_bh(&rt6_lock);
19068+ spin_unlock_bh(&ndisc_lock);
19069
19070 fib6_force_start_gc();
19071
19072@@ -826,8 +938,11 @@
19073 int freed;
19074
19075 next = NULL;
19076+ freed = 0;
19077+
19078+ spin_lock_bh(&ndisc_lock);
19079 pprev = &ndisc_dst_gc_list;
19080- freed = 0;
19081+
19082 while ((dst = *pprev) != NULL) {
19083 if (!atomic_read(&dst->__refcnt)) {
19084 *pprev = dst->next;
19085@@ -839,6 +954,8 @@
19086 }
19087 }
19088
19089+ spin_unlock_bh(&ndisc_lock);
19090+
19091 return freed;
19092 }
19093
19094@@ -899,28 +1016,24 @@
19095 *
19096 */
19097
19098-int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
19099- void *_rtattr, struct netlink_skb_parms *req)
19100+int ip6_route_add(struct fib6_config *cfg)
19101 {
19102 int err;
19103- struct rtmsg *r;
19104- struct rtattr **rta;
19105 struct rt6_info *rt = NULL;
19106 struct net_device *dev = NULL;
19107 struct inet6_dev *idev = NULL;
19108+ struct fib6_table *table;
19109 int addr_type;
19110
19111- rta = (struct rtattr **) _rtattr;
19112-
19113- if (rtmsg->rtmsg_dst_len > 128 || rtmsg->rtmsg_src_len > 128)
19114+ if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128)
19115 return -EINVAL;
19116 #ifndef CONFIG_IPV6_SUBTREES
19117- if (rtmsg->rtmsg_src_len)
19118+ if (cfg->fc_src_len)
19119 return -EINVAL;
19120 #endif
19121- if (rtmsg->rtmsg_ifindex) {
19122+ if (cfg->fc_ifindex) {
19123 err = -ENODEV;
19124- dev = dev_get_by_index(rtmsg->rtmsg_ifindex);
19125+ dev = dev_get_by_index(cfg->fc_ifindex);
19126 if (!dev)
19127 goto out;
19128 idev = in6_dev_get(dev);
19129@@ -928,8 +1041,14 @@
19130 goto out;
19131 }
19132
19133- if (rtmsg->rtmsg_metric == 0)
19134- rtmsg->rtmsg_metric = IP6_RT_PRIO_USER;
19135+ if (cfg->fc_metric == 0)
19136+ cfg->fc_metric = IP6_RT_PRIO_USER;
19137+
19138+ table = fib6_new_table(cfg->fc_table);
19139+ if (table == NULL) {
19140+ err = -ENOBUFS;
19141+ goto out;
19142+ }
19143
19144 rt = ip6_dst_alloc();
19145
19146@@ -939,14 +1058,13 @@
19147 }
19148
19149 rt->u.dst.obsolete = -1;
19150- rt->rt6i_expires = jiffies + clock_t_to_jiffies(rtmsg->rtmsg_info);
19151- if (nlh && (r = NLMSG_DATA(nlh))) {
19152- rt->rt6i_protocol = r->rtm_protocol;
19153- } else {
19154- rt->rt6i_protocol = RTPROT_BOOT;
19155- }
19156+ rt->rt6i_expires = jiffies + clock_t_to_jiffies(cfg->fc_expires);
19157
19158- addr_type = ipv6_addr_type(&rtmsg->rtmsg_dst);
19159+ if (cfg->fc_protocol == RTPROT_UNSPEC)
19160+ cfg->fc_protocol = RTPROT_BOOT;
19161+ rt->rt6i_protocol = cfg->fc_protocol;
19162+
19163+ addr_type = ipv6_addr_type(&cfg->fc_dst);
19164
19165 if (addr_type & IPV6_ADDR_MULTICAST)
19166 rt->u.dst.input = ip6_mc_input;
19167@@ -955,24 +1073,22 @@
19168
19169 rt->u.dst.output = ip6_output;
19170
19171- ipv6_addr_prefix(&rt->rt6i_dst.addr,
19172- &rtmsg->rtmsg_dst, rtmsg->rtmsg_dst_len);
19173- rt->rt6i_dst.plen = rtmsg->rtmsg_dst_len;
19174+ ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
19175+ rt->rt6i_dst.plen = cfg->fc_dst_len;
19176 if (rt->rt6i_dst.plen == 128)
19177 rt->u.dst.flags = DST_HOST;
19178
19179 #ifdef CONFIG_IPV6_SUBTREES
19180- ipv6_addr_prefix(&rt->rt6i_src.addr,
19181- &rtmsg->rtmsg_src, rtmsg->rtmsg_src_len);
19182- rt->rt6i_src.plen = rtmsg->rtmsg_src_len;
19183+ ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
19184+ rt->rt6i_src.plen = cfg->fc_src_len;
19185 #endif
19186
19187- rt->rt6i_metric = rtmsg->rtmsg_metric;
19188+ rt->rt6i_metric = cfg->fc_metric;
19189
19190 /* We cannot add true routes via loopback here,
19191 they would result in kernel looping; promote them to reject routes
19192 */
19193- if ((rtmsg->rtmsg_flags&RTF_REJECT) ||
19194+ if ((cfg->fc_flags & RTF_REJECT) ||
19195 (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
19196 /* hold loopback dev/idev if we haven't done so. */
19197 if (dev != &loopback_dev) {
19198@@ -995,12 +1111,12 @@
19199 goto install_route;
19200 }
19201
19202- if (rtmsg->rtmsg_flags & RTF_GATEWAY) {
19203+ if (cfg->fc_flags & RTF_GATEWAY) {
19204 struct in6_addr *gw_addr;
19205 int gwa_type;
19206
19207- gw_addr = &rtmsg->rtmsg_gateway;
19208- ipv6_addr_copy(&rt->rt6i_gateway, &rtmsg->rtmsg_gateway);
19209+ gw_addr = &cfg->fc_gateway;
19210+ ipv6_addr_copy(&rt->rt6i_gateway, gw_addr);
19211 gwa_type = ipv6_addr_type(gw_addr);
19212
19213 if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
19214@@ -1017,7 +1133,7 @@
19215 if (!(gwa_type&IPV6_ADDR_UNICAST))
19216 goto out;
19217
19218- grt = rt6_lookup(gw_addr, NULL, rtmsg->rtmsg_ifindex, 1);
19219+ grt = rt6_lookup(gw_addr, NULL, cfg->fc_ifindex, 1);
19220
19221 err = -EHOSTUNREACH;
19222 if (grt == NULL)
19223@@ -1049,7 +1165,7 @@
19224 if (dev == NULL)
19225 goto out;
19226
19227- if (rtmsg->rtmsg_flags & (RTF_GATEWAY|RTF_NONEXTHOP)) {
19228+ if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
19229 rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
19230 if (IS_ERR(rt->rt6i_nexthop)) {
19231 err = PTR_ERR(rt->rt6i_nexthop);
19232@@ -1058,24 +1174,24 @@
19233 }
19234 }
19235
19236- rt->rt6i_flags = rtmsg->rtmsg_flags;
19237+ rt->rt6i_flags = cfg->fc_flags;
19238
19239 install_route:
19240- if (rta && rta[RTA_METRICS-1]) {
19241- int attrlen = RTA_PAYLOAD(rta[RTA_METRICS-1]);
19242- struct rtattr *attr = RTA_DATA(rta[RTA_METRICS-1]);
19243-
19244- while (RTA_OK(attr, attrlen)) {
19245- unsigned flavor = attr->rta_type;
19246- if (flavor) {
19247- if (flavor > RTAX_MAX) {
19248+ if (cfg->fc_mx) {
19249+ struct nlattr *nla;
19250+ int remaining;
19251+
19252+ nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) {
19253+ int type = nla->nla_type;
19254+
19255+ if (type) {
19256+ if (type > RTAX_MAX) {
19257 err = -EINVAL;
19258 goto out;
19259 }
19260- rt->u.dst.metrics[flavor-1] =
19261- *(u32 *)RTA_DATA(attr);
19262+
19263+ rt->u.dst.metrics[type - 1] = nla_get_u32(nla);
19264 }
19265- attr = RTA_NEXT(attr, attrlen);
19266 }
19267 }
19268
19269@@ -1087,7 +1203,8 @@
19270 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
19271 rt->u.dst.dev = dev;
19272 rt->rt6i_idev = idev;
19273- return ip6_ins_rt(rt, nlh, _rtattr, req);
19274+ rt->rt6i_table = table;
19275+ return __ip6_ins_rt(rt, &cfg->fc_nlinfo);
19276
19277 out:
19278 if (dev)
19279@@ -1099,51 +1216,65 @@
19280 return err;
19281 }
19282
19283-int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
19284+static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
19285 {
19286 int err;
19287+ struct fib6_table *table;
19288
19289- write_lock_bh(&rt6_lock);
19290+ if (rt == &ip6_null_entry)
19291+ return -ENOENT;
19292
19293- err = fib6_del(rt, nlh, _rtattr, req);
19294+ table = rt->rt6i_table;
19295+ write_lock_bh(&table->tb6_lock);
19296+
19297+ err = fib6_del(rt, info);
19298 dst_release(&rt->u.dst);
19299
19300- write_unlock_bh(&rt6_lock);
19301+ write_unlock_bh(&table->tb6_lock);
19302
19303 return err;
19304 }
19305
19306-static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
19307+int ip6_del_rt(struct rt6_info *rt)
19308+{
19309+ return __ip6_del_rt(rt, NULL);
19310+}
19311+
19312+static int ip6_route_del(struct fib6_config *cfg)
19313 {
19314+ struct fib6_table *table;
19315 struct fib6_node *fn;
19316 struct rt6_info *rt;
19317 int err = -ESRCH;
19318
19319- read_lock_bh(&rt6_lock);
19320+ table = fib6_get_table(cfg->fc_table);
19321+ if (table == NULL)
19322+ return err;
19323
19324- fn = fib6_locate(&ip6_routing_table,
19325- &rtmsg->rtmsg_dst, rtmsg->rtmsg_dst_len,
19326- &rtmsg->rtmsg_src, rtmsg->rtmsg_src_len);
19327+ read_lock_bh(&table->tb6_lock);
19328+
19329+ fn = fib6_locate(&table->tb6_root,
19330+ &cfg->fc_dst, cfg->fc_dst_len,
19331+ &cfg->fc_src, cfg->fc_src_len);
19332
19333 if (fn) {
19334 for (rt = fn->leaf; rt; rt = rt->u.next) {
19335- if (rtmsg->rtmsg_ifindex &&
19336+ if (cfg->fc_ifindex &&
19337 (rt->rt6i_dev == NULL ||
19338- rt->rt6i_dev->ifindex != rtmsg->rtmsg_ifindex))
19339+ rt->rt6i_dev->ifindex != cfg->fc_ifindex))
19340 continue;
19341- if (rtmsg->rtmsg_flags&RTF_GATEWAY &&
19342- !ipv6_addr_equal(&rtmsg->rtmsg_gateway, &rt->rt6i_gateway))
19343+ if (cfg->fc_flags & RTF_GATEWAY &&
19344+ !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway))
19345 continue;
19346- if (rtmsg->rtmsg_metric &&
19347- rtmsg->rtmsg_metric != rt->rt6i_metric)
19348+ if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric)
19349 continue;
19350 dst_hold(&rt->u.dst);
19351- read_unlock_bh(&rt6_lock);
19352+ read_unlock_bh(&table->tb6_lock);
19353
19354- return ip6_del_rt(rt, nlh, _rtattr, req);
19355+ return __ip6_del_rt(rt, &cfg->fc_nlinfo);
19356 }
19357 }
19358- read_unlock_bh(&rt6_lock);
19359+ read_unlock_bh(&table->tb6_lock);
19360
19361 return err;
19362 }
19363@@ -1151,13 +1282,18 @@
19364 /*
19365 * Handle redirects
19366 */
19367-void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
19368- struct neighbour *neigh, u8 *lladdr, int on_link)
19369+struct ip6rd_flowi {
19370+ struct flowi fl;
19371+ struct in6_addr gateway;
19372+};
19373+
19374+static struct rt6_info *__ip6_route_redirect(struct fib6_table *table,
19375+ struct flowi *fl,
19376+ int flags)
19377 {
19378- struct rt6_info *rt, *nrt = NULL;
19379- int strict;
19380+ struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl;
19381+ struct rt6_info *rt;
19382 struct fib6_node *fn;
19383- struct netevent_redirect netevent;
19384
19385 /*
19386 * Get the "current" route for this destination and
19387@@ -1169,10 +1305,9 @@
19388 * is a bit fuzzy and one might need to check all possible
19389 * routes.
19390 */
19391- strict = ipv6_addr_type(dest) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL);
19392
19393- read_lock_bh(&rt6_lock);
19394- fn = fib6_lookup(&ip6_routing_table, dest, NULL);
19395+ read_lock_bh(&table->tb6_lock);
19396+ fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
19397 restart:
19398 for (rt = fn->leaf; rt; rt = rt->u.next) {
19399 /*
19400@@ -1187,29 +1322,60 @@
19401 continue;
19402 if (!(rt->rt6i_flags & RTF_GATEWAY))
19403 continue;
19404- if (neigh->dev != rt->rt6i_dev)
19405+ if (fl->oif != rt->rt6i_dev->ifindex)
19406 continue;
19407- if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway))
19408+ if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway))
19409 continue;
19410 break;
19411 }
19412- if (rt)
19413- dst_hold(&rt->u.dst);
19414- else if (strict) {
19415- while ((fn = fn->parent) != NULL) {
19416- if (fn->fn_flags & RTN_ROOT)
19417- break;
19418- if (fn->fn_flags & RTN_RTINFO)
19419- goto restart;
19420- }
19421- }
19422- read_unlock_bh(&rt6_lock);
19423
19424- if (!rt) {
19425+ if (!rt)
19426+ rt = &ip6_null_entry;
19427+ BACKTRACK(&fl->fl6_src);
19428+out:
19429+ dst_hold(&rt->u.dst);
19430+
19431+ read_unlock_bh(&table->tb6_lock);
19432+
19433+ return rt;
19434+};
19435+
19436+static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
19437+ struct in6_addr *src,
19438+ struct in6_addr *gateway,
19439+ struct net_device *dev)
19440+{
19441+ struct ip6rd_flowi rdfl = {
19442+ .fl = {
19443+ .oif = dev->ifindex,
19444+ .nl_u = {
19445+ .ip6_u = {
19446+ .daddr = *dest,
19447+ .saddr = *src,
19448+ },
19449+ },
19450+ },
19451+ .gateway = *gateway,
19452+ };
19453+ int flags = rt6_need_strict(dest) ? RT6_LOOKUP_F_IFACE : 0;
19454+
19455+ return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect);
19456+}
19457+
19458+void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
19459+ struct in6_addr *saddr,
19460+ struct neighbour *neigh, u8 *lladdr, int on_link)
19461+{
19462+ struct rt6_info *rt, *nrt = NULL;
19463+ struct netevent_redirect netevent;
19464+
19465+ rt = ip6_route_redirect(dest, src, saddr, neigh->dev);
19466+
19467+ if (rt == &ip6_null_entry) {
19468 if (net_ratelimit())
19469 printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
19470 "for redirect target\n");
19471- return;
19472+ goto out;
19473 }
19474
19475 /*
19476@@ -1252,7 +1418,7 @@
19477 nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
19478 nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
19479
19480- if (ip6_ins_rt(nrt, NULL, NULL, NULL))
19481+ if (ip6_ins_rt(nrt))
19482 goto out;
19483
19484 netevent.old = &rt->u.dst;
19485@@ -1260,7 +1426,7 @@
19486 call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
19487
19488 if (rt->rt6i_flags&RTF_CACHE) {
19489- ip6_del_rt(rt, NULL, NULL, NULL);
19490+ ip6_del_rt(rt);
19491 return;
19492 }
19493
19494@@ -1342,7 +1508,7 @@
19495 dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
19496 nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
19497
19498- ip6_ins_rt(nrt, NULL, NULL, NULL);
19499+ ip6_ins_rt(nrt);
19500 }
19501 out:
19502 dst_release(&rt->u.dst);
19503@@ -1378,6 +1544,7 @@
19504 #ifdef CONFIG_IPV6_SUBTREES
19505 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
19506 #endif
19507+ rt->rt6i_table = ort->rt6i_table;
19508 }
19509 return rt;
19510 }
19511@@ -1388,9 +1555,14 @@
19512 {
19513 struct fib6_node *fn;
19514 struct rt6_info *rt = NULL;
19515+ struct fib6_table *table;
19516
19517- write_lock_bh(&rt6_lock);
19518- fn = fib6_locate(&ip6_routing_table, prefix ,prefixlen, NULL, 0);
19519+ table = fib6_get_table(RT6_TABLE_INFO);
19520+ if (table == NULL)
19521+ return NULL;
19522+
19523+ write_lock_bh(&table->tb6_lock);
19524+ fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0);
19525 if (!fn)
19526 goto out;
19527
19528@@ -1405,7 +1577,7 @@
19529 break;
19530 }
19531 out:
19532- write_unlock_bh(&rt6_lock);
19533+ write_unlock_bh(&table->tb6_lock);
19534 return rt;
19535 }
19536
19537@@ -1413,21 +1585,23 @@
19538 struct in6_addr *gwaddr, int ifindex,
19539 unsigned pref)
19540 {
19541- struct in6_rtmsg rtmsg;
19542+ struct fib6_config cfg = {
19543+ .fc_table = RT6_TABLE_INFO,
19544+ .fc_metric = 1024,
19545+ .fc_ifindex = ifindex,
19546+ .fc_dst_len = prefixlen,
19547+ .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
19548+ RTF_UP | RTF_PREF(pref),
19549+ };
19550+
19551+ ipv6_addr_copy(&cfg.fc_dst, prefix);
19552+ ipv6_addr_copy(&cfg.fc_gateway, gwaddr);
19553
19554- memset(&rtmsg, 0, sizeof(rtmsg));
19555- rtmsg.rtmsg_type = RTMSG_NEWROUTE;
19556- ipv6_addr_copy(&rtmsg.rtmsg_dst, prefix);
19557- rtmsg.rtmsg_dst_len = prefixlen;
19558- ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
19559- rtmsg.rtmsg_metric = 1024;
19560- rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | RTF_UP | RTF_PREF(pref);
19561 /* We should treat it as a default route if prefix length is 0. */
19562 if (!prefixlen)
19563- rtmsg.rtmsg_flags |= RTF_DEFAULT;
19564- rtmsg.rtmsg_ifindex = ifindex;
19565+ cfg.fc_flags |= RTF_DEFAULT;
19566
19567- ip6_route_add(&rtmsg, NULL, NULL, NULL);
19568+ ip6_route_add(&cfg);
19569
19570 return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex);
19571 }
19572@@ -1436,12 +1610,14 @@
19573 struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev)
19574 {
19575 struct rt6_info *rt;
19576- struct fib6_node *fn;
19577+ struct fib6_table *table;
19578
19579- fn = &ip6_routing_table;
19580+ table = fib6_get_table(RT6_TABLE_DFLT);
19581+ if (table == NULL)
19582+ return NULL;
19583
19584- write_lock_bh(&rt6_lock);
19585- for (rt = fn->leaf; rt; rt=rt->u.next) {
19586+ write_lock_bh(&table->tb6_lock);
19587+ for (rt = table->tb6_root.leaf; rt; rt=rt->u.next) {
19588 if (dev == rt->rt6i_dev &&
19589 ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
19590 ipv6_addr_equal(&rt->rt6i_gateway, addr))
19591@@ -1449,7 +1625,7 @@
19592 }
19593 if (rt)
19594 dst_hold(&rt->u.dst);
19595- write_unlock_bh(&rt6_lock);
19596+ write_unlock_bh(&table->tb6_lock);
19597 return rt;
19598 }
19599
19600@@ -1457,43 +1633,65 @@
19601 struct net_device *dev,
19602 unsigned int pref)
19603 {
19604- struct in6_rtmsg rtmsg;
19605+ struct fib6_config cfg = {
19606+ .fc_table = RT6_TABLE_DFLT,
19607+ .fc_metric = 1024,
19608+ .fc_ifindex = dev->ifindex,
19609+ .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
19610+ RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
19611+ };
19612
19613- memset(&rtmsg, 0, sizeof(struct in6_rtmsg));
19614- rtmsg.rtmsg_type = RTMSG_NEWROUTE;
19615- ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
19616- rtmsg.rtmsg_metric = 1024;
19617- rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES |
19618- RTF_PREF(pref);
19619+ ipv6_addr_copy(&cfg.fc_gateway, gwaddr);
19620
19621- rtmsg.rtmsg_ifindex = dev->ifindex;
19622+ ip6_route_add(&cfg);
19623
19624- ip6_route_add(&rtmsg, NULL, NULL, NULL);
19625 return rt6_get_dflt_router(gwaddr, dev);
19626 }
19627
19628 void rt6_purge_dflt_routers(void)
19629 {
19630 struct rt6_info *rt;
19631+ struct fib6_table *table;
19632+
19633+ /* NOTE: Keep consistent with rt6_get_dflt_router */
19634+ table = fib6_get_table(RT6_TABLE_DFLT);
19635+ if (table == NULL)
19636+ return;
19637
19638 restart:
19639- read_lock_bh(&rt6_lock);
19640- for (rt = ip6_routing_table.leaf; rt; rt = rt->u.next) {
19641+ read_lock_bh(&table->tb6_lock);
19642+ for (rt = table->tb6_root.leaf; rt; rt = rt->u.next) {
19643 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
19644 dst_hold(&rt->u.dst);
19645-
19646- read_unlock_bh(&rt6_lock);
19647-
19648- ip6_del_rt(rt, NULL, NULL, NULL);
19649-
19650+ read_unlock_bh(&table->tb6_lock);
19651+ ip6_del_rt(rt);
19652 goto restart;
19653 }
19654 }
19655- read_unlock_bh(&rt6_lock);
19656+ read_unlock_bh(&table->tb6_lock);
19657+}
19658+
19659+static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg,
19660+ struct fib6_config *cfg)
19661+{
19662+ memset(cfg, 0, sizeof(*cfg));
19663+
19664+ cfg->fc_table = RT6_TABLE_MAIN;
19665+ cfg->fc_ifindex = rtmsg->rtmsg_ifindex;
19666+ cfg->fc_metric = rtmsg->rtmsg_metric;
19667+ cfg->fc_expires = rtmsg->rtmsg_info;
19668+ cfg->fc_dst_len = rtmsg->rtmsg_dst_len;
19669+ cfg->fc_src_len = rtmsg->rtmsg_src_len;
19670+ cfg->fc_flags = rtmsg->rtmsg_flags;
19671+
19672+ ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
19673+ ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
19674+ ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
19675 }
19676
19677 int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
19678 {
19679+ struct fib6_config cfg;
19680 struct in6_rtmsg rtmsg;
19681 int err;
19682
19683@@ -1506,14 +1704,16 @@
19684 sizeof(struct in6_rtmsg));
19685 if (err)
19686 return -EFAULT;
19687-
19688+
19689+ rtmsg_to_fib6_config(&rtmsg, &cfg);
19690+
19691 rtnl_lock();
19692 switch (cmd) {
19693 case SIOCADDRT:
19694- err = ip6_route_add(&rtmsg, NULL, NULL, NULL);
19695+ err = ip6_route_add(&cfg);
19696 break;
19697 case SIOCDELRT:
19698- err = ip6_route_del(&rtmsg, NULL, NULL, NULL);
19699+ err = ip6_route_del(&cfg);
19700 break;
19701 default:
19702 err = -EINVAL;
19703@@ -1583,6 +1787,7 @@
19704
19705 ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
19706 rt->rt6i_dst.plen = 128;
19707+ rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL);
19708
19709 atomic_set(&rt->u.dst.__refcnt, 1);
19710
19711@@ -1601,9 +1806,7 @@
19712
19713 void rt6_ifdown(struct net_device *dev)
19714 {
19715- write_lock_bh(&rt6_lock);
19716- fib6_clean_tree(&ip6_routing_table, fib6_ifdown, 0, dev);
19717- write_unlock_bh(&rt6_lock);
19718+ fib6_clean_all(fib6_ifdown, 0, dev);
19719 }
19720
19721 struct rt6_mtu_change_arg
19722@@ -1653,80 +1856,114 @@
19723
19724 void rt6_mtu_change(struct net_device *dev, unsigned mtu)
19725 {
19726- struct rt6_mtu_change_arg arg;
19727+ struct rt6_mtu_change_arg arg = {
19728+ .dev = dev,
19729+ .mtu = mtu,
19730+ };
19731
19732- arg.dev = dev;
19733- arg.mtu = mtu;
19734- read_lock_bh(&rt6_lock);
19735- fib6_clean_tree(&ip6_routing_table, rt6_mtu_change_route, 0, &arg);
19736- read_unlock_bh(&rt6_lock);
19737+ fib6_clean_all(rt6_mtu_change_route, 0, &arg);
19738 }
19739
19740-static int inet6_rtm_to_rtmsg(struct rtmsg *r, struct rtattr **rta,
19741- struct in6_rtmsg *rtmsg)
19742+static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = {
19743+ [RTA_GATEWAY] = { .len = sizeof(struct in6_addr) },
19744+ [RTA_OIF] = { .type = NLA_U32 },
19745+ [RTA_IIF] = { .type = NLA_U32 },
19746+ [RTA_PRIORITY] = { .type = NLA_U32 },
19747+ [RTA_METRICS] = { .type = NLA_NESTED },
19748+};
19749+
19750+static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
19751+ struct fib6_config *cfg)
19752 {
19753- memset(rtmsg, 0, sizeof(*rtmsg));
19754+ struct rtmsg *rtm;
19755+ struct nlattr *tb[RTA_MAX+1];
19756+ int err;
19757
19758- rtmsg->rtmsg_dst_len = r->rtm_dst_len;
19759- rtmsg->rtmsg_src_len = r->rtm_src_len;
19760- rtmsg->rtmsg_flags = RTF_UP;
19761- if (r->rtm_type == RTN_UNREACHABLE)
19762- rtmsg->rtmsg_flags |= RTF_REJECT;
19763+ err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
19764+ if (err < 0)
19765+ goto errout;
19766
19767- if (rta[RTA_GATEWAY-1]) {
19768- if (rta[RTA_GATEWAY-1]->rta_len != RTA_LENGTH(16))
19769- return -EINVAL;
19770- memcpy(&rtmsg->rtmsg_gateway, RTA_DATA(rta[RTA_GATEWAY-1]), 16);
19771- rtmsg->rtmsg_flags |= RTF_GATEWAY;
19772- }
19773- if (rta[RTA_DST-1]) {
19774- if (RTA_PAYLOAD(rta[RTA_DST-1]) < ((r->rtm_dst_len+7)>>3))
19775- return -EINVAL;
19776- memcpy(&rtmsg->rtmsg_dst, RTA_DATA(rta[RTA_DST-1]), ((r->rtm_dst_len+7)>>3));
19777+ err = -EINVAL;
19778+ rtm = nlmsg_data(nlh);
19779+ memset(cfg, 0, sizeof(*cfg));
19780+
19781+ cfg->fc_table = rtm->rtm_table;
19782+ cfg->fc_dst_len = rtm->rtm_dst_len;
19783+ cfg->fc_src_len = rtm->rtm_src_len;
19784+ cfg->fc_flags = RTF_UP;
19785+ cfg->fc_protocol = rtm->rtm_protocol;
19786+
19787+ if (rtm->rtm_type == RTN_UNREACHABLE)
19788+ cfg->fc_flags |= RTF_REJECT;
19789+
19790+ cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
19791+ cfg->fc_nlinfo.nlh = nlh;
19792+
19793+ if (tb[RTA_GATEWAY]) {
19794+ nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16);
19795+ cfg->fc_flags |= RTF_GATEWAY;
19796 }
19797- if (rta[RTA_SRC-1]) {
19798- if (RTA_PAYLOAD(rta[RTA_SRC-1]) < ((r->rtm_src_len+7)>>3))
19799- return -EINVAL;
19800- memcpy(&rtmsg->rtmsg_src, RTA_DATA(rta[RTA_SRC-1]), ((r->rtm_src_len+7)>>3));
19801+
19802+ if (tb[RTA_DST]) {
19803+ int plen = (rtm->rtm_dst_len + 7) >> 3;
19804+
19805+ if (nla_len(tb[RTA_DST]) < plen)
19806+ goto errout;
19807+
19808+ nla_memcpy(&cfg->fc_dst, tb[RTA_DST], plen);
19809 }
19810- if (rta[RTA_OIF-1]) {
19811- if (rta[RTA_OIF-1]->rta_len != RTA_LENGTH(sizeof(int)))
19812- return -EINVAL;
19813- memcpy(&rtmsg->rtmsg_ifindex, RTA_DATA(rta[RTA_OIF-1]), sizeof(int));
19814+
19815+ if (tb[RTA_SRC]) {
19816+ int plen = (rtm->rtm_src_len + 7) >> 3;
19817+
19818+ if (nla_len(tb[RTA_SRC]) < plen)
19819+ goto errout;
19820+
19821+ nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen);
19822 }
19823- if (rta[RTA_PRIORITY-1]) {
19824- if (rta[RTA_PRIORITY-1]->rta_len != RTA_LENGTH(4))
19825- return -EINVAL;
19826- memcpy(&rtmsg->rtmsg_metric, RTA_DATA(rta[RTA_PRIORITY-1]), 4);
19827+
19828+ if (tb[RTA_OIF])
19829+ cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]);
19830+
19831+ if (tb[RTA_PRIORITY])
19832+ cfg->fc_metric = nla_get_u32(tb[RTA_PRIORITY]);
19833+
19834+ if (tb[RTA_METRICS]) {
19835+ cfg->fc_mx = nla_data(tb[RTA_METRICS]);
19836+ cfg->fc_mx_len = nla_len(tb[RTA_METRICS]);
19837 }
19838- return 0;
19839+
19840+ if (tb[RTA_TABLE])
19841+ cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
19842+
19843+ err = 0;
19844+errout:
19845+ return err;
19846 }
19847
19848 int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
19849 {
19850- struct rtmsg *r = NLMSG_DATA(nlh);
19851- struct in6_rtmsg rtmsg;
19852+ struct fib6_config cfg;
19853+ int err;
19854
19855- if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
19856- return -EINVAL;
19857- return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb));
19858+ err = rtm_to_fib6_config(skb, nlh, &cfg);
19859+ if (err < 0)
19860+ return err;
19861+
19862+ return ip6_route_del(&cfg);
19863 }
19864
19865 int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
19866 {
19867- struct rtmsg *r = NLMSG_DATA(nlh);
19868- struct in6_rtmsg rtmsg;
19869+ struct fib6_config cfg;
19870+ int err;
19871
19872- if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
19873- return -EINVAL;
19874- return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb));
19875-}
19876+ err = rtm_to_fib6_config(skb, nlh, &cfg);
19877+ if (err < 0)
19878+ return err;
19879
19880-struct rt6_rtnl_dump_arg
19881-{
19882- struct sk_buff *skb;
19883- struct netlink_callback *cb;
19884-};
19885+ return ip6_route_add(&cfg);
19886+}
19887
19888 static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
19889 struct in6_addr *dst, struct in6_addr *src,
19890@@ -1734,9 +1971,9 @@
19891 int prefix, unsigned int flags)
19892 {
19893 struct rtmsg *rtm;
19894- struct nlmsghdr *nlh;
19895- unsigned char *b = skb->tail;
19896+ struct nlmsghdr *nlh;
19897 struct rta_cacheinfo ci;
19898+ u32 table;
19899
19900 if (prefix) { /* user wants prefix routes only */
19901 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
19902@@ -1745,13 +1982,21 @@
19903 }
19904 }
19905
19906- nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags);
19907- rtm = NLMSG_DATA(nlh);
19908+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags);
19909+ if (nlh == NULL)
19910+ return -ENOBUFS;
19911+
19912+ rtm = nlmsg_data(nlh);
19913 rtm->rtm_family = AF_INET6;
19914 rtm->rtm_dst_len = rt->rt6i_dst.plen;
19915 rtm->rtm_src_len = rt->rt6i_src.plen;
19916 rtm->rtm_tos = 0;
19917- rtm->rtm_table = RT_TABLE_MAIN;
19918+ if (rt->rt6i_table)
19919+ table = rt->rt6i_table->tb6_id;
19920+ else
19921+ table = RT6_TABLE_UNSPEC;
19922+ rtm->rtm_table = table;
19923+ NLA_PUT_U32(skb, RTA_TABLE, table);
19924 if (rt->rt6i_flags&RTF_REJECT)
19925 rtm->rtm_type = RTN_UNREACHABLE;
19926 else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK))
19927@@ -1772,31 +2017,35 @@
19928 rtm->rtm_flags |= RTM_F_CLONED;
19929
19930 if (dst) {
19931- RTA_PUT(skb, RTA_DST, 16, dst);
19932+ NLA_PUT(skb, RTA_DST, 16, dst);
19933 rtm->rtm_dst_len = 128;
19934 } else if (rtm->rtm_dst_len)
19935- RTA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr);
19936+ NLA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr);
19937 #ifdef CONFIG_IPV6_SUBTREES
19938 if (src) {
19939- RTA_PUT(skb, RTA_SRC, 16, src);
19940+ NLA_PUT(skb, RTA_SRC, 16, src);
19941 rtm->rtm_src_len = 128;
19942 } else if (rtm->rtm_src_len)
19943- RTA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr);
19944+ NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr);
19945 #endif
19946 if (iif)
19947- RTA_PUT(skb, RTA_IIF, 4, &iif);
19948+ NLA_PUT_U32(skb, RTA_IIF, iif);
19949 else if (dst) {
19950 struct in6_addr saddr_buf;
19951 if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)
19952- RTA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
19953+ NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
19954 }
19955+
19956 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
19957- goto rtattr_failure;
19958+ goto nla_put_failure;
19959+
19960 if (rt->u.dst.neighbour)
19961- RTA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key);
19962+ NLA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key);
19963+
19964 if (rt->u.dst.dev)
19965- RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->rt6i_dev->ifindex);
19966- RTA_PUT(skb, RTA_PRIORITY, 4, &rt->rt6i_metric);
19967+ NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
19968+
19969+ NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric);
19970 ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
19971 if (rt->rt6i_expires)
19972 ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies);
19973@@ -1808,23 +2057,21 @@
19974 ci.rta_id = 0;
19975 ci.rta_ts = 0;
19976 ci.rta_tsage = 0;
19977- RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
19978- nlh->nlmsg_len = skb->tail - b;
19979- return skb->len;
19980+ NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
19981+
19982+ return nlmsg_end(skb, nlh);
19983
19984-nlmsg_failure:
19985-rtattr_failure:
19986- skb_trim(skb, b - skb->data);
19987- return -1;
19988+nla_put_failure:
19989+ return nlmsg_cancel(skb, nlh);
19990 }
19991
19992-static int rt6_dump_route(struct rt6_info *rt, void *p_arg)
19993+int rt6_dump_route(struct rt6_info *rt, void *p_arg)
19994 {
19995 struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;
19996 int prefix;
19997
19998- if (arg->cb->nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(struct rtmsg))) {
19999- struct rtmsg *rtm = NLMSG_DATA(arg->cb->nlh);
20000+ if (nlmsg_len(arg->cb->nlh) >= sizeof(struct rtmsg)) {
20001+ struct rtmsg *rtm = nlmsg_data(arg->cb->nlh);
20002 prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0;
20003 } else
20004 prefix = 0;
20005@@ -1834,189 +2081,108 @@
20006 prefix, NLM_F_MULTI);
20007 }
20008
20009-static int fib6_dump_node(struct fib6_walker_t *w)
20010+int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
20011 {
20012- int res;
20013+ struct nlattr *tb[RTA_MAX+1];
20014 struct rt6_info *rt;
20015+ struct sk_buff *skb;
20016+ struct rtmsg *rtm;
20017+ struct flowi fl;
20018+ int err, iif = 0;
20019
20020- for (rt = w->leaf; rt; rt = rt->u.next) {
20021- res = rt6_dump_route(rt, w->args);
20022- if (res < 0) {
20023- /* Frame is full, suspend walking */
20024- w->leaf = rt;
20025- return 1;
20026- }
20027- BUG_TRAP(res!=0);
20028- }
20029- w->leaf = NULL;
20030- return 0;
20031-}
20032-
20033-static void fib6_dump_end(struct netlink_callback *cb)
20034-{
20035- struct fib6_walker_t *w = (void*)cb->args[0];
20036-
20037- if (w) {
20038- cb->args[0] = 0;
20039- fib6_walker_unlink(w);
20040- kfree(w);
20041- }
20042- cb->done = (void*)cb->args[1];
20043- cb->args[1] = 0;
20044-}
20045-
20046-static int fib6_dump_done(struct netlink_callback *cb)
20047-{
20048- fib6_dump_end(cb);
20049- return cb->done ? cb->done(cb) : 0;
20050-}
20051+ err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
20052+ if (err < 0)
20053+ goto errout;
20054
20055-int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
20056-{
20057- struct rt6_rtnl_dump_arg arg;
20058- struct fib6_walker_t *w;
20059- int res;
20060-
20061- arg.skb = skb;
20062- arg.cb = cb;
20063+ err = -EINVAL;
20064+ memset(&fl, 0, sizeof(fl));
20065
20066- w = (void*)cb->args[0];
20067- if (w == NULL) {
20068- /* New dump:
20069- *
20070- * 1. hook callback destructor.
20071- */
20072- cb->args[1] = (long)cb->done;
20073- cb->done = fib6_dump_done;
20074+ if (tb[RTA_SRC]) {
20075+ if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
20076+ goto errout;
20077
20078- /*
20079- * 2. allocate and initialize walker.
20080- */
20081- w = kzalloc(sizeof(*w), GFP_ATOMIC);
20082- if (w == NULL)
20083- return -ENOMEM;
20084- RT6_TRACE("dump<%p", w);
20085- w->root = &ip6_routing_table;
20086- w->func = fib6_dump_node;
20087- w->args = &arg;
20088- cb->args[0] = (long)w;
20089- read_lock_bh(&rt6_lock);
20090- res = fib6_walk(w);
20091- read_unlock_bh(&rt6_lock);
20092- } else {
20093- w->args = &arg;
20094- read_lock_bh(&rt6_lock);
20095- res = fib6_walk_continue(w);
20096- read_unlock_bh(&rt6_lock);
20097+ ipv6_addr_copy(&fl.fl6_src, nla_data(tb[RTA_SRC]));
20098 }
20099-#if RT6_DEBUG >= 3
20100- if (res <= 0 && skb->len == 0)
20101- RT6_TRACE("%p>dump end\n", w);
20102-#endif
20103- res = res < 0 ? res : skb->len;
20104- /* res < 0 is an error. (really, impossible)
20105- res == 0 means that dump is complete, but skb still can contain data.
20106- res > 0 dump is not complete, but frame is full.
20107- */
20108- /* Destroy walker, if dump of this table is complete. */
20109- if (res <= 0)
20110- fib6_dump_end(cb);
20111- return res;
20112-}
20113-
20114-int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
20115-{
20116- struct rtattr **rta = arg;
20117- int iif = 0;
20118- int err = -ENOBUFS;
20119- struct sk_buff *skb;
20120- struct flowi fl;
20121- struct rt6_info *rt;
20122
20123- skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
20124- if (skb == NULL)
20125- goto out;
20126+ if (tb[RTA_DST]) {
20127+ if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
20128+ goto errout;
20129
20130- /* Reserve room for dummy headers, this skb can pass
20131- through good chunk of routing engine.
20132- */
20133- skb->mac.raw = skb->data;
20134- skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
20135+ ipv6_addr_copy(&fl.fl6_dst, nla_data(tb[RTA_DST]));
20136+ }
20137
20138- memset(&fl, 0, sizeof(fl));
20139- if (rta[RTA_SRC-1])
20140- ipv6_addr_copy(&fl.fl6_src,
20141- (struct in6_addr*)RTA_DATA(rta[RTA_SRC-1]));
20142- if (rta[RTA_DST-1])
20143- ipv6_addr_copy(&fl.fl6_dst,
20144- (struct in6_addr*)RTA_DATA(rta[RTA_DST-1]));
20145+ if (tb[RTA_IIF])
20146+ iif = nla_get_u32(tb[RTA_IIF]);
20147
20148- if (rta[RTA_IIF-1])
20149- memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
20150+ if (tb[RTA_OIF])
20151+ fl.oif = nla_get_u32(tb[RTA_OIF]);
20152
20153 if (iif) {
20154 struct net_device *dev;
20155 dev = __dev_get_by_index(iif);
20156 if (!dev) {
20157 err = -ENODEV;
20158- goto out_free;
20159+ goto errout;
20160 }
20161 }
20162
20163- fl.oif = 0;
20164- if (rta[RTA_OIF-1])
20165- memcpy(&fl.oif, RTA_DATA(rta[RTA_OIF-1]), sizeof(int));
20166+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
20167+ if (skb == NULL) {
20168+ err = -ENOBUFS;
20169+ goto errout;
20170+ }
20171
20172- rt = (struct rt6_info*)ip6_route_output(NULL, &fl);
20173+ /* Reserve room for dummy headers, this skb can pass
20174+ through good chunk of routing engine.
20175+ */
20176+ skb->mac.raw = skb->data;
20177+ skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
20178
20179+ rt = (struct rt6_info*) ip6_route_output(NULL, &fl);
20180 skb->dst = &rt->u.dst;
20181
20182- NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
20183- err = rt6_fill_node(skb, rt,
20184- &fl.fl6_dst, &fl.fl6_src,
20185- iif,
20186+ err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,
20187 RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
20188 nlh->nlmsg_seq, 0, 0);
20189 if (err < 0) {
20190- err = -EMSGSIZE;
20191- goto out_free;
20192+ kfree_skb(skb);
20193+ goto errout;
20194 }
20195
20196- err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
20197- if (err > 0)
20198- err = 0;
20199-out:
20200+ err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
20201+errout:
20202 return err;
20203-out_free:
20204- kfree_skb(skb);
20205- goto out;
20206 }
20207
20208-void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh,
20209- struct netlink_skb_parms *req)
20210+void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
20211 {
20212 struct sk_buff *skb;
20213- int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
20214- u32 pid = current->pid;
20215- u32 seq = 0;
20216-
20217- if (req)
20218- pid = req->pid;
20219- if (nlh)
20220- seq = nlh->nlmsg_seq;
20221-
20222- skb = alloc_skb(size, gfp_any());
20223- if (!skb) {
20224- netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, ENOBUFS);
20225- return;
20226+ u32 pid = 0, seq = 0;
20227+ struct nlmsghdr *nlh = NULL;
20228+ int payload = sizeof(struct rtmsg) + 256;
20229+ int err = -ENOBUFS;
20230+
20231+ if (info) {
20232+ pid = info->pid;
20233+ nlh = info->nlh;
20234+ if (nlh)
20235+ seq = nlh->nlmsg_seq;
20236 }
20237- if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) {
20238+
20239+ skb = nlmsg_new(nlmsg_total_size(payload), gfp_any());
20240+ if (skb == NULL)
20241+ goto errout;
20242+
20243+ err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
20244+ if (err < 0) {
20245 kfree_skb(skb);
20246- netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, EINVAL);
20247- return;
20248+ goto errout;
20249 }
20250- NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_ROUTE;
20251- netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_ROUTE, gfp_any());
20252+
20253+ err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
20254+errout:
20255+ if (err < 0)
20256+ rtnl_set_sk_err(RTNLGRP_IPV6_ROUTE, err);
20257 }
20258
20259 /*
20260@@ -2092,16 +2258,13 @@
20261
20262 static int rt6_proc_info(char *buffer, char **start, off_t offset, int length)
20263 {
20264- struct rt6_proc_arg arg;
20265- arg.buffer = buffer;
20266- arg.offset = offset;
20267- arg.length = length;
20268- arg.skip = 0;
20269- arg.len = 0;
20270-
20271- read_lock_bh(&rt6_lock);
20272- fib6_clean_tree(&ip6_routing_table, rt6_info_route, 0, &arg);
20273- read_unlock_bh(&rt6_lock);
20274+ struct rt6_proc_arg arg = {
20275+ .buffer = buffer,
20276+ .offset = offset,
20277+ .length = length,
20278+ };
20279+
20280+ fib6_clean_all(rt6_info_route, 0, &arg);
20281
20282 *start = buffer;
20283 if (offset)
20284@@ -2256,13 +2419,9 @@
20285 {
20286 struct proc_dir_entry *p;
20287
20288- ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache",
20289- sizeof(struct rt6_info),
20290- 0, SLAB_HWCACHE_ALIGN,
20291- NULL, NULL);
20292- if (!ip6_dst_ops.kmem_cachep)
20293- panic("cannot create ip6_dst_cache");
20294-
20295+ ip6_dst_ops.kmem_cachep =
20296+ kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
20297+ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
20298 fib6_init();
20299 #ifdef CONFIG_PROC_FS
20300 p = proc_net_create("ipv6_route", 0, rt6_proc_info);
20301@@ -2274,10 +2433,16 @@
20302 #ifdef CONFIG_XFRM
20303 xfrm6_init();
20304 #endif
20305+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
20306+ fib6_rules_init();
20307+#endif
20308 }
20309
20310 void ip6_route_cleanup(void)
20311 {
20312+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
20313+ fib6_rules_cleanup();
20314+#endif
20315 #ifdef CONFIG_PROC_FS
20316 proc_net_remove("ipv6_route");
20317 proc_net_remove("rt6_stats");
20318diff -Nur linux-2.6.18-rc5/net/ipv6/tcp_ipv6.c linux-2.6.19/net/ipv6/tcp_ipv6.c
20319--- linux-2.6.18-rc5/net/ipv6/tcp_ipv6.c 2006-08-28 05:41:48.000000000 +0200
20320+++ linux-2.6.19/net/ipv6/tcp_ipv6.c 2006-09-22 10:04:59.000000000 +0200
20321@@ -251,6 +251,8 @@
20322 final_p = &final;
20323 }
20324
20325+ security_sk_classify_flow(sk, &fl);
20326+
20327 err = ip6_dst_lookup(sk, &dst, &fl);
20328 if (err)
20329 goto failure;
20330@@ -270,7 +272,7 @@
20331 inet->rcv_saddr = LOOPBACK4_IPV6;
20332
20333 sk->sk_gso_type = SKB_GSO_TCPV6;
20334- __ip6_dst_store(sk, dst, NULL);
20335+ __ip6_dst_store(sk, dst, NULL, NULL);
20336
20337 icsk->icsk_ext_hdr_len = 0;
20338 if (np->opt)
20339@@ -374,6 +376,7 @@
20340 fl.oif = sk->sk_bound_dev_if;
20341 fl.fl_ip_dport = inet->dport;
20342 fl.fl_ip_sport = inet->sport;
20343+ security_skb_classify_flow(skb, &fl);
20344
20345 if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
20346 sk->sk_err_soft = -err;
20347@@ -467,6 +470,7 @@
20348 fl.oif = treq->iif;
20349 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
20350 fl.fl_ip_sport = inet_sk(sk)->sport;
20351+ security_req_classify_flow(req, &fl);
20352
20353 if (dst == NULL) {
20354 opt = np->opt;
20355@@ -541,7 +545,7 @@
20356 struct ipv6_pinfo *np = inet6_sk(sk);
20357 struct tcphdr *th = skb->h.th;
20358
20359- if (skb->ip_summed == CHECKSUM_HW) {
20360+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
20361 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0);
20362 skb->csum = offsetof(struct tcphdr, check);
20363 } else {
20364@@ -566,7 +570,7 @@
20365 th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
20366 IPPROTO_TCP, 0);
20367 skb->csum = offsetof(struct tcphdr, check);
20368- skb->ip_summed = CHECKSUM_HW;
20369+ skb->ip_summed = CHECKSUM_PARTIAL;
20370 return 0;
20371 }
20372
20373@@ -625,6 +629,7 @@
20374 fl.oif = inet6_iif(skb);
20375 fl.fl_ip_dport = t1->dest;
20376 fl.fl_ip_sport = t1->source;
20377+ security_skb_classify_flow(skb, &fl);
20378
20379 /* sk = NULL, but it is safe for now. RST socket required. */
20380 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
20381@@ -691,6 +696,7 @@
20382 fl.oif = inet6_iif(skb);
20383 fl.fl_ip_dport = t1->dest;
20384 fl.fl_ip_sport = t1->source;
20385+ security_skb_classify_flow(skb, &fl);
20386
20387 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
20388 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
20389@@ -820,6 +826,8 @@
20390
20391 tcp_rsk(req)->snt_isn = isn;
20392
20393+ security_inet_conn_request(sk, skb, req);
20394+
20395 if (tcp_v6_send_synack(sk, req, NULL))
20396 goto drop;
20397
20398@@ -923,6 +931,7 @@
20399 fl.oif = sk->sk_bound_dev_if;
20400 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
20401 fl.fl_ip_sport = inet_sk(sk)->sport;
20402+ security_req_classify_flow(req, &fl);
20403
20404 if (ip6_dst_lookup(sk, &dst, &fl))
20405 goto out;
20406@@ -945,7 +954,7 @@
20407 */
20408
20409 newsk->sk_gso_type = SKB_GSO_TCPV6;
20410- __ip6_dst_store(newsk, dst, NULL);
20411+ __ip6_dst_store(newsk, dst, NULL, NULL);
20412
20413 newtcp6sk = (struct tcp6_sock *)newsk;
20414 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
20415@@ -1024,7 +1033,7 @@
20416
20417 static int tcp_v6_checksum_init(struct sk_buff *skb)
20418 {
20419- if (skb->ip_summed == CHECKSUM_HW) {
20420+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
20421 if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
20422 &skb->nh.ipv6h->daddr,skb->csum)) {
20423 skb->ip_summed = CHECKSUM_UNNECESSARY;
20424@@ -1066,7 +1075,7 @@
20425 if (skb->protocol == htons(ETH_P_IP))
20426 return tcp_v4_do_rcv(sk, skb);
20427
20428- if (sk_filter(sk, skb, 0))
20429+ if (sk_filter(sk, skb))
20430 goto discard;
20431
20432 /*
20433@@ -1223,7 +1232,7 @@
20434 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
20435 goto discard_and_relse;
20436
20437- if (sk_filter(sk, skb, 0))
20438+ if (sk_filter(sk, skb))
20439 goto discard_and_relse;
20440
20441 skb->dev = NULL;
20442diff -Nur linux-2.6.18-rc5/net/ipv6/udp.c linux-2.6.19/net/ipv6/udp.c
20443--- linux-2.6.18-rc5/net/ipv6/udp.c 2006-08-28 05:41:48.000000000 +0200
20444+++ linux-2.6.19/net/ipv6/udp.c 2006-09-22 10:04:59.000000000 +0200
20445@@ -61,81 +61,9 @@
20446
20447 DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
20448
20449-/* Grrr, addr_type already calculated by caller, but I don't want
20450- * to add some silly "cookie" argument to this method just for that.
20451- */
20452-static int udp_v6_get_port(struct sock *sk, unsigned short snum)
20453+static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
20454 {
20455- struct sock *sk2;
20456- struct hlist_node *node;
20457-
20458- write_lock_bh(&udp_hash_lock);
20459- if (snum == 0) {
20460- int best_size_so_far, best, result, i;
20461-
20462- if (udp_port_rover > sysctl_local_port_range[1] ||
20463- udp_port_rover < sysctl_local_port_range[0])
20464- udp_port_rover = sysctl_local_port_range[0];
20465- best_size_so_far = 32767;
20466- best = result = udp_port_rover;
20467- for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
20468- int size;
20469- struct hlist_head *list;
20470-
20471- list = &udp_hash[result & (UDP_HTABLE_SIZE - 1)];
20472- if (hlist_empty(list)) {
20473- if (result > sysctl_local_port_range[1])
20474- result = sysctl_local_port_range[0] +
20475- ((result - sysctl_local_port_range[0]) &
20476- (UDP_HTABLE_SIZE - 1));
20477- goto gotit;
20478- }
20479- size = 0;
20480- sk_for_each(sk2, node, list)
20481- if (++size >= best_size_so_far)
20482- goto next;
20483- best_size_so_far = size;
20484- best = result;
20485- next:;
20486- }
20487- result = best;
20488- for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) {
20489- if (result > sysctl_local_port_range[1])
20490- result = sysctl_local_port_range[0]
20491- + ((result - sysctl_local_port_range[0]) &
20492- (UDP_HTABLE_SIZE - 1));
20493- if (!udp_lport_inuse(result))
20494- break;
20495- }
20496- if (i >= (1 << 16) / UDP_HTABLE_SIZE)
20497- goto fail;
20498-gotit:
20499- udp_port_rover = snum = result;
20500- } else {
20501- sk_for_each(sk2, node,
20502- &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]) {
20503- if (inet_sk(sk2)->num == snum &&
20504- sk2 != sk &&
20505- (!sk2->sk_bound_dev_if ||
20506- !sk->sk_bound_dev_if ||
20507- sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
20508- (!sk2->sk_reuse || !sk->sk_reuse) &&
20509- ipv6_rcv_saddr_equal(sk, sk2))
20510- goto fail;
20511- }
20512- }
20513-
20514- inet_sk(sk)->num = snum;
20515- if (sk_unhashed(sk)) {
20516- sk_add_node(sk, &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]);
20517- sock_prot_inc_use(sk->sk_prot);
20518- }
20519- write_unlock_bh(&udp_hash_lock);
20520- return 0;
20521-
20522-fail:
20523- write_unlock_bh(&udp_hash_lock);
20524- return 1;
20525+ return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
20526 }
20527
20528 static void udp_v6_hash(struct sock *sk)
20529@@ -345,6 +273,8 @@
20530
20531 static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
20532 {
20533+ int rc;
20534+
20535 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
20536 kfree_skb(skb);
20537 return -1;
20538@@ -356,7 +286,10 @@
20539 return 0;
20540 }
20541
20542- if (sock_queue_rcv_skb(sk,skb)<0) {
20543+ if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
20544+ /* Note that an ENOMEM error is charged twice */
20545+ if (rc == -ENOMEM)
20546+ UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS);
20547 UDP6_INC_STATS_BH(UDP_MIB_INERRORS);
20548 kfree_skb(skb);
20549 return 0;
20550@@ -475,7 +408,7 @@
20551 uh = skb->h.uh;
20552 }
20553
20554- if (skb->ip_summed == CHECKSUM_HW &&
20555+ if (skb->ip_summed == CHECKSUM_COMPLETE &&
20556 !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum))
20557 skb->ip_summed = CHECKSUM_UNNECESSARY;
20558
20559@@ -782,6 +715,8 @@
20560 connected = 0;
20561 }
20562
20563+ security_sk_classify_flow(sk, fl);
20564+
20565 err = ip6_sk_dst_lookup(sk, &dst, fl);
20566 if (err)
20567 goto out;
20568@@ -840,7 +775,12 @@
20569 if (connected) {
20570 ip6_dst_store(sk, dst,
20571 ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ?
20572- &np->daddr : NULL);
20573+ &np->daddr : NULL,
20574+#ifdef CONFIG_IPV6_SUBTREES
20575+ ipv6_addr_equal(&fl->fl6_src, &np->saddr) ?
20576+ &np->saddr :
20577+#endif
20578+ NULL);
20579 } else {
20580 dst_release(dst);
20581 }
20582@@ -855,6 +795,16 @@
20583 UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS);
20584 return len;
20585 }
20586+ /*
20587+ * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space. Reporting
20588+ * ENOBUFS might not be good (it's not tunable per se), but otherwise
20589+ * we don't have a good statistic (IpOutDiscards but it can be too many
20590+ * things). We could add another new stat but at least for now that
20591+ * seems like overkill.
20592+ */
20593+ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
20594+ UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS);
20595+ }
20596 return err;
20597
20598 do_confirm:
20599diff -Nur linux-2.6.18-rc5/net/ipv6/xfrm6_input.c linux-2.6.19/net/ipv6/xfrm6_input.c
20600--- linux-2.6.18-rc5/net/ipv6/xfrm6_input.c 2006-08-28 05:41:48.000000000 +0200
20601+++ linux-2.6.19/net/ipv6/xfrm6_input.c 2006-09-22 10:04:59.000000000 +0200
20602@@ -72,7 +72,7 @@
20603 if (x->mode->input(x, skb))
20604 goto drop;
20605
20606- if (x->props.mode) { /* XXX */
20607+ if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */
20608 decaps = 1;
20609 break;
20610 }
20611@@ -138,3 +138,111 @@
20612 {
20613 return xfrm6_rcv_spi(*pskb, 0);
20614 }
20615+
20616+int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
20617+ xfrm_address_t *saddr, u8 proto)
20618+{
20619+ struct xfrm_state *x = NULL;
20620+ int wildcard = 0;
20621+ struct in6_addr any;
20622+ xfrm_address_t *xany;
20623+ struct xfrm_state *xfrm_vec_one = NULL;
20624+ int nh = 0;
20625+ int i = 0;
20626+
20627+ ipv6_addr_set(&any, 0, 0, 0, 0);
20628+ xany = (xfrm_address_t *)&any;
20629+
20630+ for (i = 0; i < 3; i++) {
20631+ xfrm_address_t *dst, *src;
20632+ switch (i) {
20633+ case 0:
20634+ dst = daddr;
20635+ src = saddr;
20636+ break;
20637+ case 1:
20638+ /* lookup state with wild-card source address */
20639+ wildcard = 1;
20640+ dst = daddr;
20641+ src = xany;
20642+ break;
20643+ case 2:
20644+ default:
20645+ /* lookup state with wild-card addresses */
20646+ wildcard = 1; /* XXX */
20647+ dst = xany;
20648+ src = xany;
20649+ break;
20650+ }
20651+
20652+ x = xfrm_state_lookup_byaddr(dst, src, proto, AF_INET6);
20653+ if (!x)
20654+ continue;
20655+
20656+ spin_lock(&x->lock);
20657+
20658+ if (wildcard) {
20659+ if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) {
20660+ spin_unlock(&x->lock);
20661+ xfrm_state_put(x);
20662+ x = NULL;
20663+ continue;
20664+ }
20665+ }
20666+
20667+ if (unlikely(x->km.state != XFRM_STATE_VALID)) {
20668+ spin_unlock(&x->lock);
20669+ xfrm_state_put(x);
20670+ x = NULL;
20671+ continue;
20672+ }
20673+ if (xfrm_state_check_expire(x)) {
20674+ spin_unlock(&x->lock);
20675+ xfrm_state_put(x);
20676+ x = NULL;
20677+ continue;
20678+ }
20679+
20680+ nh = x->type->input(x, skb);
20681+ if (nh <= 0) {
20682+ spin_unlock(&x->lock);
20683+ xfrm_state_put(x);
20684+ x = NULL;
20685+ continue;
20686+ }
20687+
20688+ x->curlft.bytes += skb->len;
20689+ x->curlft.packets++;
20690+
20691+ spin_unlock(&x->lock);
20692+
20693+ xfrm_vec_one = x;
20694+ break;
20695+ }
20696+
20697+ if (!xfrm_vec_one)
20698+ goto drop;
20699+
20700+ /* Allocate new secpath or COW existing one. */
20701+ if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
20702+ struct sec_path *sp;
20703+ sp = secpath_dup(skb->sp);
20704+ if (!sp)
20705+ goto drop;
20706+ if (skb->sp)
20707+ secpath_put(skb->sp);
20708+ skb->sp = sp;
20709+ }
20710+
20711+ if (1 + skb->sp->len > XFRM_MAX_DEPTH)
20712+ goto drop;
20713+
20714+ skb->sp->xvec[skb->sp->len] = xfrm_vec_one;
20715+ skb->sp->len ++;
20716+
20717+ return 1;
20718+drop:
20719+ if (xfrm_vec_one)
20720+ xfrm_state_put(xfrm_vec_one);
20721+ return -1;
20722+}
20723diff -Nur linux-2.6.18-rc5/net/ipv6/xfrm6_mode_ro.c linux-2.6.19/net/ipv6/xfrm6_mode_ro.c
20724--- linux-2.6.18-rc5/net/ipv6/xfrm6_mode_ro.c 1970-01-01 01:00:00.000000000 +0100
20725+++ linux-2.6.19/net/ipv6/xfrm6_mode_ro.c 2006-09-22 10:04:59.000000000 +0200
20726@@ -0,0 +1,93 @@
20727+/*
20728+ * xfrm6_mode_ro.c - Route optimization mode for IPv6.
20729+ *
20730+ * Copyright (C)2003-2006 Helsinki University of Technology
20731+ * Copyright (C)2003-2006 USAGI/WIDE Project
20732+ *
20733+ * This program is free software; you can redistribute it and/or modify
20734+ * it under the terms of the GNU General Public License as published by
20735+ * the Free Software Foundation; either version 2 of the License, or
20736+ * (at your option) any later version.
20737+ *
20738+ * This program is distributed in the hope that it will be useful,
20739+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20740+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20741+ * GNU General Public License for more details.
20742+ *
20743+ * You should have received a copy of the GNU General Public License
20744+ * along with this program; if not, write to the Free Software
20745+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20746+ */
20747+/*
20748+ * Authors:
20749+ * Noriaki TAKAMIYA @USAGI
20750+ * Masahide NAKAMURA @USAGI
20751+ */
20752+
20753+#include <linux/init.h>
20754+#include <linux/kernel.h>
20755+#include <linux/module.h>
20756+#include <linux/skbuff.h>
20757+#include <linux/stringify.h>
20758+#include <net/ipv6.h>
20759+#include <net/xfrm.h>
20760+
20761+/* Add route optimization header space.
20762+ *
20763+ * The IP header and mutable extension headers will be moved forward to make
20764+ * space for the route optimization header.
20765+ *
20766+ * On exit, skb->h will be set to the start of the encapsulation header to be
20767+ * filled in by x->type->output and skb->nh will be set to the nextheader field
20768+ * of the extension header directly preceding the encapsulation header, or in
20769+ * its absence, that of the top IP header. The value of skb->data will always
20770+ * point to the top IP header.
20771+ */
20772+static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
20773+{
20774+ struct ipv6hdr *iph;
20775+ u8 *prevhdr;
20776+ int hdr_len;
20777+
20778+ skb_push(skb, x->props.header_len);
20779+ iph = skb->nh.ipv6h;
20780+
20781+ hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
20782+ skb->nh.raw = prevhdr - x->props.header_len;
20783+ skb->h.raw = skb->data + hdr_len;
20784+ memmove(skb->data, iph, hdr_len);
20785+ return 0;
20786+}
20787+
20788+/*
20789+ * Do nothing about routing optimization header unlike IPsec.
20790+ */
20791+static int xfrm6_ro_input(struct xfrm_state *x, struct sk_buff *skb)
20792+{
20793+ return 0;
20794+}
20795+
20796+static struct xfrm_mode xfrm6_ro_mode = {
20797+ .input = xfrm6_ro_input,
20798+ .output = xfrm6_ro_output,
20799+ .owner = THIS_MODULE,
20800+ .encap = XFRM_MODE_ROUTEOPTIMIZATION,
20801+};
20802+
20803+static int __init xfrm6_ro_init(void)
20804+{
20805+ return xfrm_register_mode(&xfrm6_ro_mode, AF_INET6);
20806+}
20807+
20808+static void __exit xfrm6_ro_exit(void)
20809+{
20810+ int err;
20811+
20812+ err = xfrm_unregister_mode(&xfrm6_ro_mode, AF_INET6);
20813+ BUG_ON(err);
20814+}
20815+
20816+module_init(xfrm6_ro_init);
20817+module_exit(xfrm6_ro_exit);
20818+MODULE_LICENSE("GPL");
20819+MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_ROUTEOPTIMIZATION);
20820diff -Nur linux-2.6.18-rc5/net/ipv6/xfrm6_mode_transport.c linux-2.6.19/net/ipv6/xfrm6_mode_transport.c
20821--- linux-2.6.18-rc5/net/ipv6/xfrm6_mode_transport.c 2006-08-28 05:41:48.000000000 +0200
20822+++ linux-2.6.19/net/ipv6/xfrm6_mode_transport.c 2006-09-22 10:04:59.000000000 +0200
20823@@ -25,9 +25,8 @@
20824 * its absence, that of the top IP header. The value of skb->data will always
20825 * point to the top IP header.
20826 */
20827-static int xfrm6_transport_output(struct sk_buff *skb)
20828+static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
20829 {
20830- struct xfrm_state *x = skb->dst->xfrm;
20831 struct ipv6hdr *iph;
20832 u8 *prevhdr;
20833 int hdr_len;
20834@@ -35,7 +34,7 @@
20835 skb_push(skb, x->props.header_len);
20836 iph = skb->nh.ipv6h;
20837
20838- hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
20839+ hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
20840 skb->nh.raw = prevhdr - x->props.header_len;
20841 skb->h.raw = skb->data + hdr_len;
20842 memmove(skb->data, iph, hdr_len);
20843diff -Nur linux-2.6.18-rc5/net/ipv6/xfrm6_mode_tunnel.c linux-2.6.19/net/ipv6/xfrm6_mode_tunnel.c
20844--- linux-2.6.18-rc5/net/ipv6/xfrm6_mode_tunnel.c 2006-08-28 05:41:48.000000000 +0200
20845+++ linux-2.6.19/net/ipv6/xfrm6_mode_tunnel.c 2006-09-22 10:04:59.000000000 +0200
20846@@ -37,10 +37,9 @@
20847 * its absence, that of the top IP header. The value of skb->data will always
20848 * point to the top IP header.
20849 */
20850-static int xfrm6_tunnel_output(struct sk_buff *skb)
20851+static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
20852 {
20853 struct dst_entry *dst = skb->dst;
20854- struct xfrm_state *x = dst->xfrm;
20855 struct ipv6hdr *iph, *top_iph;
20856 int dsfield;
20857
20858diff -Nur linux-2.6.18-rc5/net/ipv6/xfrm6_output.c linux-2.6.19/net/ipv6/xfrm6_output.c
20859--- linux-2.6.18-rc5/net/ipv6/xfrm6_output.c 2006-08-28 05:41:48.000000000 +0200
20860+++ linux-2.6.19/net/ipv6/xfrm6_output.c 2006-09-22 10:04:59.000000000 +0200
20861@@ -17,6 +17,12 @@
20862 #include <net/ipv6.h>
20863 #include <net/xfrm.h>
20864
20865+int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
20866+ u8 **prevhdr)
20867+{
20868+ return ip6_find_1stfragopt(skb, prevhdr);
20869+}
20870+
20871 static int xfrm6_tunnel_check_size(struct sk_buff *skb)
20872 {
20873 int mtu, ret = 0;
20874@@ -41,13 +47,13 @@
20875 struct xfrm_state *x = dst->xfrm;
20876 int err;
20877
20878- if (skb->ip_summed == CHECKSUM_HW) {
20879- err = skb_checksum_help(skb, 0);
20880+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
20881+ err = skb_checksum_help(skb);
20882 if (err)
20883 goto error_nolock;
20884 }
20885
20886- if (x->props.mode) {
20887+ if (x->props.mode == XFRM_MODE_TUNNEL) {
20888 err = xfrm6_tunnel_check_size(skb);
20889 if (err)
20890 goto error_nolock;
20891@@ -59,7 +65,7 @@
20892 if (err)
20893 goto error;
20894
20895- err = x->mode->output(skb);
20896+ err = x->mode->output(x, skb);
20897 if (err)
20898 goto error;
20899
20900@@ -69,6 +75,8 @@
20901
20902 x->curlft.bytes += skb->len;
20903 x->curlft.packets++;
20904+ if (x->props.mode == XFRM_MODE_ROUTEOPTIMIZATION)
20905+ x->lastused = (u64)xtime.tv_sec;
20906
20907 spin_unlock_bh(&x->lock);
20908
20909@@ -80,7 +88,7 @@
20910 }
20911 dst = skb->dst;
20912 x = dst->xfrm;
20913- } while (x && !x->props.mode);
20914+ } while (x && (x->props.mode != XFRM_MODE_TUNNEL));
20915
20916 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
20917 err = 0;
20918diff -Nur linux-2.6.18-rc5/net/ipv6/xfrm6_policy.c linux-2.6.19/net/ipv6/xfrm6_policy.c
20919--- linux-2.6.18-rc5/net/ipv6/xfrm6_policy.c 2006-08-28 05:41:48.000000000 +0200
20920+++ linux-2.6.19/net/ipv6/xfrm6_policy.c 2006-09-22 10:04:59.000000000 +0200
20921@@ -18,6 +18,9 @@
20922 #include <net/ip.h>
20923 #include <net/ipv6.h>
20924 #include <net/ip6_route.h>
20925+#ifdef CONFIG_IPV6_MIP6
20926+#include <net/mip6.h>
20927+#endif
20928
20929 static struct dst_ops xfrm6_dst_ops;
20930 static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
20931@@ -31,6 +34,26 @@
20932 return err;
20933 }
20934
20935+static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
20936+{
20937+ struct rt6_info *rt;
20938+ struct flowi fl_tunnel = {
20939+ .nl_u = {
20940+ .ip6_u = {
20941+ .daddr = *(struct in6_addr *)&daddr->a6,
20942+ },
20943+ },
20944+ };
20945+
20946+ if (!xfrm6_dst_lookup((struct xfrm_dst **)&rt, &fl_tunnel)) {
20947+ ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)&daddr->a6,
20948+ (struct in6_addr *)&saddr->a6);
20949+ dst_release(&rt->u.dst);
20950+ return 0;
20951+ }
20952+ return -EHOSTUNREACH;
20953+}
20954+
20955 static struct dst_entry *
20956 __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
20957 {
20958@@ -50,7 +73,9 @@
20959 xdst->u.rt6.rt6i_src.plen);
20960 if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
20961 ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
20962- xfrm_bundle_ok(xdst, fl, AF_INET6)) {
20963+ xfrm_bundle_ok(xdst, fl, AF_INET6,
20964+ (xdst->u.rt6.rt6i_dst.plen != 128 ||
20965+ xdst->u.rt6.rt6i_src.plen != 128))) {
20966 dst_clone(dst);
20967 break;
20968 }
20969@@ -59,6 +84,40 @@
20970 return dst;
20971 }
20972
20973+static inline struct in6_addr*
20974+__xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr)
20975+{
20976+ return (x->type->remote_addr) ?
20977+ (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t *)addr) :
20978+ (struct in6_addr*)&x->id.daddr;
20979+}
20980+
20981+static inline struct in6_addr*
20982+__xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr)
20983+{
20984+ return (x->type->local_addr) ?
20985+ (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t *)addr) :
20986+ (struct in6_addr*)&x->props.saddr;
20987+}
20988+
20989+static inline void
20990+__xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x)
20991+{
20992+ if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
20993+ *nflen += x->props.header_len;
20994+ else
20995+ *len += x->props.header_len;
20996+}
20997+
20998+static inline void
20999+__xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x)
21000+{
21001+ if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
21002+ *nflen -= x->props.header_len;
21003+ else
21004+ *len -= x->props.header_len;
21005+}
21006+
21007 /* Allocate chain of dst_entry's, attach known xfrm's, calculate
21008 * all the metrics... Shortly, bundle a bundle.
21009 */
21010@@ -83,6 +142,7 @@
21011 int i;
21012 int err = 0;
21013 int header_len = 0;
21014+ int nfheader_len = 0;
21015 int trailer_len = 0;
21016
21017 dst = dst_prev = NULL;
21018@@ -109,17 +169,18 @@
21019
21020 xdst = (struct xfrm_dst *)dst1;
21021 xdst->route = &rt->u.dst;
21022+ xdst->genid = xfrm[i]->genid;
21023 if (rt->rt6i_node)
21024 xdst->route_cookie = rt->rt6i_node->fn_sernum;
21025
21026 dst1->next = dst_prev;
21027 dst_prev = dst1;
21028- if (xfrm[i]->props.mode) {
21029- remote = (struct in6_addr*)&xfrm[i]->id.daddr;
21030- local = (struct in6_addr*)&xfrm[i]->props.saddr;
21031+ if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
21032+ remote = __xfrm6_bundle_addr_remote(xfrm[i], remote);
21033+ local = __xfrm6_bundle_addr_local(xfrm[i], local);
21034 tunnel = 1;
21035 }
21036- header_len += xfrm[i]->props.header_len;
21037+ __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
21038 trailer_len += xfrm[i]->props.trailer_len;
21039
21040 if (tunnel) {
21041@@ -154,6 +215,7 @@
21042 dst_prev->flags |= DST_HOST;
21043 dst_prev->lastuse = jiffies;
21044 dst_prev->header_len = header_len;
21045+ dst_prev->nfheader_len = nfheader_len;
21046 dst_prev->trailer_len = trailer_len;
21047 memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
21048
21049@@ -172,7 +234,7 @@
21050 x->u.rt6.rt6i_src = rt0->rt6i_src;
21051 x->u.rt6.rt6i_idev = rt0->rt6i_idev;
21052 in6_dev_hold(rt0->rt6i_idev);
21053- header_len -= x->u.dst.xfrm->props.header_len;
21054+ __xfrm6_bundle_len_dec(&header_len, &nfheader_len, x->u.dst.xfrm);
21055 trailer_len -= x->u.dst.xfrm->props.trailer_len;
21056 }
21057
21058@@ -232,6 +294,18 @@
21059 fl->proto = nexthdr;
21060 return;
21061
21062+#ifdef CONFIG_IPV6_MIP6
21063+ case IPPROTO_MH:
21064+ if (pskb_may_pull(skb, skb->nh.raw + offset + 3 - skb->data)) {
21065+ struct ip6_mh *mh;
21066+ mh = (struct ip6_mh *)exthdr;
21067+
21068+ fl->fl_mh_type = mh->ip6mh_type;
21069+ }
21070+ fl->proto = nexthdr;
21071+ return;
21072+#endif
21073+
21074 /* XXX Why are there these headers? */
21075 case IPPROTO_AH:
21076 case IPPROTO_ESP:
21077@@ -308,6 +382,7 @@
21078 .family = AF_INET6,
21079 .dst_ops = &xfrm6_dst_ops,
21080 .dst_lookup = xfrm6_dst_lookup,
21081+ .get_saddr = xfrm6_get_saddr,
21082 .find_bundle = __xfrm6_find_bundle,
21083 .bundle_create = __xfrm6_bundle_create,
21084 .decode_session = _decode_session6,
21085diff -Nur linux-2.6.18-rc5/net/ipv6/xfrm6_state.c linux-2.6.19/net/ipv6/xfrm6_state.c
21086--- linux-2.6.18-rc5/net/ipv6/xfrm6_state.c 2006-08-28 05:41:48.000000000 +0200
21087+++ linux-2.6.19/net/ipv6/xfrm6_state.c 2006-09-22 10:04:59.000000000 +0200
21088@@ -42,102 +42,135 @@
21089 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
21090 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
21091 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr));
21092- if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) {
21093- struct rt6_info *rt;
21094- struct flowi fl_tunnel = {
21095- .nl_u = {
21096- .ip6_u = {
21097- .daddr = *(struct in6_addr *)daddr,
21098- }
21099- }
21100- };
21101- if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
21102- &fl_tunnel, AF_INET6)) {
21103- ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr,
21104- (struct in6_addr *)&x->props.saddr);
21105- dst_release(&rt->u.dst);
21106- }
21107- }
21108 x->props.mode = tmpl->mode;
21109 x->props.reqid = tmpl->reqid;
21110 x->props.family = AF_INET6;
21111 }
21112
21113-static struct xfrm_state *
21114-__xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto)
21115+static int
21116+__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
21117 {
21118- unsigned h = __xfrm6_spi_hash(daddr, spi, proto);
21119- struct xfrm_state *x;
21120+ int i;
21121+ int j = 0;
21122+
21123+ /* Rule 1: select IPsec transport except AH */
21124+ for (i = 0; i < n; i++) {
21125+ if (src[i]->props.mode == XFRM_MODE_TRANSPORT &&
21126+ src[i]->id.proto != IPPROTO_AH) {
21127+ dst[j++] = src[i];
21128+ src[i] = NULL;
21129+ }
21130+ }
21131+ if (j == n)
21132+ goto end;
21133+
21134+ /* Rule 2: select MIPv6 RO or inbound trigger */
21135+#ifdef CONFIG_IPV6_MIP6
21136+ for (i = 0; i < n; i++) {
21137+ if (src[i] &&
21138+ (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
21139+ src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) {
21140+ dst[j++] = src[i];
21141+ src[i] = NULL;
21142+ }
21143+ }
21144+ if (j == n)
21145+ goto end;
21146+#endif
21147+
21148+ /* Rule 3: select IPsec transport AH */
21149+ for (i = 0; i < n; i++) {
21150+ if (src[i] &&
21151+ src[i]->props.mode == XFRM_MODE_TRANSPORT &&
21152+ src[i]->id.proto == IPPROTO_AH) {
21153+ dst[j++] = src[i];
21154+ src[i] = NULL;
21155+ }
21156+ }
21157+ if (j == n)
21158+ goto end;
21159+
21160+ /* Rule 4: select IPsec tunnel */
21161+ for (i = 0; i < n; i++) {
21162+ if (src[i] &&
21163+ src[i]->props.mode == XFRM_MODE_TUNNEL) {
21164+ dst[j++] = src[i];
21165+ src[i] = NULL;
21166+ }
21167+ }
21168+ if (likely(j == n))
21169+ goto end;
21170
21171- list_for_each_entry(x, xfrm6_state_afinfo.state_byspi+h, byspi) {
21172- if (x->props.family == AF_INET6 &&
21173- spi == x->id.spi &&
21174- ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) &&
21175- proto == x->id.proto) {
21176- xfrm_state_hold(x);
21177- return x;
21178+ /* Final rule */
21179+ for (i = 0; i < n; i++) {
21180+ if (src[i]) {
21181+ dst[j++] = src[i];
21182+ src[i] = NULL;
21183 }
21184 }
21185- return NULL;
21186+
21187+ end:
21188+ return 0;
21189 }
21190
21191-static struct xfrm_state *
21192-__xfrm6_find_acq(u8 mode, u32 reqid, u8 proto,
21193- xfrm_address_t *daddr, xfrm_address_t *saddr,
21194- int create)
21195+static int
21196+__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
21197 {
21198- struct xfrm_state *x, *x0;
21199- unsigned h = __xfrm6_dst_hash(daddr);
21200+ int i;
21201+ int j = 0;
21202+
21203+ /* Rule 1: select IPsec transport */
21204+ for (i = 0; i < n; i++) {
21205+ if (src[i]->mode == XFRM_MODE_TRANSPORT) {
21206+ dst[j++] = src[i];
21207+ src[i] = NULL;
21208+ }
21209+ }
21210+ if (j == n)
21211+ goto end;
21212+
21213+ /* Rule 2: select MIPv6 RO or inbound trigger */
21214+#ifdef CONFIG_IPV6_MIP6
21215+ for (i = 0; i < n; i++) {
21216+ if (src[i] &&
21217+ (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
21218+ src[i]->mode == XFRM_MODE_IN_TRIGGER)) {
21219+ dst[j++] = src[i];
21220+ src[i] = NULL;
21221+ }
21222+ }
21223+ if (j == n)
21224+ goto end;
21225+#endif
21226+
21227+ /* Rule 3: select IPsec tunnel */
21228+ for (i = 0; i < n; i++) {
21229+ if (src[i] &&
21230+ src[i]->mode == XFRM_MODE_TUNNEL) {
21231+ dst[j++] = src[i];
21232+ src[i] = NULL;
21233+ }
21234+ }
21235+ if (likely(j == n))
21236+ goto end;
21237
21238- x0 = NULL;
21239+ /* Final rule */
21240+ for (i = 0; i < n; i++) {
21241+ if (src[i]) {
21242+ dst[j++] = src[i];
21243+ src[i] = NULL;
21244+ }
21245+ }
21246
21247- list_for_each_entry(x, xfrm6_state_afinfo.state_bydst+h, bydst) {
21248- if (x->props.family == AF_INET6 &&
21249- ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) &&
21250- mode == x->props.mode &&
21251- proto == x->id.proto &&
21252- ipv6_addr_equal((struct in6_addr *)saddr, (struct in6_addr *)x->props.saddr.a6) &&
21253- reqid == x->props.reqid &&
21254- x->km.state == XFRM_STATE_ACQ &&
21255- !x->id.spi) {
21256- x0 = x;
21257- break;
21258- }
21259- }
21260- if (!x0 && create && (x0 = xfrm_state_alloc()) != NULL) {
21261- ipv6_addr_copy((struct in6_addr *)x0->sel.daddr.a6,
21262- (struct in6_addr *)daddr);
21263- ipv6_addr_copy((struct in6_addr *)x0->sel.saddr.a6,
21264- (struct in6_addr *)saddr);
21265- x0->sel.prefixlen_d = 128;
21266- x0->sel.prefixlen_s = 128;
21267- ipv6_addr_copy((struct in6_addr *)x0->props.saddr.a6,
21268- (struct in6_addr *)saddr);
21269- x0->km.state = XFRM_STATE_ACQ;
21270- ipv6_addr_copy((struct in6_addr *)x0->id.daddr.a6,
21271- (struct in6_addr *)daddr);
21272- x0->id.proto = proto;
21273- x0->props.family = AF_INET6;
21274- x0->props.mode = mode;
21275- x0->props.reqid = reqid;
21276- x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
21277- xfrm_state_hold(x0);
21278- x0->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
21279- add_timer(&x0->timer);
21280- xfrm_state_hold(x0);
21281- list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h);
21282- wake_up(&km_waitq);
21283- }
21284- if (x0)
21285- xfrm_state_hold(x0);
21286- return x0;
21287+ end:
21288+ return 0;
21289 }
21290
21291 static struct xfrm_state_afinfo xfrm6_state_afinfo = {
21292 .family = AF_INET6,
21293 .init_tempsel = __xfrm6_init_tempsel,
21294- .state_lookup = __xfrm6_state_lookup,
21295- .find_acq = __xfrm6_find_acq,
21296+ .tmpl_sort = __xfrm6_tmpl_sort,
21297+ .state_sort = __xfrm6_state_sort,
21298 };
21299
21300 void __init xfrm6_state_init(void)
21301diff -Nur linux-2.6.18-rc5/net/ipv6/xfrm6_tunnel.c linux-2.6.19/net/ipv6/xfrm6_tunnel.c
21302--- linux-2.6.18-rc5/net/ipv6/xfrm6_tunnel.c 2006-08-28 05:41:48.000000000 +0200
21303+++ linux-2.6.19/net/ipv6/xfrm6_tunnel.c 2006-09-22 10:04:59.000000000 +0200
21304@@ -307,7 +307,7 @@
21305
21306 static int xfrm6_tunnel_init_state(struct xfrm_state *x)
21307 {
21308- if (!x->props.mode)
21309+ if (x->props.mode != XFRM_MODE_TUNNEL)
21310 return -EINVAL;
21311
21312 if (x->encap)
21313diff -Nur linux-2.6.18-rc5/net/key/af_key.c linux-2.6.19/net/key/af_key.c
21314--- linux-2.6.18-rc5/net/key/af_key.c 2006-08-28 05:41:48.000000000 +0200
21315+++ linux-2.6.19/net/key/af_key.c 2006-09-22 10:04:59.000000000 +0200
21316@@ -1731,7 +1731,8 @@
21317 ++reqid;
21318 if (reqid == 0)
21319 reqid = IPSEC_MANUAL_REQID_MAX+1;
21320- if (xfrm_policy_walk(check_reqid, (void*)&reqid) != -EEXIST)
21321+ if (xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, check_reqid,
21322+ (void*)&reqid) != -EEXIST)
21323 return reqid;
21324 } while (reqid != start);
21325 return 0;
21326@@ -1765,7 +1766,7 @@
21327 }
21328
21329 /* addresses present only in tunnel mode */
21330- if (t->mode) {
21331+ if (t->mode == XFRM_MODE_TUNNEL) {
21332 switch (xp->family) {
21333 case AF_INET:
21334 sin = (void*)(rq+1);
21335@@ -1997,7 +1998,7 @@
21336 int req_size;
21337
21338 req_size = sizeof(struct sadb_x_ipsecrequest);
21339- if (t->mode)
21340+ if (t->mode == XFRM_MODE_TUNNEL)
21341 req_size += 2*socklen;
21342 else
21343 size -= 2*socklen;
21344@@ -2013,7 +2014,7 @@
21345 if (t->optional)
21346 rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE;
21347 rq->sadb_x_ipsecrequest_reqid = t->reqid;
21348- if (t->mode) {
21349+ if (t->mode == XFRM_MODE_TUNNEL) {
21350 switch (xp->family) {
21351 case AF_INET:
21352 sin = (void*)(rq+1);
21353@@ -2268,7 +2269,8 @@
21354 return err;
21355 }
21356
21357- xp = xfrm_policy_bysel_ctx(pol->sadb_x_policy_dir-1, &sel, tmp.security, 1);
21358+ xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
21359+ &sel, tmp.security, 1);
21360 security_xfrm_policy_free(&tmp);
21361 if (xp == NULL)
21362 return -ENOENT;
21363@@ -2330,7 +2332,7 @@
21364 if (dir >= XFRM_POLICY_MAX)
21365 return -EINVAL;
21366
21367- xp = xfrm_policy_byid(dir, pol->sadb_x_policy_id,
21368+ xp = xfrm_policy_byid(XFRM_POLICY_TYPE_MAIN, dir, pol->sadb_x_policy_id,
21369 hdr->sadb_msg_type == SADB_X_SPDDELETE2);
21370 if (xp == NULL)
21371 return -ENOENT;
21372@@ -2378,7 +2380,7 @@
21373 {
21374 struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk };
21375
21376- return xfrm_policy_walk(dump_sp, &data);
21377+ return xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_sp, &data);
21378 }
21379
21380 static int key_notify_policy_flush(struct km_event *c)
21381@@ -2405,7 +2407,8 @@
21382 {
21383 struct km_event c;
21384
21385- xfrm_policy_flush();
21386+ xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN);
21387+ c.data.type = XFRM_POLICY_TYPE_MAIN;
21388 c.event = XFRM_MSG_FLUSHPOLICY;
21389 c.pid = hdr->sadb_msg_pid;
21390 c.seq = hdr->sadb_msg_seq;
21391@@ -2667,6 +2670,9 @@
21392
21393 static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
21394 {
21395+ if (xp && xp->type != XFRM_POLICY_TYPE_MAIN)
21396+ return 0;
21397+
21398 switch (c->event) {
21399 case XFRM_MSG_POLEXPIRE:
21400 return key_notify_policy_expire(xp, c);
21401@@ -2675,6 +2681,8 @@
21402 case XFRM_MSG_UPDPOLICY:
21403 return key_notify_policy(xp, dir, c);
21404 case XFRM_MSG_FLUSHPOLICY:
21405+ if (c->data.type != XFRM_POLICY_TYPE_MAIN)
21406+ break;
21407 return key_notify_policy_flush(c);
21408 default:
21409 printk("pfkey: Unknown policy event %d\n", c->event);
21410@@ -2708,6 +2716,9 @@
21411 #endif
21412 int sockaddr_size;
21413 int size;
21414+ struct sadb_x_sec_ctx *sec_ctx;
21415+ struct xfrm_sec_ctx *xfrm_ctx;
21416+ int ctx_size = 0;
21417
21418 sockaddr_size = pfkey_sockaddr_size(x->props.family);
21419 if (!sockaddr_size)
21420@@ -2723,6 +2734,11 @@
21421 else if (x->id.proto == IPPROTO_ESP)
21422 size += count_esp_combs(t);
21423
21424+ if ((xfrm_ctx = x->security)) {
21425+ ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
21426+ size += sizeof(struct sadb_x_sec_ctx) + ctx_size;
21427+ }
21428+
21429 skb = alloc_skb(size + 16, GFP_ATOMIC);
21430 if (skb == NULL)
21431 return -ENOMEM;
21432@@ -2818,17 +2834,31 @@
21433 else if (x->id.proto == IPPROTO_ESP)
21434 dump_esp_combs(skb, t);
21435
21436+ /* security context */
21437+ if (xfrm_ctx) {
21438+ sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,
21439+ sizeof(struct sadb_x_sec_ctx) + ctx_size);
21440+ sec_ctx->sadb_x_sec_len =
21441+ (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t);
21442+ sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
21443+ sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
21444+ sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
21445+ sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
21446+ memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
21447+ xfrm_ctx->ctx_len);
21448+ }
21449+
21450 return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);
21451 }
21452
21453-static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt,
21454+static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
21455 u8 *data, int len, int *dir)
21456 {
21457 struct xfrm_policy *xp;
21458 struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
21459 struct sadb_x_sec_ctx *sec_ctx;
21460
21461- switch (family) {
21462+ switch (sk->sk_family) {
21463 case AF_INET:
21464 if (opt != IP_IPSEC_POLICY) {
21465 *dir = -EOPNOTSUPP;
21466@@ -2869,7 +2899,7 @@
21467 xp->lft.hard_byte_limit = XFRM_INF;
21468 xp->lft.soft_packet_limit = XFRM_INF;
21469 xp->lft.hard_packet_limit = XFRM_INF;
21470- xp->family = family;
21471+ xp->family = sk->sk_family;
21472
21473 xp->xfrm_nr = 0;
21474 if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&
21475@@ -2885,8 +2915,10 @@
21476 p += pol->sadb_x_policy_len*8;
21477 sec_ctx = (struct sadb_x_sec_ctx *)p;
21478 if (len < pol->sadb_x_policy_len*8 +
21479- sec_ctx->sadb_x_sec_len)
21480+ sec_ctx->sadb_x_sec_len) {
21481+ *dir = -EINVAL;
21482 goto out;
21483+ }
21484 if ((*dir = verify_sec_ctx_len(p)))
21485 goto out;
21486 uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
21487@@ -2896,6 +2928,11 @@
21488 if (*dir)
21489 goto out;
21490 }
21491+ else {
21492+ *dir = security_xfrm_sock_policy_alloc(xp, sk);
21493+ if (*dir)
21494+ goto out;
21495+ }
21496
21497 *dir = pol->sadb_x_policy_dir-1;
21498 return xp;
21499diff -Nur linux-2.6.18-rc5/net/netfilter/Kconfig linux-2.6.19/net/netfilter/Kconfig
21500--- linux-2.6.18-rc5/net/netfilter/Kconfig 2006-08-28 05:41:48.000000000 +0200
21501+++ linux-2.6.19/net/netfilter/Kconfig 2006-09-22 10:04:59.000000000 +0200
21502@@ -148,6 +148,18 @@
21503 <file:Documentation/modules.txt>. The module will be called
21504 ipt_CONNMARK.o. If unsure, say `N'.
21505
21506+config NETFILTER_XT_TARGET_DSCP
21507+ tristate '"DSCP" target support'
21508+ depends on NETFILTER_XTABLES
21509+ depends on IP_NF_MANGLE || IP6_NF_MANGLE
21510+ help
21511+ This option adds a `DSCP' target, which allows you to manipulate
21512+ the IPv4/IPv6 header DSCP field (differentiated services codepoint).
21513+
21514+ The DSCP field can have any value between 0x0 and 0x3f inclusive.
21515+
21516+ To compile it as a module, choose M here. If unsure, say N.
21517+
21518 config NETFILTER_XT_TARGET_MARK
21519 tristate '"MARK" target support'
21520 depends on NETFILTER_XTABLES
21521@@ -263,6 +275,17 @@
21522 If you want to compile it as a module, say M here and read
21523 <file:Documentation/modules.txt>. If unsure, say `N'.
21524
21525+config NETFILTER_XT_MATCH_DSCP
21526+ tristate '"DSCP" match support'
21527+ depends on NETFILTER_XTABLES
21528+ help
21529+ This option adds a `DSCP' match, which allows you to match against
21530+ the IPv4/IPv6 header DSCP field (differentiated services codepoint).
21531+
21532+ The DSCP field can have any value between 0x0 and 0x3f inclusive.
21533+
21534+ To compile it as a module, choose M here. If unsure, say N.
21535+
21536 config NETFILTER_XT_MATCH_ESP
21537 tristate '"ESP" match support'
21538 depends on NETFILTER_XTABLES
21539diff -Nur linux-2.6.18-rc5/net/netfilter/Makefile linux-2.6.19/net/netfilter/Makefile
21540--- linux-2.6.18-rc5/net/netfilter/Makefile 2006-08-28 05:41:48.000000000 +0200
21541+++ linux-2.6.19/net/netfilter/Makefile 2006-09-22 10:04:59.000000000 +0200
21542@@ -25,6 +25,7 @@
21543 # targets
21544 obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
21545 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
21546+obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
21547 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
21548 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
21549 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
21550@@ -37,6 +38,7 @@
21551 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
21552 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
21553 obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
21554+obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o
21555 obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
21556 obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
21557 obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
21558diff -Nur linux-2.6.18-rc5/net/netfilter/core.c linux-2.6.19/net/netfilter/core.c
21559--- linux-2.6.18-rc5/net/netfilter/core.c 2006-08-28 05:41:48.000000000 +0200
21560+++ linux-2.6.19/net/netfilter/core.c 2006-09-22 10:04:59.000000000 +0200
21561@@ -182,7 +182,7 @@
21562 ret = -EPERM;
21563 } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
21564 NFDEBUG("nf_hook: Verdict = QUEUE.\n");
21565- if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn,
21566+ if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn,
21567 verdict >> NF_VERDICT_BITS))
21568 goto next_hook;
21569 }
21570@@ -222,6 +222,28 @@
21571 }
21572 EXPORT_SYMBOL(skb_make_writable);
21573
21574+u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, u_int32_t csum)
21575+{
21576+ u_int32_t diff[] = { oldval, newval };
21577+
21578+ return csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum));
21579+}
21580+EXPORT_SYMBOL(nf_csum_update);
21581+
21582+u_int16_t nf_proto_csum_update(struct sk_buff *skb,
21583+ u_int32_t oldval, u_int32_t newval,
21584+ u_int16_t csum, int pseudohdr)
21585+{
21586+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
21587+ csum = nf_csum_update(oldval, newval, csum);
21588+ if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
21589+ skb->csum = nf_csum_update(oldval, newval, skb->csum);
21590+ } else if (pseudohdr)
21591+ csum = ~nf_csum_update(oldval, newval, ~csum);
21592+
21593+ return csum;
21594+}
21595+EXPORT_SYMBOL(nf_proto_csum_update);
21596
21597 /* This does not belong here, but locally generated errors need it if connection
21598 tracking in use: without this, connection may not be in hash table, and hence
21599diff -Nur linux-2.6.18-rc5/net/netfilter/nf_conntrack_core.c linux-2.6.19/net/netfilter/nf_conntrack_core.c
21600--- linux-2.6.18-rc5/net/netfilter/nf_conntrack_core.c 2006-08-28 05:41:48.000000000 +0200
21601+++ linux-2.6.19/net/netfilter/nf_conntrack_core.c 2006-09-22 10:04:59.000000000 +0200
21602@@ -77,12 +77,12 @@
21603 struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
21604 struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX];
21605 static LIST_HEAD(helpers);
21606-unsigned int nf_conntrack_htable_size = 0;
21607-int nf_conntrack_max;
21608+unsigned int nf_conntrack_htable_size __read_mostly = 0;
21609+int nf_conntrack_max __read_mostly;
21610 struct list_head *nf_conntrack_hash;
21611 static kmem_cache_t *nf_conntrack_expect_cachep;
21612 struct nf_conn nf_conntrack_untracked;
21613-unsigned int nf_ct_log_invalid;
21614+unsigned int nf_ct_log_invalid __read_mostly;
21615 static LIST_HEAD(unconfirmed);
21616 static int nf_conntrack_vmalloc;
21617
21618diff -Nur linux-2.6.18-rc5/net/netfilter/nf_conntrack_ftp.c linux-2.6.19/net/netfilter/nf_conntrack_ftp.c
21619--- linux-2.6.18-rc5/net/netfilter/nf_conntrack_ftp.c 2006-08-28 05:41:48.000000000 +0200
21620+++ linux-2.6.19/net/netfilter/nf_conntrack_ftp.c 2006-09-22 10:04:59.000000000 +0200
21621@@ -21,6 +21,7 @@
21622 #include <linux/ip.h>
21623 #include <linux/ipv6.h>
21624 #include <linux/ctype.h>
21625+#include <linux/inet.h>
21626 #include <net/checksum.h>
21627 #include <net/tcp.h>
21628
21629@@ -111,101 +112,14 @@
21630 },
21631 };
21632
21633-/* This code is based on inet_pton() in glibc-2.2.4 */
21634 static int
21635 get_ipv6_addr(const char *src, size_t dlen, struct in6_addr *dst, u_int8_t term)
21636 {
21637- static const char xdigits[] = "0123456789abcdef";
21638- u_int8_t tmp[16], *tp, *endp, *colonp;
21639- int ch, saw_xdigit;
21640- u_int32_t val;
21641- size_t clen = 0;
21642-
21643- tp = memset(tmp, '\0', sizeof(tmp));
21644- endp = tp + sizeof(tmp);
21645- colonp = NULL;
21646-
21647- /* Leading :: requires some special handling. */
21648- if (*src == ':'){
21649- if (*++src != ':') {
21650- DEBUGP("invalid \":\" at the head of addr\n");
21651- return 0;
21652- }
21653- clen++;
21654- }
21655-
21656- saw_xdigit = 0;
21657- val = 0;
21658- while ((clen < dlen) && (*src != term)) {
21659- const char *pch;
21660-
21661- ch = tolower(*src++);
21662- clen++;
21663-
21664- pch = strchr(xdigits, ch);
21665- if (pch != NULL) {
21666- val <<= 4;
21667- val |= (pch - xdigits);
21668- if (val > 0xffff)
21669- return 0;
21670-
21671- saw_xdigit = 1;
21672- continue;
21673- }
21674- if (ch != ':') {
21675- DEBUGP("get_ipv6_addr: invalid char. \'%c\'\n", ch);
21676- return 0;
21677- }
21678-
21679- if (!saw_xdigit) {
21680- if (colonp) {
21681- DEBUGP("invalid location of \"::\".\n");
21682- return 0;
21683- }
21684- colonp = tp;
21685- continue;
21686- } else if (*src == term) {
21687- DEBUGP("trancated IPv6 addr\n");
21688- return 0;
21689- }
21690-
21691- if (tp + 2 > endp)
21692- return 0;
21693- *tp++ = (u_int8_t) (val >> 8) & 0xff;
21694- *tp++ = (u_int8_t) val & 0xff;
21695-
21696- saw_xdigit = 0;
21697- val = 0;
21698- continue;
21699- }
21700- if (saw_xdigit) {
21701- if (tp + 2 > endp)
21702- return 0;
21703- *tp++ = (u_int8_t) (val >> 8) & 0xff;
21704- *tp++ = (u_int8_t) val & 0xff;
21705- }
21706- if (colonp != NULL) {
21707- /*
21708- * Since some memmove()'s erroneously fail to handle
21709- * overlapping regions, we'll do the shift by hand.
21710- */
21711- const int n = tp - colonp;
21712- int i;
21713-
21714- if (tp == endp)
21715- return 0;
21716-
21717- for (i = 1; i <= n; i++) {
21718- endp[- i] = colonp[n - i];
21719- colonp[n - i] = 0;
21720- }
21721- tp = endp;
21722- }
21723- if (tp != endp || (*src != term))
21724- return 0;
21725-
21726- memcpy(dst->s6_addr, tmp, sizeof(dst->s6_addr));
21727- return clen;
21728+ const char *end;
21729+ int ret = in6_pton(src, min_t(size_t, dlen, 0xffff), (u8 *)dst, term, &end);
21730+ if (ret > 0)
21731+ return (int)(end - src);
21732+ return 0;
21733 }
21734
21735 static int try_number(const char *data, size_t dlen, u_int32_t array[],
21736diff -Nur linux-2.6.18-rc5/net/netfilter/nf_conntrack_netlink.c linux-2.6.19/net/netfilter/nf_conntrack_netlink.c
21737--- linux-2.6.18-rc5/net/netfilter/nf_conntrack_netlink.c 2006-08-28 05:41:48.000000000 +0200
21738+++ linux-2.6.19/net/netfilter/nf_conntrack_netlink.c 2006-09-22 10:04:59.000000000 +0200
21739@@ -339,11 +339,7 @@
21740 /* dump everything */
21741 events = ~0UL;
21742 group = NFNLGRP_CONNTRACK_NEW;
21743- } else if (events & (IPCT_STATUS |
21744- IPCT_PROTOINFO |
21745- IPCT_HELPER |
21746- IPCT_HELPINFO |
21747- IPCT_NATINFO)) {
21748+ } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
21749 type = IPCTNL_MSG_CT_NEW;
21750 group = NFNLGRP_CONNTRACK_UPDATE;
21751 } else
21752@@ -395,6 +391,10 @@
21753 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
21754 goto nfattr_failure;
21755
21756+ if (events & IPCT_MARK
21757+ && ctnetlink_dump_mark(skb, ct) < 0)
21758+ goto nfattr_failure;
21759+
21760 nlh->nlmsg_len = skb->tail - b;
21761 nfnetlink_send(skb, 0, group, 0);
21762 return NOTIFY_DONE;
21763@@ -1274,6 +1274,9 @@
21764 } else
21765 return NOTIFY_DONE;
21766
21767+ if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW))
21768+ return NOTIFY_DONE;
21769+
21770 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
21771 if (!skb)
21772 return NOTIFY_DONE;
21773diff -Nur linux-2.6.18-rc5/net/netfilter/nf_conntrack_proto_generic.c linux-2.6.19/net/netfilter/nf_conntrack_proto_generic.c
21774--- linux-2.6.18-rc5/net/netfilter/nf_conntrack_proto_generic.c 2006-08-28 05:41:48.000000000 +0200
21775+++ linux-2.6.19/net/netfilter/nf_conntrack_proto_generic.c 2006-09-22 10:04:59.000000000 +0200
21776@@ -17,7 +17,7 @@
21777 #include <linux/netfilter.h>
21778 #include <net/netfilter/nf_conntrack_protocol.h>
21779
21780-unsigned int nf_ct_generic_timeout = 600*HZ;
21781+unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
21782
21783 static int generic_pkt_to_tuple(const struct sk_buff *skb,
21784 unsigned int dataoff,
21785diff -Nur linux-2.6.18-rc5/net/netfilter/nf_conntrack_proto_sctp.c linux-2.6.19/net/netfilter/nf_conntrack_proto_sctp.c
21786--- linux-2.6.18-rc5/net/netfilter/nf_conntrack_proto_sctp.c 2006-08-28 05:41:48.000000000 +0200
21787+++ linux-2.6.19/net/netfilter/nf_conntrack_proto_sctp.c 2006-09-22 10:04:59.000000000 +0200
21788@@ -64,13 +64,13 @@
21789 #define HOURS * 60 MINS
21790 #define DAYS * 24 HOURS
21791
21792-static unsigned int nf_ct_sctp_timeout_closed = 10 SECS;
21793-static unsigned int nf_ct_sctp_timeout_cookie_wait = 3 SECS;
21794-static unsigned int nf_ct_sctp_timeout_cookie_echoed = 3 SECS;
21795-static unsigned int nf_ct_sctp_timeout_established = 5 DAYS;
21796-static unsigned int nf_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
21797-static unsigned int nf_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
21798-static unsigned int nf_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
21799+static unsigned int nf_ct_sctp_timeout_closed __read_mostly = 10 SECS;
21800+static unsigned int nf_ct_sctp_timeout_cookie_wait __read_mostly = 3 SECS;
21801+static unsigned int nf_ct_sctp_timeout_cookie_echoed __read_mostly = 3 SECS;
21802+static unsigned int nf_ct_sctp_timeout_established __read_mostly = 5 DAYS;
21803+static unsigned int nf_ct_sctp_timeout_shutdown_sent __read_mostly = 300 SECS / 1000;
21804+static unsigned int nf_ct_sctp_timeout_shutdown_recd __read_mostly = 300 SECS / 1000;
21805+static unsigned int nf_ct_sctp_timeout_shutdown_ack_sent __read_mostly = 3 SECS;
21806
21807 static unsigned int * sctp_timeouts[]
21808 = { NULL, /* SCTP_CONNTRACK_NONE */
21809diff -Nur linux-2.6.18-rc5/net/netfilter/nf_conntrack_proto_tcp.c linux-2.6.19/net/netfilter/nf_conntrack_proto_tcp.c
21810--- linux-2.6.18-rc5/net/netfilter/nf_conntrack_proto_tcp.c 2006-08-28 05:41:48.000000000 +0200
21811+++ linux-2.6.19/net/netfilter/nf_conntrack_proto_tcp.c 2006-09-22 10:04:59.000000000 +0200
21812@@ -57,19 +57,19 @@
21813 /* "Be conservative in what you do,
21814 be liberal in what you accept from others."
21815 If it's non-zero, we mark only out of window RST segments as INVALID. */
21816-int nf_ct_tcp_be_liberal = 0;
21817+int nf_ct_tcp_be_liberal __read_mostly = 0;
21818
21819 /* When connection is picked up from the middle, how many packets are required
21820 to pass in each direction when we assume we are in sync - if any side uses
21821 window scaling, we lost the game.
21822 If it is set to zero, we disable picking up already established
21823 connections. */
21824-int nf_ct_tcp_loose = 3;
21825+int nf_ct_tcp_loose __read_mostly = 3;
21826
21827 /* Max number of the retransmitted packets without receiving an (acceptable)
21828 ACK from the destination. If this number is reached, a shorter timer
21829 will be started. */
21830-int nf_ct_tcp_max_retrans = 3;
21831+int nf_ct_tcp_max_retrans __read_mostly = 3;
21832
21833 /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
21834 closely. They're more complex. --RR */
21835@@ -92,19 +92,19 @@
21836 #define HOURS * 60 MINS
21837 #define DAYS * 24 HOURS
21838
21839-unsigned int nf_ct_tcp_timeout_syn_sent = 2 MINS;
21840-unsigned int nf_ct_tcp_timeout_syn_recv = 60 SECS;
21841-unsigned int nf_ct_tcp_timeout_established = 5 DAYS;
21842-unsigned int nf_ct_tcp_timeout_fin_wait = 2 MINS;
21843-unsigned int nf_ct_tcp_timeout_close_wait = 60 SECS;
21844-unsigned int nf_ct_tcp_timeout_last_ack = 30 SECS;
21845-unsigned int nf_ct_tcp_timeout_time_wait = 2 MINS;
21846-unsigned int nf_ct_tcp_timeout_close = 10 SECS;
21847+unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS;
21848+unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS;
21849+unsigned int nf_ct_tcp_timeout_established __read_mostly = 5 DAYS;
21850+unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS;
21851+unsigned int nf_ct_tcp_timeout_close_wait __read_mostly = 60 SECS;
21852+unsigned int nf_ct_tcp_timeout_last_ack __read_mostly = 30 SECS;
21853+unsigned int nf_ct_tcp_timeout_time_wait __read_mostly = 2 MINS;
21854+unsigned int nf_ct_tcp_timeout_close __read_mostly = 10 SECS;
21855
21856 /* RFC1122 says the R2 limit should be at least 100 seconds.
21857 Linux uses 15 packets as limit, which corresponds
21858 to ~13-30min depending on RTO. */
21859-unsigned int nf_ct_tcp_timeout_max_retrans = 5 MINS;
21860+unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS;
21861
21862 static unsigned int * tcp_timeouts[]
21863 = { NULL, /* TCP_CONNTRACK_NONE */
21864@@ -823,8 +823,7 @@
21865
21866 /* Checksum invalid? Ignore.
21867 * We skip checking packets on the outgoing path
21868- * because the semantic of CHECKSUM_HW is different there
21869- * and moreover root might send raw packets.
21870+ * because the checksum is assumed to be correct.
21871 */
21872 /* FIXME: Source route IP option packets --RR */
21873 if (nf_conntrack_checksum &&
21874diff -Nur linux-2.6.18-rc5/net/netfilter/nf_conntrack_proto_udp.c linux-2.6.19/net/netfilter/nf_conntrack_proto_udp.c
21875--- linux-2.6.18-rc5/net/netfilter/nf_conntrack_proto_udp.c 2006-08-28 05:41:48.000000000 +0200
21876+++ linux-2.6.19/net/netfilter/nf_conntrack_proto_udp.c 2006-09-22 10:04:59.000000000 +0200
21877@@ -27,8 +27,8 @@
21878 #include <linux/netfilter_ipv6.h>
21879 #include <net/netfilter/nf_conntrack_protocol.h>
21880
21881-unsigned int nf_ct_udp_timeout = 30*HZ;
21882-unsigned int nf_ct_udp_timeout_stream = 180*HZ;
21883+unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
21884+unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
21885
21886 static int udp_pkt_to_tuple(const struct sk_buff *skb,
21887 unsigned int dataoff,
21888@@ -131,8 +131,7 @@
21889
21890 /* Checksum invalid? Ignore.
21891 * We skip checking packets on the outgoing path
21892- * because the semantic of CHECKSUM_HW is different there
21893- * and moreover root might send raw packets.
21894+ * because the checksum is assumed to be correct.
21895 * FIXME: Source route IP option packets --RR */
21896 if (nf_conntrack_checksum &&
21897 ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
21898diff -Nur linux-2.6.18-rc5/net/netfilter/nf_conntrack_standalone.c linux-2.6.19/net/netfilter/nf_conntrack_standalone.c
21899--- linux-2.6.18-rc5/net/netfilter/nf_conntrack_standalone.c 2006-08-28 05:41:48.000000000 +0200
21900+++ linux-2.6.19/net/netfilter/nf_conntrack_standalone.c 2006-09-22 10:04:59.000000000 +0200
21901@@ -428,7 +428,7 @@
21902
21903 /* Sysctl support */
21904
21905-int nf_conntrack_checksum = 1;
21906+int nf_conntrack_checksum __read_mostly = 1;
21907
21908 #ifdef CONFIG_SYSCTL
21909
21910diff -Nur linux-2.6.18-rc5/net/netfilter/nf_internals.h linux-2.6.19/net/netfilter/nf_internals.h
21911--- linux-2.6.18-rc5/net/netfilter/nf_internals.h 2006-08-28 05:41:48.000000000 +0200
21912+++ linux-2.6.19/net/netfilter/nf_internals.h 2006-09-22 10:04:59.000000000 +0200
21913@@ -23,7 +23,7 @@
21914 int hook_thresh);
21915
21916 /* nf_queue.c */
21917-extern int nf_queue(struct sk_buff **skb,
21918+extern int nf_queue(struct sk_buff *skb,
21919 struct list_head *elem,
21920 int pf, unsigned int hook,
21921 struct net_device *indev,
21922diff -Nur linux-2.6.18-rc5/net/netfilter/nf_queue.c linux-2.6.19/net/netfilter/nf_queue.c
21923--- linux-2.6.18-rc5/net/netfilter/nf_queue.c 2006-08-28 05:41:48.000000000 +0200
21924+++ linux-2.6.19/net/netfilter/nf_queue.c 2006-09-22 10:04:59.000000000 +0200
21925@@ -74,13 +74,13 @@
21926 * Any packet that leaves via this function must come back
21927 * through nf_reinject().
21928 */
21929-int nf_queue(struct sk_buff **skb,
21930- struct list_head *elem,
21931- int pf, unsigned int hook,
21932- struct net_device *indev,
21933- struct net_device *outdev,
21934- int (*okfn)(struct sk_buff *),
21935- unsigned int queuenum)
21936+static int __nf_queue(struct sk_buff *skb,
21937+ struct list_head *elem,
21938+ int pf, unsigned int hook,
21939+ struct net_device *indev,
21940+ struct net_device *outdev,
21941+ int (*okfn)(struct sk_buff *),
21942+ unsigned int queuenum)
21943 {
21944 int status;
21945 struct nf_info *info;
21946@@ -94,14 +94,14 @@
21947 read_lock(&queue_handler_lock);
21948 if (!queue_handler[pf]) {
21949 read_unlock(&queue_handler_lock);
21950- kfree_skb(*skb);
21951+ kfree_skb(skb);
21952 return 1;
21953 }
21954
21955 afinfo = nf_get_afinfo(pf);
21956 if (!afinfo) {
21957 read_unlock(&queue_handler_lock);
21958- kfree_skb(*skb);
21959+ kfree_skb(skb);
21960 return 1;
21961 }
21962
21963@@ -109,9 +109,9 @@
21964 if (!info) {
21965 if (net_ratelimit())
21966 printk(KERN_ERR "OOM queueing packet %p\n",
21967- *skb);
21968+ skb);
21969 read_unlock(&queue_handler_lock);
21970- kfree_skb(*skb);
21971+ kfree_skb(skb);
21972 return 1;
21973 }
21974
21975@@ -130,15 +130,15 @@
21976 if (outdev) dev_hold(outdev);
21977
21978 #ifdef CONFIG_BRIDGE_NETFILTER
21979- if ((*skb)->nf_bridge) {
21980- physindev = (*skb)->nf_bridge->physindev;
21981+ if (skb->nf_bridge) {
21982+ physindev = skb->nf_bridge->physindev;
21983 if (physindev) dev_hold(physindev);
21984- physoutdev = (*skb)->nf_bridge->physoutdev;
21985+ physoutdev = skb->nf_bridge->physoutdev;
21986 if (physoutdev) dev_hold(physoutdev);
21987 }
21988 #endif
21989- afinfo->saveroute(*skb, info);
21990- status = queue_handler[pf]->outfn(*skb, info, queuenum,
21991+ afinfo->saveroute(skb, info);
21992+ status = queue_handler[pf]->outfn(skb, info, queuenum,
21993 queue_handler[pf]->data);
21994
21995 read_unlock(&queue_handler_lock);
21996@@ -153,7 +153,7 @@
21997 #endif
21998 module_put(info->elem->owner);
21999 kfree(info);
22000- kfree_skb(*skb);
22001+ kfree_skb(skb);
22002
22003 return 1;
22004 }
22005@@ -161,6 +161,46 @@
22006 return 1;
22007 }
22008
22009+int nf_queue(struct sk_buff *skb,
22010+ struct list_head *elem,
22011+ int pf, unsigned int hook,
22012+ struct net_device *indev,
22013+ struct net_device *outdev,
22014+ int (*okfn)(struct sk_buff *),
22015+ unsigned int queuenum)
22016+{
22017+ struct sk_buff *segs;
22018+
22019+ if (!skb_is_gso(skb))
22020+ return __nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
22021+ queuenum);
22022+
22023+ switch (pf) {
22024+ case AF_INET:
22025+ skb->protocol = htons(ETH_P_IP);
22026+ break;
22027+ case AF_INET6:
22028+ skb->protocol = htons(ETH_P_IPV6);
22029+ break;
22030+ }
22031+
22032+ segs = skb_gso_segment(skb, 0);
22033+ kfree_skb(skb);
22034+ if (unlikely(IS_ERR(segs)))
22035+ return 1;
22036+
22037+ do {
22038+ struct sk_buff *nskb = segs->next;
22039+
22040+ segs->next = NULL;
22041+ if (!__nf_queue(segs, elem, pf, hook, indev, outdev, okfn,
22042+ queuenum))
22043+ kfree_skb(segs);
22044+ segs = nskb;
22045+ } while (segs);
22046+ return 1;
22047+}
22048+
22049 void nf_reinject(struct sk_buff *skb, struct nf_info *info,
22050 unsigned int verdict)
22051 {
22052@@ -224,9 +264,9 @@
22053 case NF_STOLEN:
22054 break;
22055 case NF_QUEUE:
22056- if (!nf_queue(&skb, elem, info->pf, info->hook,
22057- info->indev, info->outdev, info->okfn,
22058- verdict >> NF_VERDICT_BITS))
22059+ if (!__nf_queue(skb, elem, info->pf, info->hook,
22060+ info->indev, info->outdev, info->okfn,
22061+ verdict >> NF_VERDICT_BITS))
22062 goto next_hook;
22063 break;
22064 default:
22065diff -Nur linux-2.6.18-rc5/net/netfilter/nfnetlink_queue.c linux-2.6.19/net/netfilter/nfnetlink_queue.c
22066--- linux-2.6.18-rc5/net/netfilter/nfnetlink_queue.c 2006-08-28 05:41:48.000000000 +0200
22067+++ linux-2.6.19/net/netfilter/nfnetlink_queue.c 2006-09-22 10:04:59.000000000 +0200
22068@@ -377,9 +377,9 @@
22069 break;
22070
22071 case NFQNL_COPY_PACKET:
22072- if (entskb->ip_summed == CHECKSUM_HW &&
22073- (*errp = skb_checksum_help(entskb,
22074- outdev == NULL))) {
22075+ if ((entskb->ip_summed == CHECKSUM_PARTIAL ||
22076+ entskb->ip_summed == CHECKSUM_COMPLETE) &&
22077+ (*errp = skb_checksum_help(entskb))) {
22078 spin_unlock_bh(&queue->lock);
22079 return NULL;
22080 }
22081@@ -584,7 +584,7 @@
22082 queue->queue_dropped++;
22083 status = -ENOSPC;
22084 if (net_ratelimit())
22085- printk(KERN_WARNING "ip_queue: full at %d entries, "
22086+ printk(KERN_WARNING "nf_queue: full at %d entries, "
22087 "dropping packets(s). Dropped: %d\n",
22088 queue->queue_total, queue->queue_dropped);
22089 goto err_out_free_nskb;
22090@@ -635,7 +635,7 @@
22091 diff,
22092 GFP_ATOMIC);
22093 if (newskb == NULL) {
22094- printk(KERN_WARNING "ip_queue: OOM "
22095+ printk(KERN_WARNING "nf_queue: OOM "
22096 "in mangle, dropping packet\n");
22097 return -ENOMEM;
22098 }
22099diff -Nur linux-2.6.18-rc5/net/netfilter/x_tables.c linux-2.6.19/net/netfilter/x_tables.c
22100--- linux-2.6.18-rc5/net/netfilter/x_tables.c 2006-08-28 05:41:48.000000000 +0200
22101+++ linux-2.6.19/net/netfilter/x_tables.c 2006-09-22 10:04:59.000000000 +0200
22102@@ -87,6 +87,36 @@
22103 EXPORT_SYMBOL(xt_unregister_target);
22104
22105 int
22106+xt_register_targets(struct xt_target *target, unsigned int n)
22107+{
22108+ unsigned int i;
22109+ int err = 0;
22110+
22111+ for (i = 0; i < n; i++) {
22112+ err = xt_register_target(&target[i]);
22113+ if (err)
22114+ goto err;
22115+ }
22116+ return err;
22117+
22118+err:
22119+ if (i > 0)
22120+ xt_unregister_targets(target, i);
22121+ return err;
22122+}
22123+EXPORT_SYMBOL(xt_register_targets);
22124+
22125+void
22126+xt_unregister_targets(struct xt_target *target, unsigned int n)
22127+{
22128+ unsigned int i;
22129+
22130+ for (i = 0; i < n; i++)
22131+ xt_unregister_target(&target[i]);
22132+}
22133+EXPORT_SYMBOL(xt_unregister_targets);
22134+
22135+int
22136 xt_register_match(struct xt_match *match)
22137 {
22138 int ret, af = match->family;
22139@@ -113,6 +143,36 @@
22140 }
22141 EXPORT_SYMBOL(xt_unregister_match);
22142
22143+int
22144+xt_register_matches(struct xt_match *match, unsigned int n)
22145+{
22146+ unsigned int i;
22147+ int err = 0;
22148+
22149+ for (i = 0; i < n; i++) {
22150+ err = xt_register_match(&match[i]);
22151+ if (err)
22152+ goto err;
22153+ }
22154+ return err;
22155+
22156+err:
22157+ if (i > 0)
22158+ xt_unregister_matches(match, i);
22159+ return err;
22160+}
22161+EXPORT_SYMBOL(xt_register_matches);
22162+
22163+void
22164+xt_unregister_matches(struct xt_match *match, unsigned int n)
22165+{
22166+ unsigned int i;
22167+
22168+ for (i = 0; i < n; i++)
22169+ xt_unregister_match(&match[i]);
22170+}
22171+EXPORT_SYMBOL(xt_unregister_matches);
22172+
22173
22174 /*
22175 * These are weird, but module loading must not be done with mutex
22176diff -Nur linux-2.6.18-rc5/net/netfilter/xt_CLASSIFY.c linux-2.6.19/net/netfilter/xt_CLASSIFY.c
22177--- linux-2.6.18-rc5/net/netfilter/xt_CLASSIFY.c 2006-08-28 05:41:48.000000000 +0200
22178+++ linux-2.6.19/net/netfilter/xt_CLASSIFY.c 2006-09-22 10:04:59.000000000 +0200
22179@@ -29,8 +29,7 @@
22180 const struct net_device *out,
22181 unsigned int hooknum,
22182 const struct xt_target *target,
22183- const void *targinfo,
22184- void *userinfo)
22185+ const void *targinfo)
22186 {
22187 const struct xt_classify_target_info *clinfo = targinfo;
22188
22189@@ -40,47 +39,41 @@
22190 return XT_CONTINUE;
22191 }
22192
22193-static struct xt_target classify_reg = {
22194- .name = "CLASSIFY",
22195- .target = target,
22196- .targetsize = sizeof(struct xt_classify_target_info),
22197- .table = "mangle",
22198- .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
22199- (1 << NF_IP_POST_ROUTING),
22200- .family = AF_INET,
22201- .me = THIS_MODULE,
22202+static struct xt_target xt_classify_target[] = {
22203+ {
22204+ .family = AF_INET,
22205+ .name = "CLASSIFY",
22206+ .target = target,
22207+ .targetsize = sizeof(struct xt_classify_target_info),
22208+ .table = "mangle",
22209+ .hooks = (1 << NF_IP_LOCAL_OUT) |
22210+ (1 << NF_IP_FORWARD) |
22211+ (1 << NF_IP_POST_ROUTING),
22212+ .me = THIS_MODULE,
22213+ },
22214+ {
22215+ .name = "CLASSIFY",
22216+ .family = AF_INET6,
22217+ .target = target,
22218+ .targetsize = sizeof(struct xt_classify_target_info),
22219+ .table = "mangle",
22220+ .hooks = (1 << NF_IP_LOCAL_OUT) |
22221+ (1 << NF_IP_FORWARD) |
22222+ (1 << NF_IP_POST_ROUTING),
22223+ .me = THIS_MODULE,
22224+ },
22225 };
22226-static struct xt_target classify6_reg = {
22227- .name = "CLASSIFY",
22228- .target = target,
22229- .targetsize = sizeof(struct xt_classify_target_info),
22230- .table = "mangle",
22231- .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
22232- (1 << NF_IP_POST_ROUTING),
22233- .family = AF_INET6,
22234- .me = THIS_MODULE,
22235-};
22236-
22237
22238 static int __init xt_classify_init(void)
22239 {
22240- int ret;
22241-
22242- ret = xt_register_target(&classify_reg);
22243- if (ret)
22244- return ret;
22245-
22246- ret = xt_register_target(&classify6_reg);
22247- if (ret)
22248- xt_unregister_target(&classify_reg);
22249-
22250- return ret;
22251+ return xt_register_targets(xt_classify_target,
22252+ ARRAY_SIZE(xt_classify_target));
22253 }
22254
22255 static void __exit xt_classify_fini(void)
22256 {
22257- xt_unregister_target(&classify_reg);
22258- xt_unregister_target(&classify6_reg);
22259+ xt_unregister_targets(xt_classify_target,
22260+ ARRAY_SIZE(xt_classify_target));
22261 }
22262
22263 module_init(xt_classify_init);
22264diff -Nur linux-2.6.18-rc5/net/netfilter/xt_CONNMARK.c linux-2.6.19/net/netfilter/xt_CONNMARK.c
22265--- linux-2.6.18-rc5/net/netfilter/xt_CONNMARK.c 2006-08-28 05:41:48.000000000 +0200
22266+++ linux-2.6.19/net/netfilter/xt_CONNMARK.c 2006-09-22 10:04:59.000000000 +0200
22267@@ -38,8 +38,7 @@
22268 const struct net_device *out,
22269 unsigned int hooknum,
22270 const struct xt_target *target,
22271- const void *targinfo,
22272- void *userinfo)
22273+ const void *targinfo)
22274 {
22275 const struct xt_connmark_target_info *markinfo = targinfo;
22276 u_int32_t diff;
22277@@ -49,24 +48,37 @@
22278 u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo);
22279
22280 if (ctmark) {
22281- switch(markinfo->mode) {
22282- case XT_CONNMARK_SET:
22283- newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
22284- if (newmark != *ctmark)
22285- *ctmark = newmark;
22286- break;
22287- case XT_CONNMARK_SAVE:
22288- newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
22289- if (*ctmark != newmark)
22290- *ctmark = newmark;
22291- break;
22292- case XT_CONNMARK_RESTORE:
22293- nfmark = (*pskb)->nfmark;
22294- diff = (*ctmark ^ nfmark) & markinfo->mask;
22295- if (diff != 0)
22296- (*pskb)->nfmark = nfmark ^ diff;
22297- break;
22298- }
22299+ switch(markinfo->mode) {
22300+ case XT_CONNMARK_SET:
22301+ newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
22302+ if (newmark != *ctmark) {
22303+ *ctmark = newmark;
22304+#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
22305+ ip_conntrack_event_cache(IPCT_MARK, *pskb);
22306+#else
22307+ nf_conntrack_event_cache(IPCT_MARK, *pskb);
22308+#endif
22309+ }
22310+ break;
22311+ case XT_CONNMARK_SAVE:
22312+ newmark = (*ctmark & ~markinfo->mask) |
22313+ ((*pskb)->nfmark & markinfo->mask);
22314+ if (*ctmark != newmark) {
22315+ *ctmark = newmark;
22316+#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
22317+ ip_conntrack_event_cache(IPCT_MARK, *pskb);
22318+#else
22319+ nf_conntrack_event_cache(IPCT_MARK, *pskb);
22320+#endif
22321+ }
22322+ break;
22323+ case XT_CONNMARK_RESTORE:
22324+ nfmark = (*pskb)->nfmark;
22325+ diff = (*ctmark ^ nfmark) & markinfo->mask;
22326+ if (diff != 0)
22327+ (*pskb)->nfmark = nfmark ^ diff;
22328+ break;
22329+ }
22330 }
22331
22332 return XT_CONTINUE;
22333@@ -77,65 +89,55 @@
22334 const void *entry,
22335 const struct xt_target *target,
22336 void *targinfo,
22337- unsigned int targinfosize,
22338 unsigned int hook_mask)
22339 {
22340 struct xt_connmark_target_info *matchinfo = targinfo;
22341
22342 if (matchinfo->mode == XT_CONNMARK_RESTORE) {
22343- if (strcmp(tablename, "mangle") != 0) {
22344- printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
22345- return 0;
22346- }
22347+ if (strcmp(tablename, "mangle") != 0) {
22348+ printk(KERN_WARNING "CONNMARK: restore can only be "
22349+ "called from \"mangle\" table, not \"%s\"\n",
22350+ tablename);
22351+ return 0;
22352+ }
22353 }
22354-
22355 if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
22356 printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
22357 return 0;
22358 }
22359-
22360 return 1;
22361 }
22362
22363-static struct xt_target connmark_reg = {
22364- .name = "CONNMARK",
22365- .target = target,
22366- .targetsize = sizeof(struct xt_connmark_target_info),
22367- .checkentry = checkentry,
22368- .family = AF_INET,
22369- .me = THIS_MODULE
22370-};
22371-
22372-static struct xt_target connmark6_reg = {
22373- .name = "CONNMARK",
22374- .target = target,
22375- .targetsize = sizeof(struct xt_connmark_target_info),
22376- .checkentry = checkentry,
22377- .family = AF_INET6,
22378- .me = THIS_MODULE
22379+static struct xt_target xt_connmark_target[] = {
22380+ {
22381+ .name = "CONNMARK",
22382+ .family = AF_INET,
22383+ .checkentry = checkentry,
22384+ .target = target,
22385+ .targetsize = sizeof(struct xt_connmark_target_info),
22386+ .me = THIS_MODULE
22387+ },
22388+ {
22389+ .name = "CONNMARK",
22390+ .family = AF_INET6,
22391+ .checkentry = checkentry,
22392+ .target = target,
22393+ .targetsize = sizeof(struct xt_connmark_target_info),
22394+ .me = THIS_MODULE
22395+ },
22396 };
22397
22398 static int __init xt_connmark_init(void)
22399 {
22400- int ret;
22401-
22402 need_conntrack();
22403-
22404- ret = xt_register_target(&connmark_reg);
22405- if (ret)
22406- return ret;
22407-
22408- ret = xt_register_target(&connmark6_reg);
22409- if (ret)
22410- xt_unregister_target(&connmark_reg);
22411-
22412- return ret;
22413+ return xt_register_targets(xt_connmark_target,
22414+ ARRAY_SIZE(xt_connmark_target));
22415 }
22416
22417 static void __exit xt_connmark_fini(void)
22418 {
22419- xt_unregister_target(&connmark_reg);
22420- xt_unregister_target(&connmark6_reg);
22421+ xt_unregister_targets(xt_connmark_target,
22422+ ARRAY_SIZE(xt_connmark_target));
22423 }
22424
22425 module_init(xt_connmark_init);
22426diff -Nur linux-2.6.18-rc5/net/netfilter/xt_CONNSECMARK.c linux-2.6.19/net/netfilter/xt_CONNSECMARK.c
22427--- linux-2.6.18-rc5/net/netfilter/xt_CONNSECMARK.c 2006-08-28 05:41:48.000000000 +0200
22428+++ linux-2.6.19/net/netfilter/xt_CONNSECMARK.c 2006-09-22 10:04:59.000000000 +0200
22429@@ -66,7 +66,7 @@
22430 static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
22431 const struct net_device *out, unsigned int hooknum,
22432 const struct xt_target *target,
22433- const void *targinfo, void *userinfo)
22434+ const void *targinfo)
22435 {
22436 struct sk_buff *skb = *pskb;
22437 const struct xt_connsecmark_target_info *info = targinfo;
22438@@ -89,7 +89,7 @@
22439
22440 static int checkentry(const char *tablename, const void *entry,
22441 const struct xt_target *target, void *targinfo,
22442- unsigned int targinfosize, unsigned int hook_mask)
22443+ unsigned int hook_mask)
22444 {
22445 struct xt_connsecmark_target_info *info = targinfo;
22446
22447@@ -106,49 +106,38 @@
22448 return 1;
22449 }
22450
22451-static struct xt_target ipt_connsecmark_reg = {
22452- .name = "CONNSECMARK",
22453- .target = target,
22454- .targetsize = sizeof(struct xt_connsecmark_target_info),
22455- .table = "mangle",
22456- .checkentry = checkentry,
22457- .me = THIS_MODULE,
22458- .family = AF_INET,
22459- .revision = 0,
22460-};
22461-
22462-static struct xt_target ip6t_connsecmark_reg = {
22463- .name = "CONNSECMARK",
22464- .target = target,
22465- .targetsize = sizeof(struct xt_connsecmark_target_info),
22466- .table = "mangle",
22467- .checkentry = checkentry,
22468- .me = THIS_MODULE,
22469- .family = AF_INET6,
22470- .revision = 0,
22471+static struct xt_target xt_connsecmark_target[] = {
22472+ {
22473+ .name = "CONNSECMARK",
22474+ .family = AF_INET,
22475+ .checkentry = checkentry,
22476+ .target = target,
22477+ .targetsize = sizeof(struct xt_connsecmark_target_info),
22478+ .table = "mangle",
22479+ .me = THIS_MODULE,
22480+ },
22481+ {
22482+ .name = "CONNSECMARK",
22483+ .family = AF_INET6,
22484+ .checkentry = checkentry,
22485+ .target = target,
22486+ .targetsize = sizeof(struct xt_connsecmark_target_info),
22487+ .table = "mangle",
22488+ .me = THIS_MODULE,
22489+ },
22490 };
22491
22492 static int __init xt_connsecmark_init(void)
22493 {
22494- int err;
22495-
22496 need_conntrack();
22497-
22498- err = xt_register_target(&ipt_connsecmark_reg);
22499- if (err)
22500- return err;
22501-
22502- err = xt_register_target(&ip6t_connsecmark_reg);
22503- if (err)
22504- xt_unregister_target(&ipt_connsecmark_reg);
22505-
22506- return err;
22507+ return xt_register_targets(xt_connsecmark_target,
22508+ ARRAY_SIZE(xt_connsecmark_target));
22509 }
22510
22511 static void __exit xt_connsecmark_fini(void)
22512 {
22513- xt_unregister_target(&ip6t_connsecmark_reg);
22514- xt_unregister_target(&ipt_connsecmark_reg);
22515+ xt_unregister_targets(xt_connsecmark_target,
22516+ ARRAY_SIZE(xt_connsecmark_target));
22517 }
22518
22519 module_init(xt_connsecmark_init);
22520diff -Nur linux-2.6.18-rc5/net/netfilter/xt_DSCP.c linux-2.6.19/net/netfilter/xt_DSCP.c
22521--- linux-2.6.18-rc5/net/netfilter/xt_DSCP.c 1970-01-01 01:00:00.000000000 +0100
22522+++ linux-2.6.19/net/netfilter/xt_DSCP.c 2006-09-22 10:04:59.000000000 +0200
22523@@ -0,0 +1,118 @@
22524+/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8
22525+ *
22526+ * (C) 2002 by Harald Welte <laforge@netfilter.org>
22527+ * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com>
22528+ *
22529+ * This program is free software; you can redistribute it and/or modify
22530+ * it under the terms of the GNU General Public License version 2 as
22531+ * published by the Free Software Foundation.
22532+ *
22533+ * See RFC2474 for a description of the DSCP field within the IP Header.
22534+ *
22535+ * xt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp
22536+*/
22537+
22538+#include <linux/module.h>
22539+#include <linux/skbuff.h>
22540+#include <linux/ip.h>
22541+#include <linux/ipv6.h>
22542+#include <net/dsfield.h>
22543+
22544+#include <linux/netfilter/x_tables.h>
22545+#include <linux/netfilter/xt_DSCP.h>
22546+
22547+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
22548+MODULE_DESCRIPTION("x_tables DSCP modification module");
22549+MODULE_LICENSE("GPL");
22550+MODULE_ALIAS("ipt_DSCP");
22551+MODULE_ALIAS("ip6t_DSCP");
22552+
22553+static unsigned int target(struct sk_buff **pskb,
22554+ const struct net_device *in,
22555+ const struct net_device *out,
22556+ unsigned int hooknum,
22557+ const struct xt_target *target,
22558+ const void *targinfo)
22559+{
22560+ const struct xt_DSCP_info *dinfo = targinfo;
22561+ u_int8_t dscp = ipv4_get_dsfield((*pskb)->nh.iph) >> XT_DSCP_SHIFT;
22562+
22563+ if (dscp != dinfo->dscp) {
22564+ if (!skb_make_writable(pskb, sizeof(struct iphdr)))
22565+ return NF_DROP;
22566+
22567+ ipv4_change_dsfield((*pskb)->nh.iph, (__u8)(~XT_DSCP_MASK),
22568+ dinfo->dscp << XT_DSCP_SHIFT);
22569+
22570+ }
22571+ return XT_CONTINUE;
22572+}
22573+
22574+static unsigned int target6(struct sk_buff **pskb,
22575+ const struct net_device *in,
22576+ const struct net_device *out,
22577+ unsigned int hooknum,
22578+ const struct xt_target *target,
22579+ const void *targinfo)
22580+{
22581+ const struct xt_DSCP_info *dinfo = targinfo;
22582+ u_int8_t dscp = ipv6_get_dsfield((*pskb)->nh.ipv6h) >> XT_DSCP_SHIFT;
22583+
22584+ if (dscp != dinfo->dscp) {
22585+ if (!skb_make_writable(pskb, sizeof(struct ipv6hdr)))
22586+ return NF_DROP;
22587+
22588+ ipv6_change_dsfield((*pskb)->nh.ipv6h, (__u8)(~XT_DSCP_MASK),
22589+ dinfo->dscp << XT_DSCP_SHIFT);
22590+ }
22591+ return XT_CONTINUE;
22592+}
22593+
22594+static int checkentry(const char *tablename,
22595+ const void *e_void,
22596+ const struct xt_target *target,
22597+ void *targinfo,
22598+ unsigned int hook_mask)
22599+{
22600+ const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp;
22601+
22602+ if ((dscp > XT_DSCP_MAX)) {
22603+ printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
22604+ return 0;
22605+ }
22606+ return 1;
22607+}
22608+
22609+static struct xt_target xt_dscp_target[] = {
22610+ {
22611+ .name = "DSCP",
22612+ .family = AF_INET,
22613+ .checkentry = checkentry,
22614+ .target = target,
22615+ .targetsize = sizeof(struct xt_DSCP_info),
22616+ .table = "mangle",
22617+ .me = THIS_MODULE,
22618+ },
22619+ {
22620+ .name = "DSCP",
22621+ .family = AF_INET6,
22622+ .checkentry = checkentry,
22623+ .target = target6,
22624+ .targetsize = sizeof(struct xt_DSCP_info),
22625+ .table = "mangle",
22626+ .me = THIS_MODULE,
22627+ },
22628+};
22629+
22630+static int __init xt_dscp_target_init(void)
22631+{
22632+ return xt_register_targets(xt_dscp_target, ARRAY_SIZE(xt_dscp_target));
22633+}
22634+
22635+static void __exit xt_dscp_target_fini(void)
22636+{
22637+ xt_unregister_targets(xt_dscp_target, ARRAY_SIZE(xt_dscp_target));
22638+}
22639+
22640+module_init(xt_dscp_target_init);
22641+module_exit(xt_dscp_target_fini);
22642diff -Nur linux-2.6.18-rc5/net/netfilter/xt_MARK.c linux-2.6.19/net/netfilter/xt_MARK.c
22643--- linux-2.6.18-rc5/net/netfilter/xt_MARK.c 2006-08-28 05:41:48.000000000 +0200
22644+++ linux-2.6.19/net/netfilter/xt_MARK.c 2006-09-22 10:04:59.000000000 +0200
22645@@ -27,8 +27,7 @@
22646 const struct net_device *out,
22647 unsigned int hooknum,
22648 const struct xt_target *target,
22649- const void *targinfo,
22650- void *userinfo)
22651+ const void *targinfo)
22652 {
22653 const struct xt_mark_target_info *markinfo = targinfo;
22654
22655@@ -44,8 +43,7 @@
22656 const struct net_device *out,
22657 unsigned int hooknum,
22658 const struct xt_target *target,
22659- const void *targinfo,
22660- void *userinfo)
22661+ const void *targinfo)
22662 {
22663 const struct xt_mark_target_info_v1 *markinfo = targinfo;
22664 int mark = 0;
22665@@ -76,7 +74,6 @@
22666 const void *entry,
22667 const struct xt_target *target,
22668 void *targinfo,
22669- unsigned int targinfosize,
22670 unsigned int hook_mask)
22671 {
22672 struct xt_mark_target_info *markinfo = targinfo;
22673@@ -93,7 +90,6 @@
22674 const void *entry,
22675 const struct xt_target *target,
22676 void *targinfo,
22677- unsigned int targinfosize,
22678 unsigned int hook_mask)
22679 {
22680 struct xt_mark_target_info_v1 *markinfo = targinfo;
22681@@ -112,65 +108,47 @@
22682 return 1;
22683 }
22684
22685-static struct xt_target ipt_mark_reg_v0 = {
22686- .name = "MARK",
22687- .target = target_v0,
22688- .targetsize = sizeof(struct xt_mark_target_info),
22689- .table = "mangle",
22690- .checkentry = checkentry_v0,
22691- .me = THIS_MODULE,
22692- .family = AF_INET,
22693- .revision = 0,
22694-};
22695-
22696-static struct xt_target ipt_mark_reg_v1 = {
22697- .name = "MARK",
22698- .target = target_v1,
22699- .targetsize = sizeof(struct xt_mark_target_info_v1),
22700- .table = "mangle",
22701- .checkentry = checkentry_v1,
22702- .me = THIS_MODULE,
22703- .family = AF_INET,
22704- .revision = 1,
22705-};
22706-
22707-static struct xt_target ip6t_mark_reg_v0 = {
22708- .name = "MARK",
22709- .target = target_v0,
22710- .targetsize = sizeof(struct xt_mark_target_info),
22711- .table = "mangle",
22712- .checkentry = checkentry_v0,
22713- .me = THIS_MODULE,
22714- .family = AF_INET6,
22715- .revision = 0,
22716+static struct xt_target xt_mark_target[] = {
22717+ {
22718+ .name = "MARK",
22719+ .family = AF_INET,
22720+ .revision = 0,
22721+ .checkentry = checkentry_v0,
22722+ .target = target_v0,
22723+ .targetsize = sizeof(struct xt_mark_target_info),
22724+ .table = "mangle",
22725+ .me = THIS_MODULE,
22726+ },
22727+ {
22728+ .name = "MARK",
22729+ .family = AF_INET,
22730+ .revision = 1,
22731+ .checkentry = checkentry_v1,
22732+ .target = target_v1,
22733+ .targetsize = sizeof(struct xt_mark_target_info_v1),
22734+ .table = "mangle",
22735+ .me = THIS_MODULE,
22736+ },
22737+ {
22738+ .name = "MARK",
22739+ .family = AF_INET6,
22740+ .revision = 0,
22741+ .checkentry = checkentry_v0,
22742+ .target = target_v0,
22743+ .targetsize = sizeof(struct xt_mark_target_info),
22744+ .table = "mangle",
22745+ .me = THIS_MODULE,
22746+ },
22747 };
22748
22749 static int __init xt_mark_init(void)
22750 {
22751- int err;
22752-
22753- err = xt_register_target(&ipt_mark_reg_v0);
22754- if (err)
22755- return err;
22756-
22757- err = xt_register_target(&ipt_mark_reg_v1);
22758- if (err)
22759- xt_unregister_target(&ipt_mark_reg_v0);
22760-
22761- err = xt_register_target(&ip6t_mark_reg_v0);
22762- if (err) {
22763- xt_unregister_target(&ipt_mark_reg_v0);
22764- xt_unregister_target(&ipt_mark_reg_v1);
22765- }
22766-
22767- return err;
22768+ return xt_register_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
22769 }
22770
22771 static void __exit xt_mark_fini(void)
22772 {
22773- xt_unregister_target(&ipt_mark_reg_v0);
22774- xt_unregister_target(&ipt_mark_reg_v1);
22775- xt_unregister_target(&ip6t_mark_reg_v0);
22776+ xt_unregister_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
22777 }
22778
22779 module_init(xt_mark_init);
22780diff -Nur linux-2.6.18-rc5/net/netfilter/xt_NFQUEUE.c linux-2.6.19/net/netfilter/xt_NFQUEUE.c
22781--- linux-2.6.18-rc5/net/netfilter/xt_NFQUEUE.c 2006-08-28 05:41:48.000000000 +0200
22782+++ linux-2.6.19/net/netfilter/xt_NFQUEUE.c 2006-09-22 10:04:59.000000000 +0200
22783@@ -29,65 +29,46 @@
22784 const struct net_device *out,
22785 unsigned int hooknum,
22786 const struct xt_target *target,
22787- const void *targinfo,
22788- void *userinfo)
22789+ const void *targinfo)
22790 {
22791 const struct xt_NFQ_info *tinfo = targinfo;
22792
22793 return NF_QUEUE_NR(tinfo->queuenum);
22794 }
22795
22796-static struct xt_target ipt_NFQ_reg = {
22797- .name = "NFQUEUE",
22798- .target = target,
22799- .targetsize = sizeof(struct xt_NFQ_info),
22800- .family = AF_INET,
22801- .me = THIS_MODULE,
22802-};
22803-
22804-static struct xt_target ip6t_NFQ_reg = {
22805- .name = "NFQUEUE",
22806- .target = target,
22807- .targetsize = sizeof(struct xt_NFQ_info),
22808- .family = AF_INET6,
22809- .me = THIS_MODULE,
22810-};
22811-
22812-static struct xt_target arpt_NFQ_reg = {
22813- .name = "NFQUEUE",
22814- .target = target,
22815- .targetsize = sizeof(struct xt_NFQ_info),
22816- .family = NF_ARP,
22817- .me = THIS_MODULE,
22818+static struct xt_target xt_nfqueue_target[] = {
22819+ {
22820+ .name = "NFQUEUE",
22821+ .family = AF_INET,
22822+ .target = target,
22823+ .targetsize = sizeof(struct xt_NFQ_info),
22824+ .me = THIS_MODULE,
22825+ },
22826+ {
22827+ .name = "NFQUEUE",
22828+ .family = AF_INET6,
22829+ .target = target,
22830+ .targetsize = sizeof(struct xt_NFQ_info),
22831+ .me = THIS_MODULE,
22832+ },
22833+ {
22834+ .name = "NFQUEUE",
22835+ .family = NF_ARP,
22836+ .target = target,
22837+ .targetsize = sizeof(struct xt_NFQ_info),
22838+ .me = THIS_MODULE,
22839+ },
22840 };
22841
22842 static int __init xt_nfqueue_init(void)
22843 {
22844- int ret;
22845- ret = xt_register_target(&ipt_NFQ_reg);
22846- if (ret)
22847- return ret;
22848- ret = xt_register_target(&ip6t_NFQ_reg);
22849- if (ret)
22850- goto out_ip;
22851- ret = xt_register_target(&arpt_NFQ_reg);
22852- if (ret)
22853- goto out_ip6;
22854-
22855- return ret;
22856-out_ip6:
22857- xt_unregister_target(&ip6t_NFQ_reg);
22858-out_ip:
22859- xt_unregister_target(&ipt_NFQ_reg);
22860-
22861- return ret;
22862+ return xt_register_targets(xt_nfqueue_target,
22863+ ARRAY_SIZE(xt_nfqueue_target));
22864 }
22865
22866 static void __exit xt_nfqueue_fini(void)
22867 {
22868- xt_unregister_target(&arpt_NFQ_reg);
22869- xt_unregister_target(&ip6t_NFQ_reg);
22870- xt_unregister_target(&ipt_NFQ_reg);
22871+ xt_register_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target));
22872 }
22873
22874 module_init(xt_nfqueue_init);
22875diff -Nur linux-2.6.18-rc5/net/netfilter/xt_NOTRACK.c linux-2.6.19/net/netfilter/xt_NOTRACK.c
22876--- linux-2.6.18-rc5/net/netfilter/xt_NOTRACK.c 2006-08-28 05:41:48.000000000 +0200
22877+++ linux-2.6.19/net/netfilter/xt_NOTRACK.c 2006-09-22 10:04:59.000000000 +0200
22878@@ -16,8 +16,7 @@
22879 const struct net_device *out,
22880 unsigned int hooknum,
22881 const struct xt_target *target,
22882- const void *targinfo,
22883- void *userinfo)
22884+ const void *targinfo)
22885 {
22886 /* Previously seen (loopback)? Ignore. */
22887 if ((*pskb)->nfct != NULL)
22888@@ -34,43 +33,32 @@
22889 return XT_CONTINUE;
22890 }
22891
22892-static struct xt_target notrack_reg = {
22893- .name = "NOTRACK",
22894- .target = target,
22895- .targetsize = 0,
22896- .table = "raw",
22897- .family = AF_INET,
22898- .me = THIS_MODULE,
22899-};
22900-
22901-static struct xt_target notrack6_reg = {
22902- .name = "NOTRACK",
22903- .target = target,
22904- .targetsize = 0,
22905- .table = "raw",
22906- .family = AF_INET6,
22907- .me = THIS_MODULE,
22908+static struct xt_target xt_notrack_target[] = {
22909+ {
22910+ .name = "NOTRACK",
22911+ .family = AF_INET,
22912+ .target = target,
22913+ .table = "raw",
22914+ .me = THIS_MODULE,
22915+ },
22916+ {
22917+ .name = "NOTRACK",
22918+ .family = AF_INET6,
22919+ .target = target,
22920+ .table = "raw",
22921+ .me = THIS_MODULE,
22922+ },
22923 };
22924
22925 static int __init xt_notrack_init(void)
22926 {
22927- int ret;
22928-
22929- ret = xt_register_target(&notrack_reg);
22930- if (ret)
22931- return ret;
22932-
22933- ret = xt_register_target(&notrack6_reg);
22934- if (ret)
22935- xt_unregister_target(&notrack_reg);
22936-
22937- return ret;
22938+ return xt_register_targets(xt_notrack_target,
22939+ ARRAY_SIZE(xt_notrack_target));
22940 }
22941
22942 static void __exit xt_notrack_fini(void)
22943 {
22944- xt_unregister_target(&notrack6_reg);
22945- xt_unregister_target(&notrack_reg);
22946+ xt_unregister_targets(xt_notrack_target, ARRAY_SIZE(xt_notrack_target));
22947 }
22948
22949 module_init(xt_notrack_init);
22950diff -Nur linux-2.6.18-rc5/net/netfilter/xt_SECMARK.c linux-2.6.19/net/netfilter/xt_SECMARK.c
22951--- linux-2.6.18-rc5/net/netfilter/xt_SECMARK.c 2006-08-28 05:41:48.000000000 +0200
22952+++ linux-2.6.19/net/netfilter/xt_SECMARK.c 2006-09-22 10:04:59.000000000 +0200
22953@@ -31,7 +31,7 @@
22954 static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
22955 const struct net_device *out, unsigned int hooknum,
22956 const struct xt_target *target,
22957- const void *targinfo, void *userinfo)
22958+ const void *targinfo)
22959 {
22960 u32 secmark = 0;
22961 const struct xt_secmark_target_info *info = targinfo;
22962@@ -85,7 +85,7 @@
22963
22964 static int checkentry(const char *tablename, const void *entry,
22965 const struct xt_target *target, void *targinfo,
22966- unsigned int targinfosize, unsigned int hook_mask)
22967+ unsigned int hook_mask)
22968 {
22969 struct xt_secmark_target_info *info = targinfo;
22970
22971@@ -111,47 +111,36 @@
22972 return 1;
22973 }
22974
22975-static struct xt_target ipt_secmark_reg = {
22976- .name = "SECMARK",
22977- .target = target,
22978- .targetsize = sizeof(struct xt_secmark_target_info),
22979- .table = "mangle",
22980- .checkentry = checkentry,
22981- .me = THIS_MODULE,
22982- .family = AF_INET,
22983- .revision = 0,
22984-};
22985-
22986-static struct xt_target ip6t_secmark_reg = {
22987- .name = "SECMARK",
22988- .target = target,
22989- .targetsize = sizeof(struct xt_secmark_target_info),
22990- .table = "mangle",
22991- .checkentry = checkentry,
22992- .me = THIS_MODULE,
22993- .family = AF_INET6,
22994- .revision = 0,
22995+static struct xt_target xt_secmark_target[] = {
22996+ {
22997+ .name = "SECMARK",
22998+ .family = AF_INET,
22999+ .checkentry = checkentry,
23000+ .target = target,
23001+ .targetsize = sizeof(struct xt_secmark_target_info),
23002+ .table = "mangle",
23003+ .me = THIS_MODULE,
23004+ },
23005+ {
23006+ .name = "SECMARK",
23007+ .family = AF_INET6,
23008+ .checkentry = checkentry,
23009+ .target = target,
23010+ .targetsize = sizeof(struct xt_secmark_target_info),
23011+ .table = "mangle",
23012+ .me = THIS_MODULE,
23013+ },
23014 };
23015
23016 static int __init xt_secmark_init(void)
23017 {
23018- int err;
23019-
23020- err = xt_register_target(&ipt_secmark_reg);
23021- if (err)
23022- return err;
23023-
23024- err = xt_register_target(&ip6t_secmark_reg);
23025- if (err)
23026- xt_unregister_target(&ipt_secmark_reg);
23027-
23028- return err;
23029+ return xt_register_targets(xt_secmark_target,
23030+ ARRAY_SIZE(xt_secmark_target));
23031 }
23032
23033 static void __exit xt_secmark_fini(void)
23034 {
23035- xt_unregister_target(&ip6t_secmark_reg);
23036- xt_unregister_target(&ipt_secmark_reg);
23037+ xt_unregister_targets(xt_secmark_target, ARRAY_SIZE(xt_secmark_target));
23038 }
23039
23040 module_init(xt_secmark_init);
23041diff -Nur linux-2.6.18-rc5/net/netfilter/xt_comment.c linux-2.6.19/net/netfilter/xt_comment.c
23042--- linux-2.6.18-rc5/net/netfilter/xt_comment.c 2006-08-28 05:41:48.000000000 +0200
23043+++ linux-2.6.19/net/netfilter/xt_comment.c 2006-09-22 10:04:59.000000000 +0200
23044@@ -29,41 +29,32 @@
23045 return 1;
23046 }
23047
23048-static struct xt_match comment_match = {
23049- .name = "comment",
23050- .match = match,
23051- .matchsize = sizeof(struct xt_comment_info),
23052- .family = AF_INET,
23053- .me = THIS_MODULE
23054-};
23055-
23056-static struct xt_match comment6_match = {
23057- .name = "comment",
23058- .match = match,
23059- .matchsize = sizeof(struct xt_comment_info),
23060- .family = AF_INET6,
23061- .me = THIS_MODULE
23062+static struct xt_match xt_comment_match[] = {
23063+ {
23064+ .name = "comment",
23065+ .family = AF_INET,
23066+ .match = match,
23067+ .matchsize = sizeof(struct xt_comment_info),
23068+ .me = THIS_MODULE
23069+ },
23070+ {
23071+ .name = "comment",
23072+ .family = AF_INET6,
23073+ .match = match,
23074+ .matchsize = sizeof(struct xt_comment_info),
23075+ .me = THIS_MODULE
23076+ },
23077 };
23078
23079 static int __init xt_comment_init(void)
23080 {
23081- int ret;
23082-
23083- ret = xt_register_match(&comment_match);
23084- if (ret)
23085- return ret;
23086-
23087- ret = xt_register_match(&comment6_match);
23088- if (ret)
23089- xt_unregister_match(&comment_match);
23090-
23091- return ret;
23092+ return xt_register_matches(xt_comment_match,
23093+ ARRAY_SIZE(xt_comment_match));
23094 }
23095
23096 static void __exit xt_comment_fini(void)
23097 {
23098- xt_unregister_match(&comment_match);
23099- xt_unregister_match(&comment6_match);
23100+ xt_unregister_matches(xt_comment_match, ARRAY_SIZE(xt_comment_match));
23101 }
23102
23103 module_init(xt_comment_init);
23104diff -Nur linux-2.6.18-rc5/net/netfilter/xt_connbytes.c linux-2.6.19/net/netfilter/xt_connbytes.c
23105--- linux-2.6.18-rc5/net/netfilter/xt_connbytes.c 2006-08-28 05:41:48.000000000 +0200
23106+++ linux-2.6.19/net/netfilter/xt_connbytes.c 2006-09-22 10:04:59.000000000 +0200
23107@@ -125,7 +125,6 @@
23108 const void *ip,
23109 const struct xt_match *match,
23110 void *matchinfo,
23111- unsigned int matchsize,
23112 unsigned int hook_mask)
23113 {
23114 const struct xt_connbytes_info *sinfo = matchinfo;
23115@@ -143,40 +142,35 @@
23116 return 1;
23117 }
23118
23119-static struct xt_match connbytes_match = {
23120- .name = "connbytes",
23121- .match = match,
23122- .checkentry = check,
23123- .matchsize = sizeof(struct xt_connbytes_info),
23124- .family = AF_INET,
23125- .me = THIS_MODULE
23126-};
23127-static struct xt_match connbytes6_match = {
23128- .name = "connbytes",
23129- .match = match,
23130- .checkentry = check,
23131- .matchsize = sizeof(struct xt_connbytes_info),
23132- .family = AF_INET6,
23133- .me = THIS_MODULE
23134+static struct xt_match xt_connbytes_match[] = {
23135+ {
23136+ .name = "connbytes",
23137+ .family = AF_INET,
23138+ .checkentry = check,
23139+ .match = match,
23140+ .matchsize = sizeof(struct xt_connbytes_info),
23141+ .me = THIS_MODULE
23142+ },
23143+ {
23144+ .name = "connbytes",
23145+ .family = AF_INET6,
23146+ .checkentry = check,
23147+ .match = match,
23148+ .matchsize = sizeof(struct xt_connbytes_info),
23149+ .me = THIS_MODULE
23150+ },
23151 };
23152
23153 static int __init xt_connbytes_init(void)
23154 {
23155- int ret;
23156- ret = xt_register_match(&connbytes_match);
23157- if (ret)
23158- return ret;
23159-
23160- ret = xt_register_match(&connbytes6_match);
23161- if (ret)
23162- xt_unregister_match(&connbytes_match);
23163- return ret;
23164+ return xt_register_matches(xt_connbytes_match,
23165+ ARRAY_SIZE(xt_connbytes_match));
23166 }
23167
23168 static void __exit xt_connbytes_fini(void)
23169 {
23170- xt_unregister_match(&connbytes_match);
23171- xt_unregister_match(&connbytes6_match);
23172+ xt_unregister_matches(xt_connbytes_match,
23173+ ARRAY_SIZE(xt_connbytes_match));
23174 }
23175
23176 module_init(xt_connbytes_init);
23177diff -Nur linux-2.6.18-rc5/net/netfilter/xt_connmark.c linux-2.6.19/net/netfilter/xt_connmark.c
23178--- linux-2.6.18-rc5/net/netfilter/xt_connmark.c 2006-08-28 05:41:48.000000000 +0200
23179+++ linux-2.6.19/net/netfilter/xt_connmark.c 2006-09-22 10:04:59.000000000 +0200
23180@@ -55,7 +55,6 @@
23181 const void *ip,
23182 const struct xt_match *match,
23183 void *matchinfo,
23184- unsigned int matchsize,
23185 unsigned int hook_mask)
23186 {
23187 struct xt_connmark_info *cm = matchinfo;
23188@@ -75,53 +74,44 @@
23189 }
23190
23191 static void
23192-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
23193+destroy(const struct xt_match *match, void *matchinfo)
23194 {
23195 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
23196 nf_ct_l3proto_module_put(match->family);
23197 #endif
23198 }
23199
23200-static struct xt_match connmark_match = {
23201- .name = "connmark",
23202- .match = match,
23203- .matchsize = sizeof(struct xt_connmark_info),
23204- .checkentry = checkentry,
23205- .destroy = destroy,
23206- .family = AF_INET,
23207- .me = THIS_MODULE
23208-};
23209-
23210-static struct xt_match connmark6_match = {
23211- .name = "connmark",
23212- .match = match,
23213- .matchsize = sizeof(struct xt_connmark_info),
23214- .checkentry = checkentry,
23215- .destroy = destroy,
23216- .family = AF_INET6,
23217- .me = THIS_MODULE
23218+static struct xt_match xt_connmark_match[] = {
23219+ {
23220+ .name = "connmark",
23221+ .family = AF_INET,
23222+ .checkentry = checkentry,
23223+ .match = match,
23224+ .destroy = destroy,
23225+ .matchsize = sizeof(struct xt_connmark_info),
23226+ .me = THIS_MODULE
23227+ },
23228+ {
23229+ .name = "connmark",
23230+ .family = AF_INET6,
23231+ .checkentry = checkentry,
23232+ .match = match,
23233+ .destroy = destroy,
23234+ .matchsize = sizeof(struct xt_connmark_info),
23235+ .me = THIS_MODULE
23236+ },
23237 };
23238
23239 static int __init xt_connmark_init(void)
23240 {
23241- int ret;
23242-
23243 need_conntrack();
23244-
23245- ret = xt_register_match(&connmark_match);
23246- if (ret)
23247- return ret;
23248-
23249- ret = xt_register_match(&connmark6_match);
23250- if (ret)
23251- xt_unregister_match(&connmark_match);
23252- return ret;
23253+ return xt_register_matches(xt_connmark_match,
23254+ ARRAY_SIZE(xt_connmark_match));
23255 }
23256
23257 static void __exit xt_connmark_fini(void)
23258 {
23259- xt_unregister_match(&connmark6_match);
23260- xt_unregister_match(&connmark_match);
23261+ xt_register_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match));
23262 }
23263
23264 module_init(xt_connmark_init);
23265diff -Nur linux-2.6.18-rc5/net/netfilter/xt_conntrack.c linux-2.6.19/net/netfilter/xt_conntrack.c
23266--- linux-2.6.18-rc5/net/netfilter/xt_conntrack.c 2006-08-28 05:41:48.000000000 +0200
23267+++ linux-2.6.19/net/netfilter/xt_conntrack.c 2006-09-22 10:04:59.000000000 +0200
23268@@ -208,7 +208,6 @@
23269 const void *ip,
23270 const struct xt_match *match,
23271 void *matchinfo,
23272- unsigned int matchsize,
23273 unsigned int hook_mask)
23274 {
23275 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
23276@@ -222,7 +221,7 @@
23277 }
23278
23279 static void
23280-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
23281+destroy(const struct xt_match *match, void *matchinfo)
23282 {
23283 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
23284 nf_ct_l3proto_module_put(match->family);
23285@@ -241,11 +240,8 @@
23286
23287 static int __init xt_conntrack_init(void)
23288 {
23289- int ret;
23290 need_conntrack();
23291- ret = xt_register_match(&conntrack_match);
23292-
23293- return ret;
23294+ return xt_register_match(&conntrack_match);
23295 }
23296
23297 static void __exit xt_conntrack_fini(void)
23298diff -Nur linux-2.6.18-rc5/net/netfilter/xt_dccp.c linux-2.6.19/net/netfilter/xt_dccp.c
23299--- linux-2.6.18-rc5/net/netfilter/xt_dccp.c 2006-08-28 05:41:48.000000000 +0200
23300+++ linux-2.6.19/net/netfilter/xt_dccp.c 2006-09-22 10:04:59.000000000 +0200
23301@@ -131,7 +131,6 @@
23302 const void *inf,
23303 const struct xt_match *match,
23304 void *matchinfo,
23305- unsigned int matchsize,
23306 unsigned int hook_mask)
23307 {
23308 const struct xt_dccp_info *info = matchinfo;
23309@@ -141,27 +140,26 @@
23310 && !(info->invflags & ~info->flags);
23311 }
23312
23313-static struct xt_match dccp_match =
23314-{
23315- .name = "dccp",
23316- .match = match,
23317- .matchsize = sizeof(struct xt_dccp_info),
23318- .proto = IPPROTO_DCCP,
23319- .checkentry = checkentry,
23320- .family = AF_INET,
23321- .me = THIS_MODULE,
23322+static struct xt_match xt_dccp_match[] = {
23323+ {
23324+ .name = "dccp",
23325+ .family = AF_INET,
23326+ .checkentry = checkentry,
23327+ .match = match,
23328+ .matchsize = sizeof(struct xt_dccp_info),
23329+ .proto = IPPROTO_DCCP,
23330+ .me = THIS_MODULE,
23331+ },
23332+ {
23333+ .name = "dccp",
23334+ .family = AF_INET6,
23335+ .checkentry = checkentry,
23336+ .match = match,
23337+ .matchsize = sizeof(struct xt_dccp_info),
23338+ .proto = IPPROTO_DCCP,
23339+ .me = THIS_MODULE,
23340+ },
23341 };
23342-static struct xt_match dccp6_match =
23343-{
23344- .name = "dccp",
23345- .match = match,
23346- .matchsize = sizeof(struct xt_dccp_info),
23347- .proto = IPPROTO_DCCP,
23348- .checkentry = checkentry,
23349- .family = AF_INET6,
23350- .me = THIS_MODULE,
23351-};
23352-
23353
23354 static int __init xt_dccp_init(void)
23355 {
23356@@ -173,27 +171,19 @@
23357 dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
23358 if (!dccp_optbuf)
23359 return -ENOMEM;
23360- ret = xt_register_match(&dccp_match);
23361+ ret = xt_register_matches(xt_dccp_match, ARRAY_SIZE(xt_dccp_match));
23362 if (ret)
23363 goto out_kfree;
23364- ret = xt_register_match(&dccp6_match);
23365- if (ret)
23366- goto out_unreg;
23367-
23368 return ret;
23369
23370-out_unreg:
23371- xt_unregister_match(&dccp_match);
23372 out_kfree:
23373 kfree(dccp_optbuf);
23374-
23375 return ret;
23376 }
23377
23378 static void __exit xt_dccp_fini(void)
23379 {
23380- xt_unregister_match(&dccp6_match);
23381- xt_unregister_match(&dccp_match);
23382+ xt_unregister_matches(xt_dccp_match, ARRAY_SIZE(xt_dccp_match));
23383 kfree(dccp_optbuf);
23384 }
23385
23386diff -Nur linux-2.6.18-rc5/net/netfilter/xt_dscp.c linux-2.6.19/net/netfilter/xt_dscp.c
23387--- linux-2.6.18-rc5/net/netfilter/xt_dscp.c 1970-01-01 01:00:00.000000000 +0100
23388+++ linux-2.6.19/net/netfilter/xt_dscp.c 2006-09-22 10:04:59.000000000 +0200
23389@@ -0,0 +1,103 @@
23390+/* IP tables module for matching the value of the IPv4/IPv6 DSCP field
23391+ *
23392+ * xt_dscp.c,v 1.3 2002/08/05 19:00:21 laforge Exp
23393+ *
23394+ * (C) 2002 by Harald Welte <laforge@netfilter.org>
23395+ *
23396+ * This program is free software; you can redistribute it and/or modify
23397+ * it under the terms of the GNU General Public License version 2 as
23398+ * published by the Free Software Foundation.
23399+ */
23400+
23401+#include <linux/module.h>
23402+#include <linux/skbuff.h>
23403+#include <linux/ip.h>
23404+#include <linux/ipv6.h>
23405+#include <net/dsfield.h>
23406+
23407+#include <linux/netfilter/xt_dscp.h>
23408+#include <linux/netfilter/x_tables.h>
23409+
23410+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
23411+MODULE_DESCRIPTION("x_tables DSCP matching module");
23412+MODULE_LICENSE("GPL");
23413+MODULE_ALIAS("ipt_dscp");
23414+MODULE_ALIAS("ip6t_dscp");
23415+
23416+static int match(const struct sk_buff *skb,
23417+ const struct net_device *in,
23418+ const struct net_device *out,
23419+ const struct xt_match *match,
23420+ const void *matchinfo,
23421+ int offset,
23422+ unsigned int protoff,
23423+ int *hotdrop)
23424+{
23425+ const struct xt_dscp_info *info = matchinfo;
23426+ u_int8_t dscp = ipv4_get_dsfield(skb->nh.iph) >> XT_DSCP_SHIFT;
23427+
23428+ return (dscp == info->dscp) ^ !!info->invert;
23429+}
23430+
23431+static int match6(const struct sk_buff *skb,
23432+ const struct net_device *in,
23433+ const struct net_device *out,
23434+ const struct xt_match *match,
23435+ const void *matchinfo,
23436+ int offset,
23437+ unsigned int protoff,
23438+ int *hotdrop)
23439+{
23440+ const struct xt_dscp_info *info = matchinfo;
23441+ u_int8_t dscp = ipv6_get_dsfield(skb->nh.ipv6h) >> XT_DSCP_SHIFT;
23442+
23443+ return (dscp == info->dscp) ^ !!info->invert;
23444+}
23445+
23446+static int checkentry(const char *tablename,
23447+ const void *info,
23448+ const struct xt_match *match,
23449+ void *matchinfo,
23450+ unsigned int hook_mask)
23451+{
23452+ const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp;
23453+
23454+ if (dscp > XT_DSCP_MAX) {
23455+ printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp);
23456+ return 0;
23457+ }
23458+
23459+ return 1;
23460+}
23461+
23462+static struct xt_match xt_dscp_match[] = {
23463+ {
23464+ .name = "dscp",
23465+ .family = AF_INET,
23466+ .checkentry = checkentry,
23467+ .match = match,
23468+ .matchsize = sizeof(struct xt_dscp_info),
23469+ .me = THIS_MODULE,
23470+ },
23471+ {
23472+ .name = "dscp",
23473+ .family = AF_INET6,
23474+ .checkentry = checkentry,
23475+ .match = match6,
23476+ .matchsize = sizeof(struct xt_dscp_info),
23477+ .me = THIS_MODULE,
23478+ },
23479+};
23480+
23481+static int __init xt_dscp_match_init(void)
23482+{
23483+ return xt_register_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match));
23484+}
23485+
23486+static void __exit xt_dscp_match_fini(void)
23487+{
23488+ xt_unregister_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match));
23489+}
23490+
23491+module_init(xt_dscp_match_init);
23492+module_exit(xt_dscp_match_fini);
23493diff -Nur linux-2.6.18-rc5/net/netfilter/xt_esp.c linux-2.6.19/net/netfilter/xt_esp.c
23494--- linux-2.6.18-rc5/net/netfilter/xt_esp.c 2006-08-28 05:41:48.000000000 +0200
23495+++ linux-2.6.19/net/netfilter/xt_esp.c 2006-09-22 10:04:59.000000000 +0200
23496@@ -79,7 +79,6 @@
23497 const void *ip_void,
23498 const struct xt_match *match,
23499 void *matchinfo,
23500- unsigned int matchinfosize,
23501 unsigned int hook_mask)
23502 {
23503 const struct xt_esp *espinfo = matchinfo;
23504@@ -92,44 +91,35 @@
23505 return 1;
23506 }
23507
23508-static struct xt_match esp_match = {
23509- .name = "esp",
23510- .family = AF_INET,
23511- .proto = IPPROTO_ESP,
23512- .match = &match,
23513- .matchsize = sizeof(struct xt_esp),
23514- .checkentry = &checkentry,
23515- .me = THIS_MODULE,
23516-};
23517-
23518-static struct xt_match esp6_match = {
23519- .name = "esp",
23520- .family = AF_INET6,
23521- .proto = IPPROTO_ESP,
23522- .match = &match,
23523- .matchsize = sizeof(struct xt_esp),
23524- .checkentry = &checkentry,
23525- .me = THIS_MODULE,
23526+static struct xt_match xt_esp_match[] = {
23527+ {
23528+ .name = "esp",
23529+ .family = AF_INET,
23530+ .checkentry = checkentry,
23531+ .match = match,
23532+ .matchsize = sizeof(struct xt_esp),
23533+ .proto = IPPROTO_ESP,
23534+ .me = THIS_MODULE,
23535+ },
23536+ {
23537+ .name = "esp",
23538+ .family = AF_INET6,
23539+ .checkentry = checkentry,
23540+ .match = match,
23541+ .matchsize = sizeof(struct xt_esp),
23542+ .proto = IPPROTO_ESP,
23543+ .me = THIS_MODULE,
23544+ },
23545 };
23546
23547 static int __init xt_esp_init(void)
23548 {
23549- int ret;
23550- ret = xt_register_match(&esp_match);
23551- if (ret)
23552- return ret;
23553-
23554- ret = xt_register_match(&esp6_match);
23555- if (ret)
23556- xt_unregister_match(&esp_match);
23557-
23558- return ret;
23559+ return xt_register_matches(xt_esp_match, ARRAY_SIZE(xt_esp_match));
23560 }
23561
23562 static void __exit xt_esp_cleanup(void)
23563 {
23564- xt_unregister_match(&esp_match);
23565- xt_unregister_match(&esp6_match);
23566+ xt_unregister_matches(xt_esp_match, ARRAY_SIZE(xt_esp_match));
23567 }
23568
23569 module_init(xt_esp_init);
23570diff -Nur linux-2.6.18-rc5/net/netfilter/xt_helper.c linux-2.6.19/net/netfilter/xt_helper.c
23571--- linux-2.6.18-rc5/net/netfilter/xt_helper.c 2006-08-28 05:41:48.000000000 +0200
23572+++ linux-2.6.19/net/netfilter/xt_helper.c 2006-09-22 10:04:59.000000000 +0200
23573@@ -139,7 +139,6 @@
23574 const void *inf,
23575 const struct xt_match *match,
23576 void *matchinfo,
23577- unsigned int matchsize,
23578 unsigned int hook_mask)
23579 {
23580 struct xt_helper_info *info = matchinfo;
23581@@ -156,52 +155,44 @@
23582 }
23583
23584 static void
23585-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
23586+destroy(const struct xt_match *match, void *matchinfo)
23587 {
23588 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
23589 nf_ct_l3proto_module_put(match->family);
23590 #endif
23591 }
23592
23593-static struct xt_match helper_match = {
23594- .name = "helper",
23595- .match = match,
23596- .matchsize = sizeof(struct xt_helper_info),
23597- .checkentry = check,
23598- .destroy = destroy,
23599- .family = AF_INET,
23600- .me = THIS_MODULE,
23601-};
23602-static struct xt_match helper6_match = {
23603- .name = "helper",
23604- .match = match,
23605- .matchsize = sizeof(struct xt_helper_info),
23606- .checkentry = check,
23607- .destroy = destroy,
23608- .family = AF_INET6,
23609- .me = THIS_MODULE,
23610+static struct xt_match xt_helper_match[] = {
23611+ {
23612+ .name = "helper",
23613+ .family = AF_INET,
23614+ .checkentry = check,
23615+ .match = match,
23616+ .destroy = destroy,
23617+ .matchsize = sizeof(struct xt_helper_info),
23618+ .me = THIS_MODULE,
23619+ },
23620+ {
23621+ .name = "helper",
23622+ .family = AF_INET6,
23623+ .checkentry = check,
23624+ .match = match,
23625+ .destroy = destroy,
23626+ .matchsize = sizeof(struct xt_helper_info),
23627+ .me = THIS_MODULE,
23628+ },
23629 };
23630
23631 static int __init xt_helper_init(void)
23632 {
23633- int ret;
23634 need_conntrack();
23635-
23636- ret = xt_register_match(&helper_match);
23637- if (ret < 0)
23638- return ret;
23639-
23640- ret = xt_register_match(&helper6_match);
23641- if (ret < 0)
23642- xt_unregister_match(&helper_match);
23643-
23644- return ret;
23645+ return xt_register_matches(xt_helper_match,
23646+ ARRAY_SIZE(xt_helper_match));
23647 }
23648
23649 static void __exit xt_helper_fini(void)
23650 {
23651- xt_unregister_match(&helper_match);
23652- xt_unregister_match(&helper6_match);
23653+ xt_unregister_matches(xt_helper_match, ARRAY_SIZE(xt_helper_match));
23654 }
23655
23656 module_init(xt_helper_init);
23657diff -Nur linux-2.6.18-rc5/net/netfilter/xt_length.c linux-2.6.19/net/netfilter/xt_length.c
23658--- linux-2.6.18-rc5/net/netfilter/xt_length.c 2006-08-28 05:41:48.000000000 +0200
23659+++ linux-2.6.19/net/netfilter/xt_length.c 2006-09-22 10:04:59.000000000 +0200
23660@@ -52,39 +52,32 @@
23661 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
23662 }
23663
23664-static struct xt_match length_match = {
23665- .name = "length",
23666- .match = match,
23667- .matchsize = sizeof(struct xt_length_info),
23668- .family = AF_INET,
23669- .me = THIS_MODULE,
23670-};
23671-
23672-static struct xt_match length6_match = {
23673- .name = "length",
23674- .match = match6,
23675- .matchsize = sizeof(struct xt_length_info),
23676- .family = AF_INET6,
23677- .me = THIS_MODULE,
23678+static struct xt_match xt_length_match[] = {
23679+ {
23680+ .name = "length",
23681+ .family = AF_INET,
23682+ .match = match,
23683+ .matchsize = sizeof(struct xt_length_info),
23684+ .me = THIS_MODULE,
23685+ },
23686+ {
23687+ .name = "length",
23688+ .family = AF_INET6,
23689+ .match = match6,
23690+ .matchsize = sizeof(struct xt_length_info),
23691+ .me = THIS_MODULE,
23692+ },
23693 };
23694
23695 static int __init xt_length_init(void)
23696 {
23697- int ret;
23698- ret = xt_register_match(&length_match);
23699- if (ret)
23700- return ret;
23701- ret = xt_register_match(&length6_match);
23702- if (ret)
23703- xt_unregister_match(&length_match);
23704-
23705- return ret;
23706+ return xt_register_matches(xt_length_match,
23707+ ARRAY_SIZE(xt_length_match));
23708 }
23709
23710 static void __exit xt_length_fini(void)
23711 {
23712- xt_unregister_match(&length_match);
23713- xt_unregister_match(&length6_match);
23714+ xt_unregister_matches(xt_length_match, ARRAY_SIZE(xt_length_match));
23715 }
23716
23717 module_init(xt_length_init);
23718diff -Nur linux-2.6.18-rc5/net/netfilter/xt_limit.c linux-2.6.19/net/netfilter/xt_limit.c
23719--- linux-2.6.18-rc5/net/netfilter/xt_limit.c 2006-08-28 05:41:48.000000000 +0200
23720+++ linux-2.6.19/net/netfilter/xt_limit.c 2006-09-22 10:04:59.000000000 +0200
23721@@ -110,7 +110,6 @@
23722 const void *inf,
23723 const struct xt_match *match,
23724 void *matchinfo,
23725- unsigned int matchsize,
23726 unsigned int hook_mask)
23727 {
23728 struct xt_rateinfo *r = matchinfo;
23729@@ -136,42 +135,33 @@
23730 return 1;
23731 }
23732
23733-static struct xt_match ipt_limit_reg = {
23734- .name = "limit",
23735- .match = ipt_limit_match,
23736- .matchsize = sizeof(struct xt_rateinfo),
23737- .checkentry = ipt_limit_checkentry,
23738- .family = AF_INET,
23739- .me = THIS_MODULE,
23740-};
23741-static struct xt_match limit6_reg = {
23742- .name = "limit",
23743- .match = ipt_limit_match,
23744- .matchsize = sizeof(struct xt_rateinfo),
23745- .checkentry = ipt_limit_checkentry,
23746- .family = AF_INET6,
23747- .me = THIS_MODULE,
23748+static struct xt_match xt_limit_match[] = {
23749+ {
23750+ .name = "limit",
23751+ .family = AF_INET,
23752+ .checkentry = ipt_limit_checkentry,
23753+ .match = ipt_limit_match,
23754+ .matchsize = sizeof(struct xt_rateinfo),
23755+ .me = THIS_MODULE,
23756+ },
23757+ {
23758+ .name = "limit",
23759+ .family = AF_INET6,
23760+ .checkentry = ipt_limit_checkentry,
23761+ .match = ipt_limit_match,
23762+ .matchsize = sizeof(struct xt_rateinfo),
23763+ .me = THIS_MODULE,
23764+ },
23765 };
23766
23767 static int __init xt_limit_init(void)
23768 {
23769- int ret;
23770-
23771- ret = xt_register_match(&ipt_limit_reg);
23772- if (ret)
23773- return ret;
23774-
23775- ret = xt_register_match(&limit6_reg);
23776- if (ret)
23777- xt_unregister_match(&ipt_limit_reg);
23778-
23779- return ret;
23780+ return xt_register_matches(xt_limit_match, ARRAY_SIZE(xt_limit_match));
23781 }
23782
23783 static void __exit xt_limit_fini(void)
23784 {
23785- xt_unregister_match(&ipt_limit_reg);
23786- xt_unregister_match(&limit6_reg);
23787+ xt_unregister_matches(xt_limit_match, ARRAY_SIZE(xt_limit_match));
23788 }
23789
23790 module_init(xt_limit_init);
23791diff -Nur linux-2.6.18-rc5/net/netfilter/xt_mac.c linux-2.6.19/net/netfilter/xt_mac.c
23792--- linux-2.6.18-rc5/net/netfilter/xt_mac.c 2006-08-28 05:41:48.000000000 +0200
23793+++ linux-2.6.19/net/netfilter/xt_mac.c 2006-09-22 10:04:59.000000000 +0200
23794@@ -43,43 +43,37 @@
23795 ^ info->invert));
23796 }
23797
23798-static struct xt_match mac_match = {
23799- .name = "mac",
23800- .match = match,
23801- .matchsize = sizeof(struct xt_mac_info),
23802- .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
23803- (1 << NF_IP_FORWARD),
23804- .family = AF_INET,
23805- .me = THIS_MODULE,
23806-};
23807-static struct xt_match mac6_match = {
23808- .name = "mac",
23809- .match = match,
23810- .matchsize = sizeof(struct xt_mac_info),
23811- .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
23812- (1 << NF_IP_FORWARD),
23813- .family = AF_INET6,
23814- .me = THIS_MODULE,
23815+static struct xt_match xt_mac_match[] = {
23816+ {
23817+ .name = "mac",
23818+ .family = AF_INET,
23819+ .match = match,
23820+ .matchsize = sizeof(struct xt_mac_info),
23821+ .hooks = (1 << NF_IP_PRE_ROUTING) |
23822+ (1 << NF_IP_LOCAL_IN) |
23823+ (1 << NF_IP_FORWARD),
23824+ .me = THIS_MODULE,
23825+ },
23826+ {
23827+ .name = "mac",
23828+ .family = AF_INET6,
23829+ .match = match,
23830+ .matchsize = sizeof(struct xt_mac_info),
23831+ .hooks = (1 << NF_IP_PRE_ROUTING) |
23832+ (1 << NF_IP_LOCAL_IN) |
23833+ (1 << NF_IP_FORWARD),
23834+ .me = THIS_MODULE,
23835+ },
23836 };
23837
23838 static int __init xt_mac_init(void)
23839 {
23840- int ret;
23841- ret = xt_register_match(&mac_match);
23842- if (ret)
23843- return ret;
23844-
23845- ret = xt_register_match(&mac6_match);
23846- if (ret)
23847- xt_unregister_match(&mac_match);
23848-
23849- return ret;
23850+ return xt_register_matches(xt_mac_match, ARRAY_SIZE(xt_mac_match));
23851 }
23852
23853 static void __exit xt_mac_fini(void)
23854 {
23855- xt_unregister_match(&mac_match);
23856- xt_unregister_match(&mac6_match);
23857+ xt_unregister_matches(xt_mac_match, ARRAY_SIZE(xt_mac_match));
23858 }
23859
23860 module_init(xt_mac_init);
23861diff -Nur linux-2.6.18-rc5/net/netfilter/xt_mark.c linux-2.6.19/net/netfilter/xt_mark.c
23862--- linux-2.6.18-rc5/net/netfilter/xt_mark.c 2006-08-28 05:41:48.000000000 +0200
23863+++ linux-2.6.19/net/netfilter/xt_mark.c 2006-09-22 10:04:59.000000000 +0200
23864@@ -39,7 +39,6 @@
23865 const void *entry,
23866 const struct xt_match *match,
23867 void *matchinfo,
23868- unsigned int matchsize,
23869 unsigned int hook_mask)
23870 {
23871 const struct xt_mark_info *minfo = matchinfo;
23872@@ -51,42 +50,33 @@
23873 return 1;
23874 }
23875
23876-static struct xt_match mark_match = {
23877- .name = "mark",
23878- .match = match,
23879- .matchsize = sizeof(struct xt_mark_info),
23880- .checkentry = checkentry,
23881- .family = AF_INET,
23882- .me = THIS_MODULE,
23883-};
23884-
23885-static struct xt_match mark6_match = {
23886- .name = "mark",
23887- .match = match,
23888- .matchsize = sizeof(struct xt_mark_info),
23889- .checkentry = checkentry,
23890- .family = AF_INET6,
23891- .me = THIS_MODULE,
23892+static struct xt_match xt_mark_match[] = {
23893+ {
23894+ .name = "mark",
23895+ .family = AF_INET,
23896+ .checkentry = checkentry,
23897+ .match = match,
23898+ .matchsize = sizeof(struct xt_mark_info),
23899+ .me = THIS_MODULE,
23900+ },
23901+ {
23902+ .name = "mark",
23903+ .family = AF_INET6,
23904+ .checkentry = checkentry,
23905+ .match = match,
23906+ .matchsize = sizeof(struct xt_mark_info),
23907+ .me = THIS_MODULE,
23908+ },
23909 };
23910
23911 static int __init xt_mark_init(void)
23912 {
23913- int ret;
23914- ret = xt_register_match(&mark_match);
23915- if (ret)
23916- return ret;
23917-
23918- ret = xt_register_match(&mark6_match);
23919- if (ret)
23920- xt_unregister_match(&mark_match);
23921-
23922- return ret;
23923+ return xt_register_matches(xt_mark_match, ARRAY_SIZE(xt_mark_match));
23924 }
23925
23926 static void __exit xt_mark_fini(void)
23927 {
23928- xt_unregister_match(&mark_match);
23929- xt_unregister_match(&mark6_match);
23930+ xt_unregister_matches(xt_mark_match, ARRAY_SIZE(xt_mark_match));
23931 }
23932
23933 module_init(xt_mark_init);
23934diff -Nur linux-2.6.18-rc5/net/netfilter/xt_multiport.c linux-2.6.19/net/netfilter/xt_multiport.c
23935--- linux-2.6.18-rc5/net/netfilter/xt_multiport.c 2006-08-28 05:41:48.000000000 +0200
23936+++ linux-2.6.19/net/netfilter/xt_multiport.c 2006-09-22 10:04:59.000000000 +0200
23937@@ -176,7 +176,6 @@
23938 const void *info,
23939 const struct xt_match *match,
23940 void *matchinfo,
23941- unsigned int matchsize,
23942 unsigned int hook_mask)
23943 {
23944 const struct ipt_ip *ip = info;
23945@@ -191,7 +190,6 @@
23946 const void *info,
23947 const struct xt_match *match,
23948 void *matchinfo,
23949- unsigned int matchsize,
23950 unsigned int hook_mask)
23951 {
23952 const struct ipt_ip *ip = info;
23953@@ -206,7 +204,6 @@
23954 const void *info,
23955 const struct xt_match *match,
23956 void *matchinfo,
23957- unsigned int matchsize,
23958 unsigned int hook_mask)
23959 {
23960 const struct ip6t_ip6 *ip = info;
23961@@ -221,7 +218,6 @@
23962 const void *info,
23963 const struct xt_match *match,
23964 void *matchinfo,
23965- unsigned int matchsize,
23966 unsigned int hook_mask)
23967 {
23968 const struct ip6t_ip6 *ip = info;
23969@@ -231,84 +227,55 @@
23970 multiinfo->count);
23971 }
23972
23973-static struct xt_match multiport_match = {
23974- .name = "multiport",
23975- .revision = 0,
23976- .matchsize = sizeof(struct xt_multiport),
23977- .match = &match,
23978- .checkentry = &checkentry,
23979- .family = AF_INET,
23980- .me = THIS_MODULE,
23981-};
23982-
23983-static struct xt_match multiport_match_v1 = {
23984- .name = "multiport",
23985- .revision = 1,
23986- .matchsize = sizeof(struct xt_multiport_v1),
23987- .match = &match_v1,
23988- .checkentry = &checkentry_v1,
23989- .family = AF_INET,
23990- .me = THIS_MODULE,
23991-};
23992-
23993-static struct xt_match multiport6_match = {
23994- .name = "multiport",
23995- .revision = 0,
23996- .matchsize = sizeof(struct xt_multiport),
23997- .match = &match,
23998- .checkentry = &checkentry6,
23999- .family = AF_INET6,
24000- .me = THIS_MODULE,
24001-};
24002-
24003-static struct xt_match multiport6_match_v1 = {
24004- .name = "multiport",
24005- .revision = 1,
24006- .matchsize = sizeof(struct xt_multiport_v1),
24007- .match = &match_v1,
24008- .checkentry = &checkentry6_v1,
24009- .family = AF_INET6,
24010- .me = THIS_MODULE,
24011+static struct xt_match xt_multiport_match[] = {
24012+ {
24013+ .name = "multiport",
24014+ .family = AF_INET,
24015+ .revision = 0,
24016+ .checkentry = checkentry,
24017+ .match = match,
24018+ .matchsize = sizeof(struct xt_multiport),
24019+ .me = THIS_MODULE,
24020+ },
24021+ {
24022+ .name = "multiport",
24023+ .family = AF_INET,
24024+ .revision = 1,
24025+ .checkentry = checkentry_v1,
24026+ .match = match_v1,
24027+ .matchsize = sizeof(struct xt_multiport_v1),
24028+ .me = THIS_MODULE,
24029+ },
24030+ {
24031+ .name = "multiport",
24032+ .family = AF_INET6,
24033+ .revision = 0,
24034+ .checkentry = checkentry6,
24035+ .match = match,
24036+ .matchsize = sizeof(struct xt_multiport),
24037+ .me = THIS_MODULE,
24038+ },
24039+ {
24040+ .name = "multiport",
24041+ .family = AF_INET6,
24042+ .revision = 1,
24043+ .checkentry = checkentry6_v1,
24044+ .match = match_v1,
24045+ .matchsize = sizeof(struct xt_multiport_v1),
24046+ .me = THIS_MODULE,
24047+ },
24048 };
24049
24050 static int __init xt_multiport_init(void)
24051 {
24052- int ret;
24053-
24054- ret = xt_register_match(&multiport_match);
24055- if (ret)
24056- goto out;
24057-
24058- ret = xt_register_match(&multiport_match_v1);
24059- if (ret)
24060- goto out_unreg_multi_v0;
24061-
24062- ret = xt_register_match(&multiport6_match);
24063- if (ret)
24064- goto out_unreg_multi_v1;
24065-
24066- ret = xt_register_match(&multiport6_match_v1);
24067- if (ret)
24068- goto out_unreg_multi6_v0;
24069-
24070- return ret;
24071-
24072-out_unreg_multi6_v0:
24073- xt_unregister_match(&multiport6_match);
24074-out_unreg_multi_v1:
24075- xt_unregister_match(&multiport_match_v1);
24076-out_unreg_multi_v0:
24077- xt_unregister_match(&multiport_match);
24078-out:
24079- return ret;
24080+ return xt_register_matches(xt_multiport_match,
24081+ ARRAY_SIZE(xt_multiport_match));
24082 }
24083
24084 static void __exit xt_multiport_fini(void)
24085 {
24086- xt_unregister_match(&multiport_match);
24087- xt_unregister_match(&multiport_match_v1);
24088- xt_unregister_match(&multiport6_match);
24089- xt_unregister_match(&multiport6_match_v1);
24090+ xt_unregister_matches(xt_multiport_match,
24091+ ARRAY_SIZE(xt_multiport_match));
24092 }
24093
24094 module_init(xt_multiport_init);
24095diff -Nur linux-2.6.18-rc5/net/netfilter/xt_physdev.c linux-2.6.19/net/netfilter/xt_physdev.c
24096--- linux-2.6.18-rc5/net/netfilter/xt_physdev.c 2006-08-28 05:41:48.000000000 +0200
24097+++ linux-2.6.19/net/netfilter/xt_physdev.c 2006-09-22 10:04:59.000000000 +0200
24098@@ -106,7 +106,6 @@
24099 const void *ip,
24100 const struct xt_match *match,
24101 void *matchinfo,
24102- unsigned int matchsize,
24103 unsigned int hook_mask)
24104 {
24105 const struct xt_physdev_info *info = matchinfo;
24106@@ -132,43 +131,34 @@
24107 return 1;
24108 }
24109
24110-static struct xt_match physdev_match = {
24111- .name = "physdev",
24112- .match = match,
24113- .matchsize = sizeof(struct xt_physdev_info),
24114- .checkentry = checkentry,
24115- .family = AF_INET,
24116- .me = THIS_MODULE,
24117-};
24118-
24119-static struct xt_match physdev6_match = {
24120- .name = "physdev",
24121- .match = match,
24122- .matchsize = sizeof(struct xt_physdev_info),
24123- .checkentry = checkentry,
24124- .family = AF_INET6,
24125- .me = THIS_MODULE,
24126+static struct xt_match xt_physdev_match[] = {
24127+ {
24128+ .name = "physdev",
24129+ .family = AF_INET,
24130+ .checkentry = checkentry,
24131+ .match = match,
24132+ .matchsize = sizeof(struct xt_physdev_info),
24133+ .me = THIS_MODULE,
24134+ },
24135+ {
24136+ .name = "physdev",
24137+ .family = AF_INET6,
24138+ .checkentry = checkentry,
24139+ .match = match,
24140+ .matchsize = sizeof(struct xt_physdev_info),
24141+ .me = THIS_MODULE,
24142+ },
24143 };
24144
24145 static int __init xt_physdev_init(void)
24146 {
24147- int ret;
24148-
24149- ret = xt_register_match(&physdev_match);
24150- if (ret < 0)
24151- return ret;
24152-
24153- ret = xt_register_match(&physdev6_match);
24154- if (ret < 0)
24155- xt_unregister_match(&physdev_match);
24156-
24157- return ret;
24158+ return xt_register_matches(xt_physdev_match,
24159+ ARRAY_SIZE(xt_physdev_match));
24160 }
24161
24162 static void __exit xt_physdev_fini(void)
24163 {
24164- xt_unregister_match(&physdev_match);
24165- xt_unregister_match(&physdev6_match);
24166+ xt_unregister_matches(xt_physdev_match, ARRAY_SIZE(xt_physdev_match));
24167 }
24168
24169 module_init(xt_physdev_init);
24170diff -Nur linux-2.6.18-rc5/net/netfilter/xt_pkttype.c linux-2.6.19/net/netfilter/xt_pkttype.c
24171--- linux-2.6.18-rc5/net/netfilter/xt_pkttype.c 2006-08-28 05:41:48.000000000 +0200
24172+++ linux-2.6.19/net/netfilter/xt_pkttype.c 2006-09-22 10:04:59.000000000 +0200
24173@@ -43,40 +43,32 @@
24174 return (type == info->pkttype) ^ info->invert;
24175 }
24176
24177-static struct xt_match pkttype_match = {
24178- .name = "pkttype",
24179- .match = match,
24180- .matchsize = sizeof(struct xt_pkttype_info),
24181- .family = AF_INET,
24182- .me = THIS_MODULE,
24183-};
24184-
24185-static struct xt_match pkttype6_match = {
24186- .name = "pkttype",
24187- .match = match,
24188- .matchsize = sizeof(struct xt_pkttype_info),
24189- .family = AF_INET6,
24190- .me = THIS_MODULE,
24191+static struct xt_match xt_pkttype_match[] = {
24192+ {
24193+ .name = "pkttype",
24194+ .family = AF_INET,
24195+ .match = match,
24196+ .matchsize = sizeof(struct xt_pkttype_info),
24197+ .me = THIS_MODULE,
24198+ },
24199+ {
24200+ .name = "pkttype",
24201+ .family = AF_INET6,
24202+ .match = match,
24203+ .matchsize = sizeof(struct xt_pkttype_info),
24204+ .me = THIS_MODULE,
24205+ },
24206 };
24207
24208 static int __init xt_pkttype_init(void)
24209 {
24210- int ret;
24211- ret = xt_register_match(&pkttype_match);
24212- if (ret)
24213- return ret;
24214-
24215- ret = xt_register_match(&pkttype6_match);
24216- if (ret)
24217- xt_unregister_match(&pkttype_match);
24218-
24219- return ret;
24220+ return xt_register_matches(xt_pkttype_match,
24221+ ARRAY_SIZE(xt_pkttype_match));
24222 }
24223
24224 static void __exit xt_pkttype_fini(void)
24225 {
24226- xt_unregister_match(&pkttype_match);
24227- xt_unregister_match(&pkttype6_match);
24228+ xt_unregister_matches(xt_pkttype_match, ARRAY_SIZE(xt_pkttype_match));
24229 }
24230
24231 module_init(xt_pkttype_init);
24232diff -Nur linux-2.6.18-rc5/net/netfilter/xt_policy.c linux-2.6.19/net/netfilter/xt_policy.c
24233--- linux-2.6.18-rc5/net/netfilter/xt_policy.c 2006-08-28 05:41:48.000000000 +0200
24234+++ linux-2.6.19/net/netfilter/xt_policy.c 2006-09-22 10:04:59.000000000 +0200
24235@@ -135,8 +135,7 @@
24236
24237 static int checkentry(const char *tablename, const void *ip_void,
24238 const struct xt_match *match,
24239- void *matchinfo, unsigned int matchsize,
24240- unsigned int hook_mask)
24241+ void *matchinfo, unsigned int hook_mask)
24242 {
24243 struct xt_policy_info *info = matchinfo;
24244
24245@@ -165,43 +164,36 @@
24246 return 1;
24247 }
24248
24249-static struct xt_match policy_match = {
24250- .name = "policy",
24251- .family = AF_INET,
24252- .match = match,
24253- .matchsize = sizeof(struct xt_policy_info),
24254- .checkentry = checkentry,
24255- .family = AF_INET,
24256- .me = THIS_MODULE,
24257-};
24258-
24259-static struct xt_match policy6_match = {
24260- .name = "policy",
24261- .family = AF_INET6,
24262- .match = match,
24263- .matchsize = sizeof(struct xt_policy_info),
24264- .checkentry = checkentry,
24265- .family = AF_INET6,
24266- .me = THIS_MODULE,
24267+static struct xt_match xt_policy_match[] = {
24268+ {
24269+ .name = "policy",
24270+ .family = AF_INET,
24271+ .checkentry = checkentry,
24272+ .match = match,
24273+ .matchsize = sizeof(struct xt_policy_info),
24274+ .family = AF_INET,
24275+ .me = THIS_MODULE,
24276+ },
24277+ {
24278+ .name = "policy",
24279+ .family = AF_INET6,
24280+ .checkentry = checkentry,
24281+ .match = match,
24282+ .matchsize = sizeof(struct xt_policy_info),
24283+ .family = AF_INET6,
24284+ .me = THIS_MODULE,
24285+ },
24286 };
24287
24288 static int __init init(void)
24289 {
24290- int ret;
24291-
24292- ret = xt_register_match(&policy_match);
24293- if (ret)
24294- return ret;
24295- ret = xt_register_match(&policy6_match);
24296- if (ret)
24297- xt_unregister_match(&policy_match);
24298- return ret;
24299+ return xt_register_matches(xt_policy_match,
24300+ ARRAY_SIZE(xt_policy_match));
24301 }
24302
24303 static void __exit fini(void)
24304 {
24305- xt_unregister_match(&policy6_match);
24306- xt_unregister_match(&policy_match);
24307+ xt_unregister_matches(xt_policy_match, ARRAY_SIZE(xt_policy_match));
24308 }
24309
24310 module_init(init);
24311diff -Nur linux-2.6.18-rc5/net/netfilter/xt_quota.c linux-2.6.19/net/netfilter/xt_quota.c
24312--- linux-2.6.18-rc5/net/netfilter/xt_quota.c 2006-08-28 05:41:48.000000000 +0200
24313+++ linux-2.6.19/net/netfilter/xt_quota.c 2006-09-22 10:04:59.000000000 +0200
24314@@ -39,7 +39,7 @@
24315 static int
24316 checkentry(const char *tablename, const void *entry,
24317 const struct xt_match *match, void *matchinfo,
24318- unsigned int matchsize, unsigned int hook_mask)
24319+ unsigned int hook_mask)
24320 {
24321 struct xt_quota_info *q = (struct xt_quota_info *)matchinfo;
24322
24323@@ -50,46 +50,33 @@
24324 return 1;
24325 }
24326
24327-static struct xt_match quota_match = {
24328- .name = "quota",
24329- .family = AF_INET,
24330- .match = match,
24331- .matchsize = sizeof(struct xt_quota_info),
24332- .checkentry = checkentry,
24333- .me = THIS_MODULE
24334-};
24335-
24336-static struct xt_match quota_match6 = {
24337- .name = "quota",
24338- .family = AF_INET6,
24339- .match = match,
24340- .matchsize = sizeof(struct xt_quota_info),
24341- .checkentry = checkentry,
24342- .me = THIS_MODULE
24343+static struct xt_match xt_quota_match[] = {
24344+ {
24345+ .name = "quota",
24346+ .family = AF_INET,
24347+ .checkentry = checkentry,
24348+ .match = match,
24349+ .matchsize = sizeof(struct xt_quota_info),
24350+ .me = THIS_MODULE
24351+ },
24352+ {
24353+ .name = "quota",
24354+ .family = AF_INET6,
24355+ .checkentry = checkentry,
24356+ .match = match,
24357+ .matchsize = sizeof(struct xt_quota_info),
24358+ .me = THIS_MODULE
24359+ },
24360 };
24361
24362 static int __init xt_quota_init(void)
24363 {
24364- int ret;
24365-
24366- ret = xt_register_match(&quota_match);
24367- if (ret)
24368- goto err1;
24369- ret = xt_register_match(&quota_match6);
24370- if (ret)
24371- goto err2;
24372- return ret;
24373-
24374-err2:
24375- xt_unregister_match(&quota_match);
24376-err1:
24377- return ret;
24378+ return xt_register_matches(xt_quota_match, ARRAY_SIZE(xt_quota_match));
24379 }
24380
24381 static void __exit xt_quota_fini(void)
24382 {
24383- xt_unregister_match(&quota_match6);
24384- xt_unregister_match(&quota_match);
24385+ xt_unregister_matches(xt_quota_match, ARRAY_SIZE(xt_quota_match));
24386 }
24387
24388 module_init(xt_quota_init);
24389diff -Nur linux-2.6.18-rc5/net/netfilter/xt_sctp.c linux-2.6.19/net/netfilter/xt_sctp.c
24390--- linux-2.6.18-rc5/net/netfilter/xt_sctp.c 2006-08-28 05:41:48.000000000 +0200
24391+++ linux-2.6.19/net/netfilter/xt_sctp.c 2006-09-22 10:04:59.000000000 +0200
24392@@ -163,7 +163,6 @@
24393 const void *inf,
24394 const struct xt_match *match,
24395 void *matchinfo,
24396- unsigned int matchsize,
24397 unsigned int hook_mask)
24398 {
24399 const struct xt_sctp_info *info = matchinfo;
24400@@ -178,44 +177,35 @@
24401 | SCTP_CHUNK_MATCH_ONLY)));
24402 }
24403
24404-static struct xt_match sctp_match = {
24405- .name = "sctp",
24406- .match = match,
24407- .matchsize = sizeof(struct xt_sctp_info),
24408- .proto = IPPROTO_SCTP,
24409- .checkentry = checkentry,
24410- .family = AF_INET,
24411- .me = THIS_MODULE
24412-};
24413-
24414-static struct xt_match sctp6_match = {
24415- .name = "sctp",
24416- .match = match,
24417- .matchsize = sizeof(struct xt_sctp_info),
24418- .proto = IPPROTO_SCTP,
24419- .checkentry = checkentry,
24420- .family = AF_INET6,
24421- .me = THIS_MODULE
24422+static struct xt_match xt_sctp_match[] = {
24423+ {
24424+ .name = "sctp",
24425+ .family = AF_INET,
24426+ .checkentry = checkentry,
24427+ .match = match,
24428+ .matchsize = sizeof(struct xt_sctp_info),
24429+ .proto = IPPROTO_SCTP,
24430+ .me = THIS_MODULE
24431+ },
24432+ {
24433+ .name = "sctp",
24434+ .family = AF_INET6,
24435+ .checkentry = checkentry,
24436+ .match = match,
24437+ .matchsize = sizeof(struct xt_sctp_info),
24438+ .proto = IPPROTO_SCTP,
24439+ .me = THIS_MODULE
24440+ },
24441 };
24442
24443 static int __init xt_sctp_init(void)
24444 {
24445- int ret;
24446- ret = xt_register_match(&sctp_match);
24447- if (ret)
24448- return ret;
24449-
24450- ret = xt_register_match(&sctp6_match);
24451- if (ret)
24452- xt_unregister_match(&sctp_match);
24453-
24454- return ret;
24455+ return xt_register_matches(xt_sctp_match, ARRAY_SIZE(xt_sctp_match));
24456 }
24457
24458 static void __exit xt_sctp_fini(void)
24459 {
24460- xt_unregister_match(&sctp6_match);
24461- xt_unregister_match(&sctp_match);
24462+ xt_unregister_matches(xt_sctp_match, ARRAY_SIZE(xt_sctp_match));
24463 }
24464
24465 module_init(xt_sctp_init);
24466diff -Nur linux-2.6.18-rc5/net/netfilter/xt_state.c linux-2.6.19/net/netfilter/xt_state.c
24467--- linux-2.6.18-rc5/net/netfilter/xt_state.c 2006-08-28 05:41:48.000000000 +0200
24468+++ linux-2.6.19/net/netfilter/xt_state.c 2006-09-22 10:04:59.000000000 +0200
24469@@ -48,7 +48,6 @@
24470 const void *inf,
24471 const struct xt_match *match,
24472 void *matchinfo,
24473- unsigned int matchsize,
24474 unsigned int hook_mask)
24475 {
24476 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
24477@@ -62,54 +61,43 @@
24478 }
24479
24480 static void
24481-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
24482+destroy(const struct xt_match *match, void *matchinfo)
24483 {
24484 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
24485 nf_ct_l3proto_module_put(match->family);
24486 #endif
24487 }
24488
24489-static struct xt_match state_match = {
24490- .name = "state",
24491- .match = match,
24492- .checkentry = check,
24493- .destroy = destroy,
24494- .matchsize = sizeof(struct xt_state_info),
24495- .family = AF_INET,
24496- .me = THIS_MODULE,
24497-};
24498-
24499-static struct xt_match state6_match = {
24500- .name = "state",
24501- .match = match,
24502- .checkentry = check,
24503- .destroy = destroy,
24504- .matchsize = sizeof(struct xt_state_info),
24505- .family = AF_INET6,
24506- .me = THIS_MODULE,
24507+static struct xt_match xt_state_match[] = {
24508+ {
24509+ .name = "state",
24510+ .family = AF_INET,
24511+ .checkentry = check,
24512+ .match = match,
24513+ .destroy = destroy,
24514+ .matchsize = sizeof(struct xt_state_info),
24515+ .me = THIS_MODULE,
24516+ },
24517+ {
24518+ .name = "state",
24519+ .family = AF_INET6,
24520+ .checkentry = check,
24521+ .match = match,
24522+ .destroy = destroy,
24523+ .matchsize = sizeof(struct xt_state_info),
24524+ .me = THIS_MODULE,
24525+ },
24526 };
24527
24528 static int __init xt_state_init(void)
24529 {
24530- int ret;
24531-
24532 need_conntrack();
24533-
24534- ret = xt_register_match(&state_match);
24535- if (ret < 0)
24536- return ret;
24537-
24538- ret = xt_register_match(&state6_match);
24539- if (ret < 0)
24540- xt_unregister_match(&state_match);
24541-
24542- return ret;
24543+ return xt_register_matches(xt_state_match, ARRAY_SIZE(xt_state_match));
24544 }
24545
24546 static void __exit xt_state_fini(void)
24547 {
24548- xt_unregister_match(&state_match);
24549- xt_unregister_match(&state6_match);
24550+ xt_unregister_matches(xt_state_match, ARRAY_SIZE(xt_state_match));
24551 }
24552
24553 module_init(xt_state_init);
24554diff -Nur linux-2.6.18-rc5/net/netfilter/xt_statistic.c linux-2.6.19/net/netfilter/xt_statistic.c
24555--- linux-2.6.18-rc5/net/netfilter/xt_statistic.c 2006-08-28 05:41:48.000000000 +0200
24556+++ linux-2.6.19/net/netfilter/xt_statistic.c 2006-09-22 10:04:59.000000000 +0200
24557@@ -55,7 +55,7 @@
24558 static int
24559 checkentry(const char *tablename, const void *entry,
24560 const struct xt_match *match, void *matchinfo,
24561- unsigned int matchsize, unsigned int hook_mask)
24562+ unsigned int hook_mask)
24563 {
24564 struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
24565
24566@@ -66,46 +66,35 @@
24567 return 1;
24568 }
24569
24570-static struct xt_match statistic_match = {
24571- .name = "statistic",
24572- .match = match,
24573- .matchsize = sizeof(struct xt_statistic_info),
24574- .checkentry = checkentry,
24575- .family = AF_INET,
24576- .me = THIS_MODULE,
24577-};
24578-
24579-static struct xt_match statistic_match6 = {
24580- .name = "statistic",
24581- .match = match,
24582- .matchsize = sizeof(struct xt_statistic_info),
24583- .checkentry = checkentry,
24584- .family = AF_INET6,
24585- .me = THIS_MODULE,
24586+static struct xt_match xt_statistic_match[] = {
24587+ {
24588+ .name = "statistic",
24589+ .family = AF_INET,
24590+ .checkentry = checkentry,
24591+ .match = match,
24592+ .matchsize = sizeof(struct xt_statistic_info),
24593+ .me = THIS_MODULE,
24594+ },
24595+ {
24596+ .name = "statistic",
24597+ .family = AF_INET6,
24598+ .checkentry = checkentry,
24599+ .match = match,
24600+ .matchsize = sizeof(struct xt_statistic_info),
24601+ .me = THIS_MODULE,
24602+ },
24603 };
24604
24605 static int __init xt_statistic_init(void)
24606 {
24607- int ret;
24608-
24609- ret = xt_register_match(&statistic_match);
24610- if (ret)
24611- goto err1;
24612-
24613- ret = xt_register_match(&statistic_match6);
24614- if (ret)
24615- goto err2;
24616- return ret;
24617-err2:
24618- xt_unregister_match(&statistic_match);
24619-err1:
24620- return ret;
24621+ return xt_register_matches(xt_statistic_match,
24622+ ARRAY_SIZE(xt_statistic_match));
24623 }
24624
24625 static void __exit xt_statistic_fini(void)
24626 {
24627- xt_unregister_match(&statistic_match6);
24628- xt_unregister_match(&statistic_match);
24629+ xt_unregister_matches(xt_statistic_match,
24630+ ARRAY_SIZE(xt_statistic_match));
24631 }
24632
24633 module_init(xt_statistic_init);
24634diff -Nur linux-2.6.18-rc5/net/netfilter/xt_string.c linux-2.6.19/net/netfilter/xt_string.c
24635--- linux-2.6.18-rc5/net/netfilter/xt_string.c 2006-08-28 05:41:48.000000000 +0200
24636+++ linux-2.6.19/net/netfilter/xt_string.c 2006-09-22 10:04:59.000000000 +0200
24637@@ -46,7 +46,6 @@
24638 const void *ip,
24639 const struct xt_match *match,
24640 void *matchinfo,
24641- unsigned int matchsize,
24642 unsigned int hook_mask)
24643 {
24644 struct xt_string_info *conf = matchinfo;
24645@@ -69,49 +68,40 @@
24646 return 1;
24647 }
24648
24649-static void destroy(const struct xt_match *match, void *matchinfo,
24650- unsigned int matchsize)
24651+static void destroy(const struct xt_match *match, void *matchinfo)
24652 {
24653 textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
24654 }
24655
24656-static struct xt_match string_match = {
24657- .name = "string",
24658- .match = match,
24659- .matchsize = sizeof(struct xt_string_info),
24660- .checkentry = checkentry,
24661- .destroy = destroy,
24662- .family = AF_INET,
24663- .me = THIS_MODULE
24664-};
24665-static struct xt_match string6_match = {
24666- .name = "string",
24667- .match = match,
24668- .matchsize = sizeof(struct xt_string_info),
24669- .checkentry = checkentry,
24670- .destroy = destroy,
24671- .family = AF_INET6,
24672- .me = THIS_MODULE
24673+static struct xt_match xt_string_match[] = {
24674+ {
24675+ .name = "string",
24676+ .family = AF_INET,
24677+ .checkentry = checkentry,
24678+ .match = match,
24679+ .destroy = destroy,
24680+ .matchsize = sizeof(struct xt_string_info),
24681+ .me = THIS_MODULE
24682+ },
24683+ {
24684+ .name = "string",
24685+ .family = AF_INET6,
24686+ .checkentry = checkentry,
24687+ .match = match,
24688+ .destroy = destroy,
24689+ .matchsize = sizeof(struct xt_string_info),
24690+ .me = THIS_MODULE
24691+ },
24692 };
24693
24694 static int __init xt_string_init(void)
24695 {
24696- int ret;
24697-
24698- ret = xt_register_match(&string_match);
24699- if (ret)
24700- return ret;
24701- ret = xt_register_match(&string6_match);
24702- if (ret)
24703- xt_unregister_match(&string_match);
24704-
24705- return ret;
24706+ return xt_register_matches(xt_string_match, ARRAY_SIZE(xt_string_match));
24707 }
24708
24709 static void __exit xt_string_fini(void)
24710 {
24711- xt_unregister_match(&string_match);
24712- xt_unregister_match(&string6_match);
24713+ xt_unregister_matches(xt_string_match, ARRAY_SIZE(xt_string_match));
24714 }
24715
24716 module_init(xt_string_init);
24717diff -Nur linux-2.6.18-rc5/net/netfilter/xt_tcpmss.c linux-2.6.19/net/netfilter/xt_tcpmss.c
24718--- linux-2.6.18-rc5/net/netfilter/xt_tcpmss.c 2006-08-28 05:41:48.000000000 +0200
24719+++ linux-2.6.19/net/netfilter/xt_tcpmss.c 2006-09-22 10:04:59.000000000 +0200
24720@@ -18,21 +18,22 @@
24721 #include <linux/netfilter_ipv4/ip_tables.h>
24722 #include <linux/netfilter_ipv6/ip6_tables.h>
24723
24724-#define TH_SYN 0x02
24725-
24726 MODULE_LICENSE("GPL");
24727 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
24728 MODULE_DESCRIPTION("iptables TCP MSS match module");
24729 MODULE_ALIAS("ipt_tcpmss");
24730
24731-/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */
24732-static inline int
24733-mssoption_match(u_int16_t min, u_int16_t max,
24734- const struct sk_buff *skb,
24735- unsigned int protoff,
24736- int invert,
24737- int *hotdrop)
24738+static int
24739+match(const struct sk_buff *skb,
24740+ const struct net_device *in,
24741+ const struct net_device *out,
24742+ const struct xt_match *match,
24743+ const void *matchinfo,
24744+ int offset,
24745+ unsigned int protoff,
24746+ int *hotdrop)
24747 {
24748+ const struct xt_tcpmss_match_info *info = matchinfo;
24749 struct tcphdr _tcph, *th;
24750 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
24751 u8 _opt[15 * 4 - sizeof(_tcph)], *op;
24752@@ -64,72 +65,50 @@
24753
24754 mssval = (op[i+2] << 8) | op[i+3];
24755
24756- return (mssval >= min && mssval <= max) ^ invert;
24757+ return (mssval >= info->mss_min &&
24758+ mssval <= info->mss_max) ^ info->invert;
24759 }
24760- if (op[i] < 2) i++;
24761- else i += op[i+1]?:1;
24762+ if (op[i] < 2)
24763+ i++;
24764+ else
24765+ i += op[i+1] ? : 1;
24766 }
24767 out:
24768- return invert;
24769+ return info->invert;
24770
24771- dropit:
24772+dropit:
24773 *hotdrop = 1;
24774 return 0;
24775 }
24776
24777-static int
24778-match(const struct sk_buff *skb,
24779- const struct net_device *in,
24780- const struct net_device *out,
24781- const struct xt_match *match,
24782- const void *matchinfo,
24783- int offset,
24784- unsigned int protoff,
24785- int *hotdrop)
24786-{
24787- const struct xt_tcpmss_match_info *info = matchinfo;
24788-
24789- return mssoption_match(info->mss_min, info->mss_max, skb, protoff,
24790- info->invert, hotdrop);
24791-}
24792-
24793-static struct xt_match tcpmss_match = {
24794- .name = "tcpmss",
24795- .match = match,
24796- .matchsize = sizeof(struct xt_tcpmss_match_info),
24797- .proto = IPPROTO_TCP,
24798- .family = AF_INET,
24799- .me = THIS_MODULE,
24800+static struct xt_match xt_tcpmss_match[] = {
24801+ {
24802+ .name = "tcpmss",
24803+ .family = AF_INET,
24804+ .match = match,
24805+ .matchsize = sizeof(struct xt_tcpmss_match_info),
24806+ .proto = IPPROTO_TCP,
24807+ .me = THIS_MODULE,
24808+ },
24809+ {
24810+ .name = "tcpmss",
24811+ .family = AF_INET6,
24812+ .match = match,
24813+ .matchsize = sizeof(struct xt_tcpmss_match_info),
24814+ .proto = IPPROTO_TCP,
24815+ .me = THIS_MODULE,
24816+ },
24817 };
24818
24819-static struct xt_match tcpmss6_match = {
24820- .name = "tcpmss",
24821- .match = match,
24822- .matchsize = sizeof(struct xt_tcpmss_match_info),
24823- .proto = IPPROTO_TCP,
24824- .family = AF_INET6,
24825- .me = THIS_MODULE,
24826-};
24827-
24828-
24829 static int __init xt_tcpmss_init(void)
24830 {
24831- int ret;
24832- ret = xt_register_match(&tcpmss_match);
24833- if (ret)
24834- return ret;
24835-
24836- ret = xt_register_match(&tcpmss6_match);
24837- if (ret)
24838- xt_unregister_match(&tcpmss_match);
24839-
24840- return ret;
24841+ return xt_register_matches(xt_tcpmss_match,
24842+ ARRAY_SIZE(xt_tcpmss_match));
24843 }
24844
24845 static void __exit xt_tcpmss_fini(void)
24846 {
24847- xt_unregister_match(&tcpmss6_match);
24848- xt_unregister_match(&tcpmss_match);
24849+ xt_unregister_matches(xt_tcpmss_match, ARRAY_SIZE(xt_tcpmss_match));
24850 }
24851
24852 module_init(xt_tcpmss_init);
24853diff -Nur linux-2.6.18-rc5/net/netfilter/xt_tcpudp.c linux-2.6.19/net/netfilter/xt_tcpudp.c
24854--- linux-2.6.18-rc5/net/netfilter/xt_tcpudp.c 2006-08-28 05:41:48.000000000 +0200
24855+++ linux-2.6.19/net/netfilter/xt_tcpudp.c 2006-09-22 10:04:59.000000000 +0200
24856@@ -141,7 +141,6 @@
24857 const void *info,
24858 const struct xt_match *match,
24859 void *matchinfo,
24860- unsigned int matchsize,
24861 unsigned int hook_mask)
24862 {
24863 const struct xt_tcp *tcpinfo = matchinfo;
24864@@ -190,7 +189,6 @@
24865 const void *info,
24866 const struct xt_match *match,
24867 void *matchinfo,
24868- unsigned int matchsize,
24869 unsigned int hook_mask)
24870 {
24871 const struct xt_tcp *udpinfo = matchinfo;
24872@@ -199,81 +197,54 @@
24873 return !(udpinfo->invflags & ~XT_UDP_INV_MASK);
24874 }
24875
24876-static struct xt_match tcp_matchstruct = {
24877- .name = "tcp",
24878- .match = tcp_match,
24879- .matchsize = sizeof(struct xt_tcp),
24880- .proto = IPPROTO_TCP,
24881- .family = AF_INET,
24882- .checkentry = tcp_checkentry,
24883- .me = THIS_MODULE,
24884-};
24885-
24886-static struct xt_match tcp6_matchstruct = {
24887- .name = "tcp",
24888- .match = tcp_match,
24889- .matchsize = sizeof(struct xt_tcp),
24890- .proto = IPPROTO_TCP,
24891- .family = AF_INET6,
24892- .checkentry = tcp_checkentry,
24893- .me = THIS_MODULE,
24894-};
24895-
24896-static struct xt_match udp_matchstruct = {
24897- .name = "udp",
24898- .match = udp_match,
24899- .matchsize = sizeof(struct xt_udp),
24900- .proto = IPPROTO_UDP,
24901- .family = AF_INET,
24902- .checkentry = udp_checkentry,
24903- .me = THIS_MODULE,
24904-};
24905-static struct xt_match udp6_matchstruct = {
24906- .name = "udp",
24907- .match = udp_match,
24908- .matchsize = sizeof(struct xt_udp),
24909- .proto = IPPROTO_UDP,
24910- .family = AF_INET6,
24911- .checkentry = udp_checkentry,
24912- .me = THIS_MODULE,
24913+static struct xt_match xt_tcpudp_match[] = {
24914+ {
24915+ .name = "tcp",
24916+ .family = AF_INET,
24917+ .checkentry = tcp_checkentry,
24918+ .match = tcp_match,
24919+ .matchsize = sizeof(struct xt_tcp),
24920+ .proto = IPPROTO_TCP,
24921+ .me = THIS_MODULE,
24922+ },
24923+ {
24924+ .name = "tcp",
24925+ .family = AF_INET6,
24926+ .checkentry = tcp_checkentry,
24927+ .match = tcp_match,
24928+ .matchsize = sizeof(struct xt_tcp),
24929+ .proto = IPPROTO_TCP,
24930+ .me = THIS_MODULE,
24931+ },
24932+ {
24933+ .name = "udp",
24934+ .family = AF_INET,
24935+ .checkentry = udp_checkentry,
24936+ .match = udp_match,
24937+ .matchsize = sizeof(struct xt_udp),
24938+ .proto = IPPROTO_UDP,
24939+ .me = THIS_MODULE,
24940+ },
24941+ {
24942+ .name = "udp",
24943+ .family = AF_INET6,
24944+ .checkentry = udp_checkentry,
24945+ .match = udp_match,
24946+ .matchsize = sizeof(struct xt_udp),
24947+ .proto = IPPROTO_UDP,
24948+ .me = THIS_MODULE,
24949+ },
24950 };
24951
24952 static int __init xt_tcpudp_init(void)
24953 {
24954- int ret;
24955- ret = xt_register_match(&tcp_matchstruct);
24956- if (ret)
24957- return ret;
24958-
24959- ret = xt_register_match(&tcp6_matchstruct);
24960- if (ret)
24961- goto out_unreg_tcp;
24962-
24963- ret = xt_register_match(&udp_matchstruct);
24964- if (ret)
24965- goto out_unreg_tcp6;
24966-
24967- ret = xt_register_match(&udp6_matchstruct);
24968- if (ret)
24969- goto out_unreg_udp;
24970-
24971- return ret;
24972-
24973-out_unreg_udp:
24974- xt_unregister_match(&udp_matchstruct);
24975-out_unreg_tcp6:
24976- xt_unregister_match(&tcp6_matchstruct);
24977-out_unreg_tcp:
24978- xt_unregister_match(&tcp_matchstruct);
24979- return ret;
24980+ return xt_register_matches(xt_tcpudp_match,
24981+ ARRAY_SIZE(xt_tcpudp_match));
24982 }
24983
24984 static void __exit xt_tcpudp_fini(void)
24985 {
24986- xt_unregister_match(&udp6_matchstruct);
24987- xt_unregister_match(&udp_matchstruct);
24988- xt_unregister_match(&tcp6_matchstruct);
24989- xt_unregister_match(&tcp_matchstruct);
24990+ xt_unregister_matches(xt_tcpudp_match, ARRAY_SIZE(xt_tcpudp_match));
24991 }
24992
24993 module_init(xt_tcpudp_init);
24994diff -Nur linux-2.6.18-rc5/net/netlabel/Kconfig linux-2.6.19/net/netlabel/Kconfig
24995--- linux-2.6.18-rc5/net/netlabel/Kconfig 1970-01-01 01:00:00.000000000 +0100
24996+++ linux-2.6.19/net/netlabel/Kconfig 2006-09-22 10:04:59.000000000 +0200
24997@@ -0,0 +1,14 @@
24998+#
24999+# NetLabel configuration
25000+#
25001+
25002+config NETLABEL
25003+ bool "NetLabel subsystem support"
25004+ depends on NET && SECURITY
25005+ default n
25006+ ---help---
25007+ NetLabel provides support for explicit network packet labeling
25008+ protocols such as CIPSO and RIPSO. For more information see
25009+ Documentation/netlabel.
25010+
25011+ If you are unsure, say N.
25012diff -Nur linux-2.6.18-rc5/net/netlabel/Makefile linux-2.6.19/net/netlabel/Makefile
25013--- linux-2.6.18-rc5/net/netlabel/Makefile 1970-01-01 01:00:00.000000000 +0100
25014+++ linux-2.6.19/net/netlabel/Makefile 2006-09-22 10:04:59.000000000 +0200
25015@@ -0,0 +1,16 @@
25016+#
25017+# Makefile for the NetLabel subsystem.
25018+#
25019+# Feb 9, 2006, Paul Moore <paul.moore@hp.com>
25020+#
25021+
25022+# base objects
25023+obj-y := netlabel_user.o netlabel_kapi.o netlabel_domainhash.o
25024+
25025+# management objects
25026+obj-y += netlabel_mgmt.o
25027+
25028+# protocol modules
25029+obj-y += netlabel_unlabeled.o
25030+obj-y += netlabel_cipso_v4.o
25031+
25032diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_cipso_v4.c linux-2.6.19/net/netlabel/netlabel_cipso_v4.c
25033--- linux-2.6.18-rc5/net/netlabel/netlabel_cipso_v4.c 1970-01-01 01:00:00.000000000 +0100
25034+++ linux-2.6.19/net/netlabel/netlabel_cipso_v4.c 2006-09-22 10:04:59.000000000 +0200
25035@@ -0,0 +1,542 @@
25036+/*
25037+ * NetLabel CIPSO/IPv4 Support
25038+ *
25039+ * This file defines the CIPSO/IPv4 functions for the NetLabel system. The
25040+ * NetLabel system manages static and dynamic label mappings for network
25041+ * protocols such as CIPSO and RIPSO.
25042+ *
25043+ * Author: Paul Moore <paul.moore@hp.com>
25044+ *
25045+ */
25046+
25047+/*
25048+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
25049+ *
25050+ * This program is free software; you can redistribute it and/or modify
25051+ * it under the terms of the GNU General Public License as published by
25052+ * the Free Software Foundation; either version 2 of the License, or
25053+ * (at your option) any later version.
25054+ *
25055+ * This program is distributed in the hope that it will be useful,
25056+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25057+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25058+ * the GNU General Public License for more details.
25059+ *
25060+ * You should have received a copy of the GNU General Public License
25061+ * along with this program; if not, write to the Free Software
25062+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25063+ *
25064+ */
25065+
25066+#include <linux/types.h>
25067+#include <linux/socket.h>
25068+#include <linux/string.h>
25069+#include <linux/skbuff.h>
25070+#include <net/sock.h>
25071+#include <net/netlink.h>
25072+#include <net/genetlink.h>
25073+#include <net/netlabel.h>
25074+#include <net/cipso_ipv4.h>
25075+
25076+#include "netlabel_user.h"
25077+#include "netlabel_cipso_v4.h"
25078+
25079+/* NetLabel Generic NETLINK CIPSOv4 family */
25080+static struct genl_family netlbl_cipsov4_gnl_family = {
25081+ .id = GENL_ID_GENERATE,
25082+ .hdrsize = 0,
25083+ .name = NETLBL_NLTYPE_CIPSOV4_NAME,
25084+ .version = NETLBL_PROTO_VERSION,
25085+ .maxattr = 0,
25086+};
25087+
25088+
25089+/*
25090+ * Helper Functions
25091+ */
25092+
25093+/**
25094+ * netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition
25095+ * @entry: the entry's RCU field
25096+ *
25097+ * Description:
25098+ * This function is designed to be used as a callback to the call_rcu()
25099+ * function so that the memory allocated to the DOI definition can be released
25100+ * safely.
25101+ *
25102+ */
25103+static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
25104+{
25105+ struct cipso_v4_doi *ptr;
25106+
25107+ ptr = container_of(entry, struct cipso_v4_doi, rcu);
25108+ switch (ptr->type) {
25109+ case CIPSO_V4_MAP_STD:
25110+ kfree(ptr->map.std->lvl.cipso);
25111+ kfree(ptr->map.std->lvl.local);
25112+ kfree(ptr->map.std->cat.cipso);
25113+ kfree(ptr->map.std->cat.local);
25114+ break;
25115+ }
25116+ kfree(ptr);
25117+}
25118+
25119+
25120+/*
25121+ * NetLabel Command Handlers
25122+ */
25123+
25124+/**
25125+ * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
25126+ * @doi: the DOI value
25127+ * @msg: the ADD message data
25128+ * @msg_size: the size of the ADD message buffer
25129+ *
25130+ * Description:
25131+ * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message
25132+ * and add it to the CIPSO V4 engine. Return zero on success and non-zero on
25133+ * error.
25134+ *
25135+ */
25136+static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size)
25137+{
25138+ int ret_val = -EINVAL;
25139+ int msg_len = msg_size;
25140+ u32 num_tags;
25141+ u32 num_lvls;
25142+ u32 num_cats;
25143+ struct cipso_v4_doi *doi_def = NULL;
25144+ u32 iter;
25145+ u32 tmp_val_a;
25146+ u32 tmp_val_b;
25147+
25148+ if (msg_len < NETLBL_LEN_U32)
25149+ goto add_std_failure;
25150+ num_tags = netlbl_getinc_u32(&msg, &msg_len);
25151+ if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT)
25152+ goto add_std_failure;
25153+
25154+ doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
25155+ if (doi_def == NULL) {
25156+ ret_val = -ENOMEM;
25157+ goto add_std_failure;
25158+ }
25159+ doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL);
25160+ if (doi_def->map.std == NULL) {
25161+ ret_val = -ENOMEM;
25162+ goto add_std_failure;
25163+ }
25164+ doi_def->type = CIPSO_V4_MAP_STD;
25165+
25166+ for (iter = 0; iter < num_tags; iter++) {
25167+ if (msg_len < NETLBL_LEN_U8)
25168+ goto add_std_failure;
25169+ doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
25170+ switch (doi_def->tags[iter]) {
25171+ case CIPSO_V4_TAG_RBITMAP:
25172+ break;
25173+ default:
25174+ goto add_std_failure;
25175+ }
25176+ }
25177+ if (iter < CIPSO_V4_TAG_MAXCNT)
25178+ doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
25179+
25180+ if (msg_len < 6 * NETLBL_LEN_U32)
25181+ goto add_std_failure;
25182+
25183+ num_lvls = netlbl_getinc_u32(&msg, &msg_len);
25184+ if (num_lvls == 0)
25185+ goto add_std_failure;
25186+ doi_def->map.std->lvl.local_size = netlbl_getinc_u32(&msg, &msg_len);
25187+ if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS)
25188+ goto add_std_failure;
25189+ doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
25190+ sizeof(u32),
25191+ GFP_KERNEL);
25192+ if (doi_def->map.std->lvl.local == NULL) {
25193+ ret_val = -ENOMEM;
25194+ goto add_std_failure;
25195+ }
25196+ doi_def->map.std->lvl.cipso_size = netlbl_getinc_u8(&msg, &msg_len);
25197+ if (doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
25198+ goto add_std_failure;
25199+ doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
25200+ sizeof(u32),
25201+ GFP_KERNEL);
25202+ if (doi_def->map.std->lvl.cipso == NULL) {
25203+ ret_val = -ENOMEM;
25204+ goto add_std_failure;
25205+ }
25206+
25207+ num_cats = netlbl_getinc_u32(&msg, &msg_len);
25208+ doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len);
25209+ if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS)
25210+ goto add_std_failure;
25211+ doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size,
25212+ sizeof(u32),
25213+ GFP_KERNEL);
25214+ if (doi_def->map.std->cat.local == NULL) {
25215+ ret_val = -ENOMEM;
25216+ goto add_std_failure;
25217+ }
25218+ doi_def->map.std->cat.cipso_size = netlbl_getinc_u16(&msg, &msg_len);
25219+ if (doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS)
25220+ goto add_std_failure;
25221+ doi_def->map.std->cat.cipso = kcalloc(doi_def->map.std->cat.cipso_size,
25222+ sizeof(u32),
25223+ GFP_KERNEL);
25224+ if (doi_def->map.std->cat.cipso == NULL) {
25225+ ret_val = -ENOMEM;
25226+ goto add_std_failure;
25227+ }
25228+
25229+ if (msg_len <
25230+ num_lvls * (NETLBL_LEN_U32 + NETLBL_LEN_U8) +
25231+ num_cats * (NETLBL_LEN_U32 + NETLBL_LEN_U16))
25232+ goto add_std_failure;
25233+
25234+ for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
25235+ doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
25236+ for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
25237+ doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
25238+ for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
25239+ doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
25240+ for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
25241+ doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
25242+
25243+ for (iter = 0; iter < num_lvls; iter++) {
25244+ tmp_val_a = netlbl_getinc_u32(&msg, &msg_len);
25245+ tmp_val_b = netlbl_getinc_u8(&msg, &msg_len);
25246+
25247+ if (tmp_val_a >= doi_def->map.std->lvl.local_size ||
25248+ tmp_val_b >= doi_def->map.std->lvl.cipso_size)
25249+ goto add_std_failure;
25250+
25251+ doi_def->map.std->lvl.cipso[tmp_val_b] = tmp_val_a;
25252+ doi_def->map.std->lvl.local[tmp_val_a] = tmp_val_b;
25253+ }
25254+
25255+ for (iter = 0; iter < num_cats; iter++) {
25256+ tmp_val_a = netlbl_getinc_u32(&msg, &msg_len);
25257+ tmp_val_b = netlbl_getinc_u16(&msg, &msg_len);
25258+
25259+ if (tmp_val_a >= doi_def->map.std->cat.local_size ||
25260+ tmp_val_b >= doi_def->map.std->cat.cipso_size)
25261+ goto add_std_failure;
25262+
25263+ doi_def->map.std->cat.cipso[tmp_val_b] = tmp_val_a;
25264+ doi_def->map.std->cat.local[tmp_val_a] = tmp_val_b;
25265+ }
25266+
25267+ doi_def->doi = doi;
25268+ ret_val = cipso_v4_doi_add(doi_def);
25269+ if (ret_val != 0)
25270+ goto add_std_failure;
25271+ return 0;
25272+
25273+add_std_failure:
25274+ if (doi_def)
25275+ netlbl_cipsov4_doi_free(&doi_def->rcu);
25276+ return ret_val;
25277+}
25278+
25279+/**
25280+ * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
25281+ * @doi: the DOI value
25282+ * @msg: the ADD message data
25283+ * @msg_size: the size of the ADD message buffer
25284+ *
25285+ * Description:
25286+ * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
25287+ * and add it to the CIPSO V4 engine. Return zero on success and non-zero on
25288+ * error.
25289+ *
25290+ */
25291+static int netlbl_cipsov4_add_pass(u32 doi,
25292+ struct nlattr *msg,
25293+ size_t msg_size)
25294+{
25295+ int ret_val = -EINVAL;
25296+ int msg_len = msg_size;
25297+ u32 num_tags;
25298+ struct cipso_v4_doi *doi_def = NULL;
25299+ u32 iter;
25300+
25301+ if (msg_len < NETLBL_LEN_U32)
25302+ goto add_pass_failure;
25303+ num_tags = netlbl_getinc_u32(&msg, &msg_len);
25304+ if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT)
25305+ goto add_pass_failure;
25306+
25307+ doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
25308+ if (doi_def == NULL) {
25309+ ret_val = -ENOMEM;
25310+ goto add_pass_failure;
25311+ }
25312+ doi_def->type = CIPSO_V4_MAP_PASS;
25313+
25314+ for (iter = 0; iter < num_tags; iter++) {
25315+ if (msg_len < NETLBL_LEN_U8)
25316+ goto add_pass_failure;
25317+ doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
25318+ switch (doi_def->tags[iter]) {
25319+ case CIPSO_V4_TAG_RBITMAP:
25320+ break;
25321+ default:
25322+ goto add_pass_failure;
25323+ }
25324+ }
25325+ if (iter < CIPSO_V4_TAG_MAXCNT)
25326+ doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
25327+
25328+ doi_def->doi = doi;
25329+ ret_val = cipso_v4_doi_add(doi_def);
25330+ if (ret_val != 0)
25331+ goto add_pass_failure;
25332+ return 0;
25333+
25334+add_pass_failure:
25335+ if (doi_def)
25336+ netlbl_cipsov4_doi_free(&doi_def->rcu);
25337+ return ret_val;
25338+}
25339+
25340+/**
25341+ * netlbl_cipsov4_add - Handle an ADD message
25342+ * @skb: the NETLINK buffer
25343+ * @info: the Generic NETLINK info block
25344+ *
25345+ * Description:
25346+ * Create a new DOI definition based on the given ADD message and add it to the
25347+ * CIPSO V4 engine. Returns zero on success, negative values on failure.
25348+ *
25349+ */
25350+static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
25351+
25352+{
25353+ int ret_val = -EINVAL;
25354+ u32 doi;
25355+ u32 map_type;
25356+ int msg_len = netlbl_netlink_payload_len(skb);
25357+ struct nlattr *msg = netlbl_netlink_payload_data(skb);
25358+
25359+ ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
25360+ if (ret_val != 0)
25361+ goto add_return;
25362+
25363+ if (msg_len < 2 * NETLBL_LEN_U32)
25364+ goto add_return;
25365+
25366+ doi = netlbl_getinc_u32(&msg, &msg_len);
25367+ map_type = netlbl_getinc_u32(&msg, &msg_len);
25368+ switch (map_type) {
25369+ case CIPSO_V4_MAP_STD:
25370+ ret_val = netlbl_cipsov4_add_std(doi, msg, msg_len);
25371+ break;
25372+ case CIPSO_V4_MAP_PASS:
25373+ ret_val = netlbl_cipsov4_add_pass(doi, msg, msg_len);
25374+ break;
25375+ }
25376+
25377+add_return:
25378+ netlbl_netlink_send_ack(info,
25379+ netlbl_cipsov4_gnl_family.id,
25380+ NLBL_CIPSOV4_C_ACK,
25381+ -ret_val);
25382+ return ret_val;
25383+}
25384+
25385+/**
25386+ * netlbl_cipsov4_list - Handle a LIST message
25387+ * @skb: the NETLINK buffer
25388+ * @info: the Generic NETLINK info block
25389+ *
25390+ * Description:
25391+ * Process a user generated LIST message and respond accordingly. Returns
25392+ * zero on success and negative values on error.
25393+ *
25394+ */
25395+static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
25396+{
25397+ int ret_val = -EINVAL;
25398+ u32 doi;
25399+ struct nlattr *msg = netlbl_netlink_payload_data(skb);
25400+ struct sk_buff *ans_skb;
25401+
25402+ if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32)
25403+ goto list_failure;
25404+
25405+ doi = nla_get_u32(msg);
25406+ ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN));
25407+ if (ans_skb == NULL) {
25408+ ret_val = -ENOMEM;
25409+ goto list_failure;
25410+ }
25411+ netlbl_netlink_hdr_push(ans_skb,
25412+ info->snd_pid,
25413+ 0,
25414+ netlbl_cipsov4_gnl_family.id,
25415+ NLBL_CIPSOV4_C_LIST);
25416+
25417+ ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
25418+ if (ret_val != 0)
25419+ goto list_failure;
25420+
25421+ return 0;
25422+
25423+list_failure:
25424+ netlbl_netlink_send_ack(info,
25425+ netlbl_cipsov4_gnl_family.id,
25426+ NLBL_CIPSOV4_C_ACK,
25427+ -ret_val);
25428+ return ret_val;
25429+}
25430+
25431+/**
25432+ * netlbl_cipsov4_listall - Handle a LISTALL message
25433+ * @skb: the NETLINK buffer
25434+ * @info: the Generic NETLINK info block
25435+ *
25436+ * Description:
25437+ * Process a user generated LISTALL message and respond accordingly. Returns
25438+ * zero on success and negative values on error.
25439+ *
25440+ */
25441+static int netlbl_cipsov4_listall(struct sk_buff *skb, struct genl_info *info)
25442+{
25443+ int ret_val = -EINVAL;
25444+ struct sk_buff *ans_skb;
25445+
25446+ ans_skb = cipso_v4_doi_dump_all(NLMSG_SPACE(GENL_HDRLEN));
25447+ if (ans_skb == NULL) {
25448+ ret_val = -ENOMEM;
25449+ goto listall_failure;
25450+ }
25451+ netlbl_netlink_hdr_push(ans_skb,
25452+ info->snd_pid,
25453+ 0,
25454+ netlbl_cipsov4_gnl_family.id,
25455+ NLBL_CIPSOV4_C_LISTALL);
25456+
25457+ ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
25458+ if (ret_val != 0)
25459+ goto listall_failure;
25460+
25461+ return 0;
25462+
25463+listall_failure:
25464+ netlbl_netlink_send_ack(info,
25465+ netlbl_cipsov4_gnl_family.id,
25466+ NLBL_CIPSOV4_C_ACK,
25467+ -ret_val);
25468+ return ret_val;
25469+}
25470+
25471+/**
25472+ * netlbl_cipsov4_remove - Handle a REMOVE message
25473+ * @skb: the NETLINK buffer
25474+ * @info: the Generic NETLINK info block
25475+ *
25476+ * Description:
25477+ * Process a user generated REMOVE message and respond accordingly. Returns
25478+ * zero on success, negative values on failure.
25479+ *
25480+ */
25481+static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
25482+{
25483+ int ret_val;
25484+ u32 doi;
25485+ struct nlattr *msg = netlbl_netlink_payload_data(skb);
25486+
25487+ ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
25488+ if (ret_val != 0)
25489+ goto remove_return;
25490+
25491+ if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) {
25492+ ret_val = -EINVAL;
25493+ goto remove_return;
25494+ }
25495+
25496+ doi = nla_get_u32(msg);
25497+ ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
25498+
25499+remove_return:
25500+ netlbl_netlink_send_ack(info,
25501+ netlbl_cipsov4_gnl_family.id,
25502+ NLBL_CIPSOV4_C_ACK,
25503+ -ret_val);
25504+ return ret_val;
25505+}
25506+
25507+/*
25508+ * NetLabel Generic NETLINK Command Definitions
25509+ */
25510+
25511+static struct genl_ops netlbl_cipsov4_genl_c_add = {
25512+ .cmd = NLBL_CIPSOV4_C_ADD,
25513+ .flags = 0,
25514+ .doit = netlbl_cipsov4_add,
25515+ .dumpit = NULL,
25516+};
25517+
25518+static struct genl_ops netlbl_cipsov4_genl_c_remove = {
25519+ .cmd = NLBL_CIPSOV4_C_REMOVE,
25520+ .flags = 0,
25521+ .doit = netlbl_cipsov4_remove,
25522+ .dumpit = NULL,
25523+};
25524+
25525+static struct genl_ops netlbl_cipsov4_genl_c_list = {
25526+ .cmd = NLBL_CIPSOV4_C_LIST,
25527+ .flags = 0,
25528+ .doit = netlbl_cipsov4_list,
25529+ .dumpit = NULL,
25530+};
25531+
25532+static struct genl_ops netlbl_cipsov4_genl_c_listall = {
25533+ .cmd = NLBL_CIPSOV4_C_LISTALL,
25534+ .flags = 0,
25535+ .doit = netlbl_cipsov4_listall,
25536+ .dumpit = NULL,
25537+};
25538+
25539+/*
25540+ * NetLabel Generic NETLINK Protocol Functions
25541+ */
25542+
25543+/**
25544+ * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component
25545+ *
25546+ * Description:
25547+ * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK
25548+ * mechanism. Returns zero on success, negative values on failure.
25549+ *
25550+ */
25551+int netlbl_cipsov4_genl_init(void)
25552+{
25553+ int ret_val;
25554+
25555+ ret_val = genl_register_family(&netlbl_cipsov4_gnl_family);
25556+ if (ret_val != 0)
25557+ return ret_val;
25558+
25559+ ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
25560+ &netlbl_cipsov4_genl_c_add);
25561+ if (ret_val != 0)
25562+ return ret_val;
25563+ ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
25564+ &netlbl_cipsov4_genl_c_remove);
25565+ if (ret_val != 0)
25566+ return ret_val;
25567+ ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
25568+ &netlbl_cipsov4_genl_c_list);
25569+ if (ret_val != 0)
25570+ return ret_val;
25571+ ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
25572+ &netlbl_cipsov4_genl_c_listall);
25573+ if (ret_val != 0)
25574+ return ret_val;
25575+
25576+ return 0;
25577+}
25578diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_cipso_v4.h linux-2.6.19/net/netlabel/netlabel_cipso_v4.h
25579--- linux-2.6.18-rc5/net/netlabel/netlabel_cipso_v4.h 1970-01-01 01:00:00.000000000 +0100
25580+++ linux-2.6.19/net/netlabel/netlabel_cipso_v4.h 2006-09-22 10:04:59.000000000 +0200
25581@@ -0,0 +1,217 @@
25582+/*
25583+ * NetLabel CIPSO/IPv4 Support
25584+ *
25585+ * This file defines the CIPSO/IPv4 functions for the NetLabel system. The
25586+ * NetLabel system manages static and dynamic label mappings for network
25587+ * protocols such as CIPSO and RIPSO.
25588+ *
25589+ * Author: Paul Moore <paul.moore@hp.com>
25590+ *
25591+ */
25592+
25593+/*
25594+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
25595+ *
25596+ * This program is free software; you can redistribute it and/or modify
25597+ * it under the terms of the GNU General Public License as published by
25598+ * the Free Software Foundation; either version 2 of the License, or
25599+ * (at your option) any later version.
25600+ *
25601+ * This program is distributed in the hope that it will be useful,
25602+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25603+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25604+ * the GNU General Public License for more details.
25605+ *
25606+ * You should have received a copy of the GNU General Public License
25607+ * along with this program; if not, write to the Free Software
25608+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25609+ *
25610+ */
25611+
25612+#ifndef _NETLABEL_CIPSO_V4
25613+#define _NETLABEL_CIPSO_V4
25614+
25615+#include <net/netlabel.h>
25616+
25617+/*
25618+ * The following NetLabel payloads are supported by the CIPSO subsystem, all
25619+ * of which are preceeded by the nlmsghdr struct.
25620+ *
25621+ * o ACK:
25622+ * Sent by the kernel in response to an applications message, applications
25623+ * should never send this message.
25624+ *
25625+ * +----------------------+-----------------------+
25626+ * | seq number (32 bits) | return code (32 bits) |
25627+ * +----------------------+-----------------------+
25628+ *
25629+ * seq number: the sequence number of the original message, taken from the
25630+ * nlmsghdr structure
25631+ * return code: return value, based on errno values
25632+ *
25633+ * o ADD:
25634+ * Sent by an application to add a new DOI mapping table, after completion
25635+ * of the task the kernel should ACK this message.
25636+ *
25637+ * +---------------+--------------------+---------------------+
25638+ * | DOI (32 bits) | map type (32 bits) | tag count (32 bits) | ...
25639+ * +---------------+--------------------+---------------------+
25640+ *
25641+ * +-----------------+
25642+ * | tag #X (8 bits) | ... repeated
25643+ * +-----------------+
25644+ *
25645+ * +-------------- ---- --- -- -
25646+ * | mapping data
25647+ * +-------------- ---- --- -- -
25648+ *
25649+ * DOI: the DOI value
25650+ * map type: the mapping table type (defined in the cipso_ipv4.h header
25651+ * as CIPSO_V4_MAP_*)
25652+ * tag count: the number of tags, must be greater than zero
25653+ * tag: the CIPSO tag for the DOI, tags listed first are given
25654+ * higher priorirty when sending packets
25655+ * mapping data: specific to the map type (see below)
25656+ *
25657+ * CIPSO_V4_MAP_STD
25658+ *
25659+ * +------------------+-----------------------+----------------------+
25660+ * | levels (32 bits) | max l level (32 bits) | max r level (8 bits) | ...
25661+ * +------------------+-----------------------+----------------------+
25662+ *
25663+ * +----------------------+---------------------+---------------------+
25664+ * | categories (32 bits) | max l cat (32 bits) | max r cat (16 bits) | ...
25665+ * +----------------------+---------------------+---------------------+
25666+ *
25667+ * +--------------------------+-------------------------+
25668+ * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated
25669+ * +--------------------------+-------------------------+
25670+ *
25671+ * +-----------------------------+-----------------------------+
25672+ * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
25673+ * +-----------------------------+-----------------------------+
25674+ *
25675+ * levels: the number of level mappings
25676+ * max l level: the highest local level
25677+ * max r level: the highest remote/CIPSO level
25678+ * categories: the number of category mappings
25679+ * max l cat: the highest local category
25680+ * max r cat: the highest remote/CIPSO category
25681+ * local level: the local part of a level mapping
25682+ * CIPSO level: the remote/CIPSO part of a level mapping
25683+ * local category: the local part of a category mapping
25684+ * CIPSO category: the remote/CIPSO part of a category mapping
25685+ *
25686+ * CIPSO_V4_MAP_PASS
25687+ *
25688+ * No mapping data is needed for this map type.
25689+ *
25690+ * o REMOVE:
25691+ * Sent by an application to remove a specific DOI mapping table from the
25692+ * CIPSO V4 system. The kernel should ACK this message.
25693+ *
25694+ * +---------------+
25695+ * | DOI (32 bits) |
25696+ * +---------------+
25697+ *
25698+ * DOI: the DOI value
25699+ *
25700+ * o LIST:
25701+ * Sent by an application to list the details of a DOI definition. The
25702+ * kernel should send an ACK on error or a response as indicated below. The
25703+ * application generated message format is shown below.
25704+ *
25705+ * +---------------+
25706+ * | DOI (32 bits) |
25707+ * +---------------+
25708+ *
25709+ * DOI: the DOI value
25710+ *
25711+ * The valid response message format depends on the type of the DOI mapping,
25712+ * the known formats are shown below.
25713+ *
25714+ * +--------------------+
25715+ * | map type (32 bits) | ...
25716+ * +--------------------+
25717+ *
25718+ * map type: the DOI mapping table type (defined in the cipso_ipv4.h
25719+ * header as CIPSO_V4_MAP_*)
25720+ *
25721+ * (map type == CIPSO_V4_MAP_STD)
25722+ *
25723+ * +----------------+------------------+----------------------+
25724+ * | tags (32 bits) | levels (32 bits) | categories (32 bits) | ...
25725+ * +----------------+------------------+----------------------+
25726+ *
25727+ * +-----------------+
25728+ * | tag #X (8 bits) | ... repeated
25729+ * +-----------------+
25730+ *
25731+ * +--------------------------+-------------------------+
25732+ * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated
25733+ * +--------------------------+-------------------------+
25734+ *
25735+ * +-----------------------------+-----------------------------+
25736+ * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated
25737+ * +-----------------------------+-----------------------------+
25738+ *
25739+ * tags: the number of CIPSO tag types
25740+ * levels: the number of level mappings
25741+ * categories: the number of category mappings
25742+ * tag: the tag number, tags listed first are given higher
25743+ * priority when sending packets
25744+ * local level: the local part of a level mapping
25745+ * CIPSO level: the remote/CIPSO part of a level mapping
25746+ * local category: the local part of a category mapping
25747+ * CIPSO category: the remote/CIPSO part of a category mapping
25748+ *
25749+ * (map type == CIPSO_V4_MAP_PASS)
25750+ *
25751+ * +----------------+
25752+ * | tags (32 bits) | ...
25753+ * +----------------+
25754+ *
25755+ * +-----------------+
25756+ * | tag #X (8 bits) | ... repeated
25757+ * +-----------------+
25758+ *
25759+ * tags: the number of CIPSO tag types
25760+ * tag: the tag number, tags listed first are given higher
25761+ * priority when sending packets
25762+ *
25763+ * o LISTALL:
25764+ * This message is sent by an application to list the valid DOIs on the
25765+ * system. There is no payload and the kernel should respond with an ACK
25766+ * or the following message.
25767+ *
25768+ * +---------------------+------------------+-----------------------+
25769+ * | DOI count (32 bits) | DOI #X (32 bits) | map type #X (32 bits) |
25770+ * +---------------------+------------------+-----------------------+
25771+ *
25772+ * +-----------------------+
25773+ * | map type #X (32 bits) | ...
25774+ * +-----------------------+
25775+ *
25776+ * DOI count: the number of DOIs
25777+ * DOI: the DOI value
25778+ * map type: the DOI mapping table type (defined in the cipso_ipv4.h
25779+ * header as CIPSO_V4_MAP_*)
25780+ *
25781+ */
25782+
25783+/* NetLabel CIPSOv4 commands */
25784+enum {
25785+ NLBL_CIPSOV4_C_UNSPEC,
25786+ NLBL_CIPSOV4_C_ACK,
25787+ NLBL_CIPSOV4_C_ADD,
25788+ NLBL_CIPSOV4_C_REMOVE,
25789+ NLBL_CIPSOV4_C_LIST,
25790+ NLBL_CIPSOV4_C_LISTALL,
25791+ __NLBL_CIPSOV4_C_MAX,
25792+};
25793+#define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1)
25794+
25795+/* NetLabel protocol functions */
25796+int netlbl_cipsov4_genl_init(void);
25797+
25798+#endif
25799diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_domainhash.c linux-2.6.19/net/netlabel/netlabel_domainhash.c
25800--- linux-2.6.18-rc5/net/netlabel/netlabel_domainhash.c 1970-01-01 01:00:00.000000000 +0100
25801+++ linux-2.6.19/net/netlabel/netlabel_domainhash.c 2006-09-22 10:04:59.000000000 +0200
25802@@ -0,0 +1,513 @@
25803+/*
25804+ * NetLabel Domain Hash Table
25805+ *
25806+ * This file manages the domain hash table that NetLabel uses to determine
25807+ * which network labeling protocol to use for a given domain. The NetLabel
25808+ * system manages static and dynamic label mappings for network protocols such
25809+ * as CIPSO and RIPSO.
25810+ *
25811+ * Author: Paul Moore <paul.moore@hp.com>
25812+ *
25813+ */
25814+
25815+/*
25816+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
25817+ *
25818+ * This program is free software; you can redistribute it and/or modify
25819+ * it under the terms of the GNU General Public License as published by
25820+ * the Free Software Foundation; either version 2 of the License, or
25821+ * (at your option) any later version.
25822+ *
25823+ * This program is distributed in the hope that it will be useful,
25824+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25825+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
25826+ * the GNU General Public License for more details.
25827+ *
25828+ * You should have received a copy of the GNU General Public License
25829+ * along with this program; if not, write to the Free Software
25830+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25831+ *
25832+ */
25833+
25834+#include <linux/types.h>
25835+#include <linux/rcupdate.h>
25836+#include <linux/list.h>
25837+#include <linux/skbuff.h>
25838+#include <linux/spinlock.h>
25839+#include <linux/string.h>
25840+#include <net/netlabel.h>
25841+#include <net/cipso_ipv4.h>
25842+#include <asm/bug.h>
25843+
25844+#include "netlabel_mgmt.h"
25845+#include "netlabel_domainhash.h"
25846+
25847+struct netlbl_domhsh_tbl {
25848+ struct list_head *tbl;
25849+ u32 size;
25850+};
25851+
25852+/* Domain hash table */
25853+/* XXX - updates should be so rare that having one spinlock for the entire
25854+ * hash table should be okay */
25855+static DEFINE_SPINLOCK(netlbl_domhsh_lock);
25856+static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL;
25857+
25858+/* Default domain mapping */
25859+static DEFINE_SPINLOCK(netlbl_domhsh_def_lock);
25860+static struct netlbl_dom_map *netlbl_domhsh_def = NULL;
25861+
25862+/*
25863+ * Domain Hash Table Helper Functions
25864+ */
25865+
25866+/**
25867+ * netlbl_domhsh_free_entry - Frees a domain hash table entry
25868+ * @entry: the entry's RCU field
25869+ *
25870+ * Description:
25871+ * This function is designed to be used as a callback to the call_rcu()
25872+ * function so that the memory allocated to a hash table entry can be released
25873+ * safely.
25874+ *
25875+ */
25876+static void netlbl_domhsh_free_entry(struct rcu_head *entry)
25877+{
25878+ struct netlbl_dom_map *ptr;
25879+
25880+ ptr = container_of(entry, struct netlbl_dom_map, rcu);
25881+ kfree(ptr->domain);
25882+ kfree(ptr);
25883+}
25884+
25885+/**
25886+ * netlbl_domhsh_hash - Hashing function for the domain hash table
25887+ * @domain: the domain name to hash
25888+ *
25889+ * Description:
25890+ * This is the hashing function for the domain hash table, it returns the
25891+ * correct bucket number for the domain. The caller is responsibile for
25892+ * calling the rcu_read_[un]lock() functions.
25893+ *
25894+ */
25895+static u32 netlbl_domhsh_hash(const char *key)
25896+{
25897+ u32 iter;
25898+ u32 val;
25899+ u32 len;
25900+
25901+ /* This is taken (with slight modification) from
25902+ * security/selinux/ss/symtab.c:symhash() */
25903+
25904+ for (iter = 0, val = 0, len = strlen(key); iter < len; iter++)
25905+ val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter];
25906+ return val & (rcu_dereference(netlbl_domhsh)->size - 1);
25907+}
25908+
25909+/**
25910+ * netlbl_domhsh_search - Search for a domain entry
25911+ * @domain: the domain
25912+ * @def: return default if no match is found
25913+ *
25914+ * Description:
25915+ * Searches the domain hash table and returns a pointer to the hash table
25916+ * entry if found, otherwise NULL is returned. If @def is non-zero and a
25917+ * match is not found in the domain hash table the default mapping is returned
25918+ * if it exists. The caller is responsibile for the rcu hash table locks
25919+ * (i.e. the caller much call rcu_read_[un]lock()).
25920+ *
25921+ */
25922+static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def)
25923+{
25924+ u32 bkt;
25925+ struct netlbl_dom_map *iter;
25926+
25927+ if (domain != NULL) {
25928+ bkt = netlbl_domhsh_hash(domain);
25929+ list_for_each_entry_rcu(iter, &netlbl_domhsh->tbl[bkt], list)
25930+ if (iter->valid && strcmp(iter->domain, domain) == 0)
25931+ return iter;
25932+ }
25933+
25934+ if (def != 0) {
25935+ iter = rcu_dereference(netlbl_domhsh_def);
25936+ if (iter != NULL && iter->valid)
25937+ return iter;
25938+ }
25939+
25940+ return NULL;
25941+}
25942+
25943+/*
25944+ * Domain Hash Table Functions
25945+ */
25946+
25947+/**
25948+ * netlbl_domhsh_init - Init for the domain hash
25949+ * @size: the number of bits to use for the hash buckets
25950+ *
25951+ * Description:
25952+ * Initializes the domain hash table, should be called only by
25953+ * netlbl_user_init() during initialization. Returns zero on success, non-zero
25954+ * values on error.
25955+ *
25956+ */
25957+int netlbl_domhsh_init(u32 size)
25958+{
25959+ u32 iter;
25960+ struct netlbl_domhsh_tbl *hsh_tbl;
25961+
25962+ if (size == 0)
25963+ return -EINVAL;
25964+
25965+ hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL);
25966+ if (hsh_tbl == NULL)
25967+ return -ENOMEM;
25968+ hsh_tbl->size = 1 << size;
25969+ hsh_tbl->tbl = kcalloc(hsh_tbl->size,
25970+ sizeof(struct list_head),
25971+ GFP_KERNEL);
25972+ if (hsh_tbl->tbl == NULL) {
25973+ kfree(hsh_tbl);
25974+ return -ENOMEM;
25975+ }
25976+ for (iter = 0; iter < hsh_tbl->size; iter++)
25977+ INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
25978+
25979+ rcu_read_lock();
25980+ spin_lock(&netlbl_domhsh_lock);
25981+ rcu_assign_pointer(netlbl_domhsh, hsh_tbl);
25982+ spin_unlock(&netlbl_domhsh_lock);
25983+ rcu_read_unlock();
25984+
25985+ return 0;
25986+}
25987+
25988+/**
25989+ * netlbl_domhsh_add - Adds a entry to the domain hash table
25990+ * @entry: the entry to add
25991+ *
25992+ * Description:
25993+ * Adds a new entry to the domain hash table and handles any updates to the
25994+ * lower level protocol handler (i.e. CIPSO). Returns zero on success,
25995+ * negative on failure.
25996+ *
25997+ */
25998+int netlbl_domhsh_add(struct netlbl_dom_map *entry)
25999+{
26000+ int ret_val;
26001+ u32 bkt;
26002+
26003+ switch (entry->type) {
26004+ case NETLBL_NLTYPE_UNLABELED:
26005+ ret_val = 0;
26006+ break;
26007+ case NETLBL_NLTYPE_CIPSOV4:
26008+ ret_val = cipso_v4_doi_domhsh_add(entry->type_def.cipsov4,
26009+ entry->domain);
26010+ break;
26011+ default:
26012+ return -EINVAL;
26013+ }
26014+ if (ret_val != 0)
26015+ return ret_val;
26016+
26017+ entry->valid = 1;
26018+ INIT_RCU_HEAD(&entry->rcu);
26019+
26020+ ret_val = 0;
26021+ rcu_read_lock();
26022+ if (entry->domain != NULL) {
26023+ bkt = netlbl_domhsh_hash(entry->domain);
26024+ spin_lock(&netlbl_domhsh_lock);
26025+ if (netlbl_domhsh_search(entry->domain, 0) == NULL)
26026+ list_add_tail_rcu(&entry->list,
26027+ &netlbl_domhsh->tbl[bkt]);
26028+ else
26029+ ret_val = -EEXIST;
26030+ spin_unlock(&netlbl_domhsh_lock);
26031+ } else if (entry->domain == NULL) {
26032+ INIT_LIST_HEAD(&entry->list);
26033+ spin_lock(&netlbl_domhsh_def_lock);
26034+ if (rcu_dereference(netlbl_domhsh_def) == NULL)
26035+ rcu_assign_pointer(netlbl_domhsh_def, entry);
26036+ else
26037+ ret_val = -EEXIST;
26038+ spin_unlock(&netlbl_domhsh_def_lock);
26039+ } else
26040+ ret_val = -EINVAL;
26041+ rcu_read_unlock();
26042+
26043+ if (ret_val != 0) {
26044+ switch (entry->type) {
26045+ case NETLBL_NLTYPE_CIPSOV4:
26046+ if (cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
26047+ entry->domain) != 0)
26048+ BUG();
26049+ break;
26050+ }
26051+ }
26052+
26053+ return ret_val;
26054+}
26055+
26056+/**
26057+ * netlbl_domhsh_add_default - Adds the default entry to the domain hash table
26058+ * @entry: the entry to add
26059+ *
26060+ * Description:
26061+ * Adds a new default entry to the domain hash table and handles any updates
26062+ * to the lower level protocol handler (i.e. CIPSO). Returns zero on success,
26063+ * negative on failure.
26064+ *
26065+ */
26066+int netlbl_domhsh_add_default(struct netlbl_dom_map *entry)
26067+{
26068+ return netlbl_domhsh_add(entry);
26069+}
26070+
26071+/**
26072+ * netlbl_domhsh_remove - Removes an entry from the domain hash table
26073+ * @domain: the domain to remove
26074+ *
26075+ * Description:
26076+ * Removes an entry from the domain hash table and handles any updates to the
26077+ * lower level protocol handler (i.e. CIPSO). Returns zero on success,
26078+ * negative on failure.
26079+ *
26080+ */
26081+int netlbl_domhsh_remove(const char *domain)
26082+{
26083+ int ret_val = -ENOENT;
26084+ struct netlbl_dom_map *entry;
26085+
26086+ rcu_read_lock();
26087+ if (domain != NULL)
26088+ entry = netlbl_domhsh_search(domain, 0);
26089+ else
26090+ entry = netlbl_domhsh_search(domain, 1);
26091+ if (entry == NULL)
26092+ goto remove_return;
26093+ switch (entry->type) {
26094+ case NETLBL_NLTYPE_UNLABELED:
26095+ break;
26096+ case NETLBL_NLTYPE_CIPSOV4:
26097+ ret_val = cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
26098+ entry->domain);
26099+ if (ret_val != 0)
26100+ goto remove_return;
26101+ break;
26102+ }
26103+ ret_val = 0;
26104+ if (entry != rcu_dereference(netlbl_domhsh_def)) {
26105+ spin_lock(&netlbl_domhsh_lock);
26106+ if (entry->valid) {
26107+ entry->valid = 0;
26108+ list_del_rcu(&entry->list);
26109+ } else
26110+ ret_val = -ENOENT;
26111+ spin_unlock(&netlbl_domhsh_lock);
26112+ } else {
26113+ spin_lock(&netlbl_domhsh_def_lock);
26114+ if (entry->valid) {
26115+ entry->valid = 0;
26116+ rcu_assign_pointer(netlbl_domhsh_def, NULL);
26117+ } else
26118+ ret_val = -ENOENT;
26119+ spin_unlock(&netlbl_domhsh_def_lock);
26120+ }
26121+ if (ret_val == 0)
26122+ call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
26123+
26124+remove_return:
26125+ rcu_read_unlock();
26126+ return ret_val;
26127+}
26128+
26129+/**
26130+ * netlbl_domhsh_remove_default - Removes the default entry from the table
26131+ *
26132+ * Description:
26133+ * Removes/resets the default entry for the domain hash table and handles any
26134+ * updates to the lower level protocol handler (i.e. CIPSO). Returns zero on
26135+ * success, non-zero on failure.
26136+ *
26137+ */
26138+int netlbl_domhsh_remove_default(void)
26139+{
26140+ return netlbl_domhsh_remove(NULL);
26141+}
26142+
26143+/**
26144+ * netlbl_domhsh_getentry - Get an entry from the domain hash table
26145+ * @domain: the domain name to search for
26146+ *
26147+ * Description:
26148+ * Look through the domain hash table searching for an entry to match @domain,
26149+ * return a pointer to a copy of the entry or NULL. The caller is responsibile
26150+ * for ensuring that rcu_read_[un]lock() is called.
26151+ *
26152+ */
26153+struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain)
26154+{
26155+ return netlbl_domhsh_search(domain, 1);
26156+}
26157+
26158+/**
26159+ * netlbl_domhsh_dump - Dump the domain hash table into a sk_buff
26160+ *
26161+ * Description:
26162+ * Dump the domain hash table into a buffer suitable for returning to an
26163+ * application in response to a NetLabel management DOMAIN message. This
26164+ * function may fail if another process is growing the hash table at the same
26165+ * time. The returned sk_buff has room at the front of the sk_buff for
26166+ * @headroom bytes. See netlabel.h for the DOMAIN message format. Returns a
26167+ * pointer to a sk_buff on success, NULL on error.
26168+ *
26169+ */
26170+struct sk_buff *netlbl_domhsh_dump(size_t headroom)
26171+{
26172+ struct sk_buff *skb = NULL;
26173+ ssize_t buf_len;
26174+ u32 bkt_iter;
26175+ u32 dom_cnt = 0;
26176+ struct netlbl_domhsh_tbl *hsh_tbl;
26177+ struct netlbl_dom_map *list_iter;
26178+ ssize_t tmp_len;
26179+
26180+ buf_len = NETLBL_LEN_U32;
26181+ rcu_read_lock();
26182+ hsh_tbl = rcu_dereference(netlbl_domhsh);
26183+ for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
26184+ list_for_each_entry_rcu(list_iter,
26185+ &hsh_tbl->tbl[bkt_iter], list) {
26186+ buf_len += NETLBL_LEN_U32 +
26187+ nla_total_size(strlen(list_iter->domain) + 1);
26188+ switch (list_iter->type) {
26189+ case NETLBL_NLTYPE_UNLABELED:
26190+ break;
26191+ case NETLBL_NLTYPE_CIPSOV4:
26192+ buf_len += 2 * NETLBL_LEN_U32;
26193+ break;
26194+ }
26195+ dom_cnt++;
26196+ }
26197+
26198+ skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
26199+ if (skb == NULL)
26200+ goto dump_failure;
26201+
26202+ if (nla_put_u32(skb, NLA_U32, dom_cnt) != 0)
26203+ goto dump_failure;
26204+ buf_len -= NETLBL_LEN_U32;
26205+ hsh_tbl = rcu_dereference(netlbl_domhsh);
26206+ for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
26207+ list_for_each_entry_rcu(list_iter,
26208+ &hsh_tbl->tbl[bkt_iter], list) {
26209+ tmp_len = nla_total_size(strlen(list_iter->domain) +
26210+ 1);
26211+ if (buf_len < NETLBL_LEN_U32 + tmp_len)
26212+ goto dump_failure;
26213+ if (nla_put_string(skb,
26214+ NLA_STRING,
26215+ list_iter->domain) != 0)
26216+ goto dump_failure;
26217+ if (nla_put_u32(skb, NLA_U32, list_iter->type) != 0)
26218+ goto dump_failure;
26219+ buf_len -= NETLBL_LEN_U32 + tmp_len;
26220+ switch (list_iter->type) {
26221+ case NETLBL_NLTYPE_UNLABELED:
26222+ break;
26223+ case NETLBL_NLTYPE_CIPSOV4:
26224+ if (buf_len < 2 * NETLBL_LEN_U32)
26225+ goto dump_failure;
26226+ if (nla_put_u32(skb,
26227+ NLA_U32,
26228+ list_iter->type_def.cipsov4->type) != 0)
26229+ goto dump_failure;
26230+ if (nla_put_u32(skb,
26231+ NLA_U32,
26232+ list_iter->type_def.cipsov4->doi) != 0)
26233+ goto dump_failure;
26234+ buf_len -= 2 * NETLBL_LEN_U32;
26235+ break;
26236+ }
26237+ }
26238+ rcu_read_unlock();
26239+
26240+ return skb;
26241+
26242+dump_failure:
26243+ rcu_read_unlock();
26244+ kfree_skb(skb);
26245+ return NULL;
26246+}
26247+
26248+/**
26249+ * netlbl_domhsh_dump_default - Dump the default domain mapping into a sk_buff
26250+ *
26251+ * Description:
26252+ * Dump the default domain mapping into a buffer suitable for returning to an
26253+ * application in response to a NetLabel management DEFDOMAIN message. This
26254+ * function may fail if another process is changing the default domain mapping
26255+ * at the same time. The returned sk_buff has room at the front of the
26256+ * skb_buff for @headroom bytes. See netlabel.h for the DEFDOMAIN message
26257+ * format. Returns a pointer to a sk_buff on success, NULL on error.
26258+ *
26259+ */
26260+struct sk_buff *netlbl_domhsh_dump_default(size_t headroom)
26261+{
26262+ struct sk_buff *skb;
26263+ ssize_t buf_len;
26264+ struct netlbl_dom_map *entry;
26265+
26266+ buf_len = NETLBL_LEN_U32;
26267+ rcu_read_lock();
26268+ entry = rcu_dereference(netlbl_domhsh_def);
26269+ if (entry != NULL)
26270+ switch (entry->type) {
26271+ case NETLBL_NLTYPE_UNLABELED:
26272+ break;
26273+ case NETLBL_NLTYPE_CIPSOV4:
26274+ buf_len += 2 * NETLBL_LEN_U32;
26275+ break;
26276+ }
26277+
26278+ skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
26279+ if (skb == NULL)
26280+ goto dump_default_failure;
26281+
26282+ if (entry != rcu_dereference(netlbl_domhsh_def))
26283+ goto dump_default_failure;
26284+ if (entry != NULL) {
26285+ if (nla_put_u32(skb, NLA_U32, entry->type) != 0)
26286+ goto dump_default_failure;
26287+ buf_len -= NETLBL_LEN_U32;
26288+ switch (entry->type) {
26289+ case NETLBL_NLTYPE_UNLABELED:
26290+ break;
26291+ case NETLBL_NLTYPE_CIPSOV4:
26292+ if (buf_len < 2 * NETLBL_LEN_U32)
26293+ goto dump_default_failure;
26294+ if (nla_put_u32(skb,
26295+ NLA_U32,
26296+ entry->type_def.cipsov4->type) != 0)
26297+ goto dump_default_failure;
26298+ if (nla_put_u32(skb,
26299+ NLA_U32,
26300+ entry->type_def.cipsov4->doi) != 0)
26301+ goto dump_default_failure;
26302+ buf_len -= 2 * NETLBL_LEN_U32;
26303+ break;
26304+ }
26305+ } else
26306+ nla_put_u32(skb, NLA_U32, NETLBL_NLTYPE_NONE);
26307+ rcu_read_unlock();
26308+
26309+ return skb;
26310+
26311+dump_default_failure:
26312+ rcu_read_unlock();
26313+ kfree_skb(skb);
26314+ return NULL;
26315+}
26316diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_domainhash.h linux-2.6.19/net/netlabel/netlabel_domainhash.h
26317--- linux-2.6.18-rc5/net/netlabel/netlabel_domainhash.h 1970-01-01 01:00:00.000000000 +0100
26318+++ linux-2.6.19/net/netlabel/netlabel_domainhash.h 2006-09-22 10:04:59.000000000 +0200
26319@@ -0,0 +1,67 @@
26320+/*
26321+ * NetLabel Domain Hash Table
26322+ *
26323+ * This file manages the domain hash table that NetLabel uses to determine
26324+ * which network labeling protocol to use for a given domain. The NetLabel
26325+ * system manages static and dynamic label mappings for network protocols such
26326+ * as CIPSO and RIPSO.
26327+ *
26328+ * Author: Paul Moore <paul.moore@hp.com>
26329+ *
26330+ */
26331+
26332+/*
26333+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
26334+ *
26335+ * This program is free software; you can redistribute it and/or modify
26336+ * it under the terms of the GNU General Public License as published by
26337+ * the Free Software Foundation; either version 2 of the License, or
26338+ * (at your option) any later version.
26339+ *
26340+ * This program is distributed in the hope that it will be useful,
26341+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26342+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
26343+ * the GNU General Public License for more details.
26344+ *
26345+ * You should have received a copy of the GNU General Public License
26346+ * along with this program; if not, write to the Free Software
26347+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26348+ *
26349+ */
26350+
26351+#ifndef _NETLABEL_DOMAINHASH_H
26352+#define _NETLABEL_DOMAINHASH_H
26353+
26354+#include <linux/types.h>
26355+#include <linux/rcupdate.h>
26356+#include <linux/list.h>
26357+
26358+/* Domain hash table size */
26359+/* XXX - currently this number is an uneducated guess */
26360+#define NETLBL_DOMHSH_BITSIZE 7
26361+
26362+/* Domain mapping definition struct */
26363+struct netlbl_dom_map {
26364+ char *domain;
26365+ u32 type;
26366+ union {
26367+ struct cipso_v4_doi *cipsov4;
26368+ } type_def;
26369+
26370+ u32 valid;
26371+ struct list_head list;
26372+ struct rcu_head rcu;
26373+};
26374+
26375+/* init function */
26376+int netlbl_domhsh_init(u32 size);
26377+
26378+/* Manipulate the domain hash table */
26379+int netlbl_domhsh_add(struct netlbl_dom_map *entry);
26380+int netlbl_domhsh_add_default(struct netlbl_dom_map *entry);
26381+int netlbl_domhsh_remove_default(void);
26382+struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
26383+struct sk_buff *netlbl_domhsh_dump(size_t headroom);
26384+struct sk_buff *netlbl_domhsh_dump_default(size_t headroom);
26385+
26386+#endif
26387diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_kapi.c linux-2.6.19/net/netlabel/netlabel_kapi.c
26388--- linux-2.6.18-rc5/net/netlabel/netlabel_kapi.c 1970-01-01 01:00:00.000000000 +0100
26389+++ linux-2.6.19/net/netlabel/netlabel_kapi.c 2006-09-22 10:04:59.000000000 +0200
26390@@ -0,0 +1,231 @@
26391+/*
26392+ * NetLabel Kernel API
26393+ *
26394+ * This file defines the kernel API for the NetLabel system. The NetLabel
26395+ * system manages static and dynamic label mappings for network protocols such
26396+ * as CIPSO and RIPSO.
26397+ *
26398+ * Author: Paul Moore <paul.moore@hp.com>
26399+ *
26400+ */
26401+
26402+/*
26403+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
26404+ *
26405+ * This program is free software; you can redistribute it and/or modify
26406+ * it under the terms of the GNU General Public License as published by
26407+ * the Free Software Foundation; either version 2 of the License, or
26408+ * (at your option) any later version.
26409+ *
26410+ * This program is distributed in the hope that it will be useful,
26411+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26412+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
26413+ * the GNU General Public License for more details.
26414+ *
26415+ * You should have received a copy of the GNU General Public License
26416+ * along with this program; if not, write to the Free Software
26417+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26418+ *
26419+ */
26420+
26421+#include <linux/init.h>
26422+#include <linux/types.h>
26423+#include <net/ip.h>
26424+#include <net/netlabel.h>
26425+#include <net/cipso_ipv4.h>
26426+#include <asm/bug.h>
26427+
26428+#include "netlabel_domainhash.h"
26429+#include "netlabel_unlabeled.h"
26430+#include "netlabel_user.h"
26431+
26432+/*
26433+ * LSM Functions
26434+ */
26435+
26436+/**
26437+ * netlbl_socket_setattr - Label a socket using the correct protocol
26438+ * @sock: the socket to label
26439+ * @secattr: the security attributes
26440+ *
26441+ * Description:
26442+ * Attach the correct label to the given socket using the security attributes
26443+ * specified in @secattr. This function requires exclusive access to
26444+ * @sock->sk, which means it either needs to be in the process of being
26445+ * created or locked via lock_sock(sock->sk). Returns zero on success,
26446+ * negative values on failure.
26447+ *
26448+ */
26449+int netlbl_socket_setattr(const struct socket *sock,
26450+ const struct netlbl_lsm_secattr *secattr)
26451+{
26452+ int ret_val = -ENOENT;
26453+ struct netlbl_dom_map *dom_entry;
26454+
26455+ rcu_read_lock();
26456+ dom_entry = netlbl_domhsh_getentry(secattr->domain);
26457+ if (dom_entry == NULL)
26458+ goto socket_setattr_return;
26459+ switch (dom_entry->type) {
26460+ case NETLBL_NLTYPE_CIPSOV4:
26461+ ret_val = cipso_v4_socket_setattr(sock,
26462+ dom_entry->type_def.cipsov4,
26463+ secattr);
26464+ break;
26465+ case NETLBL_NLTYPE_UNLABELED:
26466+ ret_val = 0;
26467+ break;
26468+ default:
26469+ ret_val = -ENOENT;
26470+ }
26471+
26472+socket_setattr_return:
26473+ rcu_read_unlock();
26474+ return ret_val;
26475+}
26476+
26477+/**
26478+ * netlbl_socket_getattr - Determine the security attributes of a socket
26479+ * @sock: the socket
26480+ * @secattr: the security attributes
26481+ *
26482+ * Description:
26483+ * Examines the given socket to see any NetLabel style labeling has been
26484+ * applied to the socket, if so it parses the socket label and returns the
26485+ * security attributes in @secattr. Returns zero on success, negative values
26486+ * on failure.
26487+ *
26488+ */
26489+int netlbl_socket_getattr(const struct socket *sock,
26490+ struct netlbl_lsm_secattr *secattr)
26491+{
26492+ int ret_val;
26493+
26494+ ret_val = cipso_v4_socket_getattr(sock, secattr);
26495+ if (ret_val == 0)
26496+ return 0;
26497+
26498+ return netlbl_unlabel_getattr(secattr);
26499+}
26500+
26501+/**
26502+ * netlbl_skbuff_getattr - Determine the security attributes of a packet
26503+ * @skb: the packet
26504+ * @secattr: the security attributes
26505+ *
26506+ * Description:
26507+ * Examines the given packet to see if a recognized form of packet labeling
26508+ * is present, if so it parses the packet label and returns the security
26509+ * attributes in @secattr. Returns zero on success, negative values on
26510+ * failure.
26511+ *
26512+ */
26513+int netlbl_skbuff_getattr(const struct sk_buff *skb,
26514+ struct netlbl_lsm_secattr *secattr)
26515+{
26516+ int ret_val;
26517+
26518+ ret_val = cipso_v4_skbuff_getattr(skb, secattr);
26519+ if (ret_val == 0)
26520+ return 0;
26521+
26522+ return netlbl_unlabel_getattr(secattr);
26523+}
26524+
26525+/**
26526+ * netlbl_skbuff_err - Handle a LSM error on a sk_buff
26527+ * @skb: the packet
26528+ * @error: the error code
26529+ *
26530+ * Description:
26531+ * Deal with a LSM problem when handling the packet in @skb, typically this is
26532+ * a permission denied problem (-EACCES). The correct action is determined
26533+ * according to the packet's labeling protocol.
26534+ *
26535+ */
26536+void netlbl_skbuff_err(struct sk_buff *skb, int error)
26537+{
26538+ if (CIPSO_V4_OPTEXIST(skb))
26539+ cipso_v4_error(skb, error, 0);
26540+}
26541+
26542+/**
26543+ * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
26544+ *
26545+ * Description:
26546+ * For all of the NetLabel protocols that support some form of label mapping
26547+ * cache, invalidate the cache. Returns zero on success, negative values on
26548+ * error.
26549+ *
26550+ */
26551+void netlbl_cache_invalidate(void)
26552+{
26553+ cipso_v4_cache_invalidate();
26554+}
26555+
26556+/**
26557+ * netlbl_cache_add - Add an entry to a NetLabel protocol cache
26558+ * @skb: the packet
26559+ * @secattr: the packet's security attributes
26560+ *
26561+ * Description:
26562+ * Add the LSM security attributes for the given packet to the underlying
26563+ * NetLabel protocol's label mapping cache. Returns zero on success, negative
26564+ * values on error.
26565+ *
26566+ */
26567+int netlbl_cache_add(const struct sk_buff *skb,
26568+ const struct netlbl_lsm_secattr *secattr)
26569+{
26570+ if (secattr->cache.data == NULL)
26571+ return -ENOMSG;
26572+
26573+ if (CIPSO_V4_OPTEXIST(skb))
26574+ return cipso_v4_cache_add(skb, secattr);
26575+
26576+ return -ENOMSG;
26577+}
26578+
26579+/*
26580+ * Setup Functions
26581+ */
26582+
26583+/**
26584+ * netlbl_init - Initialize NetLabel
26585+ *
26586+ * Description:
26587+ * Perform the required NetLabel initialization before first use.
26588+ *
26589+ */
26590+static int __init netlbl_init(void)
26591+{
26592+ int ret_val;
26593+
26594+ printk(KERN_INFO "NetLabel: Initializing\n");
26595+ printk(KERN_INFO "NetLabel: domain hash size = %u\n",
26596+ (1 << NETLBL_DOMHSH_BITSIZE));
26597+ printk(KERN_INFO "NetLabel: protocols ="
26598+ " UNLABELED"
26599+ " CIPSOv4"
26600+ "\n");
26601+
26602+ ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
26603+ if (ret_val != 0)
26604+ goto init_failure;
26605+
26606+ ret_val = netlbl_netlink_init();
26607+ if (ret_val != 0)
26608+ goto init_failure;
26609+
26610+ ret_val = netlbl_unlabel_defconf();
26611+ if (ret_val != 0)
26612+ goto init_failure;
26613+ printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n");
26614+
26615+ return 0;
26616+
26617+init_failure:
26618+ panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
26619+}
26620+
26621+subsys_initcall(netlbl_init);
26622diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_mgmt.c linux-2.6.19/net/netlabel/netlabel_mgmt.c
26623--- linux-2.6.18-rc5/net/netlabel/netlabel_mgmt.c 1970-01-01 01:00:00.000000000 +0100
26624+++ linux-2.6.19/net/netlabel/netlabel_mgmt.c 2006-09-22 10:04:59.000000000 +0200
26625@@ -0,0 +1,624 @@
26626+/*
26627+ * NetLabel Management Support
26628+ *
26629+ * This file defines the management functions for the NetLabel system. The
26630+ * NetLabel system manages static and dynamic label mappings for network
26631+ * protocols such as CIPSO and RIPSO.
26632+ *
26633+ * Author: Paul Moore <paul.moore@hp.com>
26634+ *
26635+ */
26636+
26637+/*
26638+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
26639+ *
26640+ * This program is free software; you can redistribute it and/or modify
26641+ * it under the terms of the GNU General Public License as published by
26642+ * the Free Software Foundation; either version 2 of the License, or
26643+ * (at your option) any later version.
26644+ *
26645+ * This program is distributed in the hope that it will be useful,
26646+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26647+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
26648+ * the GNU General Public License for more details.
26649+ *
26650+ * You should have received a copy of the GNU General Public License
26651+ * along with this program; if not, write to the Free Software
26652+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26653+ *
26654+ */
26655+
26656+#include <linux/types.h>
26657+#include <linux/socket.h>
26658+#include <linux/string.h>
26659+#include <linux/skbuff.h>
26660+#include <net/sock.h>
26661+#include <net/netlink.h>
26662+#include <net/genetlink.h>
26663+#include <net/netlabel.h>
26664+#include <net/cipso_ipv4.h>
26665+
26666+#include "netlabel_domainhash.h"
26667+#include "netlabel_user.h"
26668+#include "netlabel_mgmt.h"
26669+
26670+/* NetLabel Generic NETLINK CIPSOv4 family */
26671+static struct genl_family netlbl_mgmt_gnl_family = {
26672+ .id = GENL_ID_GENERATE,
26673+ .hdrsize = 0,
26674+ .name = NETLBL_NLTYPE_MGMT_NAME,
26675+ .version = NETLBL_PROTO_VERSION,
26676+ .maxattr = 0,
26677+};
26678+
26679+
26680+/*
26681+ * NetLabel Command Handlers
26682+ */
26683+
26684+/**
26685+ * netlbl_mgmt_add - Handle an ADD message
26686+ * @skb: the NETLINK buffer
26687+ * @info: the Generic NETLINK info block
26688+ *
26689+ * Description:
26690+ * Process a user generated ADD message and add the domains from the message
26691+ * to the hash table. See netlabel.h for a description of the message format.
26692+ * Returns zero on success, negative values on failure.
26693+ *
26694+ */
26695+static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
26696+{
26697+ int ret_val = -EINVAL;
26698+ struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
26699+ int msg_len = netlbl_netlink_payload_len(skb);
26700+ u32 count;
26701+ struct netlbl_dom_map *entry = NULL;
26702+ u32 iter;
26703+ u32 tmp_val;
26704+ int tmp_size;
26705+
26706+ ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
26707+ if (ret_val != 0)
26708+ goto add_failure;
26709+
26710+ if (msg_len < NETLBL_LEN_U32)
26711+ goto add_failure;
26712+ count = netlbl_getinc_u32(&msg_ptr, &msg_len);
26713+
26714+ for (iter = 0; iter < count && msg_len > 0; iter++, entry = NULL) {
26715+ if (msg_len <= 0) {
26716+ ret_val = -EINVAL;
26717+ goto add_failure;
26718+ }
26719+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
26720+ if (entry == NULL) {
26721+ ret_val = -ENOMEM;
26722+ goto add_failure;
26723+ }
26724+ tmp_size = nla_len(msg_ptr);
26725+ if (tmp_size <= 0 || tmp_size > msg_len) {
26726+ ret_val = -EINVAL;
26727+ goto add_failure;
26728+ }
26729+ entry->domain = kmalloc(tmp_size, GFP_KERNEL);
26730+ if (entry->domain == NULL) {
26731+ ret_val = -ENOMEM;
26732+ goto add_failure;
26733+ }
26734+ nla_strlcpy(entry->domain, msg_ptr, tmp_size);
26735+ entry->domain[tmp_size - 1] = '\0';
26736+ msg_ptr = nla_next(msg_ptr, &msg_len);
26737+
26738+ if (msg_len < NETLBL_LEN_U32) {
26739+ ret_val = -EINVAL;
26740+ goto add_failure;
26741+ }
26742+ tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
26743+ entry->type = tmp_val;
26744+ switch (tmp_val) {
26745+ case NETLBL_NLTYPE_UNLABELED:
26746+ ret_val = netlbl_domhsh_add(entry);
26747+ break;
26748+ case NETLBL_NLTYPE_CIPSOV4:
26749+ if (msg_len < NETLBL_LEN_U32) {
26750+ ret_val = -EINVAL;
26751+ goto add_failure;
26752+ }
26753+ tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
26754+ /* We should be holding a rcu_read_lock() here
26755+ * while we hold the result but since the entry
26756+ * will always be deleted when the CIPSO DOI
26757+ * is deleted we aren't going to keep the lock. */
26758+ rcu_read_lock();
26759+ entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
26760+ if (entry->type_def.cipsov4 == NULL) {
26761+ rcu_read_unlock();
26762+ ret_val = -EINVAL;
26763+ goto add_failure;
26764+ }
26765+ ret_val = netlbl_domhsh_add(entry);
26766+ rcu_read_unlock();
26767+ break;
26768+ default:
26769+ ret_val = -EINVAL;
26770+ }
26771+ if (ret_val != 0)
26772+ goto add_failure;
26773+ }
26774+
26775+ netlbl_netlink_send_ack(info,
26776+ netlbl_mgmt_gnl_family.id,
26777+ NLBL_MGMT_C_ACK,
26778+ NETLBL_E_OK);
26779+ return 0;
26780+
26781+add_failure:
26782+ if (entry)
26783+ kfree(entry->domain);
26784+ kfree(entry);
26785+ netlbl_netlink_send_ack(info,
26786+ netlbl_mgmt_gnl_family.id,
26787+ NLBL_MGMT_C_ACK,
26788+ -ret_val);
26789+ return ret_val;
26790+}
26791+
26792+/**
26793+ * netlbl_mgmt_remove - Handle a REMOVE message
26794+ * @skb: the NETLINK buffer
26795+ * @info: the Generic NETLINK info block
26796+ *
26797+ * Description:
26798+ * Process a user generated REMOVE message and remove the specified domain
26799+ * mappings. Returns zero on success, negative values on failure.
26800+ *
26801+ */
26802+static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info)
26803+{
26804+ int ret_val = -EINVAL;
26805+ struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
26806+ int msg_len = netlbl_netlink_payload_len(skb);
26807+ u32 count;
26808+ u32 iter;
26809+ int tmp_size;
26810+ unsigned char *domain;
26811+
26812+ ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
26813+ if (ret_val != 0)
26814+ goto remove_return;
26815+
26816+ if (msg_len < NETLBL_LEN_U32)
26817+ goto remove_return;
26818+ count = netlbl_getinc_u32(&msg_ptr, &msg_len);
26819+
26820+ for (iter = 0; iter < count && msg_len > 0; iter++) {
26821+ if (msg_len <= 0) {
26822+ ret_val = -EINVAL;
26823+ goto remove_return;
26824+ }
26825+ tmp_size = nla_len(msg_ptr);
26826+ domain = nla_data(msg_ptr);
26827+ if (tmp_size <= 0 || tmp_size > msg_len ||
26828+ domain[tmp_size - 1] != '\0') {
26829+ ret_val = -EINVAL;
26830+ goto remove_return;
26831+ }
26832+ ret_val = netlbl_domhsh_remove(domain);
26833+ if (ret_val != 0)
26834+ goto remove_return;
26835+ msg_ptr = nla_next(msg_ptr, &msg_len);
26836+ }
26837+
26838+ ret_val = 0;
26839+
26840+remove_return:
26841+ netlbl_netlink_send_ack(info,
26842+ netlbl_mgmt_gnl_family.id,
26843+ NLBL_MGMT_C_ACK,
26844+ -ret_val);
26845+ return ret_val;
26846+}
26847+
26848+/**
26849+ * netlbl_mgmt_list - Handle a LIST message
26850+ * @skb: the NETLINK buffer
26851+ * @info: the Generic NETLINK info block
26852+ *
26853+ * Description:
26854+ * Process a user generated LIST message and dumps the domain hash table in a
26855+ * form suitable for use in a kernel generated LIST message. Returns zero on
26856+ * success, negative values on failure.
26857+ *
26858+ */
26859+static int netlbl_mgmt_list(struct sk_buff *skb, struct genl_info *info)
26860+{
26861+ int ret_val = -ENOMEM;
26862+ struct sk_buff *ans_skb;
26863+
26864+ ans_skb = netlbl_domhsh_dump(NLMSG_SPACE(GENL_HDRLEN));
26865+ if (ans_skb == NULL)
26866+ goto list_failure;
26867+ netlbl_netlink_hdr_push(ans_skb,
26868+ info->snd_pid,
26869+ 0,
26870+ netlbl_mgmt_gnl_family.id,
26871+ NLBL_MGMT_C_LIST);
26872+
26873+ ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
26874+ if (ret_val != 0)
26875+ goto list_failure;
26876+
26877+ return 0;
26878+
26879+list_failure:
26880+ netlbl_netlink_send_ack(info,
26881+ netlbl_mgmt_gnl_family.id,
26882+ NLBL_MGMT_C_ACK,
26883+ -ret_val);
26884+ return ret_val;
26885+}
26886+
26887+/**
26888+ * netlbl_mgmt_adddef - Handle an ADDDEF message
26889+ * @skb: the NETLINK buffer
26890+ * @info: the Generic NETLINK info block
26891+ *
26892+ * Description:
26893+ * Process a user generated ADDDEF message and respond accordingly. Returns
26894+ * zero on success, negative values on failure.
26895+ *
26896+ */
26897+static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
26898+{
26899+ int ret_val = -EINVAL;
26900+ struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb);
26901+ int msg_len = netlbl_netlink_payload_len(skb);
26902+ struct netlbl_dom_map *entry = NULL;
26903+ u32 tmp_val;
26904+
26905+ ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
26906+ if (ret_val != 0)
26907+ goto adddef_failure;
26908+
26909+ if (msg_len < NETLBL_LEN_U32)
26910+ goto adddef_failure;
26911+ tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
26912+
26913+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
26914+ if (entry == NULL) {
26915+ ret_val = -ENOMEM;
26916+ goto adddef_failure;
26917+ }
26918+
26919+ entry->type = tmp_val;
26920+ switch (entry->type) {
26921+ case NETLBL_NLTYPE_UNLABELED:
26922+ ret_val = netlbl_domhsh_add_default(entry);
26923+ break;
26924+ case NETLBL_NLTYPE_CIPSOV4:
26925+ if (msg_len < NETLBL_LEN_U32) {
26926+ ret_val = -EINVAL;
26927+ goto adddef_failure;
26928+ }
26929+ tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len);
26930+ /* We should be holding a rcu_read_lock here while we
26931+ * hold the result but since the entry will always be
26932+ * deleted when the CIPSO DOI is deleted we are going
26933+ * to skip the lock. */
26934+ rcu_read_lock();
26935+ entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
26936+ if (entry->type_def.cipsov4 == NULL) {
26937+ rcu_read_unlock();
26938+ ret_val = -EINVAL;
26939+ goto adddef_failure;
26940+ }
26941+ ret_val = netlbl_domhsh_add_default(entry);
26942+ rcu_read_unlock();
26943+ break;
26944+ default:
26945+ ret_val = -EINVAL;
26946+ }
26947+ if (ret_val != 0)
26948+ goto adddef_failure;
26949+
26950+ netlbl_netlink_send_ack(info,
26951+ netlbl_mgmt_gnl_family.id,
26952+ NLBL_MGMT_C_ACK,
26953+ NETLBL_E_OK);
26954+ return 0;
26955+
26956+adddef_failure:
26957+ kfree(entry);
26958+ netlbl_netlink_send_ack(info,
26959+ netlbl_mgmt_gnl_family.id,
26960+ NLBL_MGMT_C_ACK,
26961+ -ret_val);
26962+ return ret_val;
26963+}
26964+
26965+/**
26966+ * netlbl_mgmt_removedef - Handle a REMOVEDEF message
26967+ * @skb: the NETLINK buffer
26968+ * @info: the Generic NETLINK info block
26969+ *
26970+ * Description:
26971+ * Process a user generated REMOVEDEF message and remove the default domain
26972+ * mapping. Returns zero on success, negative values on failure.
26973+ *
26974+ */
26975+static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info)
26976+{
26977+ int ret_val;
26978+
26979+ ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
26980+ if (ret_val != 0)
26981+ goto removedef_return;
26982+
26983+ ret_val = netlbl_domhsh_remove_default();
26984+
26985+removedef_return:
26986+ netlbl_netlink_send_ack(info,
26987+ netlbl_mgmt_gnl_family.id,
26988+ NLBL_MGMT_C_ACK,
26989+ -ret_val);
26990+ return ret_val;
26991+}
26992+
26993+/**
26994+ * netlbl_mgmt_listdef - Handle a LISTDEF message
26995+ * @skb: the NETLINK buffer
26996+ * @info: the Generic NETLINK info block
26997+ *
26998+ * Description:
26999+ * Process a user generated LISTDEF message and dumps the default domain
27000+ * mapping in a form suitable for use in a kernel generated LISTDEF message.
27001+ * Returns zero on success, negative values on failure.
27002+ *
27003+ */
27004+static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
27005+{
27006+ int ret_val = -ENOMEM;
27007+ struct sk_buff *ans_skb;
27008+
27009+ ans_skb = netlbl_domhsh_dump_default(NLMSG_SPACE(GENL_HDRLEN));
27010+ if (ans_skb == NULL)
27011+ goto listdef_failure;
27012+ netlbl_netlink_hdr_push(ans_skb,
27013+ info->snd_pid,
27014+ 0,
27015+ netlbl_mgmt_gnl_family.id,
27016+ NLBL_MGMT_C_LISTDEF);
27017+
27018+ ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
27019+ if (ret_val != 0)
27020+ goto listdef_failure;
27021+
27022+ return 0;
27023+
27024+listdef_failure:
27025+ netlbl_netlink_send_ack(info,
27026+ netlbl_mgmt_gnl_family.id,
27027+ NLBL_MGMT_C_ACK,
27028+ -ret_val);
27029+ return ret_val;
27030+}
27031+
27032+/**
27033+ * netlbl_mgmt_modules - Handle a MODULES message
27034+ * @skb: the NETLINK buffer
27035+ * @info: the Generic NETLINK info block
27036+ *
27037+ * Description:
27038+ * Process a user generated MODULES message and respond accordingly.
27039+ *
27040+ */
27041+static int netlbl_mgmt_modules(struct sk_buff *skb, struct genl_info *info)
27042+{
27043+ int ret_val = -ENOMEM;
27044+ size_t data_size;
27045+ u32 mod_count;
27046+ struct sk_buff *ans_skb = NULL;
27047+
27048+ /* unlabeled + cipsov4 */
27049+ mod_count = 2;
27050+
27051+ data_size = GENL_HDRLEN + NETLBL_LEN_U32 + mod_count * NETLBL_LEN_U32;
27052+ ans_skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL);
27053+ if (ans_skb == NULL)
27054+ goto modules_failure;
27055+
27056+ if (netlbl_netlink_hdr_put(ans_skb,
27057+ info->snd_pid,
27058+ 0,
27059+ netlbl_mgmt_gnl_family.id,
27060+ NLBL_MGMT_C_MODULES) == NULL)
27061+ goto modules_failure;
27062+
27063+ ret_val = nla_put_u32(ans_skb, NLA_U32, mod_count);
27064+ if (ret_val != 0)
27065+ goto modules_failure;
27066+ ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_UNLABELED);
27067+ if (ret_val != 0)
27068+ goto modules_failure;
27069+ ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_CIPSOV4);
27070+ if (ret_val != 0)
27071+ goto modules_failure;
27072+
27073+ ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
27074+ if (ret_val != 0)
27075+ goto modules_failure;
27076+
27077+ return 0;
27078+
27079+modules_failure:
27080+ kfree_skb(ans_skb);
27081+ netlbl_netlink_send_ack(info,
27082+ netlbl_mgmt_gnl_family.id,
27083+ NLBL_MGMT_C_ACK,
27084+ -ret_val);
27085+ return ret_val;
27086+}
27087+
27088+/**
27089+ * netlbl_mgmt_version - Handle a VERSION message
27090+ * @skb: the NETLINK buffer
27091+ * @info: the Generic NETLINK info block
27092+ *
27093+ * Description:
27094+ * Process a user generated VERSION message and respond accordingly. Returns
27095+ * zero on success, negative values on failure.
27096+ *
27097+ */
27098+static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
27099+{
27100+ int ret_val = -ENOMEM;
27101+ struct sk_buff *ans_skb = NULL;
27102+
27103+ ans_skb = netlbl_netlink_alloc_skb(0,
27104+ GENL_HDRLEN + NETLBL_LEN_U32,
27105+ GFP_KERNEL);
27106+ if (ans_skb == NULL)
27107+ goto version_failure;
27108+ if (netlbl_netlink_hdr_put(ans_skb,
27109+ info->snd_pid,
27110+ 0,
27111+ netlbl_mgmt_gnl_family.id,
27112+ NLBL_MGMT_C_VERSION) == NULL)
27113+ goto version_failure;
27114+
27115+ ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_PROTO_VERSION);
27116+ if (ret_val != 0)
27117+ goto version_failure;
27118+
27119+ ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
27120+ if (ret_val != 0)
27121+ goto version_failure;
27122+
27123+ return 0;
27124+
27125+version_failure:
27126+ kfree_skb(ans_skb);
27127+ netlbl_netlink_send_ack(info,
27128+ netlbl_mgmt_gnl_family.id,
27129+ NLBL_MGMT_C_ACK,
27130+ -ret_val);
27131+ return ret_val;
27132+}
27133+
27134+
27135+/*
27136+ * NetLabel Generic NETLINK Command Definitions
27137+ */
27138+
27139+static struct genl_ops netlbl_mgmt_genl_c_add = {
27140+ .cmd = NLBL_MGMT_C_ADD,
27141+ .flags = 0,
27142+ .doit = netlbl_mgmt_add,
27143+ .dumpit = NULL,
27144+};
27145+
27146+static struct genl_ops netlbl_mgmt_genl_c_remove = {
27147+ .cmd = NLBL_MGMT_C_REMOVE,
27148+ .flags = 0,
27149+ .doit = netlbl_mgmt_remove,
27150+ .dumpit = NULL,
27151+};
27152+
27153+static struct genl_ops netlbl_mgmt_genl_c_list = {
27154+ .cmd = NLBL_MGMT_C_LIST,
27155+ .flags = 0,
27156+ .doit = netlbl_mgmt_list,
27157+ .dumpit = NULL,
27158+};
27159+
27160+static struct genl_ops netlbl_mgmt_genl_c_adddef = {
27161+ .cmd = NLBL_MGMT_C_ADDDEF,
27162+ .flags = 0,
27163+ .doit = netlbl_mgmt_adddef,
27164+ .dumpit = NULL,
27165+};
27166+
27167+static struct genl_ops netlbl_mgmt_genl_c_removedef = {
27168+ .cmd = NLBL_MGMT_C_REMOVEDEF,
27169+ .flags = 0,
27170+ .doit = netlbl_mgmt_removedef,
27171+ .dumpit = NULL,
27172+};
27173+
27174+static struct genl_ops netlbl_mgmt_genl_c_listdef = {
27175+ .cmd = NLBL_MGMT_C_LISTDEF,
27176+ .flags = 0,
27177+ .doit = netlbl_mgmt_listdef,
27178+ .dumpit = NULL,
27179+};
27180+
27181+static struct genl_ops netlbl_mgmt_genl_c_modules = {
27182+ .cmd = NLBL_MGMT_C_MODULES,
27183+ .flags = 0,
27184+ .doit = netlbl_mgmt_modules,
27185+ .dumpit = NULL,
27186+};
27187+
27188+static struct genl_ops netlbl_mgmt_genl_c_version = {
27189+ .cmd = NLBL_MGMT_C_VERSION,
27190+ .flags = 0,
27191+ .doit = netlbl_mgmt_version,
27192+ .dumpit = NULL,
27193+};
27194+
27195+/*
27196+ * NetLabel Generic NETLINK Protocol Functions
27197+ */
27198+
27199+/**
27200+ * netlbl_mgmt_genl_init - Register the NetLabel management component
27201+ *
27202+ * Description:
27203+ * Register the NetLabel management component with the Generic NETLINK
27204+ * mechanism. Returns zero on success, negative values on failure.
27205+ *
27206+ */
27207+int netlbl_mgmt_genl_init(void)
27208+{
27209+ int ret_val;
27210+
27211+ ret_val = genl_register_family(&netlbl_mgmt_gnl_family);
27212+ if (ret_val != 0)
27213+ return ret_val;
27214+
27215+ ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
27216+ &netlbl_mgmt_genl_c_add);
27217+ if (ret_val != 0)
27218+ return ret_val;
27219+ ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
27220+ &netlbl_mgmt_genl_c_remove);
27221+ if (ret_val != 0)
27222+ return ret_val;
27223+ ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
27224+ &netlbl_mgmt_genl_c_list);
27225+ if (ret_val != 0)
27226+ return ret_val;
27227+ ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
27228+ &netlbl_mgmt_genl_c_adddef);
27229+ if (ret_val != 0)
27230+ return ret_val;
27231+ ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
27232+ &netlbl_mgmt_genl_c_removedef);
27233+ if (ret_val != 0)
27234+ return ret_val;
27235+ ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
27236+ &netlbl_mgmt_genl_c_listdef);
27237+ if (ret_val != 0)
27238+ return ret_val;
27239+ ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
27240+ &netlbl_mgmt_genl_c_modules);
27241+ if (ret_val != 0)
27242+ return ret_val;
27243+ ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
27244+ &netlbl_mgmt_genl_c_version);
27245+ if (ret_val != 0)
27246+ return ret_val;
27247+
27248+ return 0;
27249+}
27250diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_mgmt.h linux-2.6.19/net/netlabel/netlabel_mgmt.h
27251--- linux-2.6.18-rc5/net/netlabel/netlabel_mgmt.h 1970-01-01 01:00:00.000000000 +0100
27252+++ linux-2.6.19/net/netlabel/netlabel_mgmt.h 2006-09-22 10:04:59.000000000 +0200
27253@@ -0,0 +1,246 @@
27254+/*
27255+ * NetLabel Management Support
27256+ *
27257+ * This file defines the management functions for the NetLabel system. The
27258+ * NetLabel system manages static and dynamic label mappings for network
27259+ * protocols such as CIPSO and RIPSO.
27260+ *
27261+ * Author: Paul Moore <paul.moore@hp.com>
27262+ *
27263+ */
27264+
27265+/*
27266+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
27267+ *
27268+ * This program is free software; you can redistribute it and/or modify
27269+ * it under the terms of the GNU General Public License as published by
27270+ * the Free Software Foundation; either version 2 of the License, or
27271+ * (at your option) any later version.
27272+ *
27273+ * This program is distributed in the hope that it will be useful,
27274+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27275+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
27276+ * the GNU General Public License for more details.
27277+ *
27278+ * You should have received a copy of the GNU General Public License
27279+ * along with this program; if not, write to the Free Software
27280+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27281+ *
27282+ */
27283+
27284+#ifndef _NETLABEL_MGMT_H
27285+#define _NETLABEL_MGMT_H
27286+
27287+#include <net/netlabel.h>
27288+
27289+/*
27290+ * The following NetLabel payloads are supported by the management interface,
27291+ * all of which are preceeded by the nlmsghdr struct.
27292+ *
27293+ * o ACK:
27294+ * Sent by the kernel in response to an applications message, applications
27295+ * should never send this message.
27296+ *
27297+ * +----------------------+-----------------------+
27298+ * | seq number (32 bits) | return code (32 bits) |
27299+ * +----------------------+-----------------------+
27300+ *
27301+ * seq number: the sequence number of the original message, taken from the
27302+ * nlmsghdr structure
27303+ * return code: return value, based on errno values
27304+ *
27305+ * o ADD:
27306+ * Sent by an application to add a domain mapping to the NetLabel system.
27307+ * The kernel should respond with an ACK.
27308+ *
27309+ * +-------------------+
27310+ * | domains (32 bits) | ...
27311+ * +-------------------+
27312+ *
27313+ * domains: the number of domains in the message
27314+ *
27315+ * +--------------------------+-------------------------+
27316+ * | domain string (variable) | protocol type (32 bits) | ...
27317+ * +--------------------------+-------------------------+
27318+ *
27319+ * +-------------- ---- --- -- -
27320+ * | mapping data ... repeated
27321+ * +-------------- ---- --- -- -
27322+ *
27323+ * domain string: the domain string, NULL terminated
27324+ * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
27325+ * mapping data: specific to the map type (see below)
27326+ *
27327+ * NETLBL_NLTYPE_UNLABELED
27328+ *
27329+ * No mapping data for this protocol type.
27330+ *
27331+ * NETLBL_NLTYPE_CIPSOV4
27332+ *
27333+ * +---------------+
27334+ * | doi (32 bits) |
27335+ * +---------------+
27336+ *
27337+ * doi: the CIPSO DOI value
27338+ *
27339+ * o REMOVE:
27340+ * Sent by an application to remove a domain mapping from the NetLabel
27341+ * system. The kernel should ACK this message.
27342+ *
27343+ * +-------------------+
27344+ * | domains (32 bits) | ...
27345+ * +-------------------+
27346+ *
27347+ * domains: the number of domains in the message
27348+ *
27349+ * +--------------------------+
27350+ * | domain string (variable) | ...
27351+ * +--------------------------+
27352+ *
27353+ * domain string: the domain string, NULL terminated
27354+ *
27355+ * o LIST:
27356+ * This message can be sent either from an application or by the kernel in
27357+ * response to an application generated LIST message. When sent by an
27358+ * application there is no payload. The kernel should respond to a LIST
27359+ * message either with a LIST message on success or an ACK message on
27360+ * failure.
27361+ *
27362+ * +-------------------+
27363+ * | domains (32 bits) | ...
27364+ * +-------------------+
27365+ *
27366+ * domains: the number of domains in the message
27367+ *
27368+ * +--------------------------+
27369+ * | domain string (variable) | ...
27370+ * +--------------------------+
27371+ *
27372+ * +-------------------------+-------------- ---- --- -- -
27373+ * | protocol type (32 bits) | mapping data ... repeated
27374+ * +-------------------------+-------------- ---- --- -- -
27375+ *
27376+ * domain string: the domain string, NULL terminated
27377+ * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
27378+ * mapping data: specific to the map type (see below)
27379+ *
27380+ * NETLBL_NLTYPE_UNLABELED
27381+ *
27382+ * No mapping data for this protocol type.
27383+ *
27384+ * NETLBL_NLTYPE_CIPSOV4
27385+ *
27386+ * +----------------+---------------+
27387+ * | type (32 bits) | doi (32 bits) |
27388+ * +----------------+---------------+
27389+ *
27390+ * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
27391+ * as CIPSO_V4_MAP_*)
27392+ * doi: the CIPSO DOI value
27393+ *
27394+ * o ADDDEF:
27395+ * Sent by an application to set the default domain mapping for the NetLabel
27396+ * system. The kernel should respond with an ACK.
27397+ *
27398+ * +-------------------------+-------------- ---- --- -- -
27399+ * | protocol type (32 bits) | mapping data ... repeated
27400+ * +-------------------------+-------------- ---- --- -- -
27401+ *
27402+ * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
27403+ * mapping data: specific to the map type (see below)
27404+ *
27405+ * NETLBL_NLTYPE_UNLABELED
27406+ *
27407+ * No mapping data for this protocol type.
27408+ *
27409+ * NETLBL_NLTYPE_CIPSOV4
27410+ *
27411+ * +---------------+
27412+ * | doi (32 bits) |
27413+ * +---------------+
27414+ *
27415+ * doi: the CIPSO DOI value
27416+ *
27417+ * o REMOVEDEF:
27418+ * Sent by an application to remove the default domain mapping from the
27419+ * NetLabel system, there is no payload. The kernel should ACK this message.
27420+ *
27421+ * o LISTDEF:
27422+ * This message can be sent either from an application or by the kernel in
27423+ * response to an application generated LISTDEF message. When sent by an
27424+ * application there is no payload. The kernel should respond to a
27425+ * LISTDEF message either with a LISTDEF message on success or an ACK message
27426+ * on failure.
27427+ *
27428+ * +-------------------------+-------------- ---- --- -- -
27429+ * | protocol type (32 bits) | mapping data ... repeated
27430+ * +-------------------------+-------------- ---- --- -- -
27431+ *
27432+ * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
27433+ * mapping data: specific to the map type (see below)
27434+ *
27435+ * NETLBL_NLTYPE_UNLABELED
27436+ *
27437+ * No mapping data for this protocol type.
27438+ *
27439+ * NETLBL_NLTYPE_CIPSOV4
27440+ *
27441+ * +----------------+---------------+
27442+ * | type (32 bits) | doi (32 bits) |
27443+ * +----------------+---------------+
27444+ *
27445+ * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
27446+ * as CIPSO_V4_MAP_*)
27447+ * doi: the CIPSO DOI value
27448+ *
27449+ * o MODULES:
27450+ * Sent by an application to request a list of configured NetLabel modules
27451+ * in the kernel. When sent by an application there is no payload.
27452+ *
27453+ * +-------------------+
27454+ * | modules (32 bits) | ...
27455+ * +-------------------+
27456+ *
27457+ * modules: the number of modules in the message, if this is an application
27458+ * generated message and the value is zero then return a list of
27459+ * the configured modules
27460+ *
27461+ * +------------------+
27462+ * | module (32 bits) | ... repeated
27463+ * +------------------+
27464+ *
27465+ * module: the module number as defined by NETLBL_NLTYPE_*
27466+ *
27467+ * o VERSION:
27468+ * Sent by an application to request the NetLabel version string. When sent
27469+ * by an application there is no payload. This message type is also used by
27470+ * the kernel to respond to an VERSION request.
27471+ *
27472+ * +-------------------+
27473+ * | version (32 bits) |
27474+ * +-------------------+
27475+ *
27476+ * version: the protocol version number
27477+ *
27478+ */
27479+
27480+/* NetLabel Management commands */
27481+enum {
27482+ NLBL_MGMT_C_UNSPEC,
27483+ NLBL_MGMT_C_ACK,
27484+ NLBL_MGMT_C_ADD,
27485+ NLBL_MGMT_C_REMOVE,
27486+ NLBL_MGMT_C_LIST,
27487+ NLBL_MGMT_C_ADDDEF,
27488+ NLBL_MGMT_C_REMOVEDEF,
27489+ NLBL_MGMT_C_LISTDEF,
27490+ NLBL_MGMT_C_MODULES,
27491+ NLBL_MGMT_C_VERSION,
27492+ __NLBL_MGMT_C_MAX,
27493+};
27494+#define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1)
27495+
27496+/* NetLabel protocol functions */
27497+int netlbl_mgmt_genl_init(void);
27498+
27499+#endif
27500diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_unlabeled.c linux-2.6.19/net/netlabel/netlabel_unlabeled.c
27501--- linux-2.6.18-rc5/net/netlabel/netlabel_unlabeled.c 1970-01-01 01:00:00.000000000 +0100
27502+++ linux-2.6.19/net/netlabel/netlabel_unlabeled.c 2006-09-22 10:04:59.000000000 +0200
27503@@ -0,0 +1,253 @@
27504+/*
27505+ * NetLabel Unlabeled Support
27506+ *
27507+ * This file defines functions for dealing with unlabeled packets for the
27508+ * NetLabel system. The NetLabel system manages static and dynamic label
27509+ * mappings for network protocols such as CIPSO and RIPSO.
27510+ *
27511+ * Author: Paul Moore <paul.moore@hp.com>
27512+ *
27513+ */
27514+
27515+/*
27516+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
27517+ *
27518+ * This program is free software; you can redistribute it and/or modify
27519+ * it under the terms of the GNU General Public License as published by
27520+ * the Free Software Foundation; either version 2 of the License, or
27521+ * (at your option) any later version.
27522+ *
27523+ * This program is distributed in the hope that it will be useful,
27524+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27525+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
27526+ * the GNU General Public License for more details.
27527+ *
27528+ * You should have received a copy of the GNU General Public License
27529+ * along with this program; if not, write to the Free Software
27530+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27531+ *
27532+ */
27533+
27534+#include <linux/types.h>
27535+#include <linux/rcupdate.h>
27536+#include <linux/list.h>
27537+#include <linux/spinlock.h>
27538+#include <linux/socket.h>
27539+#include <linux/string.h>
27540+#include <linux/skbuff.h>
27541+#include <net/sock.h>
27542+#include <net/netlink.h>
27543+#include <net/genetlink.h>
27544+
27545+#include <net/netlabel.h>
27546+#include <asm/bug.h>
27547+
27548+#include "netlabel_user.h"
27549+#include "netlabel_domainhash.h"
27550+#include "netlabel_unlabeled.h"
27551+
27552+/* Accept unlabeled packets flag */
27553+static atomic_t netlabel_unlabel_accept_flg = ATOMIC_INIT(0);
27554+
27555+/* NetLabel Generic NETLINK CIPSOv4 family */
27556+static struct genl_family netlbl_unlabel_gnl_family = {
27557+ .id = GENL_ID_GENERATE,
27558+ .hdrsize = 0,
27559+ .name = NETLBL_NLTYPE_UNLABELED_NAME,
27560+ .version = NETLBL_PROTO_VERSION,
27561+ .maxattr = 0,
27562+};
27563+
27564+
27565+/*
27566+ * NetLabel Command Handlers
27567+ */
27568+
27569+/**
27570+ * netlbl_unlabel_accept - Handle an ACCEPT message
27571+ * @skb: the NETLINK buffer
27572+ * @info: the Generic NETLINK info block
27573+ *
27574+ * Description:
27575+ * Process a user generated ACCEPT message and set the accept flag accordingly.
27576+ * Returns zero on success, negative values on failure.
27577+ *
27578+ */
27579+static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
27580+{
27581+ int ret_val;
27582+ struct nlattr *data = netlbl_netlink_payload_data(skb);
27583+ u32 value;
27584+
27585+ ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
27586+ if (ret_val != 0)
27587+ return ret_val;
27588+
27589+ if (netlbl_netlink_payload_len(skb) == NETLBL_LEN_U32) {
27590+ value = nla_get_u32(data);
27591+ if (value == 1 || value == 0) {
27592+ atomic_set(&netlabel_unlabel_accept_flg, value);
27593+ netlbl_netlink_send_ack(info,
27594+ netlbl_unlabel_gnl_family.id,
27595+ NLBL_UNLABEL_C_ACK,
27596+ NETLBL_E_OK);
27597+ return 0;
27598+ }
27599+ }
27600+
27601+ netlbl_netlink_send_ack(info,
27602+ netlbl_unlabel_gnl_family.id,
27603+ NLBL_UNLABEL_C_ACK,
27604+ EINVAL);
27605+ return -EINVAL;
27606+}
27607+
27608+/**
27609+ * netlbl_unlabel_list - Handle a LIST message
27610+ * @skb: the NETLINK buffer
27611+ * @info: the Generic NETLINK info block
27612+ *
27613+ * Description:
27614+ * Process a user generated LIST message and respond with the current status.
27615+ * Returns zero on success, negative values on failure.
27616+ *
27617+ */
27618+static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
27619+{
27620+ int ret_val = -ENOMEM;
27621+ struct sk_buff *ans_skb;
27622+
27623+ ans_skb = netlbl_netlink_alloc_skb(0,
27624+ GENL_HDRLEN + NETLBL_LEN_U32,
27625+ GFP_KERNEL);
27626+ if (ans_skb == NULL)
27627+ goto list_failure;
27628+
27629+ if (netlbl_netlink_hdr_put(ans_skb,
27630+ info->snd_pid,
27631+ 0,
27632+ netlbl_unlabel_gnl_family.id,
27633+ NLBL_UNLABEL_C_LIST) == NULL)
27634+ goto list_failure;
27635+
27636+ ret_val = nla_put_u32(ans_skb,
27637+ NLA_U32,
27638+ atomic_read(&netlabel_unlabel_accept_flg));
27639+ if (ret_val != 0)
27640+ goto list_failure;
27641+
27642+ ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
27643+ if (ret_val != 0)
27644+ goto list_failure;
27645+
27646+ return 0;
27647+
27648+list_failure:
27649+ netlbl_netlink_send_ack(info,
27650+ netlbl_unlabel_gnl_family.id,
27651+ NLBL_UNLABEL_C_ACK,
27652+ -ret_val);
27653+ return ret_val;
27654+}
27655+
27656+
27657+/*
27658+ * NetLabel Generic NETLINK Command Definitions
27659+ */
27660+
27661+static struct genl_ops netlbl_unlabel_genl_c_accept = {
27662+ .cmd = NLBL_UNLABEL_C_ACCEPT,
27663+ .flags = 0,
27664+ .doit = netlbl_unlabel_accept,
27665+ .dumpit = NULL,
27666+};
27667+
27668+static struct genl_ops netlbl_unlabel_genl_c_list = {
27669+ .cmd = NLBL_UNLABEL_C_LIST,
27670+ .flags = 0,
27671+ .doit = netlbl_unlabel_list,
27672+ .dumpit = NULL,
27673+};
27674+
27675+
27676+/*
27677+ * NetLabel Generic NETLINK Protocol Functions
27678+ */
27679+
27680+/**
27681+ * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component
27682+ *
27683+ * Description:
27684+ * Register the unlabeled packet NetLabel component with the Generic NETLINK
27685+ * mechanism. Returns zero on success, negative values on failure.
27686+ *
27687+ */
27688+int netlbl_unlabel_genl_init(void)
27689+{
27690+ int ret_val;
27691+
27692+ ret_val = genl_register_family(&netlbl_unlabel_gnl_family);
27693+ if (ret_val != 0)
27694+ return ret_val;
27695+
27696+ ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
27697+ &netlbl_unlabel_genl_c_accept);
27698+ if (ret_val != 0)
27699+ return ret_val;
27700+
27701+ ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
27702+ &netlbl_unlabel_genl_c_list);
27703+ if (ret_val != 0)
27704+ return ret_val;
27705+
27706+ return 0;
27707+}
27708+
27709+/*
27710+ * NetLabel KAPI Hooks
27711+ */
27712+
27713+/**
27714+ * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet
27715+ * @secattr: the security attributes
27716+ *
27717+ * Description:
27718+ * Determine the security attributes, if any, for an unlabled packet and return
27719+ * them in @secattr. Returns zero on success and negative values on failure.
27720+ *
27721+ */
27722+int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr)
27723+{
27724+ if (atomic_read(&netlabel_unlabel_accept_flg) == 1) {
27725+ memset(secattr, 0, sizeof(*secattr));
27726+ return 0;
27727+ }
27728+
27729+ return -ENOMSG;
27730+}
27731+
27732+/**
27733+ * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets
27734+ *
27735+ * Description:
27736+ * Set the default NetLabel configuration to allow incoming unlabeled packets
27737+ * and to send unlabeled network traffic by default.
27738+ *
27739+ */
27740+int netlbl_unlabel_defconf(void)
27741+{
27742+ int ret_val;
27743+ struct netlbl_dom_map *entry;
27744+
27745+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
27746+ if (entry == NULL)
27747+ return -ENOMEM;
27748+ entry->type = NETLBL_NLTYPE_UNLABELED;
27749+ ret_val = netlbl_domhsh_add_default(entry);
27750+ if (ret_val != 0)
27751+ return ret_val;
27752+
27753+ atomic_set(&netlabel_unlabel_accept_flg, 1);
27754+
27755+ return 0;
27756+}
27757diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_unlabeled.h linux-2.6.19/net/netlabel/netlabel_unlabeled.h
27758--- linux-2.6.18-rc5/net/netlabel/netlabel_unlabeled.h 1970-01-01 01:00:00.000000000 +0100
27759+++ linux-2.6.19/net/netlabel/netlabel_unlabeled.h 2006-09-22 10:04:59.000000000 +0200
27760@@ -0,0 +1,98 @@
27761+/*
27762+ * NetLabel Unlabeled Support
27763+ *
27764+ * This file defines functions for dealing with unlabeled packets for the
27765+ * NetLabel system. The NetLabel system manages static and dynamic label
27766+ * mappings for network protocols such as CIPSO and RIPSO.
27767+ *
27768+ * Author: Paul Moore <paul.moore@hp.com>
27769+ *
27770+ */
27771+
27772+/*
27773+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
27774+ *
27775+ * This program is free software; you can redistribute it and/or modify
27776+ * it under the terms of the GNU General Public License as published by
27777+ * the Free Software Foundation; either version 2 of the License, or
27778+ * (at your option) any later version.
27779+ *
27780+ * This program is distributed in the hope that it will be useful,
27781+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27782+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
27783+ * the GNU General Public License for more details.
27784+ *
27785+ * You should have received a copy of the GNU General Public License
27786+ * along with this program; if not, write to the Free Software
27787+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27788+ *
27789+ */
27790+
27791+#ifndef _NETLABEL_UNLABELED_H
27792+#define _NETLABEL_UNLABELED_H
27793+
27794+#include <net/netlabel.h>
27795+
27796+/*
27797+ * The following NetLabel payloads are supported by the Unlabeled subsystem.
27798+ *
27799+ * o ACK:
27800+ * Sent by the kernel in response to an applications message, applications
27801+ * should never send this message.
27802+ *
27803+ * +----------------------+-----------------------+
27804+ * | seq number (32 bits) | return code (32 bits) |
27805+ * +----------------------+-----------------------+
27806+ *
27807+ * seq number: the sequence number of the original message, taken from the
27808+ * nlmsghdr structure
27809+ * return code: return value, based on errno values
27810+ *
27811+ * o ACCEPT
27812+ * This message is sent from an application to specify if the kernel should
27813+ * allow unlabled packets to pass if they do not match any of the static
27814+ * mappings defined in the unlabeled module.
27815+ *
27816+ * +-----------------+
27817+ * | allow (32 bits) |
27818+ * +-----------------+
27819+ *
27820+ * allow: if true (1) then allow the packets to pass, if false (0) then
27821+ * reject the packets
27822+ *
27823+ * o LIST
27824+ * This message can be sent either from an application or by the kernel in
27825+ * response to an application generated LIST message. When sent by an
27826+ * application there is no payload. The kernel should respond to a LIST
27827+ * message either with a LIST message on success or an ACK message on
27828+ * failure.
27829+ *
27830+ * +-----------------------+
27831+ * | accept flag (32 bits) |
27832+ * +-----------------------+
27833+ *
27834+ * accept flag: if true (1) then unlabeled packets are allowed to pass,
27835+ * if false (0) then unlabeled packets are rejected
27836+ *
27837+ */
27838+
27839+/* NetLabel Unlabeled commands */
27840+enum {
27841+ NLBL_UNLABEL_C_UNSPEC,
27842+ NLBL_UNLABEL_C_ACK,
27843+ NLBL_UNLABEL_C_ACCEPT,
27844+ NLBL_UNLABEL_C_LIST,
27845+ __NLBL_UNLABEL_C_MAX,
27846+};
27847+#define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1)
27848+
27849+/* NetLabel protocol functions */
27850+int netlbl_unlabel_genl_init(void);
27851+
27852+/* Process Unlabeled incoming network packets */
27853+int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr);
27854+
27855+/* Set the default configuration to allow Unlabeled packets */
27856+int netlbl_unlabel_defconf(void);
27857+
27858+#endif
27859diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_user.c linux-2.6.19/net/netlabel/netlabel_user.c
27860--- linux-2.6.18-rc5/net/netlabel/netlabel_user.c 1970-01-01 01:00:00.000000000 +0100
27861+++ linux-2.6.19/net/netlabel/netlabel_user.c 2006-09-22 10:04:59.000000000 +0200
27862@@ -0,0 +1,158 @@
27863+/*
27864+ * NetLabel NETLINK Interface
27865+ *
27866+ * This file defines the NETLINK interface for the NetLabel system. The
27867+ * NetLabel system manages static and dynamic label mappings for network
27868+ * protocols such as CIPSO and RIPSO.
27869+ *
27870+ * Author: Paul Moore <paul.moore@hp.com>
27871+ *
27872+ */
27873+
27874+/*
27875+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
27876+ *
27877+ * This program is free software; you can redistribute it and/or modify
27878+ * it under the terms of the GNU General Public License as published by
27879+ * the Free Software Foundation; either version 2 of the License, or
27880+ * (at your option) any later version.
27881+ *
27882+ * This program is distributed in the hope that it will be useful,
27883+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27884+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
27885+ * the GNU General Public License for more details.
27886+ *
27887+ * You should have received a copy of the GNU General Public License
27888+ * along with this program; if not, write to the Free Software
27889+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27890+ *
27891+ */
27892+
27893+#include <linux/init.h>
27894+#include <linux/types.h>
27895+#include <linux/list.h>
27896+#include <linux/socket.h>
27897+#include <net/sock.h>
27898+#include <net/netlink.h>
27899+#include <net/genetlink.h>
27900+#include <net/netlabel.h>
27901+#include <asm/bug.h>
27902+
27903+#include "netlabel_mgmt.h"
27904+#include "netlabel_unlabeled.h"
27905+#include "netlabel_cipso_v4.h"
27906+#include "netlabel_user.h"
27907+
27908+/*
27909+ * NetLabel NETLINK Setup Functions
27910+ */
27911+
27912+/**
27913+ * netlbl_netlink_init - Initialize the NETLINK communication channel
27914+ *
27915+ * Description:
27916+ * Call out to the NetLabel components so they can register their families and
27917+ * commands with the Generic NETLINK mechanism. Returns zero on success and
27918+ * non-zero on failure.
27919+ *
27920+ */
27921+int netlbl_netlink_init(void)
27922+{
27923+ int ret_val;
27924+
27925+ ret_val = netlbl_mgmt_genl_init();
27926+ if (ret_val != 0)
27927+ return ret_val;
27928+
27929+ ret_val = netlbl_cipsov4_genl_init();
27930+ if (ret_val != 0)
27931+ return ret_val;
27932+
27933+ ret_val = netlbl_unlabel_genl_init();
27934+ if (ret_val != 0)
27935+ return ret_val;
27936+
27937+ return 0;
27938+}
27939+
27940+/*
27941+ * NetLabel Common Protocol Functions
27942+ */
27943+
27944+/**
27945+ * netlbl_netlink_send_ack - Send an ACK message
27946+ * @info: the generic NETLINK information
27947+ * @genl_family: the generic NETLINK family ID value
27948+ * @ack_cmd: the generic NETLINK family ACK command value
27949+ * @ret_code: return code to use
27950+ *
27951+ * Description:
27952+ * This function sends an ACK message to the sender of the NETLINK message
27953+ * specified by @info.
27954+ *
27955+ */
27956+void netlbl_netlink_send_ack(const struct genl_info *info,
27957+ u32 genl_family,
27958+ u8 ack_cmd,
27959+ u32 ret_code)
27960+{
27961+ size_t data_size;
27962+ struct sk_buff *skb;
27963+
27964+ data_size = GENL_HDRLEN + 2 * NETLBL_LEN_U32;
27965+ skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL);
27966+ if (skb == NULL)
27967+ return;
27968+
27969+ if (netlbl_netlink_hdr_put(skb,
27970+ info->snd_pid,
27971+ 0,
27972+ genl_family,
27973+ ack_cmd) == NULL)
27974+ goto send_ack_failure;
27975+
27976+ if (nla_put_u32(skb, NLA_U32, info->snd_seq) != 0)
27977+ goto send_ack_failure;
27978+ if (nla_put_u32(skb, NLA_U32, ret_code) != 0)
27979+ goto send_ack_failure;
27980+
27981+ netlbl_netlink_snd(skb, info->snd_pid);
27982+ return;
27983+
27984+send_ack_failure:
27985+ kfree_skb(skb);
27986+}
27987+
27988+/*
27989+ * NETLINK I/O Functions
27990+ */
27991+
27992+/**
27993+ * netlbl_netlink_snd - Send a NetLabel message
27994+ * @skb: NetLabel message
27995+ * @pid: destination PID
27996+ *
27997+ * Description:
27998+ * Sends a unicast NetLabel message over the NETLINK socket.
27999+ *
28000+ */
28001+int netlbl_netlink_snd(struct sk_buff *skb, u32 pid)
28002+{
28003+ return genlmsg_unicast(skb, pid);
28004+}
28005+
28006+/**
28007+ * netlbl_netlink_snd - Send a NetLabel message
28008+ * @skb: NetLabel message
28009+ * @pid: sending PID
28010+ * @group: multicast group id
28011+ *
28012+ * Description:
28013+ * Sends a multicast NetLabel message over the NETLINK socket to all members
28014+ * of @group except @pid.
28015+ *
28016+ */
28017+int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group)
28018+{
28019+ return genlmsg_multicast(skb, pid, group, GFP_KERNEL);
28020+}
28021diff -Nur linux-2.6.18-rc5/net/netlabel/netlabel_user.h linux-2.6.19/net/netlabel/netlabel_user.h
28022--- linux-2.6.18-rc5/net/netlabel/netlabel_user.h 1970-01-01 01:00:00.000000000 +0100
28023+++ linux-2.6.19/net/netlabel/netlabel_user.h 2006-09-22 10:04:59.000000000 +0200
28024@@ -0,0 +1,215 @@
28025+/*
28026+ * NetLabel NETLINK Interface
28027+ *
28028+ * This file defines the NETLINK interface for the NetLabel system. The
28029+ * NetLabel system manages static and dynamic label mappings for network
28030+ * protocols such as CIPSO and RIPSO.
28031+ *
28032+ * Author: Paul Moore <paul.moore@hp.com>
28033+ *
28034+ */
28035+
28036+/*
28037+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
28038+ *
28039+ * This program is free software; you can redistribute it and/or modify
28040+ * it under the terms of the GNU General Public License as published by
28041+ * the Free Software Foundation; either version 2 of the License, or
28042+ * (at your option) any later version.
28043+ *
28044+ * This program is distributed in the hope that it will be useful,
28045+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28046+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
28047+ * the GNU General Public License for more details.
28048+ *
28049+ * You should have received a copy of the GNU General Public License
28050+ * along with this program; if not, write to the Free Software
28051+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28052+ *
28053+ */
28054+
28055+#ifndef _NETLABEL_USER_H
28056+#define _NETLABEL_USER_H
28057+
28058+#include <linux/types.h>
28059+#include <linux/skbuff.h>
28060+#include <linux/capability.h>
28061+#include <net/netlink.h>
28062+#include <net/genetlink.h>
28063+#include <net/netlabel.h>
28064+
28065+/* NetLabel NETLINK helper functions */
28066+
28067+/**
28068+ * netlbl_netlink_cap_check - Check the NETLINK msg capabilities
28069+ * @skb: the NETLINK buffer
28070+ * @req_cap: the required capability
28071+ *
28072+ * Description:
28073+ * Check the NETLINK buffer's capabilities against the required capabilities.
28074+ * Returns zero on success, negative values on failure.
28075+ *
28076+ */
28077+static inline int netlbl_netlink_cap_check(const struct sk_buff *skb,
28078+ kernel_cap_t req_cap)
28079+{
28080+ if (cap_raised(NETLINK_CB(skb).eff_cap, req_cap))
28081+ return 0;
28082+ return -EPERM;
28083+}
28084+
28085+/**
28086+ * netlbl_getinc_u8 - Read a u8 value from a nlattr stream and move on
28087+ * @nla: the attribute
28088+ * @rem_len: remaining length
28089+ *
28090+ * Description:
28091+ * Return a u8 value pointed to by @nla and advance it to the next attribute.
28092+ *
28093+ */
28094+static inline u8 netlbl_getinc_u8(struct nlattr **nla, int *rem_len)
28095+{
28096+ u8 val = nla_get_u8(*nla);
28097+ *nla = nla_next(*nla, rem_len);
28098+ return val;
28099+}
28100+
28101+/**
28102+ * netlbl_getinc_u16 - Read a u16 value from a nlattr stream and move on
28103+ * @nla: the attribute
28104+ * @rem_len: remaining length
28105+ *
28106+ * Description:
28107+ * Return a u16 value pointed to by @nla and advance it to the next attribute.
28108+ *
28109+ */
28110+static inline u16 netlbl_getinc_u16(struct nlattr **nla, int *rem_len)
28111+{
28112+ u16 val = nla_get_u16(*nla);
28113+ *nla = nla_next(*nla, rem_len);
28114+ return val;
28115+}
28116+
28117+/**
28118+ * netlbl_getinc_u32 - Read a u32 value from a nlattr stream and move on
28119+ * @nla: the attribute
28120+ * @rem_len: remaining length
28121+ *
28122+ * Description:
28123+ * Return a u32 value pointed to by @nla and advance it to the next attribute.
28124+ *
28125+ */
28126+static inline u32 netlbl_getinc_u32(struct nlattr **nla, int *rem_len)
28127+{
28128+ u32 val = nla_get_u32(*nla);
28129+ *nla = nla_next(*nla, rem_len);
28130+ return val;
28131+}
28132+
28133+/**
28134+ * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff
28135+ * @skb: the packet
28136+ * @pid: the PID of the receipient
28137+ * @seq: the sequence number
28138+ * @type: the generic NETLINK message family type
28139+ * @cmd: command
28140+ *
28141+ * Description:
28142+ * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr
28143+ * struct to the packet. Returns a pointer to the start of the payload buffer
28144+ * on success or NULL on failure.
28145+ *
28146+ */
28147+static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb,
28148+ u32 pid,
28149+ u32 seq,
28150+ int type,
28151+ u8 cmd)
28152+{
28153+ return genlmsg_put(skb,
28154+ pid,
28155+ seq,
28156+ type,
28157+ 0,
28158+ 0,
28159+ cmd,
28160+ NETLBL_PROTO_VERSION);
28161+}
28162+
28163+/**
28164+ * netlbl_netlink_hdr_push - Write the NETLINK buffers into a sk_buff
28165+ * @skb: the packet
28166+ * @pid: the PID of the receipient
28167+ * @seq: the sequence number
28168+ * @type: the generic NETLINK message family type
28169+ * @cmd: command
28170+ *
28171+ * Description:
28172+ * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr
28173+ * struct to the packet.
28174+ *
28175+ */
28176+static inline void netlbl_netlink_hdr_push(struct sk_buff *skb,
28177+ u32 pid,
28178+ u32 seq,
28179+ int type,
28180+ u8 cmd)
28181+
28182+{
28183+ struct nlmsghdr *nlh;
28184+ struct genlmsghdr *hdr;
28185+
28186+ nlh = (struct nlmsghdr *)skb_push(skb, NLMSG_SPACE(GENL_HDRLEN));
28187+ nlh->nlmsg_type = type;
28188+ nlh->nlmsg_len = skb->len;
28189+ nlh->nlmsg_flags = 0;
28190+ nlh->nlmsg_pid = pid;
28191+ nlh->nlmsg_seq = seq;
28192+
28193+ hdr = nlmsg_data(nlh);
28194+ hdr->cmd = cmd;
28195+ hdr->version = NETLBL_PROTO_VERSION;
28196+ hdr->reserved = 0;
28197+}
28198+
28199+/**
28200+ * netlbl_netlink_payload_len - Return the length of the payload
28201+ * @skb: the NETLINK buffer
28202+ *
28203+ * Description:
28204+ * This function returns the length of the NetLabel payload.
28205+ *
28206+ */
28207+static inline u32 netlbl_netlink_payload_len(const struct sk_buff *skb)
28208+{
28209+ return nlmsg_len((struct nlmsghdr *)skb->data) - GENL_HDRLEN;
28210+}
28211+
28212+/**
28213+ * netlbl_netlink_payload_data - Returns a pointer to the start of the payload
28214+ * @skb: the NETLINK buffer
28215+ *
28216+ * Description:
28217+ * This function returns a pointer to the start of the NetLabel payload.
28218+ *
28219+ */
28220+static inline void *netlbl_netlink_payload_data(const struct sk_buff *skb)
28221+{
28222+ return (unsigned char *)nlmsg_data((struct nlmsghdr *)skb->data) +
28223+ GENL_HDRLEN;
28224+}
28225+
28226+/* NetLabel common protocol functions */
28227+
28228+void netlbl_netlink_send_ack(const struct genl_info *info,
28229+ u32 genl_family,
28230+ u8 ack_cmd,
28231+ u32 ret_code);
28232+
28233+/* NetLabel NETLINK I/O functions */
28234+
28235+int netlbl_netlink_init(void);
28236+int netlbl_netlink_snd(struct sk_buff *skb, u32 pid);
28237+int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group);
28238+
28239+#endif
28240diff -Nur linux-2.6.18-rc5/net/netlink/af_netlink.c linux-2.6.19/net/netlink/af_netlink.c
28241--- linux-2.6.18-rc5/net/netlink/af_netlink.c 2006-08-28 05:41:48.000000000 +0200
28242+++ linux-2.6.19/net/netlink/af_netlink.c 2006-09-22 10:04:59.000000000 +0200
28243@@ -1147,7 +1147,7 @@
28244 if (len > sk->sk_sndbuf - 32)
28245 goto out;
28246 err = -ENOBUFS;
28247- skb = alloc_skb(len, GFP_KERNEL);
28248+ skb = nlmsg_new(len, GFP_KERNEL);
28249 if (skb==NULL)
28250 goto out;
28251
28252@@ -1342,19 +1341,18 @@
28253 struct netlink_callback *cb;
28254 struct sk_buff *skb;
28255 struct nlmsghdr *nlh;
28256- int len;
28257+ int len, err = -ENOBUFS;
28258
28259 skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL);
28260 if (!skb)
28261- return -ENOBUFS;
28262+ goto errout;
28263
28264 spin_lock(&nlk->cb_lock);
28265
28266 cb = nlk->cb;
28267 if (cb == NULL) {
28268- spin_unlock(&nlk->cb_lock);
28269- kfree_skb(skb);
28270- return -EINVAL;
28271+ err = -EINVAL;
28272+ goto errout_skb;
28273 }
28274
28275 len = cb->dump(skb, cb);
28276@@ -1366,8 +1364,12 @@
28277 return 0;
28278 }
28279
28280- nlh = NLMSG_NEW_ANSWER(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI);
28281- memcpy(NLMSG_DATA(nlh), &len, sizeof(len));
28282+ nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI);
28283+ if (!nlh)
28284+ goto errout_skb;
28285+
28286+ memcpy(nlmsg_data(nlh), &len, sizeof(len));
28287+
28288 skb_queue_tail(&sk->sk_receive_queue, skb);
28289 sk->sk_data_ready(sk, skb->len);
28290
28291@@ -1379,8 +1381,11 @@
28292 netlink_destroy_callback(cb);
28293 return 0;
28294
28295-nlmsg_failure:
28296- return -ENOBUFS;
28297+errout_skb:
28298+ spin_unlock(&nlk->cb_lock);
28299+ kfree_skb(skb);
28300+errout:
28301+ return err;
28302 }
28303
28304 int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
28305@@ -1432,11 +1437,11 @@
28306 int size;
28307
28308 if (err == 0)
28309- size = NLMSG_SPACE(sizeof(struct nlmsgerr));
28310+ size = nlmsg_total_size(sizeof(*errmsg));
28311 else
28312- size = NLMSG_SPACE(4 + NLMSG_ALIGN(nlh->nlmsg_len));
28313+ size = nlmsg_total_size(sizeof(*errmsg) + nlmsg_len(nlh));
28314
28315- skb = alloc_skb(size, GFP_KERNEL);
28316+ skb = nlmsg_new(size, GFP_KERNEL);
28317 if (!skb) {
28318 struct sock *sk;
28319
28320@@ -1452,16 +1457,15 @@
28321
28322 rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
28323 NLMSG_ERROR, sizeof(struct nlmsgerr), 0);
28324- errmsg = NLMSG_DATA(rep);
28325+ errmsg = nlmsg_data(rep);
28326 errmsg->error = err;
28327- memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(struct nlmsghdr));
28328+ memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh));
28329 netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
28330 }
28331
28332 static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
28333 struct nlmsghdr *, int *))
28334 {
28335- unsigned int total_len;
28336 struct nlmsghdr *nlh;
28337 int err;
28338
28339@@ -1471,8 +1475,6 @@
28340 if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len)
28341 return 0;
28342
28343- total_len = min(NLMSG_ALIGN(nlh->nlmsg_len), skb->len);
28344-
28345 if (cb(skb, nlh, &err) < 0) {
28346 /* Not an error, but we have to interrupt processing
28347 * here. Note: that in this case we do not pull
28348@@ -1484,7 +1486,7 @@
28349 } else if (nlh->nlmsg_flags & NLM_F_ACK)
28350 netlink_ack(skb, nlh, 0);
28351
28352- skb_pull(skb, total_len);
28353+ netlink_queue_skip(nlh, skb);
28354 }
28355
28356 return 0;
28357@@ -1547,6 +1549,38 @@
28358 skb_pull(skb, msglen);
28359 }
28360
28361+/**
28362+ * nlmsg_notify - send a notification netlink message
28363+ * @sk: netlink socket to use
28364+ * @skb: notification message
28365+ * @pid: destination netlink pid for reports or 0
28366+ * @group: destination multicast group or 0
28367+ * @report: 1 to report back, 0 to disable
28368+ * @flags: allocation flags
28369+ */
28370+int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid,
28371+ unsigned int group, int report, gfp_t flags)
28372+{
28373+ int err = 0;
28374+
28375+ if (group) {
28376+ int exclude_pid = 0;
28377+
28378+ if (report) {
28379+ atomic_inc(&skb->users);
28380+ exclude_pid = pid;
28381+ }
28382+
28383+ /* errors reported via destination sk->sk_err */
28384+ nlmsg_multicast(sk, skb, exclude_pid, group, flags);
28385+ }
28386+
28387+ if (report)
28388+ err = nlmsg_unicast(sk, skb, pid);
28389+
28390+ return err;
28391+}
28392+
28393 #ifdef CONFIG_PROC_FS
28394 struct nl_seq_iter {
28395 int link;
28396@@ -1728,8 +1762,6 @@
28397 .owner = THIS_MODULE, /* for consistency 8) */
28398 };
28399
28400-extern void netlink_skb_parms_too_large(void);
28401-
28402 static int __init netlink_proto_init(void)
28403 {
28404 struct sk_buff *dummy_skb;
28405@@ -1801,4 +1831,4 @@
28406 EXPORT_SYMBOL(netlink_set_nonroot);
28407 EXPORT_SYMBOL(netlink_unicast);
28408 EXPORT_SYMBOL(netlink_unregister_notifier);
28409-
28410+EXPORT_SYMBOL(nlmsg_notify);
28411diff -Nur linux-2.6.18-rc5/net/netlink/attr.c linux-2.6.19/net/netlink/attr.c
28412--- linux-2.6.18-rc5/net/netlink/attr.c 2006-08-28 05:41:48.000000000 +0200
28413+++ linux-2.6.19/net/netlink/attr.c 2006-09-22 10:04:59.000000000 +0200
28414@@ -20,7 +20,6 @@
28415 [NLA_U16] = sizeof(u16),
28416 [NLA_U32] = sizeof(u32),
28417 [NLA_U64] = sizeof(u64),
28418- [NLA_STRING] = 1,
28419 [NLA_NESTED] = NLA_HDRLEN,
28420 };
28421
28422@@ -28,7 +27,7 @@
28423 struct nla_policy *policy)
28424 {
28425 struct nla_policy *pt;
28426- int minlen = 0;
28427+ int minlen = 0, attrlen = nla_len(nla);
28428
28429 if (nla->nla_type <= 0 || nla->nla_type > maxtype)
28430 return 0;
28431@@ -37,16 +36,46 @@
28432
28433 BUG_ON(pt->type > NLA_TYPE_MAX);
28434
28435- if (pt->minlen)
28436- minlen = pt->minlen;
28437- else if (pt->type != NLA_UNSPEC)
28438- minlen = nla_attr_minlen[pt->type];
28439+ switch (pt->type) {
28440+ case NLA_FLAG:
28441+ if (attrlen > 0)
28442+ return -ERANGE;
28443+ break;
28444+
28445+ case NLA_NUL_STRING:
28446+ if (pt->len)
28447+ minlen = min_t(int, attrlen, pt->len + 1);
28448+ else
28449+ minlen = attrlen;
28450+
28451+ if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL)
28452+ return -EINVAL;
28453+ /* fall through */
28454+
28455+ case NLA_STRING:
28456+ if (attrlen < 1)
28457+ return -ERANGE;
28458
28459- if (pt->type == NLA_FLAG && nla_len(nla) > 0)
28460- return -ERANGE;
28461+ if (pt->len) {
28462+ char *buf = nla_data(nla);
28463
28464- if (nla_len(nla) < minlen)
28465- return -ERANGE;
28466+ if (buf[attrlen - 1] == '\0')
28467+ attrlen--;
28468+
28469+ if (attrlen > pt->len)
28470+ return -ERANGE;
28471+ }
28472+ break;
28473+
28474+ default:
28475+ if (pt->len)
28476+ minlen = pt->len;
28477+ else if (pt->type != NLA_UNSPEC)
28478+ minlen = nla_attr_minlen[pt->type];
28479+
28480+ if (attrlen < minlen)
28481+ return -ERANGE;
28482+ }
28483
28484 return 0;
28485 }
28486@@ -255,6 +284,26 @@
28487 }
28488
28489 /**
28490+ * __nla_reserve_nohdr - reserve room for attribute without header
28491+ * @skb: socket buffer to reserve room on
28492+ * @attrlen: length of attribute payload
28493+ *
28494+ * Reserves room for attribute payload without a header.
28495+ *
28496+ * The caller is responsible to ensure that the skb provides enough
28497+ * tailroom for the payload.
28498+ */
28499+void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
28500+{
28501+ void *start;
28502+
28503+ start = skb_put(skb, NLA_ALIGN(attrlen));
28504+ memset(start, 0, NLA_ALIGN(attrlen));
28505+
28506+ return start;
28507+}
28508+
28509+/**
28510 * nla_reserve - reserve room for attribute on the skb
28511 * @skb: socket buffer to reserve room on
28512 * @attrtype: attribute type
28513@@ -275,6 +324,24 @@
28514 }
28515
28516 /**
28517+ * nla_reserve - reserve room for attribute without header
28518+ * @skb: socket buffer to reserve room on
28519+ * @len: length of attribute payload
28520+ *
28521+ * Reserves room for attribute payload without a header.
28522+ *
28523+ * Returns NULL if the tailroom of the skb is insufficient to store
28524+ * the attribute payload.
28525+ */
28526+void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
28527+{
28528+ if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
28529+ return NULL;
28530+
28531+ return __nla_reserve_nohdr(skb, attrlen);
28532+}
28533+
28534+/**
28535 * __nla_put - Add a netlink attribute to a socket buffer
28536 * @skb: socket buffer to add attribute to
28537 * @attrtype: attribute type
28538@@ -293,6 +360,22 @@
28539 memcpy(nla_data(nla), data, attrlen);
28540 }
28541
28542+/**
28543+ * __nla_put_nohdr - Add a netlink attribute without header
28544+ * @skb: socket buffer to add attribute to
28545+ * @attrlen: length of attribute payload
28546+ * @data: head of attribute payload
28547+ *
28548+ * The caller is responsible to ensure that the skb provides enough
28549+ * tailroom for the attribute payload.
28550+ */
28551+void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
28552+{
28553+ void *start;
28554+
28555+ start = __nla_reserve_nohdr(skb, attrlen);
28556+ memcpy(start, data, attrlen);
28557+}
28558
28559 /**
28560 * nla_put - Add a netlink attribute to a socket buffer
28561@@ -313,15 +396,36 @@
28562 return 0;
28563 }
28564
28565+/**
28566+ * nla_put_nohdr - Add a netlink attribute without header
28567+ * @skb: socket buffer to add attribute to
28568+ * @attrlen: length of attribute payload
28569+ * @data: head of attribute payload
28570+ *
28571+ * Returns -1 if the tailroom of the skb is insufficient to store
28572+ * the attribute payload.
28573+ */
28574+int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
28575+{
28576+ if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
28577+ return -1;
28578+
28579+ __nla_put_nohdr(skb, attrlen, data);
28580+ return 0;
28581+}
28582
28583 EXPORT_SYMBOL(nla_validate);
28584 EXPORT_SYMBOL(nla_parse);
28585 EXPORT_SYMBOL(nla_find);
28586 EXPORT_SYMBOL(nla_strlcpy);
28587 EXPORT_SYMBOL(__nla_reserve);
28588+EXPORT_SYMBOL(__nla_reserve_nohdr);
28589 EXPORT_SYMBOL(nla_reserve);
28590+EXPORT_SYMBOL(nla_reserve_nohdr);
28591 EXPORT_SYMBOL(__nla_put);
28592+EXPORT_SYMBOL(__nla_put_nohdr);
28593 EXPORT_SYMBOL(nla_put);
28594+EXPORT_SYMBOL(nla_put_nohdr);
28595 EXPORT_SYMBOL(nla_memcpy);
28596 EXPORT_SYMBOL(nla_memcmp);
28597 EXPORT_SYMBOL(nla_strcmp);
28598diff -Nur linux-2.6.18-rc5/net/netlink/genetlink.c linux-2.6.19/net/netlink/genetlink.c
28599--- linux-2.6.18-rc5/net/netlink/genetlink.c 2006-08-28 05:41:48.000000000 +0200
28600+++ linux-2.6.19/net/netlink/genetlink.c 2006-09-22 10:04:59.000000000 +0200
28601@@ -387,7 +387,10 @@
28602 static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq,
28603 u32 flags, struct sk_buff *skb, u8 cmd)
28604 {
28605+ struct nlattr *nla_ops;
28606+ struct genl_ops *ops;
28607 void *hdr;
28608+ int idx = 1;
28609
28610 hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd,
28611 family->version);
28612@@ -396,6 +399,37 @@
28613
28614 NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name);
28615 NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id);
28616+ NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version);
28617+ NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize);
28618+ NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr);
28619+
28620+ nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS);
28621+ if (nla_ops == NULL)
28622+ goto nla_put_failure;
28623+
28624+ list_for_each_entry(ops, &family->ops_list, ops_list) {
28625+ struct nlattr *nest;
28626+
28627+ nest = nla_nest_start(skb, idx++);
28628+ if (nest == NULL)
28629+ goto nla_put_failure;
28630+
28631+ NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd);
28632+ NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags);
28633+
28634+ if (ops->policy)
28635+ NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY);
28636+
28637+ if (ops->doit)
28638+ NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT);
28639+
28640+ if (ops->dumpit)
28641+ NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT);
28642+
28643+ nla_nest_end(skb, nest);
28644+ }
28645+
28646+ nla_nest_end(skb, nla_ops);
28647
28648 return genlmsg_end(skb, hdr);
28649
28650@@ -411,6 +445,9 @@
28651 int chains_to_skip = cb->args[0];
28652 int fams_to_skip = cb->args[1];
28653
28654+ if (chains_to_skip != 0)
28655+ genl_lock();
28656+
28657 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
28658 if (i < chains_to_skip)
28659 continue;
28660@@ -428,6 +465,9 @@
28661 }
28662
28663 errout:
28664+ if (chains_to_skip != 0)
28665+ genl_unlock();
28666+
28667 cb->args[0] = i;
28668 cb->args[1] = n;
28669
28670@@ -440,7 +480,7 @@
28671 struct sk_buff *skb;
28672 int err;
28673
28674- skb = nlmsg_new(NLMSG_GOODSIZE);
28675+ skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
28676 if (skb == NULL)
28677 return ERR_PTR(-ENOBUFS);
28678
28679@@ -455,7 +495,8 @@
28680
28681 static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] __read_mostly = {
28682 [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
28683- [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING },
28684+ [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
28685+ .len = GENL_NAMSIZ - 1 },
28686 };
28687
28688 static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
28689@@ -470,12 +511,9 @@
28690 }
28691
28692 if (info->attrs[CTRL_ATTR_FAMILY_NAME]) {
28693- char name[GENL_NAMSIZ];
28694-
28695- if (nla_strlcpy(name, info->attrs[CTRL_ATTR_FAMILY_NAME],
28696- GENL_NAMSIZ) >= GENL_NAMSIZ)
28697- goto errout;
28698+ char *name;
28699
28700+ name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]);
28701 res = genl_family_find_byname(name);
28702 }
28703
28704@@ -510,7 +548,7 @@
28705 if (IS_ERR(msg))
28706 return PTR_ERR(msg);
28707
28708- genlmsg_multicast(msg, 0, GENL_ID_CTRL);
28709+ genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
28710 break;
28711 }
28712
28713diff -Nur linux-2.6.18-rc5/net/packet/af_packet.c linux-2.6.19/net/packet/af_packet.c
28714--- linux-2.6.18-rc5/net/packet/af_packet.c 2006-08-28 05:41:48.000000000 +0200
28715+++ linux-2.6.19/net/packet/af_packet.c 2006-09-22 10:04:59.000000000 +0200
28716@@ -427,21 +427,24 @@
28717 }
28718 #endif
28719
28720-static inline unsigned run_filter(struct sk_buff *skb, struct sock *sk, unsigned res)
28721+static inline int run_filter(struct sk_buff *skb, struct sock *sk,
28722+ unsigned *snaplen)
28723 {
28724 struct sk_filter *filter;
28725+ int err = 0;
28726
28727- bh_lock_sock(sk);
28728- filter = sk->sk_filter;
28729- /*
28730- * Our caller already checked that filter != NULL but we need to
28731- * verify that under bh_lock_sock() to be safe
28732- */
28733- if (likely(filter != NULL))
28734- res = sk_run_filter(skb, filter->insns, filter->len);
28735- bh_unlock_sock(sk);
28736+ rcu_read_lock_bh();
28737+ filter = rcu_dereference(sk->sk_filter);
28738+ if (filter != NULL) {
28739+ err = sk_run_filter(skb, filter->insns, filter->len);
28740+ if (!err)
28741+ err = -EPERM;
28742+ else if (*snaplen > err)
28743+ *snaplen = err;
28744+ }
28745+ rcu_read_unlock_bh();
28746
28747- return res;
28748+ return err;
28749 }
28750
28751 /*
28752@@ -491,13 +494,8 @@
28753
28754 snaplen = skb->len;
28755
28756- if (sk->sk_filter) {
28757- unsigned res = run_filter(skb, sk, snaplen);
28758- if (res == 0)
28759- goto drop_n_restore;
28760- if (snaplen > res)
28761- snaplen = res;
28762- }
28763+ if (run_filter(skb, sk, &snaplen) < 0)
28764+ goto drop_n_restore;
28765
28766 if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
28767 (unsigned)sk->sk_rcvbuf)
28768@@ -586,20 +584,15 @@
28769 else if (skb->pkt_type == PACKET_OUTGOING) {
28770 /* Special case: outgoing packets have ll header at head */
28771 skb_pull(skb, skb->nh.raw - skb->data);
28772- if (skb->ip_summed == CHECKSUM_HW)
28773+ if (skb->ip_summed == CHECKSUM_PARTIAL)
28774 status |= TP_STATUS_CSUMNOTREADY;
28775 }
28776 }
28777
28778 snaplen = skb->len;
28779
28780- if (sk->sk_filter) {
28781- unsigned res = run_filter(skb, sk, snaplen);
28782- if (res == 0)
28783- goto drop_n_restore;
28784- if (snaplen > res)
28785- snaplen = res;
28786- }
28787+ if (run_filter(skb, sk, &snaplen) < 0)
28788+ goto drop_n_restore;
28789
28790 if (sk->sk_type == SOCK_DGRAM) {
28791 macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16;
28792diff -Nur linux-2.6.18-rc5/net/sched/act_api.c linux-2.6.19/net/sched/act_api.c
28793--- linux-2.6.18-rc5/net/sched/act_api.c 2006-08-28 05:41:48.000000000 +0200
28794+++ linux-2.6.19/net/sched/act_api.c 2006-09-22 10:04:59.000000000 +0200
28795@@ -33,16 +33,230 @@
28796 #include <net/sch_generic.h>
28797 #include <net/act_api.h>
28798
28799-#if 0 /* control */
28800-#define DPRINTK(format, args...) printk(KERN_DEBUG format, ##args)
28801-#else
28802-#define DPRINTK(format, args...)
28803+void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
28804+{
28805+ unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask);
28806+ struct tcf_common **p1p;
28807+
28808+ for (p1p = &hinfo->htab[h]; *p1p; p1p = &(*p1p)->tcfc_next) {
28809+ if (*p1p == p) {
28810+ write_lock_bh(hinfo->lock);
28811+ *p1p = p->tcfc_next;
28812+ write_unlock_bh(hinfo->lock);
28813+#ifdef CONFIG_NET_ESTIMATOR
28814+ gen_kill_estimator(&p->tcfc_bstats,
28815+ &p->tcfc_rate_est);
28816 #endif
28817-#if 0 /* data */
28818-#define D2PRINTK(format, args...) printk(KERN_DEBUG format, ##args)
28819-#else
28820-#define D2PRINTK(format, args...)
28821+ kfree(p);
28822+ return;
28823+ }
28824+ }
28825+ BUG_TRAP(0);
28826+}
28827+EXPORT_SYMBOL(tcf_hash_destroy);
28828+
28829+int tcf_hash_release(struct tcf_common *p, int bind,
28830+ struct tcf_hashinfo *hinfo)
28831+{
28832+ int ret = 0;
28833+
28834+ if (p) {
28835+ if (bind)
28836+ p->tcfc_bindcnt--;
28837+
28838+ p->tcfc_refcnt--;
28839+ if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
28840+ tcf_hash_destroy(p, hinfo);
28841+ ret = 1;
28842+ }
28843+ }
28844+ return ret;
28845+}
28846+EXPORT_SYMBOL(tcf_hash_release);
28847+
28848+static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
28849+ struct tc_action *a, struct tcf_hashinfo *hinfo)
28850+{
28851+ struct tcf_common *p;
28852+ int err = 0, index = -1,i = 0, s_i = 0, n_i = 0;
28853+ struct rtattr *r ;
28854+
28855+ read_lock(hinfo->lock);
28856+
28857+ s_i = cb->args[0];
28858+
28859+ for (i = 0; i < (hinfo->hmask + 1); i++) {
28860+ p = hinfo->htab[tcf_hash(i, hinfo->hmask)];
28861+
28862+ for (; p; p = p->tcfc_next) {
28863+ index++;
28864+ if (index < s_i)
28865+ continue;
28866+ a->priv = p;
28867+ a->order = n_i;
28868+ r = (struct rtattr*) skb->tail;
28869+ RTA_PUT(skb, a->order, 0, NULL);
28870+ err = tcf_action_dump_1(skb, a, 0, 0);
28871+ if (err < 0) {
28872+ index--;
28873+ skb_trim(skb, (u8*)r - skb->data);
28874+ goto done;
28875+ }
28876+ r->rta_len = skb->tail - (u8*)r;
28877+ n_i++;
28878+ if (n_i >= TCA_ACT_MAX_PRIO)
28879+ goto done;
28880+ }
28881+ }
28882+done:
28883+ read_unlock(hinfo->lock);
28884+ if (n_i)
28885+ cb->args[0] += n_i;
28886+ return n_i;
28887+
28888+rtattr_failure:
28889+ skb_trim(skb, (u8*)r - skb->data);
28890+ goto done;
28891+}
28892+
28893+static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
28894+ struct tcf_hashinfo *hinfo)
28895+{
28896+ struct tcf_common *p, *s_p;
28897+ struct rtattr *r ;
28898+ int i= 0, n_i = 0;
28899+
28900+ r = (struct rtattr*) skb->tail;
28901+ RTA_PUT(skb, a->order, 0, NULL);
28902+ RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
28903+ for (i = 0; i < (hinfo->hmask + 1); i++) {
28904+ p = hinfo->htab[tcf_hash(i, hinfo->hmask)];
28905+
28906+ while (p != NULL) {
28907+ s_p = p->tcfc_next;
28908+ if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo))
28909+ module_put(a->ops->owner);
28910+ n_i++;
28911+ p = s_p;
28912+ }
28913+ }
28914+ RTA_PUT(skb, TCA_FCNT, 4, &n_i);
28915+ r->rta_len = skb->tail - (u8*)r;
28916+
28917+ return n_i;
28918+rtattr_failure:
28919+ skb_trim(skb, (u8*)r - skb->data);
28920+ return -EINVAL;
28921+}
28922+
28923+int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
28924+ int type, struct tc_action *a)
28925+{
28926+ struct tcf_hashinfo *hinfo = a->ops->hinfo;
28927+
28928+ if (type == RTM_DELACTION) {
28929+ return tcf_del_walker(skb, a, hinfo);
28930+ } else if (type == RTM_GETACTION) {
28931+ return tcf_dump_walker(skb, cb, a, hinfo);
28932+ } else {
28933+ printk("tcf_generic_walker: unknown action %d\n", type);
28934+ return -EINVAL;
28935+ }
28936+}
28937+EXPORT_SYMBOL(tcf_generic_walker);
28938+
28939+struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo)
28940+{
28941+ struct tcf_common *p;
28942+
28943+ read_lock(hinfo->lock);
28944+ for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p;
28945+ p = p->tcfc_next) {
28946+ if (p->tcfc_index == index)
28947+ break;
28948+ }
28949+ read_unlock(hinfo->lock);
28950+
28951+ return p;
28952+}
28953+EXPORT_SYMBOL(tcf_hash_lookup);
28954+
28955+u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo)
28956+{
28957+ u32 val = *idx_gen;
28958+
28959+ do {
28960+ if (++val == 0)
28961+ val = 1;
28962+ } while (tcf_hash_lookup(val, hinfo));
28963+
28964+ return (*idx_gen = val);
28965+}
28966+EXPORT_SYMBOL(tcf_hash_new_index);
28967+
28968+int tcf_hash_search(struct tc_action *a, u32 index)
28969+{
28970+ struct tcf_hashinfo *hinfo = a->ops->hinfo;
28971+ struct tcf_common *p = tcf_hash_lookup(index, hinfo);
28972+
28973+ if (p) {
28974+ a->priv = p;
28975+ return 1;
28976+ }
28977+ return 0;
28978+}
28979+EXPORT_SYMBOL(tcf_hash_search);
28980+
28981+struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind,
28982+ struct tcf_hashinfo *hinfo)
28983+{
28984+ struct tcf_common *p = NULL;
28985+ if (index && (p = tcf_hash_lookup(index, hinfo)) != NULL) {
28986+ if (bind) {
28987+ p->tcfc_bindcnt++;
28988+ p->tcfc_refcnt++;
28989+ }
28990+ a->priv = p;
28991+ }
28992+ return p;
28993+}
28994+EXPORT_SYMBOL(tcf_hash_check);
28995+
28996+struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, struct tc_action *a, int size, int bind, u32 *idx_gen, struct tcf_hashinfo *hinfo)
28997+{
28998+ struct tcf_common *p = kzalloc(size, GFP_KERNEL);
28999+
29000+ if (unlikely(!p))
29001+ return p;
29002+ p->tcfc_refcnt = 1;
29003+ if (bind)
29004+ p->tcfc_bindcnt = 1;
29005+
29006+ spin_lock_init(&p->tcfc_lock);
29007+ p->tcfc_stats_lock = &p->tcfc_lock;
29008+ p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo);
29009+ p->tcfc_tm.install = jiffies;
29010+ p->tcfc_tm.lastuse = jiffies;
29011+#ifdef CONFIG_NET_ESTIMATOR
29012+ if (est)
29013+ gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est,
29014+ p->tcfc_stats_lock, est);
29015 #endif
29016+ a->priv = (void *) p;
29017+ return p;
29018+}
29019+EXPORT_SYMBOL(tcf_hash_create);
29020+
29021+void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo)
29022+{
29023+ unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask);
29024+
29025+ write_lock_bh(hinfo->lock);
29026+ p->tcfc_next = hinfo->htab[h];
29027+ hinfo->htab[h] = p;
29028+ write_unlock_bh(hinfo->lock);
29029+}
29030+EXPORT_SYMBOL(tcf_hash_insert);
29031
29032 static struct tc_action_ops *act_base = NULL;
29033 static DEFINE_RWLOCK(act_mod_lock);
29034@@ -155,9 +369,6 @@
29035
29036 if (skb->tc_verd & TC_NCLS) {
29037 skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
29038- D2PRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n",
29039- skb, skb->input_dev ? skb->input_dev->name : "xxx",
29040- skb->dev->name);
29041 ret = TC_ACT_OK;
29042 goto exec_done;
29043 }
29044@@ -187,8 +398,6 @@
29045
29046 for (a = act; a; a = act) {
29047 if (a->ops && a->ops->cleanup) {
29048- DPRINTK("tcf_action_destroy destroying %p next %p\n",
29049- a, a->next);
29050 if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
29051 module_put(a->ops->owner);
29052 act = act->next;
29053@@ -331,7 +540,6 @@
29054 if (*err != ACT_P_CREATED)
29055 module_put(a_o->owner);
29056 a->ops = a_o;
29057- DPRINTK("tcf_action_init_1: successfull %s\n", act_name);
29058
29059 *err = 0;
29060 return a;
29061@@ -392,12 +600,12 @@
29062 if (compat_mode) {
29063 if (a->type == TCA_OLD_COMPAT)
29064 err = gnet_stats_start_copy_compat(skb, 0,
29065- TCA_STATS, TCA_XSTATS, h->stats_lock, &d);
29066+ TCA_STATS, TCA_XSTATS, h->tcf_stats_lock, &d);
29067 else
29068 return 0;
29069 } else
29070 err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
29071- h->stats_lock, &d);
29072+ h->tcf_stats_lock, &d);
29073
29074 if (err < 0)
29075 goto errout;
29076@@ -406,11 +614,11 @@
29077 if (a->ops->get_stats(skb, a) < 0)
29078 goto errout;
29079
29080- if (gnet_stats_copy_basic(&d, &h->bstats) < 0 ||
29081+ if (gnet_stats_copy_basic(&d, &h->tcf_bstats) < 0 ||
29082 #ifdef CONFIG_NET_ESTIMATOR
29083- gnet_stats_copy_rate_est(&d, &h->rate_est) < 0 ||
29084+ gnet_stats_copy_rate_est(&d, &h->tcf_rate_est) < 0 ||
29085 #endif
29086- gnet_stats_copy_queue(&d, &h->qstats) < 0)
29087+ gnet_stats_copy_queue(&d, &h->tcf_qstats) < 0)
29088 goto errout;
29089
29090 if (gnet_stats_finish_copy(&d) < 0)
29091@@ -459,7 +667,6 @@
29092 act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event)
29093 {
29094 struct sk_buff *skb;
29095- int err = 0;
29096
29097 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
29098 if (!skb)
29099@@ -468,10 +675,8 @@
29100 kfree_skb(skb);
29101 return -EINVAL;
29102 }
29103- err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
29104- if (err > 0)
29105- err = 0;
29106- return err;
29107+
29108+ return rtnl_unicast(skb, pid);
29109 }
29110
29111 static struct tc_action *
29112diff -Nur linux-2.6.18-rc5/net/sched/act_gact.c linux-2.6.19/net/sched/act_gact.c
29113--- linux-2.6.18-rc5/net/sched/act_gact.c 2006-08-28 05:41:48.000000000 +0200
29114+++ linux-2.6.19/net/sched/act_gact.c 2006-09-22 10:04:59.000000000 +0200
29115@@ -34,48 +34,43 @@
29116 #include <linux/tc_act/tc_gact.h>
29117 #include <net/tc_act/tc_gact.h>
29118
29119-/* use generic hash table */
29120-#define MY_TAB_SIZE 16
29121-#define MY_TAB_MASK 15
29122-
29123-static u32 idx_gen;
29124-static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE];
29125+#define GACT_TAB_MASK 15
29126+static struct tcf_common *tcf_gact_ht[GACT_TAB_MASK + 1];
29127+static u32 gact_idx_gen;
29128 static DEFINE_RWLOCK(gact_lock);
29129
29130-/* ovewrride the defaults */
29131-#define tcf_st tcf_gact
29132-#define tc_st tc_gact
29133-#define tcf_t_lock gact_lock
29134-#define tcf_ht tcf_gact_ht
29135-
29136-#define CONFIG_NET_ACT_INIT 1
29137-#include <net/pkt_act.h>
29138+static struct tcf_hashinfo gact_hash_info = {
29139+ .htab = tcf_gact_ht,
29140+ .hmask = GACT_TAB_MASK,
29141+ .lock = &gact_lock,
29142+};
29143
29144 #ifdef CONFIG_GACT_PROB
29145-static int gact_net_rand(struct tcf_gact *p)
29146+static int gact_net_rand(struct tcf_gact *gact)
29147 {
29148- if (net_random()%p->pval)
29149- return p->action;
29150- return p->paction;
29151+ if (net_random() % gact->tcfg_pval)
29152+ return gact->tcf_action;
29153+ return gact->tcfg_paction;
29154 }
29155
29156-static int gact_determ(struct tcf_gact *p)
29157+static int gact_determ(struct tcf_gact *gact)
29158 {
29159- if (p->bstats.packets%p->pval)
29160- return p->action;
29161- return p->paction;
29162+ if (gact->tcf_bstats.packets % gact->tcfg_pval)
29163+ return gact->tcf_action;
29164+ return gact->tcfg_paction;
29165 }
29166
29167-typedef int (*g_rand)(struct tcf_gact *p);
29168+typedef int (*g_rand)(struct tcf_gact *gact);
29169 static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ };
29170-#endif
29171+#endif /* CONFIG_GACT_PROB */
29172
29173 static int tcf_gact_init(struct rtattr *rta, struct rtattr *est,
29174 struct tc_action *a, int ovr, int bind)
29175 {
29176 struct rtattr *tb[TCA_GACT_MAX];
29177 struct tc_gact *parm;
29178- struct tcf_gact *p;
29179+ struct tcf_gact *gact;
29180+ struct tcf_common *pc;
29181 int ret = 0;
29182
29183 if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0)
29184@@ -94,105 +89,106 @@
29185 return -EOPNOTSUPP;
29186 #endif
29187
29188- p = tcf_hash_check(parm->index, a, ovr, bind);
29189- if (p == NULL) {
29190- p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
29191- if (p == NULL)
29192+ pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info);
29193+ if (!pc) {
29194+ pc = tcf_hash_create(parm->index, est, a, sizeof(*gact),
29195+ bind, &gact_idx_gen, &gact_hash_info);
29196+ if (unlikely(!pc))
29197 return -ENOMEM;
29198 ret = ACT_P_CREATED;
29199 } else {
29200 if (!ovr) {
29201- tcf_hash_release(p, bind);
29202+ tcf_hash_release(pc, bind, &gact_hash_info);
29203 return -EEXIST;
29204 }
29205 }
29206
29207- spin_lock_bh(&p->lock);
29208- p->action = parm->action;
29209+ gact = to_gact(pc);
29210+
29211+ spin_lock_bh(&gact->tcf_lock);
29212+ gact->tcf_action = parm->action;
29213 #ifdef CONFIG_GACT_PROB
29214 if (tb[TCA_GACT_PROB-1] != NULL) {
29215 struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]);
29216- p->paction = p_parm->paction;
29217- p->pval = p_parm->pval;
29218- p->ptype = p_parm->ptype;
29219+ gact->tcfg_paction = p_parm->paction;
29220+ gact->tcfg_pval = p_parm->pval;
29221+ gact->tcfg_ptype = p_parm->ptype;
29222 }
29223 #endif
29224- spin_unlock_bh(&p->lock);
29225+ spin_unlock_bh(&gact->tcf_lock);
29226 if (ret == ACT_P_CREATED)
29227- tcf_hash_insert(p);
29228+ tcf_hash_insert(pc, &gact_hash_info);
29229 return ret;
29230 }
29231
29232-static int
29233-tcf_gact_cleanup(struct tc_action *a, int bind)
29234+static int tcf_gact_cleanup(struct tc_action *a, int bind)
29235 {
29236- struct tcf_gact *p = PRIV(a, gact);
29237+ struct tcf_gact *gact = a->priv;
29238
29239- if (p != NULL)
29240- return tcf_hash_release(p, bind);
29241+ if (gact)
29242+ return tcf_hash_release(&gact->common, bind, &gact_hash_info);
29243 return 0;
29244 }
29245
29246-static int
29247-tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
29248+static int tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
29249 {
29250- struct tcf_gact *p = PRIV(a, gact);
29251+ struct tcf_gact *gact = a->priv;
29252 int action = TC_ACT_SHOT;
29253
29254- spin_lock(&p->lock);
29255+ spin_lock(&gact->tcf_lock);
29256 #ifdef CONFIG_GACT_PROB
29257- if (p->ptype && gact_rand[p->ptype] != NULL)
29258- action = gact_rand[p->ptype](p);
29259+ if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL)
29260+ action = gact_rand[gact->tcfg_ptype](gact);
29261 else
29262- action = p->action;
29263+ action = gact->tcf_action;
29264 #else
29265- action = p->action;
29266+ action = gact->tcf_action;
29267 #endif
29268- p->bstats.bytes += skb->len;
29269- p->bstats.packets++;
29270+ gact->tcf_bstats.bytes += skb->len;
29271+ gact->tcf_bstats.packets++;
29272 if (action == TC_ACT_SHOT)
29273- p->qstats.drops++;
29274- p->tm.lastuse = jiffies;
29275- spin_unlock(&p->lock);
29276+ gact->tcf_qstats.drops++;
29277+ gact->tcf_tm.lastuse = jiffies;
29278+ spin_unlock(&gact->tcf_lock);
29279
29280 return action;
29281 }
29282
29283-static int
29284-tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
29285+static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
29286 {
29287 unsigned char *b = skb->tail;
29288 struct tc_gact opt;
29289- struct tcf_gact *p = PRIV(a, gact);
29290+ struct tcf_gact *gact = a->priv;
29291 struct tcf_t t;
29292
29293- opt.index = p->index;
29294- opt.refcnt = p->refcnt - ref;
29295- opt.bindcnt = p->bindcnt - bind;
29296- opt.action = p->action;
29297+ opt.index = gact->tcf_index;
29298+ opt.refcnt = gact->tcf_refcnt - ref;
29299+ opt.bindcnt = gact->tcf_bindcnt - bind;
29300+ opt.action = gact->tcf_action;
29301 RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt);
29302 #ifdef CONFIG_GACT_PROB
29303- if (p->ptype) {
29304+ if (gact->tcfg_ptype) {
29305 struct tc_gact_p p_opt;
29306- p_opt.paction = p->paction;
29307- p_opt.pval = p->pval;
29308- p_opt.ptype = p->ptype;
29309+ p_opt.paction = gact->tcfg_paction;
29310+ p_opt.pval = gact->tcfg_pval;
29311+ p_opt.ptype = gact->tcfg_ptype;
29312 RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt);
29313 }
29314 #endif
29315- t.install = jiffies_to_clock_t(jiffies - p->tm.install);
29316- t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
29317- t.expires = jiffies_to_clock_t(p->tm.expires);
29318+ t.install = jiffies_to_clock_t(jiffies - gact->tcf_tm.install);
29319+ t.lastuse = jiffies_to_clock_t(jiffies - gact->tcf_tm.lastuse);
29320+ t.expires = jiffies_to_clock_t(gact->tcf_tm.expires);
29321 RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t);
29322 return skb->len;
29323
29324- rtattr_failure:
29325+rtattr_failure:
29326 skb_trim(skb, b - skb->data);
29327 return -1;
29328 }
29329
29330 static struct tc_action_ops act_gact_ops = {
29331 .kind = "gact",
29332+ .hinfo = &gact_hash_info,
29333 .type = TCA_ACT_GACT,
29334 .capab = TCA_CAP_NONE,
29335 .owner = THIS_MODULE,
29336@@ -208,8 +204,7 @@
29337 MODULE_DESCRIPTION("Generic Classifier actions");
29338 MODULE_LICENSE("GPL");
29339
29340-static int __init
29341-gact_init_module(void)
29342+static int __init gact_init_module(void)
29343 {
29344 #ifdef CONFIG_GACT_PROB
29345 printk("GACT probability on\n");
29346@@ -219,8 +214,7 @@
29347 return tcf_register_action(&act_gact_ops);
29348 }
29349
29350-static void __exit
29351-gact_cleanup_module(void)
29352+static void __exit gact_cleanup_module(void)
29353 {
29354 tcf_unregister_action(&act_gact_ops);
29355 }
29356diff -Nur linux-2.6.18-rc5/net/sched/act_ipt.c linux-2.6.19/net/sched/act_ipt.c
29357--- linux-2.6.18-rc5/net/sched/act_ipt.c 2006-08-28 05:41:48.000000000 +0200
29358+++ linux-2.6.19/net/sched/act_ipt.c 2006-09-22 10:04:59.000000000 +0200
29359@@ -38,25 +38,19 @@
29360
29361 #include <linux/netfilter_ipv4/ip_tables.h>
29362
29363-/* use generic hash table */
29364-#define MY_TAB_SIZE 16
29365-#define MY_TAB_MASK 15
29366-
29367-static u32 idx_gen;
29368-static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE];
29369-/* ipt hash table lock */
29370-static DEFINE_RWLOCK(ipt_lock);
29371
29372-/* ovewrride the defaults */
29373-#define tcf_st tcf_ipt
29374-#define tcf_t_lock ipt_lock
29375-#define tcf_ht tcf_ipt_ht
29376+#define IPT_TAB_MASK 15
29377+static struct tcf_common *tcf_ipt_ht[IPT_TAB_MASK + 1];
29378+static u32 ipt_idx_gen;
29379+static DEFINE_RWLOCK(ipt_lock);
29380
29381-#define CONFIG_NET_ACT_INIT
29382-#include <net/pkt_act.h>
29383+static struct tcf_hashinfo ipt_hash_info = {
29384+ .htab = tcf_ipt_ht,
29385+ .hmask = IPT_TAB_MASK,
29386+ .lock = &ipt_lock,
29387+};
29388
29389-static int
29390-ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
29391+static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
29392 {
29393 struct ipt_target *target;
29394 int ret = 0;
29395@@ -65,7 +59,6 @@
29396 if (!target)
29397 return -ENOENT;
29398
29399- DPRINTK("ipt_init_target: found %s\n", target->name);
29400 t->u.kernel.target = target;
29401
29402 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
29403@@ -76,10 +69,7 @@
29404 if (t->u.kernel.target->checkentry
29405 && !t->u.kernel.target->checkentry(table, NULL,
29406 t->u.kernel.target, t->data,
29407- t->u.target_size - sizeof(*t),
29408 hook)) {
29409- DPRINTK("ipt_init_target: check failed for `%s'.\n",
29410- t->u.kernel.target->name);
29411 module_put(t->u.kernel.target->me);
29412 ret = -EINVAL;
29413 }
29414@@ -87,40 +77,37 @@
29415 return ret;
29416 }
29417
29418-static void
29419-ipt_destroy_target(struct ipt_entry_target *t)
29420+static void ipt_destroy_target(struct ipt_entry_target *t)
29421 {
29422 if (t->u.kernel.target->destroy)
29423- t->u.kernel.target->destroy(t->u.kernel.target, t->data,
29424- t->u.target_size - sizeof(*t));
29425+ t->u.kernel.target->destroy(t->u.kernel.target, t->data);
29426 module_put(t->u.kernel.target->me);
29427 }
29428
29429-static int
29430-tcf_ipt_release(struct tcf_ipt *p, int bind)
29431+static int tcf_ipt_release(struct tcf_ipt *ipt, int bind)
29432 {
29433 int ret = 0;
29434- if (p) {
29435+ if (ipt) {
29436 if (bind)
29437- p->bindcnt--;
29438- p->refcnt--;
29439- if (p->bindcnt <= 0 && p->refcnt <= 0) {
29440- ipt_destroy_target(p->t);
29441- kfree(p->tname);
29442- kfree(p->t);
29443- tcf_hash_destroy(p);
29444+ ipt->tcf_bindcnt--;
29445+ ipt->tcf_refcnt--;
29446+ if (ipt->tcf_bindcnt <= 0 && ipt->tcf_refcnt <= 0) {
29447+ ipt_destroy_target(ipt->tcfi_t);
29448+ kfree(ipt->tcfi_tname);
29449+ kfree(ipt->tcfi_t);
29450+ tcf_hash_destroy(&ipt->common, &ipt_hash_info);
29451 ret = ACT_P_DELETED;
29452 }
29453 }
29454 return ret;
29455 }
29456
29457-static int
29458-tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
29459- int ovr, int bind)
29460+static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est,
29461+ struct tc_action *a, int ovr, int bind)
29462 {
29463 struct rtattr *tb[TCA_IPT_MAX];
29464- struct tcf_ipt *p;
29465+ struct tcf_ipt *ipt;
29466+ struct tcf_common *pc;
29467 struct ipt_entry_target *td, *t;
29468 char *tname;
29469 int ret = 0, err;
29470@@ -144,49 +131,51 @@
29471 RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32))
29472 index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]);
29473
29474- p = tcf_hash_check(index, a, ovr, bind);
29475- if (p == NULL) {
29476- p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind);
29477- if (p == NULL)
29478+ pc = tcf_hash_check(index, a, bind, &ipt_hash_info);
29479+ if (!pc) {
29480+ pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind,
29481+ &ipt_idx_gen, &ipt_hash_info);
29482+ if (unlikely(!pc))
29483 return -ENOMEM;
29484 ret = ACT_P_CREATED;
29485 } else {
29486 if (!ovr) {
29487- tcf_ipt_release(p, bind);
29488+ tcf_ipt_release(to_ipt(pc), bind);
29489 return -EEXIST;
29490 }
29491 }
29492+ ipt = to_ipt(pc);
29493
29494 hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]);
29495
29496 err = -ENOMEM;
29497 tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
29498- if (tname == NULL)
29499+ if (unlikely(!tname))
29500 goto err1;
29501 if (tb[TCA_IPT_TABLE - 1] == NULL ||
29502 rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ)
29503 strcpy(tname, "mangle");
29504
29505 t = kmalloc(td->u.target_size, GFP_KERNEL);
29506- if (t == NULL)
29507+ if (unlikely(!t))
29508 goto err2;
29509 memcpy(t, td, td->u.target_size);
29510
29511 if ((err = ipt_init_target(t, tname, hook)) < 0)
29512 goto err3;
29513
29514- spin_lock_bh(&p->lock);
29515+ spin_lock_bh(&ipt->tcf_lock);
29516 if (ret != ACT_P_CREATED) {
29517- ipt_destroy_target(p->t);
29518- kfree(p->tname);
29519- kfree(p->t);
29520+ ipt_destroy_target(ipt->tcfi_t);
29521+ kfree(ipt->tcfi_tname);
29522+ kfree(ipt->tcfi_t);
29523 }
29524- p->tname = tname;
29525- p->t = t;
29526- p->hook = hook;
29527- spin_unlock_bh(&p->lock);
29528+ ipt->tcfi_tname = tname;
29529+ ipt->tcfi_t = t;
29530+ ipt->tcfi_hook = hook;
29531+ spin_unlock_bh(&ipt->tcf_lock);
29532 if (ret == ACT_P_CREATED)
29533- tcf_hash_insert(p);
29534+ tcf_hash_insert(pc, &ipt_hash_info);
29535 return ret;
29536
29537 err3:
29538@@ -194,33 +183,32 @@
29539 err2:
29540 kfree(tname);
29541 err1:
29542- kfree(p);
29543+ kfree(pc);
29544 return err;
29545 }
29546
29547-static int
29548-tcf_ipt_cleanup(struct tc_action *a, int bind)
29549+static int tcf_ipt_cleanup(struct tc_action *a, int bind)
29550 {
29551- struct tcf_ipt *p = PRIV(a, ipt);
29552- return tcf_ipt_release(p, bind);
29553+ struct tcf_ipt *ipt = a->priv;
29554+ return tcf_ipt_release(ipt, bind);
29555 }
29556
29557-static int
29558-tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
29559+static int tcf_ipt(struct sk_buff *skb, struct tc_action *a,
29560+ struct tcf_result *res)
29561 {
29562 int ret = 0, result = 0;
29563- struct tcf_ipt *p = PRIV(a, ipt);
29564+ struct tcf_ipt *ipt = a->priv;
29565
29566 if (skb_cloned(skb)) {
29567 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
29568 return TC_ACT_UNSPEC;
29569 }
29570
29571- spin_lock(&p->lock);
29572+ spin_lock(&ipt->tcf_lock);
29573
29574- p->tm.lastuse = jiffies;
29575- p->bstats.bytes += skb->len;
29576- p->bstats.packets++;
29577+ ipt->tcf_tm.lastuse = jiffies;
29578+ ipt->tcf_bstats.bytes += skb->len;
29579+ ipt->tcf_bstats.packets++;
29580
29581 /* yes, we have to worry about both in and out dev
29582 worry later - danger - this API seems to have changed
29583@@ -229,16 +217,17 @@
29584 /* iptables targets take a double skb pointer in case the skb
29585 * needs to be replaced. We don't own the skb, so this must not
29586 * happen. The pskb_expand_head above should make sure of this */
29587- ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, p->hook,
29588- p->t->u.kernel.target, p->t->data,
29589- NULL);
29590+ ret = ipt->tcfi_t->u.kernel.target->target(&skb, skb->dev, NULL,
29591+ ipt->tcfi_hook,
29592+ ipt->tcfi_t->u.kernel.target,
29593+ ipt->tcfi_t->data);
29594 switch (ret) {
29595 case NF_ACCEPT:
29596 result = TC_ACT_OK;
29597 break;
29598 case NF_DROP:
29599 result = TC_ACT_SHOT;
29600- p->qstats.drops++;
29601+ ipt->tcf_qstats.drops++;
29602 break;
29603 case IPT_CONTINUE:
29604 result = TC_ACT_PIPE;
29605@@ -249,53 +238,46 @@
29606 result = TC_POLICE_OK;
29607 break;
29608 }
29609- spin_unlock(&p->lock);
29610+ spin_unlock(&ipt->tcf_lock);
29611 return result;
29612
29613 }
29614
29615-static int
29616-tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
29617+static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
29618 {
29619+ unsigned char *b = skb->tail;
29620+ struct tcf_ipt *ipt = a->priv;
29621 struct ipt_entry_target *t;
29622 struct tcf_t tm;
29623 struct tc_cnt c;
29624- unsigned char *b = skb->tail;
29625- struct tcf_ipt *p = PRIV(a, ipt);
29626
29627 /* for simple targets kernel size == user size
29628 ** user name = target name
29629 ** for foolproof you need to not assume this
29630 */
29631
29632- t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC);
29633- if (t == NULL)
29634+ t = kmalloc(ipt->tcfi_t->u.user.target_size, GFP_ATOMIC);
29635+ if (unlikely(!t))
29636 goto rtattr_failure;
29637
29638- c.bindcnt = p->bindcnt - bind;
29639- c.refcnt = p->refcnt - ref;
29640- memcpy(t, p->t, p->t->u.user.target_size);
29641- strcpy(t->u.user.name, p->t->u.kernel.target->name);
29642-
29643- DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname,
29644- strlen(p->tname));
29645- DPRINTK("\tdump target name %s size %d size user %d "
29646- "data[0] %x data[1] %x\n", p->t->u.kernel.target->name,
29647- p->t->u.target_size, p->t->u.user.target_size,
29648- p->t->data[0], p->t->data[1]);
29649- RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t);
29650- RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index);
29651- RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook);
29652+ c.bindcnt = ipt->tcf_bindcnt - bind;
29653+ c.refcnt = ipt->tcf_refcnt - ref;
29654+ memcpy(t, ipt->tcfi_t, ipt->tcfi_t->u.user.target_size);
29655+ strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name);
29656+
29657+ RTA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t);
29658+ RTA_PUT(skb, TCA_IPT_INDEX, 4, &ipt->tcf_index);
29659+ RTA_PUT(skb, TCA_IPT_HOOK, 4, &ipt->tcfi_hook);
29660 RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c);
29661- RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, p->tname);
29662- tm.install = jiffies_to_clock_t(jiffies - p->tm.install);
29663- tm.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
29664- tm.expires = jiffies_to_clock_t(p->tm.expires);
29665+ RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, ipt->tcfi_tname);
29666+ tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install);
29667+ tm.lastuse = jiffies_to_clock_t(jiffies - ipt->tcf_tm.lastuse);
29668+ tm.expires = jiffies_to_clock_t(ipt->tcf_tm.expires);
29669 RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm);
29670 kfree(t);
29671 return skb->len;
29672
29673- rtattr_failure:
29674+rtattr_failure:
29675 skb_trim(skb, b - skb->data);
29676 kfree(t);
29677 return -1;
29678@@ -303,6 +285,7 @@
29679
29680 static struct tc_action_ops act_ipt_ops = {
29681 .kind = "ipt",
29682+ .hinfo = &ipt_hash_info,
29683 .type = TCA_ACT_IPT,
29684 .capab = TCA_CAP_NONE,
29685 .owner = THIS_MODULE,
29686@@ -318,14 +301,12 @@
29687 MODULE_DESCRIPTION("Iptables target actions");
29688 MODULE_LICENSE("GPL");
29689
29690-static int __init
29691-ipt_init_module(void)
29692+static int __init ipt_init_module(void)
29693 {
29694 return tcf_register_action(&act_ipt_ops);
29695 }
29696
29697-static void __exit
29698-ipt_cleanup_module(void)
29699+static void __exit ipt_cleanup_module(void)
29700 {
29701 tcf_unregister_action(&act_ipt_ops);
29702 }
29703diff -Nur linux-2.6.18-rc5/net/sched/act_mirred.c linux-2.6.19/net/sched/act_mirred.c
29704--- linux-2.6.18-rc5/net/sched/act_mirred.c 2006-08-28 05:41:48.000000000 +0200
29705+++ linux-2.6.19/net/sched/act_mirred.c 2006-09-22 10:04:59.000000000 +0200
29706@@ -39,46 +39,39 @@
29707 #include <linux/etherdevice.h>
29708 #include <linux/if_arp.h>
29709
29710-
29711-/* use generic hash table */
29712-#define MY_TAB_SIZE 8
29713-#define MY_TAB_MASK (MY_TAB_SIZE - 1)
29714-static u32 idx_gen;
29715-static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE];
29716+#define MIRRED_TAB_MASK 7
29717+static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1];
29718+static u32 mirred_idx_gen;
29719 static DEFINE_RWLOCK(mirred_lock);
29720
29721-/* ovewrride the defaults */
29722-#define tcf_st tcf_mirred
29723-#define tc_st tc_mirred
29724-#define tcf_t_lock mirred_lock
29725-#define tcf_ht tcf_mirred_ht
29726-
29727-#define CONFIG_NET_ACT_INIT 1
29728-#include <net/pkt_act.h>
29729+static struct tcf_hashinfo mirred_hash_info = {
29730+ .htab = tcf_mirred_ht,
29731+ .hmask = MIRRED_TAB_MASK,
29732+ .lock = &mirred_lock,
29733+};
29734
29735-static inline int
29736-tcf_mirred_release(struct tcf_mirred *p, int bind)
29737+static inline int tcf_mirred_release(struct tcf_mirred *m, int bind)
29738 {
29739- if (p) {
29740+ if (m) {
29741 if (bind)
29742- p->bindcnt--;
29743- p->refcnt--;
29744- if(!p->bindcnt && p->refcnt <= 0) {
29745- dev_put(p->dev);
29746- tcf_hash_destroy(p);
29747+ m->tcf_bindcnt--;
29748+ m->tcf_refcnt--;
29749+ if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
29750+ dev_put(m->tcfm_dev);
29751+ tcf_hash_destroy(&m->common, &mirred_hash_info);
29752 return 1;
29753 }
29754 }
29755 return 0;
29756 }
29757
29758-static int
29759-tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
29760- int ovr, int bind)
29761+static int tcf_mirred_init(struct rtattr *rta, struct rtattr *est,
29762+ struct tc_action *a, int ovr, int bind)
29763 {
29764 struct rtattr *tb[TCA_MIRRED_MAX];
29765 struct tc_mirred *parm;
29766- struct tcf_mirred *p;
29767+ struct tcf_mirred *m;
29768+ struct tcf_common *pc;
29769 struct net_device *dev = NULL;
29770 int ret = 0;
29771 int ok_push = 0;
29772@@ -110,64 +103,62 @@
29773 }
29774 }
29775
29776- p = tcf_hash_check(parm->index, a, ovr, bind);
29777- if (p == NULL) {
29778+ pc = tcf_hash_check(parm->index, a, bind, &mirred_hash_info);
29779+ if (!pc) {
29780 if (!parm->ifindex)
29781 return -EINVAL;
29782- p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
29783- if (p == NULL)
29784+ pc = tcf_hash_create(parm->index, est, a, sizeof(*m), bind,
29785+ &mirred_idx_gen, &mirred_hash_info);
29786+ if (unlikely(!pc))
29787 return -ENOMEM;
29788 ret = ACT_P_CREATED;
29789 } else {
29790 if (!ovr) {
29791- tcf_mirred_release(p, bind);
29792+ tcf_mirred_release(to_mirred(pc), bind);
29793 return -EEXIST;
29794 }
29795 }
29796+ m = to_mirred(pc);
29797
29798- spin_lock_bh(&p->lock);
29799- p->action = parm->action;
29800- p->eaction = parm->eaction;
29801+ spin_lock_bh(&m->tcf_lock);
29802+ m->tcf_action = parm->action;
29803+ m->tcfm_eaction = parm->eaction;
29804 if (parm->ifindex) {
29805- p->ifindex = parm->ifindex;
29806+ m->tcfm_ifindex = parm->ifindex;
29807 if (ret != ACT_P_CREATED)
29808- dev_put(p->dev);
29809- p->dev = dev;
29810+ dev_put(m->tcfm_dev);
29811+ m->tcfm_dev = dev;
29812 dev_hold(dev);
29813- p->ok_push = ok_push;
29814+ m->tcfm_ok_push = ok_push;
29815 }
29816- spin_unlock_bh(&p->lock);
29817+ spin_unlock_bh(&m->tcf_lock);
29818 if (ret == ACT_P_CREATED)
29819- tcf_hash_insert(p);
29820+ tcf_hash_insert(pc, &mirred_hash_info);
29821
29822- DPRINTK("tcf_mirred_init index %d action %d eaction %d device %s "
29823- "ifindex %d\n", parm->index, parm->action, parm->eaction,
29824- dev->name, parm->ifindex);
29825 return ret;
29826 }
29827
29828-static int
29829-tcf_mirred_cleanup(struct tc_action *a, int bind)
29830+static int tcf_mirred_cleanup(struct tc_action *a, int bind)
29831 {
29832- struct tcf_mirred *p = PRIV(a, mirred);
29833+ struct tcf_mirred *m = a->priv;
29834
29835- if (p != NULL)
29836- return tcf_mirred_release(p, bind);
29837+ if (m)
29838+ return tcf_mirred_release(m, bind);
29839 return 0;
29840 }
29841
29842-static int
29843-tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
29844+static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
29845+ struct tcf_result *res)
29846 {
29847- struct tcf_mirred *p = PRIV(a, mirred);
29848+ struct tcf_mirred *m = a->priv;
29849 struct net_device *dev;
29850 struct sk_buff *skb2 = NULL;
29851 u32 at = G_TC_AT(skb->tc_verd);
29852
29853- spin_lock(&p->lock);
29854+ spin_lock(&m->tcf_lock);
29855
29856- dev = p->dev;
29857- p->tm.lastuse = jiffies;
29858+ dev = m->tcfm_dev;
29859+ m->tcf_tm.lastuse = jiffies;
29860
29861 if (!(dev->flags&IFF_UP) ) {
29862 if (net_ratelimit())
29863@@ -176,10 +167,10 @@
29864 bad_mirred:
29865 if (skb2 != NULL)
29866 kfree_skb(skb2);
29867- p->qstats.overlimits++;
29868- p->bstats.bytes += skb->len;
29869- p->bstats.packets++;
29870- spin_unlock(&p->lock);
29871+ m->tcf_qstats.overlimits++;
29872+ m->tcf_bstats.bytes += skb->len;
29873+ m->tcf_bstats.packets++;
29874+ spin_unlock(&m->tcf_lock);
29875 /* should we be asking for packet to be dropped?
29876 * may make sense for redirect case only
29877 */
29878@@ -189,59 +180,59 @@
29879 skb2 = skb_clone(skb, GFP_ATOMIC);
29880 if (skb2 == NULL)
29881 goto bad_mirred;
29882- if (p->eaction != TCA_EGRESS_MIRROR && p->eaction != TCA_EGRESS_REDIR) {
29883+ if (m->tcfm_eaction != TCA_EGRESS_MIRROR &&
29884+ m->tcfm_eaction != TCA_EGRESS_REDIR) {
29885 if (net_ratelimit())
29886- printk("tcf_mirred unknown action %d\n", p->eaction);
29887+ printk("tcf_mirred unknown action %d\n",
29888+ m->tcfm_eaction);
29889 goto bad_mirred;
29890 }
29891
29892- p->bstats.bytes += skb2->len;
29893- p->bstats.packets++;
29894+ m->tcf_bstats.bytes += skb2->len;
29895+ m->tcf_bstats.packets++;
29896 if (!(at & AT_EGRESS))
29897- if (p->ok_push)
29898+ if (m->tcfm_ok_push)
29899 skb_push(skb2, skb2->dev->hard_header_len);
29900
29901 /* mirror is always swallowed */
29902- if (p->eaction != TCA_EGRESS_MIRROR)
29903+ if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
29904 skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
29905
29906 skb2->dev = dev;
29907 skb2->input_dev = skb->dev;
29908 dev_queue_xmit(skb2);
29909- spin_unlock(&p->lock);
29910- return p->action;
29911+ spin_unlock(&m->tcf_lock);
29912+ return m->tcf_action;
29913 }
29914
29915-static int
29916-tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
29917+static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
29918 {
29919 unsigned char *b = skb->tail;
29920+ struct tcf_mirred *m = a->priv;
29921 struct tc_mirred opt;
29922- struct tcf_mirred *p = PRIV(a, mirred);
29923 struct tcf_t t;
29924
29925- opt.index = p->index;
29926- opt.action = p->action;
29927- opt.refcnt = p->refcnt - ref;
29928- opt.bindcnt = p->bindcnt - bind;
29929- opt.eaction = p->eaction;
29930- opt.ifindex = p->ifindex;
29931- DPRINTK("tcf_mirred_dump index %d action %d eaction %d ifindex %d\n",
29932- p->index, p->action, p->eaction, p->ifindex);
29933+ opt.index = m->tcf_index;
29934+ opt.action = m->tcf_action;
29935+ opt.refcnt = m->tcf_refcnt - ref;
29936+ opt.bindcnt = m->tcf_bindcnt - bind;
29937+ opt.eaction = m->tcfm_eaction;
29938+ opt.ifindex = m->tcfm_ifindex;
29939 RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt);
29940- t.install = jiffies_to_clock_t(jiffies - p->tm.install);
29941- t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
29942- t.expires = jiffies_to_clock_t(p->tm.expires);
29943+ t.install = jiffies_to_clock_t(jiffies - m->tcf_tm.install);
29944+ t.lastuse = jiffies_to_clock_t(jiffies - m->tcf_tm.lastuse);
29945+ t.expires = jiffies_to_clock_t(m->tcf_tm.expires);
29946 RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t);
29947 return skb->len;
29948
29949- rtattr_failure:
29950+rtattr_failure:
29951 skb_trim(skb, b - skb->data);
29952 return -1;
29953 }
29954
29955 static struct tc_action_ops act_mirred_ops = {
29956 .kind = "mirred",
29957+ .hinfo = &mirred_hash_info,
29958 .type = TCA_ACT_MIRRED,
29959 .capab = TCA_CAP_NONE,
29960 .owner = THIS_MODULE,
29961@@ -257,15 +248,13 @@
29962 MODULE_DESCRIPTION("Device Mirror/redirect actions");
29963 MODULE_LICENSE("GPL");
29964
29965-static int __init
29966-mirred_init_module(void)
29967+static int __init mirred_init_module(void)
29968 {
29969 printk("Mirror/redirect action on\n");
29970 return tcf_register_action(&act_mirred_ops);
29971 }
29972
29973-static void __exit
29974-mirred_cleanup_module(void)
29975+static void __exit mirred_cleanup_module(void)
29976 {
29977 tcf_unregister_action(&act_mirred_ops);
29978 }
29979diff -Nur linux-2.6.18-rc5/net/sched/act_pedit.c linux-2.6.19/net/sched/act_pedit.c
29980--- linux-2.6.18-rc5/net/sched/act_pedit.c 2006-08-28 05:41:48.000000000 +0200
29981+++ linux-2.6.19/net/sched/act_pedit.c 2006-09-22 10:04:59.000000000 +0200
29982@@ -33,32 +33,25 @@
29983 #include <linux/tc_act/tc_pedit.h>
29984 #include <net/tc_act/tc_pedit.h>
29985
29986-
29987-#define PEDIT_DEB 1
29988-
29989-/* use generic hash table */
29990-#define MY_TAB_SIZE 16
29991-#define MY_TAB_MASK 15
29992-static u32 idx_gen;
29993-static struct tcf_pedit *tcf_pedit_ht[MY_TAB_SIZE];
29994+#define PEDIT_TAB_MASK 15
29995+static struct tcf_common *tcf_pedit_ht[PEDIT_TAB_MASK + 1];
29996+static u32 pedit_idx_gen;
29997 static DEFINE_RWLOCK(pedit_lock);
29998
29999-#define tcf_st tcf_pedit
30000-#define tc_st tc_pedit
30001-#define tcf_t_lock pedit_lock
30002-#define tcf_ht tcf_pedit_ht
30003-
30004-#define CONFIG_NET_ACT_INIT 1
30005-#include <net/pkt_act.h>
30006-
30007-static int
30008-tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,
30009- int ovr, int bind)
30010+static struct tcf_hashinfo pedit_hash_info = {
30011+ .htab = tcf_pedit_ht,
30012+ .hmask = PEDIT_TAB_MASK,
30013+ .lock = &pedit_lock,
30014+};
30015+
30016+static int tcf_pedit_init(struct rtattr *rta, struct rtattr *est,
30017+ struct tc_action *a, int ovr, int bind)
30018 {
30019 struct rtattr *tb[TCA_PEDIT_MAX];
30020 struct tc_pedit *parm;
30021 int ret = 0;
30022 struct tcf_pedit *p;
30023+ struct tcf_common *pc;
30024 struct tc_pedit_key *keys = NULL;
30025 int ksize;
30026
30027@@ -73,54 +66,56 @@
30028 if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize)
30029 return -EINVAL;
30030
30031- p = tcf_hash_check(parm->index, a, ovr, bind);
30032- if (p == NULL) {
30033+ pc = tcf_hash_check(parm->index, a, bind, &pedit_hash_info);
30034+ if (!pc) {
30035 if (!parm->nkeys)
30036 return -EINVAL;
30037- p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
30038- if (p == NULL)
30039+ pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
30040+ &pedit_idx_gen, &pedit_hash_info);
30041+ if (unlikely(!pc))
30042 return -ENOMEM;
30043+ p = to_pedit(pc);
30044 keys = kmalloc(ksize, GFP_KERNEL);
30045 if (keys == NULL) {
30046- kfree(p);
30047+ kfree(pc);
30048 return -ENOMEM;
30049 }
30050 ret = ACT_P_CREATED;
30051 } else {
30052+ p = to_pedit(pc);
30053 if (!ovr) {
30054- tcf_hash_release(p, bind);
30055+ tcf_hash_release(pc, bind, &pedit_hash_info);
30056 return -EEXIST;
30057 }
30058- if (p->nkeys && p->nkeys != parm->nkeys) {
30059+ if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
30060 keys = kmalloc(ksize, GFP_KERNEL);
30061 if (keys == NULL)
30062 return -ENOMEM;
30063 }
30064 }
30065
30066- spin_lock_bh(&p->lock);
30067- p->flags = parm->flags;
30068- p->action = parm->action;
30069+ spin_lock_bh(&p->tcf_lock);
30070+ p->tcfp_flags = parm->flags;
30071+ p->tcf_action = parm->action;
30072 if (keys) {
30073- kfree(p->keys);
30074- p->keys = keys;
30075- p->nkeys = parm->nkeys;
30076+ kfree(p->tcfp_keys);
30077+ p->tcfp_keys = keys;
30078+ p->tcfp_nkeys = parm->nkeys;
30079 }
30080- memcpy(p->keys, parm->keys, ksize);
30081- spin_unlock_bh(&p->lock);
30082+ memcpy(p->tcfp_keys, parm->keys, ksize);
30083+ spin_unlock_bh(&p->tcf_lock);
30084 if (ret == ACT_P_CREATED)
30085- tcf_hash_insert(p);
30086+ tcf_hash_insert(pc, &pedit_hash_info);
30087 return ret;
30088 }
30089
30090-static int
30091-tcf_pedit_cleanup(struct tc_action *a, int bind)
30092+static int tcf_pedit_cleanup(struct tc_action *a, int bind)
30093 {
30094- struct tcf_pedit *p = PRIV(a, pedit);
30095+ struct tcf_pedit *p = a->priv;
30096
30097- if (p != NULL) {
30098- struct tc_pedit_key *keys = p->keys;
30099- if (tcf_hash_release(p, bind)) {
30100+ if (p) {
30101+ struct tc_pedit_key *keys = p->tcfp_keys;
30102+ if (tcf_hash_release(&p->common, bind, &pedit_hash_info)) {
30103 kfree(keys);
30104 return 1;
30105 }
30106@@ -128,30 +123,30 @@
30107 return 0;
30108 }
30109
30110-static int
30111-tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
30112+static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
30113+ struct tcf_result *res)
30114 {
30115- struct tcf_pedit *p = PRIV(a, pedit);
30116+ struct tcf_pedit *p = a->priv;
30117 int i, munged = 0;
30118 u8 *pptr;
30119
30120 if (!(skb->tc_verd & TC_OK2MUNGE)) {
30121 /* should we set skb->cloned? */
30122 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
30123- return p->action;
30124+ return p->tcf_action;
30125 }
30126 }
30127
30128 pptr = skb->nh.raw;
30129
30130- spin_lock(&p->lock);
30131+ spin_lock(&p->tcf_lock);
30132
30133- p->tm.lastuse = jiffies;
30134+ p->tcf_tm.lastuse = jiffies;
30135
30136- if (p->nkeys > 0) {
30137- struct tc_pedit_key *tkey = p->keys;
30138+ if (p->tcfp_nkeys > 0) {
30139+ struct tc_pedit_key *tkey = p->tcfp_keys;
30140
30141- for (i = p->nkeys; i > 0; i--, tkey++) {
30142+ for (i = p->tcfp_nkeys; i > 0; i--, tkey++) {
30143 u32 *ptr;
30144 int offset = tkey->off;
30145
30146@@ -169,7 +164,8 @@
30147 printk("offset must be on 32 bit boundaries\n");
30148 goto bad;
30149 }
30150- if (skb->len < 0 || (offset > 0 && offset > skb->len)) {
30151+ if (skb->len < 0 ||
30152+ (offset > 0 && offset > skb->len)) {
30153 printk("offset %d cant exceed pkt length %d\n",
30154 offset, skb->len);
30155 goto bad;
30156@@ -185,63 +181,47 @@
30157 skb->tc_verd = SET_TC_MUNGED(skb->tc_verd);
30158 goto done;
30159 } else {
30160- printk("pedit BUG: index %d\n",p->index);
30161+ printk("pedit BUG: index %d\n", p->tcf_index);
30162 }
30163
30164 bad:
30165- p->qstats.overlimits++;
30166+ p->tcf_qstats.overlimits++;
30167 done:
30168- p->bstats.bytes += skb->len;
30169- p->bstats.packets++;
30170- spin_unlock(&p->lock);
30171- return p->action;
30172+ p->tcf_bstats.bytes += skb->len;
30173+ p->tcf_bstats.packets++;
30174+ spin_unlock(&p->tcf_lock);
30175+ return p->tcf_action;
30176 }
30177
30178-static int
30179-tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
30180+static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
30181+ int bind, int ref)
30182 {
30183 unsigned char *b = skb->tail;
30184+ struct tcf_pedit *p = a->priv;
30185 struct tc_pedit *opt;
30186- struct tcf_pedit *p = PRIV(a, pedit);
30187 struct tcf_t t;
30188 int s;
30189
30190- s = sizeof(*opt) + p->nkeys * sizeof(struct tc_pedit_key);
30191+ s = sizeof(*opt) + p->tcfp_nkeys * sizeof(struct tc_pedit_key);
30192
30193 /* netlink spinlocks held above us - must use ATOMIC */
30194 opt = kzalloc(s, GFP_ATOMIC);
30195- if (opt == NULL)
30196+ if (unlikely(!opt))
30197 return -ENOBUFS;
30198
30199- memcpy(opt->keys, p->keys, p->nkeys * sizeof(struct tc_pedit_key));
30200- opt->index = p->index;
30201- opt->nkeys = p->nkeys;
30202- opt->flags = p->flags;
30203- opt->action = p->action;
30204- opt->refcnt = p->refcnt - ref;
30205- opt->bindcnt = p->bindcnt - bind;
30206-
30207-
30208-#ifdef PEDIT_DEB
30209- {
30210- /* Debug - get rid of later */
30211- int i;
30212- struct tc_pedit_key *key = opt->keys;
30213-
30214- for (i=0; i<opt->nkeys; i++, key++) {
30215- printk( "\n key #%d",i);
30216- printk( " at %d: val %08x mask %08x",
30217- (unsigned int)key->off,
30218- (unsigned int)key->val,
30219- (unsigned int)key->mask);
30220- }
30221- }
30222-#endif
30223+ memcpy(opt->keys, p->tcfp_keys,
30224+ p->tcfp_nkeys * sizeof(struct tc_pedit_key));
30225+ opt->index = p->tcf_index;
30226+ opt->nkeys = p->tcfp_nkeys;
30227+ opt->flags = p->tcfp_flags;
30228+ opt->action = p->tcf_action;
30229+ opt->refcnt = p->tcf_refcnt - ref;
30230+ opt->bindcnt = p->tcf_bindcnt - bind;
30231
30232 RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt);
30233- t.install = jiffies_to_clock_t(jiffies - p->tm.install);
30234- t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
30235- t.expires = jiffies_to_clock_t(p->tm.expires);
30236+ t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install);
30237+ t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse);
30238+ t.expires = jiffies_to_clock_t(p->tcf_tm.expires);
30239 RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t);
30240 kfree(opt);
30241 return skb->len;
30242@@ -252,9 +232,9 @@
30243 return -1;
30244 }
30245
30246-static
30247-struct tc_action_ops act_pedit_ops = {
30248+static struct tc_action_ops act_pedit_ops = {
30249 .kind = "pedit",
30250+ .hinfo = &pedit_hash_info,
30251 .type = TCA_ACT_PEDIT,
30252 .capab = TCA_CAP_NONE,
30253 .owner = THIS_MODULE,
30254@@ -270,14 +250,12 @@
30255 MODULE_DESCRIPTION("Generic Packet Editor actions");
30256 MODULE_LICENSE("GPL");
30257
30258-static int __init
30259-pedit_init_module(void)
30260+static int __init pedit_init_module(void)
30261 {
30262 return tcf_register_action(&act_pedit_ops);
30263 }
30264
30265-static void __exit
30266-pedit_cleanup_module(void)
30267+static void __exit pedit_cleanup_module(void)
30268 {
30269 tcf_unregister_action(&act_pedit_ops);
30270 }
30271diff -Nur linux-2.6.18-rc5/net/sched/act_police.c linux-2.6.19/net/sched/act_police.c
30272--- linux-2.6.18-rc5/net/sched/act_police.c 2006-08-28 05:41:48.000000000 +0200
30273+++ linux-2.6.19/net/sched/act_police.c 2006-09-22 10:04:59.000000000 +0200
30274@@ -32,43 +32,27 @@
30275 #include <net/sock.h>
30276 #include <net/act_api.h>
30277
30278-#define L2T(p,L) ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log])
30279-#define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log])
30280-#define PRIV(a) ((struct tcf_police *) (a)->priv)
30281-
30282-/* use generic hash table */
30283-#define MY_TAB_SIZE 16
30284-#define MY_TAB_MASK 15
30285-static u32 idx_gen;
30286-static struct tcf_police *tcf_police_ht[MY_TAB_SIZE];
30287-/* Policer hash table lock */
30288-static DEFINE_RWLOCK(police_lock);
30289-
30290-/* Each policer is serialized by its individual spinlock */
30291+#define L2T(p,L) ((p)->tcfp_R_tab->data[(L)>>(p)->tcfp_R_tab->rate.cell_log])
30292+#define L2T_P(p,L) ((p)->tcfp_P_tab->data[(L)>>(p)->tcfp_P_tab->rate.cell_log])
30293
30294-static __inline__ unsigned tcf_police_hash(u32 index)
30295-{
30296- return index&0xF;
30297-}
30298+#define POL_TAB_MASK 15
30299+static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1];
30300+static u32 police_idx_gen;
30301+static DEFINE_RWLOCK(police_lock);
30302
30303-static __inline__ struct tcf_police * tcf_police_lookup(u32 index)
30304-{
30305- struct tcf_police *p;
30306+static struct tcf_hashinfo police_hash_info = {
30307+ .htab = tcf_police_ht,
30308+ .hmask = POL_TAB_MASK,
30309+ .lock = &police_lock,
30310+};
30311
30312- read_lock(&police_lock);
30313- for (p = tcf_police_ht[tcf_police_hash(index)]; p; p = p->next) {
30314- if (p->index == index)
30315- break;
30316- }
30317- read_unlock(&police_lock);
30318- return p;
30319-}
30320+/* Each policer is serialized by its individual spinlock */
30321
30322 #ifdef CONFIG_NET_CLS_ACT
30323 static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
30324 int type, struct tc_action *a)
30325 {
30326- struct tcf_police *p;
30327+ struct tcf_common *p;
30328 int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
30329 struct rtattr *r;
30330
30331@@ -76,10 +60,10 @@
30332
30333 s_i = cb->args[0];
30334
30335- for (i = 0; i < MY_TAB_SIZE; i++) {
30336- p = tcf_police_ht[tcf_police_hash(i)];
30337+ for (i = 0; i < (POL_TAB_MASK + 1); i++) {
30338+ p = tcf_police_ht[tcf_hash(i, POL_TAB_MASK)];
30339
30340- for (; p; p = p->next) {
30341+ for (; p; p = p->tcfc_next) {
30342 index++;
30343 if (index < s_i)
30344 continue;
30345@@ -110,48 +94,26 @@
30346 skb_trim(skb, (u8*)r - skb->data);
30347 goto done;
30348 }
30349-
30350-static inline int
30351-tcf_act_police_hash_search(struct tc_action *a, u32 index)
30352-{
30353- struct tcf_police *p = tcf_police_lookup(index);
30354-
30355- if (p != NULL) {
30356- a->priv = p;
30357- return 1;
30358- } else {
30359- return 0;
30360- }
30361-}
30362 #endif
30363
30364-static inline u32 tcf_police_new_index(void)
30365-{
30366- do {
30367- if (++idx_gen == 0)
30368- idx_gen = 1;
30369- } while (tcf_police_lookup(idx_gen));
30370-
30371- return idx_gen;
30372-}
30373-
30374 void tcf_police_destroy(struct tcf_police *p)
30375 {
30376- unsigned h = tcf_police_hash(p->index);
30377- struct tcf_police **p1p;
30378+ unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
30379+ struct tcf_common **p1p;
30380
30381- for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) {
30382- if (*p1p == p) {
30383+ for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->tcfc_next) {
30384+ if (*p1p == &p->common) {
30385 write_lock_bh(&police_lock);
30386- *p1p = p->next;
30387+ *p1p = p->tcf_next;
30388 write_unlock_bh(&police_lock);
30389 #ifdef CONFIG_NET_ESTIMATOR
30390- gen_kill_estimator(&p->bstats, &p->rate_est);
30391+ gen_kill_estimator(&p->tcf_bstats,
30392+ &p->tcf_rate_est);
30393 #endif
30394- if (p->R_tab)
30395- qdisc_put_rtab(p->R_tab);
30396- if (p->P_tab)
30397- qdisc_put_rtab(p->P_tab);
30398+ if (p->tcfp_R_tab)
30399+ qdisc_put_rtab(p->tcfp_R_tab);
30400+ if (p->tcfp_P_tab)
30401+ qdisc_put_rtab(p->tcfp_P_tab);
30402 kfree(p);
30403 return;
30404 }
30405@@ -167,7 +129,7 @@
30406 int ret = 0, err;
30407 struct rtattr *tb[TCA_POLICE_MAX];
30408 struct tc_police *parm;
30409- struct tcf_police *p;
30410+ struct tcf_police *police;
30411 struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
30412
30413 if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
30414@@ -185,27 +147,32 @@
30415 RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
30416 return -EINVAL;
30417
30418- if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
30419- a->priv = p;
30420- if (bind) {
30421- p->bindcnt += 1;
30422- p->refcnt += 1;
30423+ if (parm->index) {
30424+ struct tcf_common *pc;
30425+
30426+ pc = tcf_hash_lookup(parm->index, &police_hash_info);
30427+ if (pc != NULL) {
30428+ a->priv = pc;
30429+ police = to_police(pc);
30430+ if (bind) {
30431+ police->tcf_bindcnt += 1;
30432+ police->tcf_refcnt += 1;
30433+ }
30434+ if (ovr)
30435+ goto override;
30436+ return ret;
30437 }
30438- if (ovr)
30439- goto override;
30440- return ret;
30441 }
30442
30443- p = kzalloc(sizeof(*p), GFP_KERNEL);
30444- if (p == NULL)
30445+ police = kzalloc(sizeof(*police), GFP_KERNEL);
30446+ if (police == NULL)
30447 return -ENOMEM;
30448-
30449 ret = ACT_P_CREATED;
30450- p->refcnt = 1;
30451- spin_lock_init(&p->lock);
30452- p->stats_lock = &p->lock;
30453+ police->tcf_refcnt = 1;
30454+ spin_lock_init(&police->tcf_lock);
30455+ police->tcf_stats_lock = &police->tcf_lock;
30456 if (bind)
30457- p->bindcnt = 1;
30458+ police->tcf_bindcnt = 1;
30459 override:
30460 if (parm->rate.rate) {
30461 err = -ENOMEM;
30462@@ -215,67 +182,71 @@
30463 if (parm->peakrate.rate) {
30464 P_tab = qdisc_get_rtab(&parm->peakrate,
30465 tb[TCA_POLICE_PEAKRATE-1]);
30466- if (p->P_tab == NULL) {
30467+ if (P_tab == NULL) {
30468 qdisc_put_rtab(R_tab);
30469 goto failure;
30470 }
30471 }
30472 }
30473 /* No failure allowed after this point */
30474- spin_lock_bh(&p->lock);
30475+ spin_lock_bh(&police->tcf_lock);
30476 if (R_tab != NULL) {
30477- qdisc_put_rtab(p->R_tab);
30478- p->R_tab = R_tab;
30479+ qdisc_put_rtab(police->tcfp_R_tab);
30480+ police->tcfp_R_tab = R_tab;
30481 }
30482 if (P_tab != NULL) {
30483- qdisc_put_rtab(p->P_tab);
30484- p->P_tab = P_tab;
30485+ qdisc_put_rtab(police->tcfp_P_tab);
30486+ police->tcfp_P_tab = P_tab;
30487 }
30488
30489 if (tb[TCA_POLICE_RESULT-1])
30490- p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
30491- p->toks = p->burst = parm->burst;
30492- p->mtu = parm->mtu;
30493- if (p->mtu == 0) {
30494- p->mtu = ~0;
30495- if (p->R_tab)
30496- p->mtu = 255<<p->R_tab->rate.cell_log;
30497- }
30498- if (p->P_tab)
30499- p->ptoks = L2T_P(p, p->mtu);
30500- p->action = parm->action;
30501+ police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
30502+ police->tcfp_toks = police->tcfp_burst = parm->burst;
30503+ police->tcfp_mtu = parm->mtu;
30504+ if (police->tcfp_mtu == 0) {
30505+ police->tcfp_mtu = ~0;
30506+ if (police->tcfp_R_tab)
30507+ police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log;
30508+ }
30509+ if (police->tcfp_P_tab)
30510+ police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
30511+ police->tcf_action = parm->action;
30512
30513 #ifdef CONFIG_NET_ESTIMATOR
30514 if (tb[TCA_POLICE_AVRATE-1])
30515- p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
30516+ police->tcfp_ewma_rate =
30517+ *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
30518 if (est)
30519- gen_replace_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
30520+ gen_replace_estimator(&police->tcf_bstats,
30521+ &police->tcf_rate_est,
30522+ police->tcf_stats_lock, est);
30523 #endif
30524
30525- spin_unlock_bh(&p->lock);
30526+ spin_unlock_bh(&police->tcf_lock);
30527 if (ret != ACT_P_CREATED)
30528 return ret;
30529
30530- PSCHED_GET_TIME(p->t_c);
30531- p->index = parm->index ? : tcf_police_new_index();
30532- h = tcf_police_hash(p->index);
30533+ PSCHED_GET_TIME(police->tcfp_t_c);
30534+ police->tcf_index = parm->index ? parm->index :
30535+ tcf_hash_new_index(&police_idx_gen, &police_hash_info);
30536+ h = tcf_hash(police->tcf_index, POL_TAB_MASK);
30537 write_lock_bh(&police_lock);
30538- p->next = tcf_police_ht[h];
30539- tcf_police_ht[h] = p;
30540+ police->tcf_next = tcf_police_ht[h];
30541+ tcf_police_ht[h] = &police->common;
30542 write_unlock_bh(&police_lock);
30543
30544- a->priv = p;
30545+ a->priv = police;
30546 return ret;
30547
30548 failure:
30549 if (ret == ACT_P_CREATED)
30550- kfree(p);
30551+ kfree(police);
30552 return err;
30553 }
30554
30555 static int tcf_act_police_cleanup(struct tc_action *a, int bind)
30556 {
30557- struct tcf_police *p = PRIV(a);
30558+ struct tcf_police *p = a->priv;
30559
30560 if (p != NULL)
30561 return tcf_police_release(p, bind);
30562@@ -285,86 +256,87 @@
30563 static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
30564 struct tcf_result *res)
30565 {
30566+ struct tcf_police *police = a->priv;
30567 psched_time_t now;
30568- struct tcf_police *p = PRIV(a);
30569 long toks;
30570 long ptoks = 0;
30571
30572- spin_lock(&p->lock);
30573+ spin_lock(&police->tcf_lock);
30574
30575- p->bstats.bytes += skb->len;
30576- p->bstats.packets++;
30577+ police->tcf_bstats.bytes += skb->len;
30578+ police->tcf_bstats.packets++;
30579
30580 #ifdef CONFIG_NET_ESTIMATOR
30581- if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) {
30582- p->qstats.overlimits++;
30583- spin_unlock(&p->lock);
30584- return p->action;
30585+ if (police->tcfp_ewma_rate &&
30586+ police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
30587+ police->tcf_qstats.overlimits++;
30588+ spin_unlock(&police->tcf_lock);
30589+ return police->tcf_action;
30590 }
30591 #endif
30592
30593- if (skb->len <= p->mtu) {
30594- if (p->R_tab == NULL) {
30595- spin_unlock(&p->lock);
30596- return p->result;
30597+ if (skb->len <= police->tcfp_mtu) {
30598+ if (police->tcfp_R_tab == NULL) {
30599+ spin_unlock(&police->tcf_lock);
30600+ return police->tcfp_result;
30601 }
30602
30603 PSCHED_GET_TIME(now);
30604
30605- toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst);
30606-
30607- if (p->P_tab) {
30608- ptoks = toks + p->ptoks;
30609- if (ptoks > (long)L2T_P(p, p->mtu))
30610- ptoks = (long)L2T_P(p, p->mtu);
30611- ptoks -= L2T_P(p, skb->len);
30612- }
30613- toks += p->toks;
30614- if (toks > (long)p->burst)
30615- toks = p->burst;
30616- toks -= L2T(p, skb->len);
30617-
30618+ toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c,
30619+ police->tcfp_burst);
30620+ if (police->tcfp_P_tab) {
30621+ ptoks = toks + police->tcfp_ptoks;
30622+ if (ptoks > (long)L2T_P(police, police->tcfp_mtu))
30623+ ptoks = (long)L2T_P(police, police->tcfp_mtu);
30624+ ptoks -= L2T_P(police, skb->len);
30625+ }
30626+ toks += police->tcfp_toks;
30627+ if (toks > (long)police->tcfp_burst)
30628+ toks = police->tcfp_burst;
30629+ toks -= L2T(police, skb->len);
30630 if ((toks|ptoks) >= 0) {
30631- p->t_c = now;
30632- p->toks = toks;
30633- p->ptoks = ptoks;
30634- spin_unlock(&p->lock);
30635- return p->result;
30636+ police->tcfp_t_c = now;
30637+ police->tcfp_toks = toks;
30638+ police->tcfp_ptoks = ptoks;
30639+ spin_unlock(&police->tcf_lock);
30640+ return police->tcfp_result;
30641 }
30642 }
30643
30644- p->qstats.overlimits++;
30645- spin_unlock(&p->lock);
30646- return p->action;
30647+ police->tcf_qstats.overlimits++;
30648+ spin_unlock(&police->tcf_lock);
30649+ return police->tcf_action;
30650 }
30651
30652 static int
30653 tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
30654 {
30655 unsigned char *b = skb->tail;
30656+ struct tcf_police *police = a->priv;
30657 struct tc_police opt;
30658- struct tcf_police *p = PRIV(a);
30659
30660- opt.index = p->index;
30661- opt.action = p->action;
30662- opt.mtu = p->mtu;
30663- opt.burst = p->burst;
30664- opt.refcnt = p->refcnt - ref;
30665- opt.bindcnt = p->bindcnt - bind;
30666- if (p->R_tab)
30667- opt.rate = p->R_tab->rate;
30668+ opt.index = police->tcf_index;
30669+ opt.action = police->tcf_action;
30670+ opt.mtu = police->tcfp_mtu;
30671+ opt.burst = police->tcfp_burst;
30672+ opt.refcnt = police->tcf_refcnt - ref;
30673+ opt.bindcnt = police->tcf_bindcnt - bind;
30674+ if (police->tcfp_R_tab)
30675+ opt.rate = police->tcfp_R_tab->rate;
30676 else
30677 memset(&opt.rate, 0, sizeof(opt.rate));
30678- if (p->P_tab)
30679- opt.peakrate = p->P_tab->rate;
30680+ if (police->tcfp_P_tab)
30681+ opt.peakrate = police->tcfp_P_tab->rate;
30682 else
30683 memset(&opt.peakrate, 0, sizeof(opt.peakrate));
30684 RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
30685- if (p->result)
30686- RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result);
30687+ if (police->tcfp_result)
30688+ RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
30689+ &police->tcfp_result);
30690 #ifdef CONFIG_NET_ESTIMATOR
30691- if (p->ewma_rate)
30692- RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate);
30693+ if (police->tcfp_ewma_rate)
30694+ RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
30695 #endif
30696 return skb->len;
30697
30698@@ -379,13 +351,14 @@
30699
30700 static struct tc_action_ops act_police_ops = {
30701 .kind = "police",
30702+ .hinfo = &police_hash_info,
30703 .type = TCA_ID_POLICE,
30704 .capab = TCA_CAP_NONE,
30705 .owner = THIS_MODULE,
30706 .act = tcf_act_police,
30707 .dump = tcf_act_police_dump,
30708 .cleanup = tcf_act_police_cleanup,
30709- .lookup = tcf_act_police_hash_search,
30710+ .lookup = tcf_hash_search,
30711 .init = tcf_act_police_locate,
30712 .walk = tcf_act_police_walker
30713 };
30714@@ -407,10 +380,39 @@
30715
30716 #else /* CONFIG_NET_CLS_ACT */
30717
30718-struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
30719+static struct tcf_common *tcf_police_lookup(u32 index)
30720 {
30721- unsigned h;
30722- struct tcf_police *p;
30723+ struct tcf_hashinfo *hinfo = &police_hash_info;
30724+ struct tcf_common *p;
30725+
30726+ read_lock(hinfo->lock);
30727+ for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p;
30728+ p = p->tcfc_next) {
30729+ if (p->tcfc_index == index)
30730+ break;
30731+ }
30732+ read_unlock(hinfo->lock);
30733+
30734+ return p;
30735+}
30736+
30737+static u32 tcf_police_new_index(void)
30738+{
30739+ u32 *idx_gen = &police_idx_gen;
30740+ u32 val = *idx_gen;
30741+
30742+ do {
30743+ if (++val == 0)
30744+ val = 1;
30745+ } while (tcf_police_lookup(val));
30746+
30747+ return (*idx_gen = val);
30748+}
30749+
30750+struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est)
30751+{
30752+ unsigned int h;
30753+ struct tcf_police *police;
30754 struct rtattr *tb[TCA_POLICE_MAX];
30755 struct tc_police *parm;
30756
30757@@ -423,149 +425,158 @@
30758
30759 parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
30760
30761- if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
30762- p->refcnt++;
30763- return p;
30764- }
30765+ if (parm->index) {
30766+ struct tcf_common *pc;
30767
30768- p = kzalloc(sizeof(*p), GFP_KERNEL);
30769- if (p == NULL)
30770+ pc = tcf_police_lookup(parm->index);
30771+ if (pc) {
30772+ police = to_police(pc);
30773+ police->tcf_refcnt++;
30774+ return police;
30775+ }
30776+ }
30777+ police = kzalloc(sizeof(*police), GFP_KERNEL);
30778+ if (unlikely(!police))
30779 return NULL;
30780
30781- p->refcnt = 1;
30782- spin_lock_init(&p->lock);
30783- p->stats_lock = &p->lock;
30784+ police->tcf_refcnt = 1;
30785+ spin_lock_init(&police->tcf_lock);
30786+ police->tcf_stats_lock = &police->tcf_lock;
30787 if (parm->rate.rate) {
30788- p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
30789- if (p->R_tab == NULL)
30790+ police->tcfp_R_tab =
30791+ qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
30792+ if (police->tcfp_R_tab == NULL)
30793 goto failure;
30794 if (parm->peakrate.rate) {
30795- p->P_tab = qdisc_get_rtab(&parm->peakrate,
30796- tb[TCA_POLICE_PEAKRATE-1]);
30797- if (p->P_tab == NULL)
30798+ police->tcfp_P_tab =
30799+ qdisc_get_rtab(&parm->peakrate,
30800+ tb[TCA_POLICE_PEAKRATE-1]);
30801+ if (police->tcfp_P_tab == NULL)
30802 goto failure;
30803 }
30804 }
30805 if (tb[TCA_POLICE_RESULT-1]) {
30806 if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
30807 goto failure;
30808- p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
30809+ police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
30810 }
30811 #ifdef CONFIG_NET_ESTIMATOR
30812 if (tb[TCA_POLICE_AVRATE-1]) {
30813 if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32))
30814 goto failure;
30815- p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
30816+ police->tcfp_ewma_rate =
30817+ *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
30818 }
30819 #endif
30820- p->toks = p->burst = parm->burst;
30821- p->mtu = parm->mtu;
30822- if (p->mtu == 0) {
30823- p->mtu = ~0;
30824- if (p->R_tab)
30825- p->mtu = 255<<p->R_tab->rate.cell_log;
30826- }
30827- if (p->P_tab)
30828- p->ptoks = L2T_P(p, p->mtu);
30829- PSCHED_GET_TIME(p->t_c);
30830- p->index = parm->index ? : tcf_police_new_index();
30831- p->action = parm->action;
30832+ police->tcfp_toks = police->tcfp_burst = parm->burst;
30833+ police->tcfp_mtu = parm->mtu;
30834+ if (police->tcfp_mtu == 0) {
30835+ police->tcfp_mtu = ~0;
30836+ if (police->tcfp_R_tab)
30837+ police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log;
30838+ }
30839+ if (police->tcfp_P_tab)
30840+ police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
30841+ PSCHED_GET_TIME(police->tcfp_t_c);
30842+ police->tcf_index = parm->index ? parm->index :
30843+ tcf_police_new_index();
30844+ police->tcf_action = parm->action;
30845 #ifdef CONFIG_NET_ESTIMATOR
30846 if (est)
30847- gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
30848+ gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est,
30849+ police->tcf_stats_lock, est);
30850 #endif
30851- h = tcf_police_hash(p->index);
30852+ h = tcf_hash(police->tcf_index, POL_TAB_MASK);
30853 write_lock_bh(&police_lock);
30854- p->next = tcf_police_ht[h];
30855- tcf_police_ht[h] = p;
30856+ police->tcf_next = tcf_police_ht[h];
30857+ tcf_police_ht[h] = &police->common;
30858 write_unlock_bh(&police_lock);
30859- return p;
30860+ return police;
30861
30862 failure:
30863- if (p->R_tab)
30864- qdisc_put_rtab(p->R_tab);
30865- kfree(p);
30866+ if (police->tcfp_R_tab)
30867+ qdisc_put_rtab(police->tcfp_R_tab);
30868+ kfree(police);
30869 return NULL;
30870 }
30871
30872-int tcf_police(struct sk_buff *skb, struct tcf_police *p)
30873+int tcf_police(struct sk_buff *skb, struct tcf_police *police)
30874 {
30875 psched_time_t now;
30876 long toks;
30877 long ptoks = 0;
30878
30879- spin_lock(&p->lock);
30880+ spin_lock(&police->tcf_lock);
30881
30882- p->bstats.bytes += skb->len;
30883- p->bstats.packets++;
30884+ police->tcf_bstats.bytes += skb->len;
30885+ police->tcf_bstats.packets++;
30886
30887 #ifdef CONFIG_NET_ESTIMATOR
30888- if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) {
30889- p->qstats.overlimits++;
30890- spin_unlock(&p->lock);
30891- return p->action;
30892+ if (police->tcfp_ewma_rate &&
30893+ police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
30894+ police->tcf_qstats.overlimits++;
30895+ spin_unlock(&police->tcf_lock);
30896+ return police->tcf_action;
30897 }
30898 #endif
30899-
30900- if (skb->len <= p->mtu) {
30901- if (p->R_tab == NULL) {
30902- spin_unlock(&p->lock);
30903- return p->result;
30904+ if (skb->len <= police->tcfp_mtu) {
30905+ if (police->tcfp_R_tab == NULL) {
30906+ spin_unlock(&police->tcf_lock);
30907+ return police->tcfp_result;
30908 }
30909
30910 PSCHED_GET_TIME(now);
30911-
30912- toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst);
30913-
30914- if (p->P_tab) {
30915- ptoks = toks + p->ptoks;
30916- if (ptoks > (long)L2T_P(p, p->mtu))
30917- ptoks = (long)L2T_P(p, p->mtu);
30918- ptoks -= L2T_P(p, skb->len);
30919- }
30920- toks += p->toks;
30921- if (toks > (long)p->burst)
30922- toks = p->burst;
30923- toks -= L2T(p, skb->len);
30924-
30925+ toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c,
30926+ police->tcfp_burst);
30927+ if (police->tcfp_P_tab) {
30928+ ptoks = toks + police->tcfp_ptoks;
30929+ if (ptoks > (long)L2T_P(police, police->tcfp_mtu))
30930+ ptoks = (long)L2T_P(police, police->tcfp_mtu);
30931+ ptoks -= L2T_P(police, skb->len);
30932+ }
30933+ toks += police->tcfp_toks;
30934+ if (toks > (long)police->tcfp_burst)
30935+ toks = police->tcfp_burst;
30936+ toks -= L2T(police, skb->len);
30937 if ((toks|ptoks) >= 0) {
30938- p->t_c = now;
30939- p->toks = toks;
30940- p->ptoks = ptoks;
30941- spin_unlock(&p->lock);
30942- return p->result;
30943+ police->tcfp_t_c = now;
30944+ police->tcfp_toks = toks;
30945+ police->tcfp_ptoks = ptoks;
30946+ spin_unlock(&police->tcf_lock);
30947+ return police->tcfp_result;
30948 }
30949 }
30950
30951- p->qstats.overlimits++;
30952- spin_unlock(&p->lock);
30953- return p->action;
30954+ police->tcf_qstats.overlimits++;
30955+ spin_unlock(&police->tcf_lock);
30956+ return police->tcf_action;
30957 }
30958 EXPORT_SYMBOL(tcf_police);
30959
30960-int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p)
30961+int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police)
30962 {
30963- unsigned char *b = skb->tail;
30964+ unsigned char *b = skb->tail;
30965 struct tc_police opt;
30966
30967- opt.index = p->index;
30968- opt.action = p->action;
30969- opt.mtu = p->mtu;
30970- opt.burst = p->burst;
30971- if (p->R_tab)
30972- opt.rate = p->R_tab->rate;
30973+ opt.index = police->tcf_index;
30974+ opt.action = police->tcf_action;
30975+ opt.mtu = police->tcfp_mtu;
30976+ opt.burst = police->tcfp_burst;
30977+ if (police->tcfp_R_tab)
30978+ opt.rate = police->tcfp_R_tab->rate;
30979 else
30980 memset(&opt.rate, 0, sizeof(opt.rate));
30981- if (p->P_tab)
30982- opt.peakrate = p->P_tab->rate;
30983+ if (police->tcfp_P_tab)
30984+ opt.peakrate = police->tcfp_P_tab->rate;
30985 else
30986 memset(&opt.peakrate, 0, sizeof(opt.peakrate));
30987 RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
30988- if (p->result)
30989- RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result);
30990+ if (police->tcfp_result)
30991+ RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
30992+ &police->tcfp_result);
30993 #ifdef CONFIG_NET_ESTIMATOR
30994- if (p->ewma_rate)
30995- RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate);
30996+ if (police->tcfp_ewma_rate)
30997+ RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
30998 #endif
30999 return skb->len;
31000
31001@@ -574,19 +585,20 @@
31002 return -1;
31003 }
31004
31005-int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p)
31006+int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police)
31007 {
31008 struct gnet_dump d;
31009
31010 if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
31011- TCA_XSTATS, p->stats_lock, &d) < 0)
31012+ TCA_XSTATS, police->tcf_stats_lock,
31013+ &d) < 0)
31014 goto errout;
31015
31016- if (gnet_stats_copy_basic(&d, &p->bstats) < 0 ||
31017+ if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 ||
31018 #ifdef CONFIG_NET_ESTIMATOR
31019- gnet_stats_copy_rate_est(&d, &p->rate_est) < 0 ||
31020+ gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 ||
31021 #endif
31022- gnet_stats_copy_queue(&d, &p->qstats) < 0)
31023+ gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0)
31024 goto errout;
31025
31026 if (gnet_stats_finish_copy(&d) < 0)
31027diff -Nur linux-2.6.18-rc5/net/sched/act_simple.c linux-2.6.19/net/sched/act_simple.c
31028--- linux-2.6.18-rc5/net/sched/act_simple.c 2006-08-28 05:41:48.000000000 +0200
31029+++ linux-2.6.19/net/sched/act_simple.c 2006-09-22 10:04:59.000000000 +0200
31030@@ -20,54 +20,175 @@
31031
31032 #define TCA_ACT_SIMP 22
31033
31034-/* XXX: Hide all these common elements under some macro
31035- * probably
31036-*/
31037 #include <linux/tc_act/tc_defact.h>
31038 #include <net/tc_act/tc_defact.h>
31039
31040-/* use generic hash table with 8 buckets */
31041-#define MY_TAB_SIZE 8
31042-#define MY_TAB_MASK (MY_TAB_SIZE - 1)
31043-static u32 idx_gen;
31044-static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE];
31045+#define SIMP_TAB_MASK 7
31046+static struct tcf_common *tcf_simp_ht[SIMP_TAB_MASK + 1];
31047+static u32 simp_idx_gen;
31048 static DEFINE_RWLOCK(simp_lock);
31049
31050-/* override the defaults */
31051-#define tcf_st tcf_defact
31052-#define tc_st tc_defact
31053-#define tcf_t_lock simp_lock
31054-#define tcf_ht tcf_simp_ht
31055-
31056-#define CONFIG_NET_ACT_INIT 1
31057-#include <net/pkt_act.h>
31058-#include <net/act_generic.h>
31059+static struct tcf_hashinfo simp_hash_info = {
31060+ .htab = tcf_simp_ht,
31061+ .hmask = SIMP_TAB_MASK,
31062+ .lock = &simp_lock,
31063+};
31064
31065 static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
31066 {
31067- struct tcf_defact *p = PRIV(a, defact);
31068+ struct tcf_defact *d = a->priv;
31069
31070- spin_lock(&p->lock);
31071- p->tm.lastuse = jiffies;
31072- p->bstats.bytes += skb->len;
31073- p->bstats.packets++;
31074+ spin_lock(&d->tcf_lock);
31075+ d->tcf_tm.lastuse = jiffies;
31076+ d->tcf_bstats.bytes += skb->len;
31077+ d->tcf_bstats.packets++;
31078
31079 /* print policy string followed by _ then packet count
31080 * Example if this was the 3rd packet and the string was "hello"
31081 * then it would look like "hello_3" (without quotes)
31082 **/
31083- printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets);
31084- spin_unlock(&p->lock);
31085- return p->action;
31086+ printk("simple: %s_%d\n",
31087+ (char *)d->tcfd_defdata, d->tcf_bstats.packets);
31088+ spin_unlock(&d->tcf_lock);
31089+ return d->tcf_action;
31090+}
31091+
31092+static int tcf_simp_release(struct tcf_defact *d, int bind)
31093+{
31094+ int ret = 0;
31095+ if (d) {
31096+ if (bind)
31097+ d->tcf_bindcnt--;
31098+ d->tcf_refcnt--;
31099+ if (d->tcf_bindcnt <= 0 && d->tcf_refcnt <= 0) {
31100+ kfree(d->tcfd_defdata);
31101+ tcf_hash_destroy(&d->common, &simp_hash_info);
31102+ ret = 1;
31103+ }
31104+ }
31105+ return ret;
31106+}
31107+
31108+static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
31109+{
31110+ d->tcfd_defdata = kmalloc(datalen, GFP_KERNEL);
31111+ if (unlikely(!d->tcfd_defdata))
31112+ return -ENOMEM;
31113+ d->tcfd_datalen = datalen;
31114+ memcpy(d->tcfd_defdata, defdata, datalen);
31115+ return 0;
31116+}
31117+
31118+static int realloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
31119+{
31120+ kfree(d->tcfd_defdata);
31121+ return alloc_defdata(d, datalen, defdata);
31122+}
31123+
31124+static int tcf_simp_init(struct rtattr *rta, struct rtattr *est,
31125+ struct tc_action *a, int ovr, int bind)
31126+{
31127+ struct rtattr *tb[TCA_DEF_MAX];
31128+ struct tc_defact *parm;
31129+ struct tcf_defact *d;
31130+ struct tcf_common *pc;
31131+ void *defdata;
31132+ u32 datalen = 0;
31133+ int ret = 0;
31134+
31135+ if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
31136+ return -EINVAL;
31137+
31138+ if (tb[TCA_DEF_PARMS - 1] == NULL ||
31139+ RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm))
31140+ return -EINVAL;
31141+
31142+ parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);
31143+ defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]);
31144+ if (defdata == NULL)
31145+ return -EINVAL;
31146+
31147+ datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]);
31148+ if (datalen <= 0)
31149+ return -EINVAL;
31150+
31151+ pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info);
31152+ if (!pc) {
31153+ pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind,
31154+ &simp_idx_gen, &simp_hash_info);
31155+ if (unlikely(!pc))
31156+ return -ENOMEM;
31157+
31158+ d = to_defact(pc);
31159+ ret = alloc_defdata(d, datalen, defdata);
31160+ if (ret < 0) {
31161+ kfree(pc);
31162+ return ret;
31163+ }
31164+ ret = ACT_P_CREATED;
31165+ } else {
31166+ d = to_defact(pc);
31167+ if (!ovr) {
31168+ tcf_simp_release(d, bind);
31169+ return -EEXIST;
31170+ }
31171+ realloc_defdata(d, datalen, defdata);
31172+ }
31173+
31174+ spin_lock_bh(&d->tcf_lock);
31175+ d->tcf_action = parm->action;
31176+ spin_unlock_bh(&d->tcf_lock);
31177+
31178+ if (ret == ACT_P_CREATED)
31179+ tcf_hash_insert(pc, &simp_hash_info);
31180+ return ret;
31181+}
31182+
31183+static inline int tcf_simp_cleanup(struct tc_action *a, int bind)
31184+{
31185+ struct tcf_defact *d = a->priv;
31186+
31187+ if (d)
31188+ return tcf_simp_release(d, bind);
31189+ return 0;
31190+}
31191+
31192+static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
31193+ int bind, int ref)
31194+{
31195+ unsigned char *b = skb->tail;
31196+ struct tcf_defact *d = a->priv;
31197+ struct tc_defact opt;
31198+ struct tcf_t t;
31199+
31200+ opt.index = d->tcf_index;
31201+ opt.refcnt = d->tcf_refcnt - ref;
31202+ opt.bindcnt = d->tcf_bindcnt - bind;
31203+ opt.action = d->tcf_action;
31204+ RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
31205+ RTA_PUT(skb, TCA_DEF_DATA, d->tcfd_datalen, d->tcfd_defdata);
31206+ t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install);
31207+ t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse);
31208+ t.expires = jiffies_to_clock_t(d->tcf_tm.expires);
31209+ RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
31210+ return skb->len;
31211+
31212+rtattr_failure:
31213+ skb_trim(skb, b - skb->data);
31214+ return -1;
31215 }
31216
31217 static struct tc_action_ops act_simp_ops = {
31218- .kind = "simple",
31219- .type = TCA_ACT_SIMP,
31220- .capab = TCA_CAP_NONE,
31221- .owner = THIS_MODULE,
31222- .act = tcf_simp,
31223- tca_use_default_ops
31224+ .kind = "simple",
31225+ .hinfo = &simp_hash_info,
31226+ .type = TCA_ACT_SIMP,
31227+ .capab = TCA_CAP_NONE,
31228+ .owner = THIS_MODULE,
31229+ .act = tcf_simp,
31230+ .dump = tcf_simp_dump,
31231+ .cleanup = tcf_simp_cleanup,
31232+ .init = tcf_simp_init,
31233+ .walk = tcf_generic_walker,
31234 };
31235
31236 MODULE_AUTHOR("Jamal Hadi Salim(2005)");
31237diff -Nur linux-2.6.18-rc5/net/sched/cls_fw.c linux-2.6.19/net/sched/cls_fw.c
31238--- linux-2.6.18-rc5/net/sched/cls_fw.c 2006-08-28 05:41:48.000000000 +0200
31239+++ linux-2.6.19/net/sched/cls_fw.c 2006-09-22 10:04:59.000000000 +0200
31240@@ -50,6 +50,7 @@
31241 struct fw_head
31242 {
31243 struct fw_filter *ht[HTSIZE];
31244+ u32 mask;
31245 };
31246
31247 struct fw_filter
31248@@ -101,7 +102,7 @@
31249 struct fw_filter *f;
31250 int r;
31251 #ifdef CONFIG_NETFILTER
31252- u32 id = skb->nfmark;
31253+ u32 id = skb->nfmark & head->mask;
31254 #else
31255 u32 id = 0;
31256 #endif
31257@@ -209,7 +210,9 @@
31258 fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
31259 struct rtattr **tb, struct rtattr **tca, unsigned long base)
31260 {
31261+ struct fw_head *head = (struct fw_head *)tp->root;
31262 struct tcf_exts e;
31263+ u32 mask;
31264 int err;
31265
31266 err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &fw_ext_map);
31267@@ -232,6 +235,15 @@
31268 }
31269 #endif /* CONFIG_NET_CLS_IND */
31270
31271+ if (tb[TCA_FW_MASK-1]) {
31272+ if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32))
31273+ goto errout;
31274+ mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]);
31275+ if (mask != head->mask)
31276+ goto errout;
31277+ } else if (head->mask != 0xFFFFFFFF)
31278+ goto errout;
31279+
31280 tcf_exts_change(tp, &f->exts, &e);
31281
31282 return 0;
31283@@ -267,9 +279,17 @@
31284 return -EINVAL;
31285
31286 if (head == NULL) {
31287+ u32 mask = 0xFFFFFFFF;
31288+ if (tb[TCA_FW_MASK-1]) {
31289+ if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32))
31290+ return -EINVAL;
31291+ mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]);
31292+ }
31293+
31294 head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
31295 if (head == NULL)
31296 return -ENOBUFS;
31297+ head->mask = mask;
31298
31299 tcf_tree_lock(tp);
31300 tp->root = head;
31301@@ -330,6 +350,7 @@
31302 static int fw_dump(struct tcf_proto *tp, unsigned long fh,
31303 struct sk_buff *skb, struct tcmsg *t)
31304 {
31305+ struct fw_head *head = (struct fw_head *)tp->root;
31306 struct fw_filter *f = (struct fw_filter*)fh;
31307 unsigned char *b = skb->tail;
31308 struct rtattr *rta;
31309@@ -351,6 +372,8 @@
31310 if (strlen(f->indev))
31311 RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev);
31312 #endif /* CONFIG_NET_CLS_IND */
31313+ if (head->mask != 0xFFFFFFFF)
31314+ RTA_PUT(skb, TCA_FW_MASK, 4, &head->mask);
31315
31316 if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0)
31317 goto rtattr_failure;
31318diff -Nur linux-2.6.18-rc5/net/sched/sch_htb.c linux-2.6.19/net/sched/sch_htb.c
31319--- linux-2.6.18-rc5/net/sched/sch_htb.c 2006-08-28 05:41:48.000000000 +0200
31320+++ linux-2.6.19/net/sched/sch_htb.c 2006-09-22 10:04:59.000000000 +0200
31321@@ -1,4 +1,4 @@
31322-/* vim: ts=8 sw=8
31323+/*
31324 * net/sched/sch_htb.c Hierarchical token bucket, feed tree version
31325 *
31326 * This program is free software; you can redistribute it and/or
31327@@ -68,218 +68,165 @@
31328 one less than their parent.
31329 */
31330
31331-#define HTB_HSIZE 16 /* classid hash size */
31332-#define HTB_EWMAC 2 /* rate average over HTB_EWMAC*HTB_HSIZE sec */
31333-#undef HTB_DEBUG /* compile debugging support (activated by tc tool) */
31334-#define HTB_RATECM 1 /* whether to use rate computer */
31335-#define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */
31336-#define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock)
31337-#define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock)
31338-#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */
31339+#define HTB_HSIZE 16 /* classid hash size */
31340+#define HTB_EWMAC 2 /* rate average over HTB_EWMAC*HTB_HSIZE sec */
31341+#define HTB_RATECM 1 /* whether to use rate computer */
31342+#define HTB_HYSTERESIS 1 /* whether to use mode hysteresis for speedup */
31343+#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */
31344
31345 #if HTB_VER >> 16 != TC_HTB_PROTOVER
31346 #error "Mismatched sch_htb.c and pkt_sch.h"
31347 #endif
31348
31349-/* debugging support; S is subsystem, these are defined:
31350- 0 - netlink messages
31351- 1 - enqueue
31352- 2 - drop & requeue
31353- 3 - dequeue main
31354- 4 - dequeue one prio DRR part
31355- 5 - dequeue class accounting
31356- 6 - class overlimit status computation
31357- 7 - hint tree
31358- 8 - event queue
31359- 10 - rate estimator
31360- 11 - classifier
31361- 12 - fast dequeue cache
31362-
31363- L is level; 0 = none, 1 = basic info, 2 = detailed, 3 = full
31364- q->debug uint32 contains 16 2-bit fields one for subsystem starting
31365- from LSB
31366- */
31367-#ifdef HTB_DEBUG
31368-#define HTB_DBG_COND(S,L) (((q->debug>>(2*S))&3) >= L)
31369-#define HTB_DBG(S,L,FMT,ARG...) if (HTB_DBG_COND(S,L)) \
31370- printk(KERN_DEBUG FMT,##ARG)
31371-#define HTB_CHCL(cl) BUG_TRAP((cl)->magic == HTB_CMAGIC)
31372-#define HTB_PASSQ q,
31373-#define HTB_ARGQ struct htb_sched *q,
31374-#define static
31375-#undef __inline__
31376-#define __inline__
31377-#undef inline
31378-#define inline
31379-#define HTB_CMAGIC 0xFEFAFEF1
31380-#define htb_safe_rb_erase(N,R) do { BUG_TRAP((N)->rb_color != -1); \
31381- if ((N)->rb_color == -1) break; \
31382- rb_erase(N,R); \
31383- (N)->rb_color = -1; } while (0)
31384-#else
31385-#define HTB_DBG_COND(S,L) (0)
31386-#define HTB_DBG(S,L,FMT,ARG...)
31387-#define HTB_PASSQ
31388-#define HTB_ARGQ
31389-#define HTB_CHCL(cl)
31390-#define htb_safe_rb_erase(N,R) rb_erase(N,R)
31391-#endif
31392-
31393-
31394 /* used internaly to keep status of single class */
31395 enum htb_cmode {
31396- HTB_CANT_SEND, /* class can't send and can't borrow */
31397- HTB_MAY_BORROW, /* class can't send but may borrow */
31398- HTB_CAN_SEND /* class can send */
31399+ HTB_CANT_SEND, /* class can't send and can't borrow */
31400+ HTB_MAY_BORROW, /* class can't send but may borrow */
31401+ HTB_CAN_SEND /* class can send */
31402 };
31403
31404 /* interior & leaf nodes; props specific to leaves are marked L: */
31405-struct htb_class
31406-{
31407-#ifdef HTB_DEBUG
31408- unsigned magic;
31409-#endif
31410- /* general class parameters */
31411- u32 classid;
31412- struct gnet_stats_basic bstats;
31413- struct gnet_stats_queue qstats;
31414- struct gnet_stats_rate_est rate_est;
31415- struct tc_htb_xstats xstats;/* our special stats */
31416- int refcnt; /* usage count of this class */
31417+struct htb_class {
31418+ /* general class parameters */
31419+ u32 classid;
31420+ struct gnet_stats_basic bstats;
31421+ struct gnet_stats_queue qstats;
31422+ struct gnet_stats_rate_est rate_est;
31423+ struct tc_htb_xstats xstats; /* our special stats */
31424+ int refcnt; /* usage count of this class */
31425
31426 #ifdef HTB_RATECM
31427- /* rate measurement counters */
31428- unsigned long rate_bytes,sum_bytes;
31429- unsigned long rate_packets,sum_packets;
31430-#endif
31431-
31432- /* topology */
31433- int level; /* our level (see above) */
31434- struct htb_class *parent; /* parent class */
31435- struct list_head hlist; /* classid hash list item */
31436- struct list_head sibling; /* sibling list item */
31437- struct list_head children; /* children list */
31438-
31439- union {
31440- struct htb_class_leaf {
31441- struct Qdisc *q;
31442- int prio;
31443- int aprio;
31444- int quantum;
31445- int deficit[TC_HTB_MAXDEPTH];
31446- struct list_head drop_list;
31447- } leaf;
31448- struct htb_class_inner {
31449- struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */
31450- struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */
31451- /* When class changes from state 1->2 and disconnects from
31452- parent's feed then we lost ptr value and start from the
31453- first child again. Here we store classid of the
31454- last valid ptr (used when ptr is NULL). */
31455- u32 last_ptr_id[TC_HTB_NUMPRIO];
31456- } inner;
31457- } un;
31458- struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */
31459- struct rb_node pq_node; /* node for event queue */
31460- unsigned long pq_key; /* the same type as jiffies global */
31461-
31462- int prio_activity; /* for which prios are we active */
31463- enum htb_cmode cmode; /* current mode of the class */
31464-
31465- /* class attached filters */
31466- struct tcf_proto *filter_list;
31467- int filter_cnt;
31468-
31469- int warned; /* only one warning about non work conserving .. */
31470-
31471- /* token bucket parameters */
31472- struct qdisc_rate_table *rate; /* rate table of the class itself */
31473- struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */
31474- long buffer,cbuffer; /* token bucket depth/rate */
31475- psched_tdiff_t mbuffer; /* max wait time */
31476- long tokens,ctokens; /* current number of tokens */
31477- psched_time_t t_c; /* checkpoint time */
31478+ /* rate measurement counters */
31479+ unsigned long rate_bytes, sum_bytes;
31480+ unsigned long rate_packets, sum_packets;
31481+#endif
31482+
31483+ /* topology */
31484+ int level; /* our level (see above) */
31485+ struct htb_class *parent; /* parent class */
31486+ struct hlist_node hlist; /* classid hash list item */
31487+ struct list_head sibling; /* sibling list item */
31488+ struct list_head children; /* children list */
31489+
31490+ union {
31491+ struct htb_class_leaf {
31492+ struct Qdisc *q;
31493+ int prio;
31494+ int aprio;
31495+ int quantum;
31496+ int deficit[TC_HTB_MAXDEPTH];
31497+ struct list_head drop_list;
31498+ } leaf;
31499+ struct htb_class_inner {
31500+ struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */
31501+ struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */
31502+ /* When class changes from state 1->2 and disconnects from
31503+ parent's feed then we lost ptr value and start from the
31504+ first child again. Here we store classid of the
31505+ last valid ptr (used when ptr is NULL). */
31506+ u32 last_ptr_id[TC_HTB_NUMPRIO];
31507+ } inner;
31508+ } un;
31509+ struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */
31510+ struct rb_node pq_node; /* node for event queue */
31511+ unsigned long pq_key; /* the same type as jiffies global */
31512+
31513+ int prio_activity; /* for which prios are we active */
31514+ enum htb_cmode cmode; /* current mode of the class */
31515+
31516+ /* class attached filters */
31517+ struct tcf_proto *filter_list;
31518+ int filter_cnt;
31519+
31520+ int warned; /* only one warning about non work conserving .. */
31521+
31522+ /* token bucket parameters */
31523+ struct qdisc_rate_table *rate; /* rate table of the class itself */
31524+ struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */
31525+ long buffer, cbuffer; /* token bucket depth/rate */
31526+ psched_tdiff_t mbuffer; /* max wait time */
31527+ long tokens, ctokens; /* current number of tokens */
31528+ psched_time_t t_c; /* checkpoint time */
31529 };
31530
31531 /* TODO: maybe compute rate when size is too large .. or drop ? */
31532-static __inline__ long L2T(struct htb_class *cl,struct qdisc_rate_table *rate,
31533- int size)
31534-{
31535- int slot = size >> rate->rate.cell_log;
31536- if (slot > 255) {
31537- cl->xstats.giants++;
31538- slot = 255;
31539- }
31540- return rate->data[slot];
31541-}
31542-
31543-struct htb_sched
31544-{
31545- struct list_head root; /* root classes list */
31546- struct list_head hash[HTB_HSIZE]; /* hashed by classid */
31547- struct list_head drops[TC_HTB_NUMPRIO]; /* active leaves (for drops) */
31548-
31549- /* self list - roots of self generating tree */
31550- struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
31551- int row_mask[TC_HTB_MAXDEPTH];
31552- struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
31553- u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
31554-
31555- /* self wait list - roots of wait PQs per row */
31556- struct rb_root wait_pq[TC_HTB_MAXDEPTH];
31557-
31558- /* time of nearest event per level (row) */
31559- unsigned long near_ev_cache[TC_HTB_MAXDEPTH];
31560-
31561- /* cached value of jiffies in dequeue */
31562- unsigned long jiffies;
31563-
31564- /* whether we hit non-work conserving class during this dequeue; we use */
31565- int nwc_hit; /* this to disable mindelay complaint in dequeue */
31566-
31567- int defcls; /* class where unclassified flows go to */
31568- u32 debug; /* subsystem debug levels */
31569-
31570- /* filters for qdisc itself */
31571- struct tcf_proto *filter_list;
31572- int filter_cnt;
31573-
31574- int rate2quantum; /* quant = rate / rate2quantum */
31575- psched_time_t now; /* cached dequeue time */
31576- struct timer_list timer; /* send delay timer */
31577+static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate,
31578+ int size)
31579+{
31580+ int slot = size >> rate->rate.cell_log;
31581+ if (slot > 255) {
31582+ cl->xstats.giants++;
31583+ slot = 255;
31584+ }
31585+ return rate->data[slot];
31586+}
31587+
31588+struct htb_sched {
31589+ struct list_head root; /* root classes list */
31590+ struct hlist_head hash[HTB_HSIZE]; /* hashed by classid */
31591+ struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */
31592+
31593+ /* self list - roots of self generating tree */
31594+ struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
31595+ int row_mask[TC_HTB_MAXDEPTH];
31596+ struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
31597+ u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
31598+
31599+ /* self wait list - roots of wait PQs per row */
31600+ struct rb_root wait_pq[TC_HTB_MAXDEPTH];
31601+
31602+ /* time of nearest event per level (row) */
31603+ unsigned long near_ev_cache[TC_HTB_MAXDEPTH];
31604+
31605+ /* cached value of jiffies in dequeue */
31606+ unsigned long jiffies;
31607+
31608+ /* whether we hit non-work conserving class during this dequeue; we use */
31609+ int nwc_hit; /* this to disable mindelay complaint in dequeue */
31610+
31611+ int defcls; /* class where unclassified flows go to */
31612+
31613+ /* filters for qdisc itself */
31614+ struct tcf_proto *filter_list;
31615+ int filter_cnt;
31616+
31617+ int rate2quantum; /* quant = rate / rate2quantum */
31618+ psched_time_t now; /* cached dequeue time */
31619+ struct timer_list timer; /* send delay timer */
31620 #ifdef HTB_RATECM
31621- struct timer_list rttim; /* rate computer timer */
31622- int recmp_bucket; /* which hash bucket to recompute next */
31623+ struct timer_list rttim; /* rate computer timer */
31624+ int recmp_bucket; /* which hash bucket to recompute next */
31625 #endif
31626-
31627- /* non shaped skbs; let them go directly thru */
31628- struct sk_buff_head direct_queue;
31629- int direct_qlen; /* max qlen of above */
31630
31631- long direct_pkts;
31632+ /* non shaped skbs; let them go directly thru */
31633+ struct sk_buff_head direct_queue;
31634+ int direct_qlen; /* max qlen of above */
31635+
31636+ long direct_pkts;
31637 };
31638
31639 /* compute hash of size HTB_HSIZE for given handle */
31640-static __inline__ int htb_hash(u32 h)
31641+static inline int htb_hash(u32 h)
31642 {
31643 #if HTB_HSIZE != 16
31644- #error "Declare new hash for your HTB_HSIZE"
31645+#error "Declare new hash for your HTB_HSIZE"
31646 #endif
31647- h ^= h>>8; /* stolen from cbq_hash */
31648- h ^= h>>4;
31649- return h & 0xf;
31650+ h ^= h >> 8; /* stolen from cbq_hash */
31651+ h ^= h >> 4;
31652+ return h & 0xf;
31653 }
31654
31655 /* find class in global hash table using given handle */
31656-static __inline__ struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
31657+static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
31658 {
31659 struct htb_sched *q = qdisc_priv(sch);
31660- struct list_head *p;
31661- if (TC_H_MAJ(handle) != sch->handle)
31662+ struct hlist_node *p;
31663+ struct htb_class *cl;
31664+
31665+ if (TC_H_MAJ(handle) != sch->handle)
31666 return NULL;
31667-
31668- list_for_each (p,q->hash+htb_hash(handle)) {
31669- struct htb_class *cl = list_entry(p,struct htb_class,hlist);
31670+
31671+ hlist_for_each_entry(cl, p, q->hash + htb_hash(handle), hlist) {
31672 if (cl->classid == handle)
31673 return cl;
31674 }
31675@@ -304,7 +251,8 @@
31676 return (cl && cl != HTB_DIRECT) ? cl->classid : TC_H_UNSPEC;
31677 }
31678
31679-static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
31680+static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
31681+ int *qerr)
31682 {
31683 struct htb_sched *q = qdisc_priv(sch);
31684 struct htb_class *cl;
31685@@ -316,8 +264,8 @@
31686 note that nfmark can be used too by attaching filter fw with no
31687 rules in it */
31688 if (skb->priority == sch->handle)
31689- return HTB_DIRECT; /* X:0 (direct flow) selected */
31690- if ((cl = htb_find(skb->priority,sch)) != NULL && cl->level == 0)
31691+ return HTB_DIRECT; /* X:0 (direct flow) selected */
31692+ if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0)
31693 return cl;
31694
31695 *qerr = NET_XMIT_BYPASS;
31696@@ -326,7 +274,7 @@
31697 #ifdef CONFIG_NET_CLS_ACT
31698 switch (result) {
31699 case TC_ACT_QUEUED:
31700- case TC_ACT_STOLEN:
31701+ case TC_ACT_STOLEN:
31702 *qerr = NET_XMIT_SUCCESS;
31703 case TC_ACT_SHOT:
31704 return NULL;
31705@@ -335,97 +283,44 @@
31706 if (result == TC_POLICE_SHOT)
31707 return HTB_DIRECT;
31708 #endif
31709- if ((cl = (void*)res.class) == NULL) {
31710+ if ((cl = (void *)res.class) == NULL) {
31711 if (res.classid == sch->handle)
31712- return HTB_DIRECT; /* X:0 (direct flow) */
31713- if ((cl = htb_find(res.classid,sch)) == NULL)
31714- break; /* filter selected invalid classid */
31715+ return HTB_DIRECT; /* X:0 (direct flow) */
31716+ if ((cl = htb_find(res.classid, sch)) == NULL)
31717+ break; /* filter selected invalid classid */
31718 }
31719 if (!cl->level)
31720- return cl; /* we hit leaf; return it */
31721+ return cl; /* we hit leaf; return it */
31722
31723 /* we have got inner class; apply inner filter chain */
31724 tcf = cl->filter_list;
31725 }
31726 /* classification failed; try to use default class */
31727- cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle),q->defcls),sch);
31728+ cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch);
31729 if (!cl || cl->level)
31730- return HTB_DIRECT; /* bad default .. this is safe bet */
31731+ return HTB_DIRECT; /* bad default .. this is safe bet */
31732 return cl;
31733 }
31734
31735-#ifdef HTB_DEBUG
31736-static void htb_next_rb_node(struct rb_node **n);
31737-#define HTB_DUMTREE(root,memb) if(root) { \
31738- struct rb_node *n = (root)->rb_node; \
31739- while (n->rb_left) n = n->rb_left; \
31740- while (n) { \
31741- struct htb_class *cl = rb_entry(n, struct htb_class, memb); \
31742- printk(" %x",cl->classid); htb_next_rb_node (&n); \
31743- } }
31744-
31745-static void htb_debug_dump (struct htb_sched *q)
31746-{
31747- int i,p;
31748- printk(KERN_DEBUG "htb*g j=%lu lj=%lu\n",jiffies,q->jiffies);
31749- /* rows */
31750- for (i=TC_HTB_MAXDEPTH-1;i>=0;i--) {
31751- printk(KERN_DEBUG "htb*r%d m=%x",i,q->row_mask[i]);
31752- for (p=0;p<TC_HTB_NUMPRIO;p++) {
31753- if (!q->row[i][p].rb_node) continue;
31754- printk(" p%d:",p);
31755- HTB_DUMTREE(q->row[i]+p,node[p]);
31756- }
31757- printk("\n");
31758- }
31759- /* classes */
31760- for (i = 0; i < HTB_HSIZE; i++) {
31761- struct list_head *l;
31762- list_for_each (l,q->hash+i) {
31763- struct htb_class *cl = list_entry(l,struct htb_class,hlist);
31764- long diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer);
31765- printk(KERN_DEBUG "htb*c%x m=%d t=%ld c=%ld pq=%lu df=%ld ql=%d "
31766- "pa=%x f:",
31767- cl->classid,cl->cmode,cl->tokens,cl->ctokens,
31768- cl->pq_node.rb_color==-1?0:cl->pq_key,diff,
31769- cl->level?0:cl->un.leaf.q->q.qlen,cl->prio_activity);
31770- if (cl->level)
31771- for (p=0;p<TC_HTB_NUMPRIO;p++) {
31772- if (!cl->un.inner.feed[p].rb_node) continue;
31773- printk(" p%d a=%x:",p,cl->un.inner.ptr[p]?rb_entry(cl->un.inner.ptr[p], struct htb_class,node[p])->classid:0);
31774- HTB_DUMTREE(cl->un.inner.feed+p,node[p]);
31775- }
31776- printk("\n");
31777- }
31778- }
31779-}
31780-#endif
31781 /**
31782 * htb_add_to_id_tree - adds class to the round robin list
31783 *
31784 * Routine adds class to the list (actually tree) sorted by classid.
31785 * Make sure that class is not already on such list for given prio.
31786 */
31787-static void htb_add_to_id_tree (HTB_ARGQ struct rb_root *root,
31788- struct htb_class *cl,int prio)
31789+static void htb_add_to_id_tree(struct rb_root *root,
31790+ struct htb_class *cl, int prio)
31791 {
31792 struct rb_node **p = &root->rb_node, *parent = NULL;
31793- HTB_DBG(7,3,"htb_add_id_tree cl=%X prio=%d\n",cl->classid,prio);
31794-#ifdef HTB_DEBUG
31795- if (cl->node[prio].rb_color != -1) { BUG_TRAP(0); return; }
31796- HTB_CHCL(cl);
31797- if (*p) {
31798- struct htb_class *x = rb_entry(*p,struct htb_class,node[prio]);
31799- HTB_CHCL(x);
31800- }
31801-#endif
31802+
31803 while (*p) {
31804- struct htb_class *c; parent = *p;
31805+ struct htb_class *c;
31806+ parent = *p;
31807 c = rb_entry(parent, struct htb_class, node[prio]);
31808- HTB_CHCL(c);
31809+
31810 if (cl->classid > c->classid)
31811 p = &parent->rb_right;
31812- else
31813+ else
31814 p = &parent->rb_left;
31815 }
31816 rb_link_node(&cl->node[prio], parent, p);
31817@@ -439,17 +334,11 @@
31818 * change its mode in cl->pq_key microseconds. Make sure that class is not
31819 * already in the queue.
31820 */
31821-static void htb_add_to_wait_tree (struct htb_sched *q,
31822- struct htb_class *cl,long delay,int debug_hint)
31823+static void htb_add_to_wait_tree(struct htb_sched *q,
31824+ struct htb_class *cl, long delay)
31825 {
31826 struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL;
31827- HTB_DBG(7,3,"htb_add_wt cl=%X key=%lu\n",cl->classid,cl->pq_key);
31828-#ifdef HTB_DEBUG
31829- if (cl->pq_node.rb_color != -1) { BUG_TRAP(0); return; }
31830- HTB_CHCL(cl);
31831- if ((delay <= 0 || delay > cl->mbuffer) && net_ratelimit())
31832- printk(KERN_ERR "HTB: suspicious delay in wait_tree d=%ld cl=%X h=%d\n",delay,cl->classid,debug_hint);
31833-#endif
31834+
31835 cl->pq_key = q->jiffies + PSCHED_US2JIFFIE(delay);
31836 if (cl->pq_key == q->jiffies)
31837 cl->pq_key++;
31838@@ -457,13 +346,14 @@
31839 /* update the nearest event cache */
31840 if (time_after(q->near_ev_cache[cl->level], cl->pq_key))
31841 q->near_ev_cache[cl->level] = cl->pq_key;
31842-
31843+
31844 while (*p) {
31845- struct htb_class *c; parent = *p;
31846+ struct htb_class *c;
31847+ parent = *p;
31848 c = rb_entry(parent, struct htb_class, pq_node);
31849 if (time_after_eq(cl->pq_key, c->pq_key))
31850 p = &parent->rb_right;
31851- else
31852+ else
31853 p = &parent->rb_left;
31854 }
31855 rb_link_node(&cl->pq_node, parent, p);
31856@@ -476,7 +366,7 @@
31857 * When we are past last key we return NULL.
31858 * Average complexity is 2 steps per call.
31859 */
31860-static void htb_next_rb_node(struct rb_node **n)
31861+static inline void htb_next_rb_node(struct rb_node **n)
31862 {
31863 *n = rb_next(*n);
31864 }
31865@@ -487,42 +377,51 @@
31866 * The class is added to row at priorities marked in mask.
31867 * It does nothing if mask == 0.
31868 */
31869-static inline void htb_add_class_to_row(struct htb_sched *q,
31870- struct htb_class *cl,int mask)
31871+static inline void htb_add_class_to_row(struct htb_sched *q,
31872+ struct htb_class *cl, int mask)
31873 {
31874- HTB_DBG(7,2,"htb_addrow cl=%X mask=%X rmask=%X\n",
31875- cl->classid,mask,q->row_mask[cl->level]);
31876- HTB_CHCL(cl);
31877 q->row_mask[cl->level] |= mask;
31878 while (mask) {
31879 int prio = ffz(~mask);
31880 mask &= ~(1 << prio);
31881- htb_add_to_id_tree(HTB_PASSQ q->row[cl->level]+prio,cl,prio);
31882+ htb_add_to_id_tree(q->row[cl->level] + prio, cl, prio);
31883 }
31884 }
31885
31886+/* If this triggers, it is a bug in this code, but it need not be fatal */
31887+static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root)
31888+{
31889+ if (RB_EMPTY_NODE(rb)) {
31890+ WARN_ON(1);
31891+ } else {
31892+ rb_erase(rb, root);
31893+ RB_CLEAR_NODE(rb);
31894+ }
31895+}
31896+
31897+
31898 /**
31899 * htb_remove_class_from_row - removes class from its row
31900 *
31901 * The class is removed from row at priorities marked in mask.
31902 * It does nothing if mask == 0.
31903 */
31904-static __inline__ void htb_remove_class_from_row(struct htb_sched *q,
31905- struct htb_class *cl,int mask)
31906+static inline void htb_remove_class_from_row(struct htb_sched *q,
31907+ struct htb_class *cl, int mask)
31908 {
31909 int m = 0;
31910- HTB_CHCL(cl);
31911+
31912 while (mask) {
31913 int prio = ffz(~mask);
31914+
31915 mask &= ~(1 << prio);
31916- if (q->ptr[cl->level][prio] == cl->node+prio)
31917- htb_next_rb_node(q->ptr[cl->level]+prio);
31918- htb_safe_rb_erase(cl->node + prio,q->row[cl->level]+prio);
31919- if (!q->row[cl->level][prio].rb_node)
31920+ if (q->ptr[cl->level][prio] == cl->node + prio)
31921+ htb_next_rb_node(q->ptr[cl->level] + prio);
31922+
31923+ htb_safe_rb_erase(cl->node + prio, q->row[cl->level] + prio);
31924+ if (!q->row[cl->level][prio].rb_node)
31925 m |= 1 << prio;
31926 }
31927- HTB_DBG(7,2,"htb_delrow cl=%X mask=%X rmask=%X maskdel=%X\n",
31928- cl->classid,mask,q->row_mask[cl->level],m);
31929 q->row_mask[cl->level] &= ~m;
31930 }
31931
31932@@ -533,34 +432,31 @@
31933 * for priorities it is participating on. cl->cmode must be new
31934 * (activated) mode. It does nothing if cl->prio_activity == 0.
31935 */
31936-static void htb_activate_prios(struct htb_sched *q,struct htb_class *cl)
31937+static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
31938 {
31939 struct htb_class *p = cl->parent;
31940- long m,mask = cl->prio_activity;
31941- HTB_DBG(7,2,"htb_act_prios cl=%X mask=%lX cmode=%d\n",cl->classid,mask,cl->cmode);
31942- HTB_CHCL(cl);
31943+ long m, mask = cl->prio_activity;
31944
31945 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
31946- HTB_CHCL(p);
31947- m = mask; while (m) {
31948+ m = mask;
31949+ while (m) {
31950 int prio = ffz(~m);
31951 m &= ~(1 << prio);
31952-
31953+
31954 if (p->un.inner.feed[prio].rb_node)
31955 /* parent already has its feed in use so that
31956 reset bit in mask as parent is already ok */
31957 mask &= ~(1 << prio);
31958-
31959- htb_add_to_id_tree(HTB_PASSQ p->un.inner.feed+prio,cl,prio);
31960+
31961+ htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio);
31962 }
31963- HTB_DBG(7,3,"htb_act_pr_aft p=%X pact=%X mask=%lX pmode=%d\n",
31964- p->classid,p->prio_activity,mask,p->cmode);
31965 p->prio_activity |= mask;
31966- cl = p; p = cl->parent;
31967- HTB_CHCL(cl);
31968+ cl = p;
31969+ p = cl->parent;
31970+
31971 }
31972 if (cl->cmode == HTB_CAN_SEND && mask)
31973- htb_add_class_to_row(q,cl,mask);
31974+ htb_add_class_to_row(q, cl, mask);
31975 }
31976
31977 /**
31978@@ -573,39 +469,52 @@
31979 static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
31980 {
31981 struct htb_class *p = cl->parent;
31982- long m,mask = cl->prio_activity;
31983- HTB_DBG(7,2,"htb_deact_prios cl=%X mask=%lX cmode=%d\n",cl->classid,mask,cl->cmode);
31984- HTB_CHCL(cl);
31985+ long m, mask = cl->prio_activity;
31986
31987 while (cl->cmode == HTB_MAY_BORROW && p && mask) {
31988- m = mask; mask = 0;
31989+ m = mask;
31990+ mask = 0;
31991 while (m) {
31992 int prio = ffz(~m);
31993 m &= ~(1 << prio);
31994-
31995- if (p->un.inner.ptr[prio] == cl->node+prio) {
31996+
31997+ if (p->un.inner.ptr[prio] == cl->node + prio) {
31998 /* we are removing child which is pointed to from
31999 parent feed - forget the pointer but remember
32000 classid */
32001 p->un.inner.last_ptr_id[prio] = cl->classid;
32002 p->un.inner.ptr[prio] = NULL;
32003 }
32004-
32005- htb_safe_rb_erase(cl->node + prio,p->un.inner.feed + prio);
32006-
32007- if (!p->un.inner.feed[prio].rb_node)
32008+
32009+ htb_safe_rb_erase(cl->node + prio, p->un.inner.feed + prio);
32010+
32011+ if (!p->un.inner.feed[prio].rb_node)
32012 mask |= 1 << prio;
32013 }
32014- HTB_DBG(7,3,"htb_deact_pr_aft p=%X pact=%X mask=%lX pmode=%d\n",
32015- p->classid,p->prio_activity,mask,p->cmode);
32016+
32017 p->prio_activity &= ~mask;
32018- cl = p; p = cl->parent;
32019- HTB_CHCL(cl);
32020+ cl = p;
32021+ p = cl->parent;
32022+
32023 }
32024- if (cl->cmode == HTB_CAN_SEND && mask)
32025- htb_remove_class_from_row(q,cl,mask);
32026+ if (cl->cmode == HTB_CAN_SEND && mask)
32027+ htb_remove_class_from_row(q, cl, mask);
32028 }
32029
32030+#if HTB_HYSTERESIS
32031+static inline long htb_lowater(const struct htb_class *cl)
32032+{
32033+ return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
32034+}
32035+static inline long htb_hiwater(const struct htb_class *cl)
32036+{
32037+ return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
32038+}
32039+#else
32040+#define htb_lowater(cl) (0)
32041+#define htb_hiwater(cl) (0)
32042+#endif
32043+
32044 /**
32045 * htb_class_mode - computes and returns current class mode
32046 *
32047@@ -617,28 +526,21 @@
32048 * 0 .. -cl->{c,}buffer range. It is meant to limit number of
32049 * mode transitions per time unit. The speed gain is about 1/6.
32050 */
32051-static __inline__ enum htb_cmode
32052-htb_class_mode(struct htb_class *cl,long *diff)
32053+static inline enum htb_cmode
32054+htb_class_mode(struct htb_class *cl, long *diff)
32055 {
32056- long toks;
32057+ long toks;
32058
32059- if ((toks = (cl->ctokens + *diff)) < (
32060-#if HTB_HYSTERESIS
32061- cl->cmode != HTB_CANT_SEND ? -cl->cbuffer :
32062-#endif
32063- 0)) {
32064- *diff = -toks;
32065- return HTB_CANT_SEND;
32066- }
32067- if ((toks = (cl->tokens + *diff)) >= (
32068-#if HTB_HYSTERESIS
32069- cl->cmode == HTB_CAN_SEND ? -cl->buffer :
32070-#endif
32071- 0))
32072- return HTB_CAN_SEND;
32073+ if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
32074+ *diff = -toks;
32075+ return HTB_CANT_SEND;
32076+ }
32077
32078- *diff = -toks;
32079- return HTB_MAY_BORROW;
32080+ if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl))
32081+ return HTB_CAN_SEND;
32082+
32083+ *diff = -toks;
32084+ return HTB_MAY_BORROW;
32085 }
32086
32087 /**
32088@@ -650,24 +552,21 @@
32089 * be different from old one and cl->pq_key has to be valid if changing
32090 * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
32091 */
32092-static void
32093+static void
32094 htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
32095-{
32096- enum htb_cmode new_mode = htb_class_mode(cl,diff);
32097-
32098- HTB_CHCL(cl);
32099- HTB_DBG(7,1,"htb_chging_clmode %d->%d cl=%X\n",cl->cmode,new_mode,cl->classid);
32100+{
32101+ enum htb_cmode new_mode = htb_class_mode(cl, diff);
32102
32103 if (new_mode == cl->cmode)
32104- return;
32105-
32106- if (cl->prio_activity) { /* not necessary: speed optimization */
32107- if (cl->cmode != HTB_CANT_SEND)
32108- htb_deactivate_prios(q,cl);
32109+ return;
32110+
32111+ if (cl->prio_activity) { /* not necessary: speed optimization */
32112+ if (cl->cmode != HTB_CANT_SEND)
32113+ htb_deactivate_prios(q, cl);
32114 cl->cmode = new_mode;
32115- if (new_mode != HTB_CANT_SEND)
32116- htb_activate_prios(q,cl);
32117- } else
32118+ if (new_mode != HTB_CANT_SEND)
32119+ htb_activate_prios(q, cl);
32120+ } else
32121 cl->cmode = new_mode;
32122 }
32123
32124@@ -678,14 +577,15 @@
32125 * for the prio. It can be called on already active leaf safely.
32126 * It also adds leaf into droplist.
32127 */
32128-static __inline__ void htb_activate(struct htb_sched *q,struct htb_class *cl)
32129+static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
32130 {
32131 BUG_TRAP(!cl->level && cl->un.leaf.q && cl->un.leaf.q->q.qlen);
32132- HTB_CHCL(cl);
32133+
32134 if (!cl->prio_activity) {
32135 cl->prio_activity = 1 << (cl->un.leaf.aprio = cl->un.leaf.prio);
32136- htb_activate_prios(q,cl);
32137- list_add_tail(&cl->un.leaf.drop_list,q->drops+cl->un.leaf.aprio);
32138+ htb_activate_prios(q, cl);
32139+ list_add_tail(&cl->un.leaf.drop_list,
32140+ q->drops + cl->un.leaf.aprio);
32141 }
32142 }
32143
32144@@ -695,120 +595,120 @@
32145 * Make sure that leaf is active. In the other words it can't be called
32146 * with non-active leaf. It also removes class from the drop list.
32147 */
32148-static __inline__ void
32149-htb_deactivate(struct htb_sched *q,struct htb_class *cl)
32150+static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
32151 {
32152 BUG_TRAP(cl->prio_activity);
32153- HTB_CHCL(cl);
32154- htb_deactivate_prios(q,cl);
32155+
32156+ htb_deactivate_prios(q, cl);
32157 cl->prio_activity = 0;
32158 list_del_init(&cl->un.leaf.drop_list);
32159 }
32160
32161 static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
32162 {
32163- int ret;
32164- struct htb_sched *q = qdisc_priv(sch);
32165- struct htb_class *cl = htb_classify(skb,sch,&ret);
32166-
32167- if (cl == HTB_DIRECT) {
32168- /* enqueue to helper queue */
32169- if (q->direct_queue.qlen < q->direct_qlen) {
32170- __skb_queue_tail(&q->direct_queue, skb);
32171- q->direct_pkts++;
32172- } else {
32173- kfree_skb(skb);
32174- sch->qstats.drops++;
32175- return NET_XMIT_DROP;
32176- }
32177+ int ret;
32178+ struct htb_sched *q = qdisc_priv(sch);
32179+ struct htb_class *cl = htb_classify(skb, sch, &ret);
32180+
32181+ if (cl == HTB_DIRECT) {
32182+ /* enqueue to helper queue */
32183+ if (q->direct_queue.qlen < q->direct_qlen) {
32184+ __skb_queue_tail(&q->direct_queue, skb);
32185+ q->direct_pkts++;
32186+ } else {
32187+ kfree_skb(skb);
32188+ sch->qstats.drops++;
32189+ return NET_XMIT_DROP;
32190+ }
32191 #ifdef CONFIG_NET_CLS_ACT
32192- } else if (!cl) {
32193- if (ret == NET_XMIT_BYPASS)
32194- sch->qstats.drops++;
32195- kfree_skb (skb);
32196- return ret;
32197+ } else if (!cl) {
32198+ if (ret == NET_XMIT_BYPASS)
32199+ sch->qstats.drops++;
32200+ kfree_skb(skb);
32201+ return ret;
32202 #endif
32203- } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
32204- sch->qstats.drops++;
32205- cl->qstats.drops++;
32206- return NET_XMIT_DROP;
32207- } else {
32208- cl->bstats.packets++; cl->bstats.bytes += skb->len;
32209- htb_activate (q,cl);
32210- }
32211-
32212- sch->q.qlen++;
32213- sch->bstats.packets++; sch->bstats.bytes += skb->len;
32214- HTB_DBG(1,1,"htb_enq_ok cl=%X skb=%p\n",(cl && cl != HTB_DIRECT)?cl->classid:0,skb);
32215- return NET_XMIT_SUCCESS;
32216+ } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) !=
32217+ NET_XMIT_SUCCESS) {
32218+ sch->qstats.drops++;
32219+ cl->qstats.drops++;
32220+ return NET_XMIT_DROP;
32221+ } else {
32222+ cl->bstats.packets++;
32223+ cl->bstats.bytes += skb->len;
32224+ htb_activate(q, cl);
32225+ }
32226+
32227+ sch->q.qlen++;
32228+ sch->bstats.packets++;
32229+ sch->bstats.bytes += skb->len;
32230+ return NET_XMIT_SUCCESS;
32231 }
32232
32233 /* TODO: requeuing packet charges it to policers again !! */
32234 static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
32235 {
32236- struct htb_sched *q = qdisc_priv(sch);
32237- int ret = NET_XMIT_SUCCESS;
32238- struct htb_class *cl = htb_classify(skb,sch, &ret);
32239- struct sk_buff *tskb;
32240-
32241- if (cl == HTB_DIRECT || !cl) {
32242- /* enqueue to helper queue */
32243- if (q->direct_queue.qlen < q->direct_qlen && cl) {
32244- __skb_queue_head(&q->direct_queue, skb);
32245- } else {
32246- __skb_queue_head(&q->direct_queue, skb);
32247- tskb = __skb_dequeue_tail(&q->direct_queue);
32248- kfree_skb (tskb);
32249- sch->qstats.drops++;
32250- return NET_XMIT_CN;
32251- }
32252- } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
32253- sch->qstats.drops++;
32254- cl->qstats.drops++;
32255- return NET_XMIT_DROP;
32256- } else
32257- htb_activate (q,cl);
32258-
32259- sch->q.qlen++;
32260- sch->qstats.requeues++;
32261- HTB_DBG(1,1,"htb_req_ok cl=%X skb=%p\n",(cl && cl != HTB_DIRECT)?cl->classid:0,skb);
32262- return NET_XMIT_SUCCESS;
32263+ struct htb_sched *q = qdisc_priv(sch);
32264+ int ret = NET_XMIT_SUCCESS;
32265+ struct htb_class *cl = htb_classify(skb, sch, &ret);
32266+ struct sk_buff *tskb;
32267+
32268+ if (cl == HTB_DIRECT || !cl) {
32269+ /* enqueue to helper queue */
32270+ if (q->direct_queue.qlen < q->direct_qlen && cl) {
32271+ __skb_queue_head(&q->direct_queue, skb);
32272+ } else {
32273+ __skb_queue_head(&q->direct_queue, skb);
32274+ tskb = __skb_dequeue_tail(&q->direct_queue);
32275+ kfree_skb(tskb);
32276+ sch->qstats.drops++;
32277+ return NET_XMIT_CN;
32278+ }
32279+ } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) !=
32280+ NET_XMIT_SUCCESS) {
32281+ sch->qstats.drops++;
32282+ cl->qstats.drops++;
32283+ return NET_XMIT_DROP;
32284+ } else
32285+ htb_activate(q, cl);
32286+
32287+ sch->q.qlen++;
32288+ sch->qstats.requeues++;
32289+ return NET_XMIT_SUCCESS;
32290 }
32291
32292 static void htb_timer(unsigned long arg)
32293 {
32294- struct Qdisc *sch = (struct Qdisc*)arg;
32295- sch->flags &= ~TCQ_F_THROTTLED;
32296- wmb();
32297- netif_schedule(sch->dev);
32298+ struct Qdisc *sch = (struct Qdisc *)arg;
32299+ sch->flags &= ~TCQ_F_THROTTLED;
32300+ wmb();
32301+ netif_schedule(sch->dev);
32302 }
32303
32304 #ifdef HTB_RATECM
32305 #define RT_GEN(D,R) R+=D-(R/HTB_EWMAC);D=0
32306 static void htb_rate_timer(unsigned long arg)
32307 {
32308- struct Qdisc *sch = (struct Qdisc*)arg;
32309+ struct Qdisc *sch = (struct Qdisc *)arg;
32310 struct htb_sched *q = qdisc_priv(sch);
32311- struct list_head *p;
32312+ struct hlist_node *p;
32313+ struct htb_class *cl;
32314+
32315
32316 /* lock queue so that we can muck with it */
32317- HTB_QLOCK(sch);
32318- HTB_DBG(10,1,"htb_rttmr j=%ld\n",jiffies);
32319+ spin_lock_bh(&sch->dev->queue_lock);
32320
32321 q->rttim.expires = jiffies + HZ;
32322 add_timer(&q->rttim);
32323
32324 /* scan and recompute one bucket at time */
32325- if (++q->recmp_bucket >= HTB_HSIZE)
32326+ if (++q->recmp_bucket >= HTB_HSIZE)
32327 q->recmp_bucket = 0;
32328- list_for_each (p,q->hash+q->recmp_bucket) {
32329- struct htb_class *cl = list_entry(p,struct htb_class,hlist);
32330- HTB_DBG(10,2,"htb_rttmr_cl cl=%X sbyte=%lu spkt=%lu\n",
32331- cl->classid,cl->sum_bytes,cl->sum_packets);
32332- RT_GEN (cl->sum_bytes,cl->rate_bytes);
32333- RT_GEN (cl->sum_packets,cl->rate_packets);
32334+
32335+ hlist_for_each_entry(cl,p, q->hash + q->recmp_bucket, hlist) {
32336+ RT_GEN(cl->sum_bytes, cl->rate_bytes);
32337+ RT_GEN(cl->sum_packets, cl->rate_packets);
32338 }
32339- HTB_QUNLOCK(sch);
32340+ spin_unlock_bh(&sch->dev->queue_lock);
32341 }
32342 #endif
32343
32344@@ -823,12 +723,11 @@
32345 * CAN_SEND) because we can use more precise clock that event queue here.
32346 * In such case we remove class from event queue first.
32347 */
32348-static void htb_charge_class(struct htb_sched *q,struct htb_class *cl,
32349- int level,int bytes)
32350-{
32351- long toks,diff;
32352+static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
32353+ int level, int bytes)
32354+{
32355+ long toks, diff;
32356 enum htb_cmode old_mode;
32357- HTB_DBG(5,1,"htb_chrg_cl cl=%X lev=%d len=%d\n",cl->classid,level,bytes);
32358
32359 #define HTB_ACCNT(T,B,R) toks = diff + cl->T; \
32360 if (toks > cl->B) toks = cl->B; \
32361@@ -837,47 +736,31 @@
32362 cl->T = toks
32363
32364 while (cl) {
32365- HTB_CHCL(cl);
32366- diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer);
32367-#ifdef HTB_DEBUG
32368- if (diff > cl->mbuffer || diff < 0 || PSCHED_TLESS(q->now, cl->t_c)) {
32369- if (net_ratelimit())
32370- printk(KERN_ERR "HTB: bad diff in charge, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n",
32371- cl->classid, diff,
32372-#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
32373- q->now.tv_sec * 1000000ULL + q->now.tv_usec,
32374- cl->t_c.tv_sec * 1000000ULL + cl->t_c.tv_usec,
32375-#else
32376- (unsigned long long) q->now,
32377- (unsigned long long) cl->t_c,
32378-#endif
32379- q->jiffies);
32380- diff = 1000;
32381- }
32382-#endif
32383+ diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32) cl->mbuffer);
32384 if (cl->level >= level) {
32385- if (cl->level == level) cl->xstats.lends++;
32386- HTB_ACCNT (tokens,buffer,rate);
32387+ if (cl->level == level)
32388+ cl->xstats.lends++;
32389+ HTB_ACCNT(tokens, buffer, rate);
32390 } else {
32391 cl->xstats.borrows++;
32392- cl->tokens += diff; /* we moved t_c; update tokens */
32393+ cl->tokens += diff; /* we moved t_c; update tokens */
32394 }
32395- HTB_ACCNT (ctokens,cbuffer,ceil);
32396+ HTB_ACCNT(ctokens, cbuffer, ceil);
32397 cl->t_c = q->now;
32398- HTB_DBG(5,2,"htb_chrg_clp cl=%X diff=%ld tok=%ld ctok=%ld\n",cl->classid,diff,cl->tokens,cl->ctokens);
32399
32400- old_mode = cl->cmode; diff = 0;
32401- htb_change_class_mode(q,cl,&diff);
32402+ old_mode = cl->cmode;
32403+ diff = 0;
32404+ htb_change_class_mode(q, cl, &diff);
32405 if (old_mode != cl->cmode) {
32406 if (old_mode != HTB_CAN_SEND)
32407- htb_safe_rb_erase(&cl->pq_node,q->wait_pq+cl->level);
32408+ htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
32409 if (cl->cmode != HTB_CAN_SEND)
32410- htb_add_to_wait_tree (q,cl,diff,1);
32411+ htb_add_to_wait_tree(q, cl, diff);
32412 }
32413-
32414 #ifdef HTB_RATECM
32415 /* update rate counters */
32416- cl->sum_bytes += bytes; cl->sum_packets++;
32417+ cl->sum_bytes += bytes;
32418+ cl->sum_packets++;
32419 #endif
32420
32421 /* update byte stats except for leaves which are already updated */
32422@@ -896,60 +779,46 @@
32423 * next pending event (0 for no event in pq).
32424 * Note: Aplied are events whose have cl->pq_key <= jiffies.
32425 */
32426-static long htb_do_events(struct htb_sched *q,int level)
32427+static long htb_do_events(struct htb_sched *q, int level)
32428 {
32429 int i;
32430- HTB_DBG(8,1,"htb_do_events l=%d root=%p rmask=%X\n",
32431- level,q->wait_pq[level].rb_node,q->row_mask[level]);
32432+
32433 for (i = 0; i < 500; i++) {
32434 struct htb_class *cl;
32435 long diff;
32436 struct rb_node *p = q->wait_pq[level].rb_node;
32437- if (!p) return 0;
32438- while (p->rb_left) p = p->rb_left;
32439+ if (!p)
32440+ return 0;
32441+ while (p->rb_left)
32442+ p = p->rb_left;
32443
32444 cl = rb_entry(p, struct htb_class, pq_node);
32445 if (time_after(cl->pq_key, q->jiffies)) {
32446- HTB_DBG(8,3,"htb_do_ev_ret delay=%ld\n",cl->pq_key - q->jiffies);
32447 return cl->pq_key - q->jiffies;
32448 }
32449- htb_safe_rb_erase(p,q->wait_pq+level);
32450- diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer);
32451-#ifdef HTB_DEBUG
32452- if (diff > cl->mbuffer || diff < 0 || PSCHED_TLESS(q->now, cl->t_c)) {
32453- if (net_ratelimit())
32454- printk(KERN_ERR "HTB: bad diff in events, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n",
32455- cl->classid, diff,
32456-#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
32457- q->now.tv_sec * 1000000ULL + q->now.tv_usec,
32458- cl->t_c.tv_sec * 1000000ULL + cl->t_c.tv_usec,
32459-#else
32460- (unsigned long long) q->now,
32461- (unsigned long long) cl->t_c,
32462-#endif
32463- q->jiffies);
32464- diff = 1000;
32465- }
32466-#endif
32467- htb_change_class_mode(q,cl,&diff);
32468+ htb_safe_rb_erase(p, q->wait_pq + level);
32469+ diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32) cl->mbuffer);
32470+ htb_change_class_mode(q, cl, &diff);
32471 if (cl->cmode != HTB_CAN_SEND)
32472- htb_add_to_wait_tree (q,cl,diff,2);
32473+ htb_add_to_wait_tree(q, cl, diff);
32474 }
32475 if (net_ratelimit())
32476 printk(KERN_WARNING "htb: too many events !\n");
32477- return HZ/10;
32478+ return HZ / 10;
32479 }
32480
32481 /* Returns class->node+prio from id-tree where classe's id is >= id. NULL
32482 is no such one exists. */
32483-static struct rb_node *
32484-htb_id_find_next_upper(int prio,struct rb_node *n,u32 id)
32485+static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n,
32486+ u32 id)
32487 {
32488 struct rb_node *r = NULL;
32489 while (n) {
32490- struct htb_class *cl = rb_entry(n,struct htb_class,node[prio]);
32491- if (id == cl->classid) return n;
32492-
32493+ struct htb_class *cl =
32494+ rb_entry(n, struct htb_class, node[prio]);
32495+ if (id == cl->classid)
32496+ return n;
32497+
32498 if (id > cl->classid) {
32499 n = n->rb_right;
32500 } else {
32501@@ -965,49 +834,49 @@
32502 *
32503 * Find leaf where current feed pointers points to.
32504 */
32505-static struct htb_class *
32506-htb_lookup_leaf(HTB_ARGQ struct rb_root *tree,int prio,struct rb_node **pptr,u32 *pid)
32507+static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
32508+ struct rb_node **pptr, u32 * pid)
32509 {
32510 int i;
32511 struct {
32512 struct rb_node *root;
32513 struct rb_node **pptr;
32514 u32 *pid;
32515- } stk[TC_HTB_MAXDEPTH],*sp = stk;
32516-
32517+ } stk[TC_HTB_MAXDEPTH], *sp = stk;
32518+
32519 BUG_TRAP(tree->rb_node);
32520 sp->root = tree->rb_node;
32521 sp->pptr = pptr;
32522 sp->pid = pid;
32523
32524 for (i = 0; i < 65535; i++) {
32525- HTB_DBG(4,2,"htb_lleaf ptr=%p pid=%X\n",*sp->pptr,*sp->pid);
32526-
32527- if (!*sp->pptr && *sp->pid) {
32528+ if (!*sp->pptr && *sp->pid) {
32529 /* ptr was invalidated but id is valid - try to recover
32530 the original or next ptr */
32531- *sp->pptr = htb_id_find_next_upper(prio,sp->root,*sp->pid);
32532+ *sp->pptr =
32533+ htb_id_find_next_upper(prio, sp->root, *sp->pid);
32534 }
32535- *sp->pid = 0; /* ptr is valid now so that remove this hint as it
32536- can become out of date quickly */
32537- if (!*sp->pptr) { /* we are at right end; rewind & go up */
32538+ *sp->pid = 0; /* ptr is valid now so that remove this hint as it
32539+ can become out of date quickly */
32540+ if (!*sp->pptr) { /* we are at right end; rewind & go up */
32541 *sp->pptr = sp->root;
32542- while ((*sp->pptr)->rb_left)
32543+ while ((*sp->pptr)->rb_left)
32544 *sp->pptr = (*sp->pptr)->rb_left;
32545 if (sp > stk) {
32546 sp--;
32547- BUG_TRAP(*sp->pptr); if(!*sp->pptr) return NULL;
32548- htb_next_rb_node (sp->pptr);
32549+ BUG_TRAP(*sp->pptr);
32550+ if (!*sp->pptr)
32551+ return NULL;
32552+ htb_next_rb_node(sp->pptr);
32553 }
32554 } else {
32555 struct htb_class *cl;
32556- cl = rb_entry(*sp->pptr,struct htb_class,node[prio]);
32557- HTB_CHCL(cl);
32558- if (!cl->level)
32559+ cl = rb_entry(*sp->pptr, struct htb_class, node[prio]);
32560+ if (!cl->level)
32561 return cl;
32562 (++sp)->root = cl->un.inner.feed[prio].rb_node;
32563- sp->pptr = cl->un.inner.ptr+prio;
32564- sp->pid = cl->un.inner.last_ptr_id+prio;
32565+ sp->pptr = cl->un.inner.ptr + prio;
32566+ sp->pid = cl->un.inner.last_ptr_id + prio;
32567 }
32568 }
32569 BUG_TRAP(0);
32570@@ -1016,21 +885,21 @@
32571
32572 /* dequeues packet at given priority and level; call only if
32573 you are sure that there is active class at prio/level */
32574-static struct sk_buff *
32575-htb_dequeue_tree(struct htb_sched *q,int prio,int level)
32576+static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
32577+ int level)
32578 {
32579 struct sk_buff *skb = NULL;
32580- struct htb_class *cl,*start;
32581+ struct htb_class *cl, *start;
32582 /* look initial class up in the row */
32583- start = cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,
32584- q->ptr[level]+prio,q->last_ptr_id[level]+prio);
32585-
32586+ start = cl = htb_lookup_leaf(q->row[level] + prio, prio,
32587+ q->ptr[level] + prio,
32588+ q->last_ptr_id[level] + prio);
32589+
32590 do {
32591 next:
32592- BUG_TRAP(cl);
32593- if (!cl) return NULL;
32594- HTB_DBG(4,1,"htb_deq_tr prio=%d lev=%d cl=%X defic=%d\n",
32595- prio,level,cl->classid,cl->un.leaf.deficit[level]);
32596+ BUG_TRAP(cl);
32597+ if (!cl)
32598+ return NULL;
32599
32600 /* class can be empty - it is unlikely but can be true if leaf
32601 qdisc drops packets in enqueue routine or if someone used
32602@@ -1038,64 +907,69 @@
32603 simply deactivate and skip such class */
32604 if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
32605 struct htb_class *next;
32606- htb_deactivate(q,cl);
32607+ htb_deactivate(q, cl);
32608
32609 /* row/level might become empty */
32610 if ((q->row_mask[level] & (1 << prio)) == 0)
32611- return NULL;
32612-
32613- next = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,
32614- prio,q->ptr[level]+prio,q->last_ptr_id[level]+prio);
32615+ return NULL;
32616+
32617+ next = htb_lookup_leaf(q->row[level] + prio,
32618+ prio, q->ptr[level] + prio,
32619+ q->last_ptr_id[level] + prio);
32620
32621- if (cl == start) /* fix start if we just deleted it */
32622+ if (cl == start) /* fix start if we just deleted it */
32623 start = next;
32624 cl = next;
32625 goto next;
32626 }
32627-
32628- if (likely((skb = cl->un.leaf.q->dequeue(cl->un.leaf.q)) != NULL))
32629+
32630+ skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
32631+ if (likely(skb != NULL))
32632 break;
32633 if (!cl->warned) {
32634- printk(KERN_WARNING "htb: class %X isn't work conserving ?!\n",cl->classid);
32635+ printk(KERN_WARNING
32636+ "htb: class %X isn't work conserving ?!\n",
32637+ cl->classid);
32638 cl->warned = 1;
32639 }
32640 q->nwc_hit++;
32641- htb_next_rb_node((level?cl->parent->un.inner.ptr:q->ptr[0])+prio);
32642- cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,q->ptr[level]+prio,
32643- q->last_ptr_id[level]+prio);
32644+ htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
32645+ ptr[0]) + prio);
32646+ cl = htb_lookup_leaf(q->row[level] + prio, prio,
32647+ q->ptr[level] + prio,
32648+ q->last_ptr_id[level] + prio);
32649
32650 } while (cl != start);
32651
32652 if (likely(skb != NULL)) {
32653 if ((cl->un.leaf.deficit[level] -= skb->len) < 0) {
32654- HTB_DBG(4,2,"htb_next_cl oldptr=%p quant_add=%d\n",
32655- level?cl->parent->un.inner.ptr[prio]:q->ptr[0][prio],cl->un.leaf.quantum);
32656 cl->un.leaf.deficit[level] += cl->un.leaf.quantum;
32657- htb_next_rb_node((level?cl->parent->un.inner.ptr:q->ptr[0])+prio);
32658+ htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
32659+ ptr[0]) + prio);
32660 }
32661 /* this used to be after charge_class but this constelation
32662 gives us slightly better performance */
32663 if (!cl->un.leaf.q->q.qlen)
32664- htb_deactivate (q,cl);
32665- htb_charge_class (q,cl,level,skb->len);
32666+ htb_deactivate(q, cl);
32667+ htb_charge_class(q, cl, level, skb->len);
32668 }
32669 return skb;
32670 }
32671
32672-static void htb_delay_by(struct Qdisc *sch,long delay)
32673+static void htb_delay_by(struct Qdisc *sch, long delay)
32674 {
32675 struct htb_sched *q = qdisc_priv(sch);
32676- if (delay <= 0) delay = 1;
32677- if (unlikely(delay > 5*HZ)) {
32678+ if (delay <= 0)
32679+ delay = 1;
32680+ if (unlikely(delay > 5 * HZ)) {
32681 if (net_ratelimit())
32682 printk(KERN_INFO "HTB delay %ld > 5sec\n", delay);
32683- delay = 5*HZ;
32684+ delay = 5 * HZ;
32685 }
32686 /* why don't use jiffies here ? because expires can be in past */
32687 mod_timer(&q->timer, q->jiffies + delay);
32688 sch->flags |= TCQ_F_THROTTLED;
32689 sch->qstats.overlimits++;
32690- HTB_DBG(3,1,"htb_deq t_delay=%ld\n",delay);
32691 }
32692
32693 static struct sk_buff *htb_dequeue(struct Qdisc *sch)
32694@@ -1104,22 +978,19 @@
32695 struct htb_sched *q = qdisc_priv(sch);
32696 int level;
32697 long min_delay;
32698-#ifdef HTB_DEBUG
32699- int evs_used = 0;
32700-#endif
32701
32702 q->jiffies = jiffies;
32703- HTB_DBG(3,1,"htb_deq dircnt=%d qlen=%d\n",skb_queue_len(&q->direct_queue),
32704- sch->q.qlen);
32705
32706 /* try to dequeue direct packets as high prio (!) to minimize cpu work */
32707- if ((skb = __skb_dequeue(&q->direct_queue)) != NULL) {
32708+ skb = __skb_dequeue(&q->direct_queue);
32709+ if (skb != NULL) {
32710 sch->flags &= ~TCQ_F_THROTTLED;
32711 sch->q.qlen--;
32712 return skb;
32713 }
32714
32715- if (!sch->q.qlen) goto fin;
32716+ if (!sch->q.qlen)
32717+ goto fin;
32718 PSCHED_GET_TIME(q->now);
32719
32720 min_delay = LONG_MAX;
32721@@ -1129,21 +1000,19 @@
32722 int m;
32723 long delay;
32724 if (time_after_eq(q->jiffies, q->near_ev_cache[level])) {
32725- delay = htb_do_events(q,level);
32726- q->near_ev_cache[level] = q->jiffies + (delay ? delay : HZ);
32727-#ifdef HTB_DEBUG
32728- evs_used++;
32729-#endif
32730+ delay = htb_do_events(q, level);
32731+ q->near_ev_cache[level] =
32732+ q->jiffies + (delay ? delay : HZ);
32733 } else
32734- delay = q->near_ev_cache[level] - q->jiffies;
32735-
32736- if (delay && min_delay > delay)
32737+ delay = q->near_ev_cache[level] - q->jiffies;
32738+
32739+ if (delay && min_delay > delay)
32740 min_delay = delay;
32741 m = ~q->row_mask[level];
32742 while (m != (int)(-1)) {
32743- int prio = ffz (m);
32744+ int prio = ffz(m);
32745 m |= 1 << prio;
32746- skb = htb_dequeue_tree(q,prio,level);
32747+ skb = htb_dequeue_tree(q, prio, level);
32748 if (likely(skb != NULL)) {
32749 sch->q.qlen--;
32750 sch->flags &= ~TCQ_F_THROTTLED;
32751@@ -1151,40 +1020,28 @@
32752 }
32753 }
32754 }
32755-#ifdef HTB_DEBUG
32756- if (!q->nwc_hit && min_delay >= 10*HZ && net_ratelimit()) {
32757- if (min_delay == LONG_MAX) {
32758- printk(KERN_ERR "HTB: dequeue bug (%d,%lu,%lu), report it please !\n",
32759- evs_used,q->jiffies,jiffies);
32760- htb_debug_dump(q);
32761- } else
32762- printk(KERN_WARNING "HTB: mindelay=%ld, some class has "
32763- "too small rate\n",min_delay);
32764- }
32765-#endif
32766- htb_delay_by (sch,min_delay > 5*HZ ? 5*HZ : min_delay);
32767+ htb_delay_by(sch, min_delay > 5 * HZ ? 5 * HZ : min_delay);
32768 fin:
32769- HTB_DBG(3,1,"htb_deq_end %s j=%lu skb=%p\n",sch->dev->name,q->jiffies,skb);
32770 return skb;
32771 }
32772
32773 /* try to drop from each class (by prio) until one succeed */
32774-static unsigned int htb_drop(struct Qdisc* sch)
32775+static unsigned int htb_drop(struct Qdisc *sch)
32776 {
32777 struct htb_sched *q = qdisc_priv(sch);
32778 int prio;
32779
32780 for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) {
32781 struct list_head *p;
32782- list_for_each (p,q->drops+prio) {
32783+ list_for_each(p, q->drops + prio) {
32784 struct htb_class *cl = list_entry(p, struct htb_class,
32785 un.leaf.drop_list);
32786 unsigned int len;
32787- if (cl->un.leaf.q->ops->drop &&
32788- (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
32789+ if (cl->un.leaf.q->ops->drop &&
32790+ (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
32791 sch->q.qlen--;
32792 if (!cl->un.leaf.q->q.qlen)
32793- htb_deactivate (q,cl);
32794+ htb_deactivate(q, cl);
32795 return len;
32796 }
32797 }
32798@@ -1194,29 +1051,25 @@
32799
32800 /* reset all classes */
32801 /* always caled under BH & queue lock */
32802-static void htb_reset(struct Qdisc* sch)
32803+static void htb_reset(struct Qdisc *sch)
32804 {
32805 struct htb_sched *q = qdisc_priv(sch);
32806 int i;
32807- HTB_DBG(0,1,"htb_reset sch=%p, handle=%X\n",sch,sch->handle);
32808
32809 for (i = 0; i < HTB_HSIZE; i++) {
32810- struct list_head *p;
32811- list_for_each (p,q->hash+i) {
32812- struct htb_class *cl = list_entry(p,struct htb_class,hlist);
32813+ struct hlist_node *p;
32814+ struct htb_class *cl;
32815+
32816+ hlist_for_each_entry(cl, p, q->hash + i, hlist) {
32817 if (cl->level)
32818- memset(&cl->un.inner,0,sizeof(cl->un.inner));
32819+ memset(&cl->un.inner, 0, sizeof(cl->un.inner));
32820 else {
32821- if (cl->un.leaf.q)
32822+ if (cl->un.leaf.q)
32823 qdisc_reset(cl->un.leaf.q);
32824 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
32825 }
32826 cl->prio_activity = 0;
32827 cl->cmode = HTB_CAN_SEND;
32828-#ifdef HTB_DEBUG
32829- cl->pq_node.rb_color = -1;
32830- memset(cl->node,255,sizeof(cl->node));
32831-#endif
32832
32833 }
32834 }
32835@@ -1224,12 +1077,12 @@
32836 del_timer(&q->timer);
32837 __skb_queue_purge(&q->direct_queue);
32838 sch->q.qlen = 0;
32839- memset(q->row,0,sizeof(q->row));
32840- memset(q->row_mask,0,sizeof(q->row_mask));
32841- memset(q->wait_pq,0,sizeof(q->wait_pq));
32842- memset(q->ptr,0,sizeof(q->ptr));
32843+ memset(q->row, 0, sizeof(q->row));
32844+ memset(q->row_mask, 0, sizeof(q->row_mask));
32845+ memset(q->wait_pq, 0, sizeof(q->wait_pq));
32846+ memset(q->ptr, 0, sizeof(q->ptr));
32847 for (i = 0; i < TC_HTB_NUMPRIO; i++)
32848- INIT_LIST_HEAD(q->drops+i);
32849+ INIT_LIST_HEAD(q->drops + i);
32850 }
32851
32852 static int htb_init(struct Qdisc *sch, struct rtattr *opt)
32853@@ -1238,36 +1091,31 @@
32854 struct rtattr *tb[TCA_HTB_INIT];
32855 struct tc_htb_glob *gopt;
32856 int i;
32857-#ifdef HTB_DEBUG
32858- printk(KERN_INFO "HTB init, kernel part version %d.%d\n",
32859- HTB_VER >> 16,HTB_VER & 0xffff);
32860-#endif
32861 if (!opt || rtattr_parse_nested(tb, TCA_HTB_INIT, opt) ||
32862- tb[TCA_HTB_INIT-1] == NULL ||
32863- RTA_PAYLOAD(tb[TCA_HTB_INIT-1]) < sizeof(*gopt)) {
32864+ tb[TCA_HTB_INIT - 1] == NULL ||
32865+ RTA_PAYLOAD(tb[TCA_HTB_INIT - 1]) < sizeof(*gopt)) {
32866 printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
32867 return -EINVAL;
32868 }
32869- gopt = RTA_DATA(tb[TCA_HTB_INIT-1]);
32870+ gopt = RTA_DATA(tb[TCA_HTB_INIT - 1]);
32871 if (gopt->version != HTB_VER >> 16) {
32872- printk(KERN_ERR "HTB: need tc/htb version %d (minor is %d), you have %d\n",
32873- HTB_VER >> 16,HTB_VER & 0xffff,gopt->version);
32874+ printk(KERN_ERR
32875+ "HTB: need tc/htb version %d (minor is %d), you have %d\n",
32876+ HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
32877 return -EINVAL;
32878 }
32879- q->debug = gopt->debug;
32880- HTB_DBG(0,1,"htb_init sch=%p handle=%X r2q=%d\n",sch,sch->handle,gopt->rate2quantum);
32881
32882 INIT_LIST_HEAD(&q->root);
32883 for (i = 0; i < HTB_HSIZE; i++)
32884- INIT_LIST_HEAD(q->hash+i);
32885+ INIT_HLIST_HEAD(q->hash + i);
32886 for (i = 0; i < TC_HTB_NUMPRIO; i++)
32887- INIT_LIST_HEAD(q->drops+i);
32888+ INIT_LIST_HEAD(q->drops + i);
32889
32890 init_timer(&q->timer);
32891 skb_queue_head_init(&q->direct_queue);
32892
32893 q->direct_qlen = sch->dev->tx_queue_len;
32894- if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
32895+ if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
32896 q->direct_qlen = 2;
32897 q->timer.function = htb_timer;
32898 q->timer.data = (unsigned long)sch;
32899@@ -1289,80 +1137,72 @@
32900 static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
32901 {
32902 struct htb_sched *q = qdisc_priv(sch);
32903- unsigned char *b = skb->tail;
32904+ unsigned char *b = skb->tail;
32905 struct rtattr *rta;
32906 struct tc_htb_glob gopt;
32907- HTB_DBG(0,1,"htb_dump sch=%p, handle=%X\n",sch,sch->handle);
32908- HTB_QLOCK(sch);
32909+ spin_lock_bh(&sch->dev->queue_lock);
32910 gopt.direct_pkts = q->direct_pkts;
32911
32912-#ifdef HTB_DEBUG
32913- if (HTB_DBG_COND(0,2))
32914- htb_debug_dump(q);
32915-#endif
32916 gopt.version = HTB_VER;
32917 gopt.rate2quantum = q->rate2quantum;
32918 gopt.defcls = q->defcls;
32919- gopt.debug = q->debug;
32920- rta = (struct rtattr*)b;
32921+ gopt.debug = 0;
32922+ rta = (struct rtattr *)b;
32923 RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
32924 RTA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
32925 rta->rta_len = skb->tail - b;
32926- HTB_QUNLOCK(sch);
32927+ spin_unlock_bh(&sch->dev->queue_lock);
32928 return skb->len;
32929 rtattr_failure:
32930- HTB_QUNLOCK(sch);
32931+ spin_unlock_bh(&sch->dev->queue_lock);
32932 skb_trim(skb, skb->tail - skb->data);
32933 return -1;
32934 }
32935
32936 static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
32937- struct sk_buff *skb, struct tcmsg *tcm)
32938+ struct sk_buff *skb, struct tcmsg *tcm)
32939 {
32940-#ifdef HTB_DEBUG
32941- struct htb_sched *q = qdisc_priv(sch);
32942-#endif
32943- struct htb_class *cl = (struct htb_class*)arg;
32944- unsigned char *b = skb->tail;
32945+ struct htb_class *cl = (struct htb_class *)arg;
32946+ unsigned char *b = skb->tail;
32947 struct rtattr *rta;
32948 struct tc_htb_opt opt;
32949
32950- HTB_DBG(0,1,"htb_dump_class handle=%X clid=%X\n",sch->handle,cl->classid);
32951-
32952- HTB_QLOCK(sch);
32953+ spin_lock_bh(&sch->dev->queue_lock);
32954 tcm->tcm_parent = cl->parent ? cl->parent->classid : TC_H_ROOT;
32955 tcm->tcm_handle = cl->classid;
32956 if (!cl->level && cl->un.leaf.q)
32957 tcm->tcm_info = cl->un.leaf.q->handle;
32958
32959- rta = (struct rtattr*)b;
32960+ rta = (struct rtattr *)b;
32961 RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
32962
32963- memset (&opt,0,sizeof(opt));
32964+ memset(&opt, 0, sizeof(opt));
32965
32966- opt.rate = cl->rate->rate; opt.buffer = cl->buffer;
32967- opt.ceil = cl->ceil->rate; opt.cbuffer = cl->cbuffer;
32968- opt.quantum = cl->un.leaf.quantum; opt.prio = cl->un.leaf.prio;
32969- opt.level = cl->level;
32970+ opt.rate = cl->rate->rate;
32971+ opt.buffer = cl->buffer;
32972+ opt.ceil = cl->ceil->rate;
32973+ opt.cbuffer = cl->cbuffer;
32974+ opt.quantum = cl->un.leaf.quantum;
32975+ opt.prio = cl->un.leaf.prio;
32976+ opt.level = cl->level;
32977 RTA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
32978 rta->rta_len = skb->tail - b;
32979- HTB_QUNLOCK(sch);
32980+ spin_unlock_bh(&sch->dev->queue_lock);
32981 return skb->len;
32982 rtattr_failure:
32983- HTB_QUNLOCK(sch);
32984+ spin_unlock_bh(&sch->dev->queue_lock);
32985 skb_trim(skb, b - skb->data);
32986 return -1;
32987 }
32988
32989 static int
32990-htb_dump_class_stats(struct Qdisc *sch, unsigned long arg,
32991- struct gnet_dump *d)
32992+htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
32993 {
32994- struct htb_class *cl = (struct htb_class*)arg;
32995+ struct htb_class *cl = (struct htb_class *)arg;
32996
32997 #ifdef HTB_RATECM
32998- cl->rate_est.bps = cl->rate_bytes/(HTB_EWMAC*HTB_HSIZE);
32999- cl->rate_est.pps = cl->rate_packets/(HTB_EWMAC*HTB_HSIZE);
33000+ cl->rate_est.bps = cl->rate_bytes / (HTB_EWMAC * HTB_HSIZE);
33001+ cl->rate_est.pps = cl->rate_packets / (HTB_EWMAC * HTB_HSIZE);
33002 #endif
33003
33004 if (!cl->level && cl->un.leaf.q)
33005@@ -1379,21 +1219,22 @@
33006 }
33007
33008 static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
33009- struct Qdisc **old)
33010+ struct Qdisc **old)
33011 {
33012- struct htb_class *cl = (struct htb_class*)arg;
33013+ struct htb_class *cl = (struct htb_class *)arg;
33014
33015 if (cl && !cl->level) {
33016- if (new == NULL && (new = qdisc_create_dflt(sch->dev,
33017- &pfifo_qdisc_ops)) == NULL)
33018- return -ENOBUFS;
33019+ if (new == NULL && (new = qdisc_create_dflt(sch->dev,
33020+ &pfifo_qdisc_ops))
33021+ == NULL)
33022+ return -ENOBUFS;
33023 sch_tree_lock(sch);
33024 if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) {
33025 if (cl->prio_activity)
33026- htb_deactivate (qdisc_priv(sch),cl);
33027+ htb_deactivate(qdisc_priv(sch), cl);
33028
33029 /* TODO: is it correct ? Why CBQ doesn't do it ? */
33030- sch->q.qlen -= (*old)->q.qlen;
33031+ sch->q.qlen -= (*old)->q.qlen;
33032 qdisc_reset(*old);
33033 }
33034 sch_tree_unlock(sch);
33035@@ -1402,20 +1243,16 @@
33036 return -ENOENT;
33037 }
33038
33039-static struct Qdisc * htb_leaf(struct Qdisc *sch, unsigned long arg)
33040+static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
33041 {
33042- struct htb_class *cl = (struct htb_class*)arg;
33043+ struct htb_class *cl = (struct htb_class *)arg;
33044 return (cl && !cl->level) ? cl->un.leaf.q : NULL;
33045 }
33046
33047 static unsigned long htb_get(struct Qdisc *sch, u32 classid)
33048 {
33049-#ifdef HTB_DEBUG
33050- struct htb_sched *q = qdisc_priv(sch);
33051-#endif
33052- struct htb_class *cl = htb_find(classid,sch);
33053- HTB_DBG(0,1,"htb_get clid=%X q=%p cl=%p ref=%d\n",classid,q,cl,cl?cl->refcnt:0);
33054- if (cl)
33055+ struct htb_class *cl = htb_find(classid, sch);
33056+ if (cl)
33057 cl->refcnt++;
33058 return (unsigned long)cl;
33059 }
33060@@ -1430,10 +1267,9 @@
33061 }
33062 }
33063
33064-static void htb_destroy_class(struct Qdisc* sch,struct htb_class *cl)
33065+static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
33066 {
33067 struct htb_sched *q = qdisc_priv(sch);
33068- HTB_DBG(0,1,"htb_destrycls clid=%X ref=%d\n", cl?cl->classid:0,cl?cl->refcnt:0);
33069 if (!cl->level) {
33070 BUG_TRAP(cl->un.leaf.q);
33071 sch->q.qlen -= cl->un.leaf.q->q.qlen;
33072@@ -1441,45 +1277,45 @@
33073 }
33074 qdisc_put_rtab(cl->rate);
33075 qdisc_put_rtab(cl->ceil);
33076-
33077- htb_destroy_filters (&cl->filter_list);
33078-
33079- while (!list_empty(&cl->children))
33080- htb_destroy_class (sch,list_entry(cl->children.next,
33081- struct htb_class,sibling));
33082+
33083+ htb_destroy_filters(&cl->filter_list);
33084+
33085+ while (!list_empty(&cl->children))
33086+ htb_destroy_class(sch, list_entry(cl->children.next,
33087+ struct htb_class, sibling));
33088
33089 /* note: this delete may happen twice (see htb_delete) */
33090- list_del(&cl->hlist);
33091+ if (!hlist_unhashed(&cl->hlist))
33092+ hlist_del(&cl->hlist);
33093 list_del(&cl->sibling);
33094-
33095+
33096 if (cl->prio_activity)
33097- htb_deactivate (q,cl);
33098-
33099+ htb_deactivate(q, cl);
33100+
33101 if (cl->cmode != HTB_CAN_SEND)
33102- htb_safe_rb_erase(&cl->pq_node,q->wait_pq+cl->level);
33103-
33104+ htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
33105+
33106 kfree(cl);
33107 }
33108
33109 /* always caled under BH & queue lock */
33110-static void htb_destroy(struct Qdisc* sch)
33111+static void htb_destroy(struct Qdisc *sch)
33112 {
33113 struct htb_sched *q = qdisc_priv(sch);
33114- HTB_DBG(0,1,"htb_destroy q=%p\n",q);
33115
33116- del_timer_sync (&q->timer);
33117+ del_timer_sync(&q->timer);
33118 #ifdef HTB_RATECM
33119- del_timer_sync (&q->rttim);
33120+ del_timer_sync(&q->rttim);
33121 #endif
33122 /* This line used to be after htb_destroy_class call below
33123 and surprisingly it worked in 2.4. But it must precede it
33124 because filter need its target class alive to be able to call
33125 unbind_filter on it (without Oops). */
33126 htb_destroy_filters(&q->filter_list);
33127-
33128- while (!list_empty(&q->root))
33129- htb_destroy_class (sch,list_entry(q->root.next,
33130- struct htb_class,sibling));
33131+
33132+ while (!list_empty(&q->root))
33133+ htb_destroy_class(sch, list_entry(q->root.next,
33134+ struct htb_class, sibling));
33135
33136 __skb_queue_purge(&q->direct_queue);
33137 }
33138@@ -1487,24 +1323,25 @@
33139 static int htb_delete(struct Qdisc *sch, unsigned long arg)
33140 {
33141 struct htb_sched *q = qdisc_priv(sch);
33142- struct htb_class *cl = (struct htb_class*)arg;
33143- HTB_DBG(0,1,"htb_delete q=%p cl=%X ref=%d\n",q,cl?cl->classid:0,cl?cl->refcnt:0);
33144+ struct htb_class *cl = (struct htb_class *)arg;
33145
33146 // TODO: why don't allow to delete subtree ? references ? does
33147 // tc subsys quarantee us that in htb_destroy it holds no class
33148 // refs so that we can remove children safely there ?
33149 if (!list_empty(&cl->children) || cl->filter_cnt)
33150 return -EBUSY;
33151-
33152+
33153 sch_tree_lock(sch);
33154-
33155+
33156 /* delete from hash and active; remainder in destroy_class */
33157- list_del_init(&cl->hlist);
33158+ if (!hlist_unhashed(&cl->hlist))
33159+ hlist_del(&cl->hlist);
33160+
33161 if (cl->prio_activity)
33162- htb_deactivate (q,cl);
33163+ htb_deactivate(q, cl);
33164
33165 if (--cl->refcnt == 0)
33166- htb_destroy_class(sch,cl);
33167+ htb_destroy_class(sch, cl);
33168
33169 sch_tree_unlock(sch);
33170 return 0;
33171@@ -1512,45 +1349,46 @@
33172
33173 static void htb_put(struct Qdisc *sch, unsigned long arg)
33174 {
33175-#ifdef HTB_DEBUG
33176- struct htb_sched *q = qdisc_priv(sch);
33177-#endif
33178- struct htb_class *cl = (struct htb_class*)arg;
33179- HTB_DBG(0,1,"htb_put q=%p cl=%X ref=%d\n",q,cl?cl->classid:0,cl?cl->refcnt:0);
33180+ struct htb_class *cl = (struct htb_class *)arg;
33181
33182 if (--cl->refcnt == 0)
33183- htb_destroy_class(sch,cl);
33184+ htb_destroy_class(sch, cl);
33185 }
33186
33187-static int htb_change_class(struct Qdisc *sch, u32 classid,
33188- u32 parentid, struct rtattr **tca, unsigned long *arg)
33189+static int htb_change_class(struct Qdisc *sch, u32 classid,
33190+ u32 parentid, struct rtattr **tca,
33191+ unsigned long *arg)
33192 {
33193 int err = -EINVAL;
33194 struct htb_sched *q = qdisc_priv(sch);
33195- struct htb_class *cl = (struct htb_class*)*arg,*parent;
33196- struct rtattr *opt = tca[TCA_OPTIONS-1];
33197+ struct htb_class *cl = (struct htb_class *)*arg, *parent;
33198+ struct rtattr *opt = tca[TCA_OPTIONS - 1];
33199 struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
33200 struct rtattr *tb[TCA_HTB_RTAB];
33201 struct tc_htb_opt *hopt;
33202
33203 /* extract all subattrs from opt attr */
33204 if (!opt || rtattr_parse_nested(tb, TCA_HTB_RTAB, opt) ||
33205- tb[TCA_HTB_PARMS-1] == NULL ||
33206- RTA_PAYLOAD(tb[TCA_HTB_PARMS-1]) < sizeof(*hopt))
33207+ tb[TCA_HTB_PARMS - 1] == NULL ||
33208+ RTA_PAYLOAD(tb[TCA_HTB_PARMS - 1]) < sizeof(*hopt))
33209 goto failure;
33210-
33211- parent = parentid == TC_H_ROOT ? NULL : htb_find (parentid,sch);
33212
33213- hopt = RTA_DATA(tb[TCA_HTB_PARMS-1]);
33214- HTB_DBG(0,1,"htb_chg cl=%p(%X), clid=%X, parid=%X, opt/prio=%d, rate=%u, buff=%d, quant=%d\n", cl,cl?cl->classid:0,classid,parentid,(int)hopt->prio,hopt->rate.rate,hopt->buffer,hopt->quantum);
33215- rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB-1]);
33216- ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB-1]);
33217- if (!rtab || !ctab) goto failure;
33218+ parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
33219+
33220+ hopt = RTA_DATA(tb[TCA_HTB_PARMS - 1]);
33221+
33222+ rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB - 1]);
33223+ ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB - 1]);
33224+ if (!rtab || !ctab)
33225+ goto failure;
33226
33227- if (!cl) { /* new class */
33228+ if (!cl) { /* new class */
33229 struct Qdisc *new_q;
33230+ int prio;
33231+
33232 /* check for valid classid */
33233- if (!classid || TC_H_MAJ(classid^sch->handle) || htb_find(classid,sch))
33234+ if (!classid || TC_H_MAJ(classid ^ sch->handle)
33235+ || htb_find(classid, sch))
33236 goto failure;
33237
33238 /* check maximal depth */
33239@@ -1561,15 +1399,16 @@
33240 err = -ENOBUFS;
33241 if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
33242 goto failure;
33243-
33244+
33245 cl->refcnt = 1;
33246 INIT_LIST_HEAD(&cl->sibling);
33247- INIT_LIST_HEAD(&cl->hlist);
33248+ INIT_HLIST_NODE(&cl->hlist);
33249 INIT_LIST_HEAD(&cl->children);
33250 INIT_LIST_HEAD(&cl->un.leaf.drop_list);
33251-#ifdef HTB_DEBUG
33252- cl->magic = HTB_CMAGIC;
33253-#endif
33254+ RB_CLEAR_NODE(&cl->pq_node);
33255+
33256+ for (prio = 0; prio < TC_HTB_NUMPRIO; prio++)
33257+ RB_CLEAR_NODE(&cl->node[prio]);
33258
33259 /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
33260 so that can't be used inside of sch_tree_lock
33261@@ -1579,53 +1418,53 @@
33262 if (parent && !parent->level) {
33263 /* turn parent into inner node */
33264 sch->q.qlen -= parent->un.leaf.q->q.qlen;
33265- qdisc_destroy (parent->un.leaf.q);
33266- if (parent->prio_activity)
33267- htb_deactivate (q,parent);
33268+ qdisc_destroy(parent->un.leaf.q);
33269+ if (parent->prio_activity)
33270+ htb_deactivate(q, parent);
33271
33272 /* remove from evt list because of level change */
33273 if (parent->cmode != HTB_CAN_SEND) {
33274- htb_safe_rb_erase(&parent->pq_node,q->wait_pq /*+0*/);
33275+ htb_safe_rb_erase(&parent->pq_node, q->wait_pq);
33276 parent->cmode = HTB_CAN_SEND;
33277 }
33278 parent->level = (parent->parent ? parent->parent->level
33279- : TC_HTB_MAXDEPTH) - 1;
33280- memset (&parent->un.inner,0,sizeof(parent->un.inner));
33281+ : TC_HTB_MAXDEPTH) - 1;
33282+ memset(&parent->un.inner, 0, sizeof(parent->un.inner));
33283 }
33284 /* leaf (we) needs elementary qdisc */
33285 cl->un.leaf.q = new_q ? new_q : &noop_qdisc;
33286
33287- cl->classid = classid; cl->parent = parent;
33288+ cl->classid = classid;
33289+ cl->parent = parent;
33290
33291 /* set class to be in HTB_CAN_SEND state */
33292 cl->tokens = hopt->buffer;
33293 cl->ctokens = hopt->cbuffer;
33294- cl->mbuffer = PSCHED_JIFFIE2US(HZ*60); /* 1min */
33295+ cl->mbuffer = PSCHED_JIFFIE2US(HZ * 60); /* 1min */
33296 PSCHED_GET_TIME(cl->t_c);
33297 cl->cmode = HTB_CAN_SEND;
33298
33299 /* attach to the hash list and parent's family */
33300- list_add_tail(&cl->hlist, q->hash+htb_hash(classid));
33301- list_add_tail(&cl->sibling, parent ? &parent->children : &q->root);
33302-#ifdef HTB_DEBUG
33303- {
33304- int i;
33305- for (i = 0; i < TC_HTB_NUMPRIO; i++) cl->node[i].rb_color = -1;
33306- cl->pq_node.rb_color = -1;
33307- }
33308-#endif
33309- } else sch_tree_lock(sch);
33310+ hlist_add_head(&cl->hlist, q->hash + htb_hash(classid));
33311+ list_add_tail(&cl->sibling,
33312+ parent ? &parent->children : &q->root);
33313+ } else
33314+ sch_tree_lock(sch);
33315
33316 /* it used to be a nasty bug here, we have to check that node
33317- is really leaf before changing cl->un.leaf ! */
33318+ is really leaf before changing cl->un.leaf ! */
33319 if (!cl->level) {
33320 cl->un.leaf.quantum = rtab->rate.rate / q->rate2quantum;
33321 if (!hopt->quantum && cl->un.leaf.quantum < 1000) {
33322- printk(KERN_WARNING "HTB: quantum of class %X is small. Consider r2q change.\n", cl->classid);
33323+ printk(KERN_WARNING
33324+ "HTB: quantum of class %X is small. Consider r2q change.\n",
33325+ cl->classid);
33326 cl->un.leaf.quantum = 1000;
33327 }
33328 if (!hopt->quantum && cl->un.leaf.quantum > 200000) {
33329- printk(KERN_WARNING "HTB: quantum of class %X is big. Consider r2q change.\n", cl->classid);
33330+ printk(KERN_WARNING
33331+ "HTB: quantum of class %X is big. Consider r2q change.\n",
33332+ cl->classid);
33333 cl->un.leaf.quantum = 200000;
33334 }
33335 if (hopt->quantum)
33336@@ -1636,16 +1475,22 @@
33337
33338 cl->buffer = hopt->buffer;
33339 cl->cbuffer = hopt->cbuffer;
33340- if (cl->rate) qdisc_put_rtab(cl->rate); cl->rate = rtab;
33341- if (cl->ceil) qdisc_put_rtab(cl->ceil); cl->ceil = ctab;
33342+ if (cl->rate)
33343+ qdisc_put_rtab(cl->rate);
33344+ cl->rate = rtab;
33345+ if (cl->ceil)
33346+ qdisc_put_rtab(cl->ceil);
33347+ cl->ceil = ctab;
33348 sch_tree_unlock(sch);
33349
33350 *arg = (unsigned long)cl;
33351 return 0;
33352
33353 failure:
33354- if (rtab) qdisc_put_rtab(rtab);
33355- if (ctab) qdisc_put_rtab(ctab);
33356+ if (rtab)
33357+ qdisc_put_rtab(rtab);
33358+ if (ctab)
33359+ qdisc_put_rtab(ctab);
33360 return err;
33361 }
33362
33363@@ -1654,28 +1499,28 @@
33364 struct htb_sched *q = qdisc_priv(sch);
33365 struct htb_class *cl = (struct htb_class *)arg;
33366 struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list;
33367- HTB_DBG(0,2,"htb_tcf q=%p clid=%X fref=%d fl=%p\n",q,cl?cl->classid:0,cl?cl->filter_cnt:q->filter_cnt,*fl);
33368+
33369 return fl;
33370 }
33371
33372 static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
33373- u32 classid)
33374+ u32 classid)
33375 {
33376 struct htb_sched *q = qdisc_priv(sch);
33377- struct htb_class *cl = htb_find (classid,sch);
33378- HTB_DBG(0,2,"htb_bind q=%p clid=%X cl=%p fref=%d\n",q,classid,cl,cl?cl->filter_cnt:q->filter_cnt);
33379+ struct htb_class *cl = htb_find(classid, sch);
33380+
33381 /*if (cl && !cl->level) return 0;
33382- The line above used to be there to prevent attaching filters to
33383- leaves. But at least tc_index filter uses this just to get class
33384- for other reasons so that we have to allow for it.
33385- ----
33386- 19.6.2002 As Werner explained it is ok - bind filter is just
33387- another way to "lock" the class - unlike "get" this lock can
33388- be broken by class during destroy IIUC.
33389+ The line above used to be there to prevent attaching filters to
33390+ leaves. But at least tc_index filter uses this just to get class
33391+ for other reasons so that we have to allow for it.
33392+ ----
33393+ 19.6.2002 As Werner explained it is ok - bind filter is just
33394+ another way to "lock" the class - unlike "get" this lock can
33395+ be broken by class during destroy IIUC.
33396 */
33397- if (cl)
33398- cl->filter_cnt++;
33399- else
33400+ if (cl)
33401+ cl->filter_cnt++;
33402+ else
33403 q->filter_cnt++;
33404 return (unsigned long)cl;
33405 }
33406@@ -1684,10 +1529,10 @@
33407 {
33408 struct htb_sched *q = qdisc_priv(sch);
33409 struct htb_class *cl = (struct htb_class *)arg;
33410- HTB_DBG(0,2,"htb_unbind q=%p cl=%p fref=%d\n",q,cl,cl?cl->filter_cnt:q->filter_cnt);
33411- if (cl)
33412- cl->filter_cnt--;
33413- else
33414+
33415+ if (cl)
33416+ cl->filter_cnt--;
33417+ else
33418 q->filter_cnt--;
33419 }
33420
33421@@ -1700,9 +1545,10 @@
33422 return;
33423
33424 for (i = 0; i < HTB_HSIZE; i++) {
33425- struct list_head *p;
33426- list_for_each (p,q->hash+i) {
33427- struct htb_class *cl = list_entry(p,struct htb_class,hlist);
33428+ struct hlist_node *p;
33429+ struct htb_class *cl;
33430+
33431+ hlist_for_each_entry(cl, p, q->hash + i, hlist) {
33432 if (arg->count < arg->skip) {
33433 arg->count++;
33434 continue;
33435@@ -1750,12 +1596,13 @@
33436
33437 static int __init htb_module_init(void)
33438 {
33439- return register_qdisc(&htb_qdisc_ops);
33440+ return register_qdisc(&htb_qdisc_ops);
33441 }
33442-static void __exit htb_module_exit(void)
33443+static void __exit htb_module_exit(void)
33444 {
33445- unregister_qdisc(&htb_qdisc_ops);
33446+ unregister_qdisc(&htb_qdisc_ops);
33447 }
33448+
33449 module_init(htb_module_init)
33450 module_exit(htb_module_exit)
33451 MODULE_LICENSE("GPL");
33452diff -Nur linux-2.6.18-rc5/net/sched/sch_netem.c linux-2.6.19/net/sched/sch_netem.c
33453--- linux-2.6.18-rc5/net/sched/sch_netem.c 2006-08-28 05:41:48.000000000 +0200
33454+++ linux-2.6.19/net/sched/sch_netem.c 2006-09-22 10:04:59.000000000 +0200
33455@@ -192,8 +192,8 @@
33456 */
33457 if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
33458 if (!(skb = skb_unshare(skb, GFP_ATOMIC))
33459- || (skb->ip_summed == CHECKSUM_HW
33460- && skb_checksum_help(skb, 0))) {
33461+ || (skb->ip_summed == CHECKSUM_PARTIAL
33462+ && skb_checksum_help(skb))) {
33463 sch->qstats.drops++;
33464 return NET_XMIT_DROP;
33465 }
33466diff -Nur linux-2.6.18-rc5/net/sctp/input.c linux-2.6.19/net/sctp/input.c
33467--- linux-2.6.18-rc5/net/sctp/input.c 2006-08-28 05:41:48.000000000 +0200
33468+++ linux-2.6.19/net/sctp/input.c 2006-09-22 10:04:59.000000000 +0200
33469@@ -228,7 +228,7 @@
33470 goto discard_release;
33471 nf_reset(skb);
33472
33473- if (sk_filter(sk, skb, 1))
33474+ if (sk_filter(sk, skb))
33475 goto discard_release;
33476
33477 /* Create an SCTP packet structure. */
33478@@ -255,10 +255,13 @@
33479 */
33480 sctp_bh_lock_sock(sk);
33481
33482- if (sock_owned_by_user(sk))
33483+ if (sock_owned_by_user(sk)) {
33484+ SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG);
33485 sctp_add_backlog(sk, skb);
33486- else
33487+ } else {
33488+ SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ);
33489 sctp_inq_push(&chunk->rcvr->inqueue, chunk);
33490+ }
33491
33492 sctp_bh_unlock_sock(sk);
33493
33494@@ -271,6 +274,7 @@
33495 return 0;
33496
33497 discard_it:
33498+ SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_DISCARDS);
33499 kfree_skb(skb);
33500 return 0;
33501
33502diff -Nur linux-2.6.18-rc5/net/sctp/inqueue.c linux-2.6.19/net/sctp/inqueue.c
33503--- linux-2.6.18-rc5/net/sctp/inqueue.c 2006-08-28 05:41:48.000000000 +0200
33504+++ linux-2.6.19/net/sctp/inqueue.c 2006-09-22 10:04:59.000000000 +0200
33505@@ -87,7 +87,7 @@
33506 /* Put a new packet in an SCTP inqueue.
33507 * We assume that packet->sctp_hdr is set and in host byte order.
33508 */
33509-void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *packet)
33510+void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
33511 {
33512 /* Directly call the packet handling routine. */
33513
33514@@ -96,7 +96,7 @@
33515 * Eventually, we should clean up inqueue to not rely
33516 * on the BH related data structures.
33517 */
33518- list_add_tail(&packet->list, &q->in_chunk_list);
33519+ list_add_tail(&chunk->list, &q->in_chunk_list);
33520 q->immediate.func(q->immediate.data);
33521 }
33522
33523diff -Nur linux-2.6.18-rc5/net/sctp/ipv6.c linux-2.6.19/net/sctp/ipv6.c
33524--- linux-2.6.18-rc5/net/sctp/ipv6.c 2006-08-28 05:41:48.000000000 +0200
33525+++ linux-2.6.19/net/sctp/ipv6.c 2006-09-22 10:04:59.000000000 +0200
33526@@ -78,7 +78,6 @@
33527
33528 #include <asm/uaccess.h>
33529
33530-extern int sctp_inetaddr_event(struct notifier_block *, unsigned long, void *);
33531 static struct notifier_block sctp_inet6addr_notifier = {
33532 .notifier_call = sctp_inetaddr_event,
33533 };
33534diff -Nur linux-2.6.18-rc5/net/sctp/outqueue.c linux-2.6.19/net/sctp/outqueue.c
33535--- linux-2.6.18-rc5/net/sctp/outqueue.c 2006-08-28 05:41:48.000000000 +0200
33536+++ linux-2.6.19/net/sctp/outqueue.c 2006-09-22 10:04:59.000000000 +0200
33537@@ -467,6 +467,7 @@
33538
33539 switch(reason) {
33540 case SCTP_RTXR_T3_RTX:
33541+ SCTP_INC_STATS(SCTP_MIB_T3_RETRANSMITS);
33542 sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX);
33543 /* Update the retran path if the T3-rtx timer has expired for
33544 * the current retran path.
33545@@ -475,12 +476,15 @@
33546 sctp_assoc_update_retran_path(transport->asoc);
33547 break;
33548 case SCTP_RTXR_FAST_RTX:
33549+ SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
33550 sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
33551 fast_retransmit = 1;
33552 break;
33553 case SCTP_RTXR_PMTUD:
33554- default:
33555+ SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
33556 break;
33557+ default:
33558+ BUG();
33559 }
33560
33561 sctp_retransmit_mark(q, transport, fast_retransmit);
33562diff -Nur linux-2.6.18-rc5/net/sctp/proc.c linux-2.6.19/net/sctp/proc.c
33563--- linux-2.6.18-rc5/net/sctp/proc.c 2006-08-28 05:41:48.000000000 +0200
33564+++ linux-2.6.19/net/sctp/proc.c 2006-09-22 10:04:59.000000000 +0200
33565@@ -57,6 +57,21 @@
33566 SNMP_MIB_ITEM("SctpReasmUsrMsgs", SCTP_MIB_REASMUSRMSGS),
33567 SNMP_MIB_ITEM("SctpOutSCTPPacks", SCTP_MIB_OUTSCTPPACKS),
33568 SNMP_MIB_ITEM("SctpInSCTPPacks", SCTP_MIB_INSCTPPACKS),
33569+ SNMP_MIB_ITEM("SctpT1InitExpireds", SCTP_MIB_T1_INIT_EXPIREDS),
33570+ SNMP_MIB_ITEM("SctpT1CookieExpireds", SCTP_MIB_T1_COOKIE_EXPIREDS),
33571+ SNMP_MIB_ITEM("SctpT2ShutdownExpireds", SCTP_MIB_T2_SHUTDOWN_EXPIREDS),
33572+ SNMP_MIB_ITEM("SctpT3RtxExpireds", SCTP_MIB_T3_RTX_EXPIREDS),
33573+ SNMP_MIB_ITEM("SctpT4RtoExpireds", SCTP_MIB_T4_RTO_EXPIREDS),
33574+ SNMP_MIB_ITEM("SctpT5ShutdownGuardExpireds", SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS),
33575+ SNMP_MIB_ITEM("SctpDelaySackExpireds", SCTP_MIB_DELAY_SACK_EXPIREDS),
33576+ SNMP_MIB_ITEM("SctpAutocloseExpireds", SCTP_MIB_AUTOCLOSE_EXPIREDS),
33577+ SNMP_MIB_ITEM("SctpT3Retransmits", SCTP_MIB_T3_RETRANSMITS),
33578+ SNMP_MIB_ITEM("SctpPmtudRetransmits", SCTP_MIB_PMTUD_RETRANSMITS),
33579+ SNMP_MIB_ITEM("SctpFastRetransmits", SCTP_MIB_FAST_RETRANSMITS),
33580+ SNMP_MIB_ITEM("SctpInPktSoftirq", SCTP_MIB_IN_PKT_SOFTIRQ),
33581+ SNMP_MIB_ITEM("SctpInPktBacklog", SCTP_MIB_IN_PKT_BACKLOG),
33582+ SNMP_MIB_ITEM("SctpInPktDiscards", SCTP_MIB_IN_PKT_DISCARDS),
33583+ SNMP_MIB_ITEM("SctpInDataChunkDiscards", SCTP_MIB_IN_DATA_CHUNK_DISCARDS),
33584 SNMP_MIB_SENTINEL
33585 };
33586
33587@@ -328,8 +343,8 @@
33588 "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
33589 assoc, sk, sctp_sk(sk)->type, sk->sk_state,
33590 assoc->state, hash, assoc->assoc_id,
33591- (sk->sk_rcvbuf - assoc->rwnd),
33592 assoc->sndbuf_used,
33593+ (sk->sk_rcvbuf - assoc->rwnd),
33594 sock_i_uid(sk), sock_i_ino(sk),
33595 epb->bind_addr.port,
33596 assoc->peer.port);
33597diff -Nur linux-2.6.18-rc5/net/sctp/protocol.c linux-2.6.19/net/sctp/protocol.c
33598--- linux-2.6.18-rc5/net/sctp/protocol.c 2006-08-28 05:41:48.000000000 +0200
33599+++ linux-2.6.19/net/sctp/protocol.c 2006-09-22 10:04:59.000000000 +0200
33600@@ -61,7 +61,7 @@
33601 #include <net/inet_ecn.h>
33602
33603 /* Global data structures. */
33604-struct sctp_globals sctp_globals;
33605+struct sctp_globals sctp_globals __read_mostly;
33606 struct proc_dir_entry *proc_net_sctp;
33607 DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly;
33608
33609@@ -82,13 +82,6 @@
33610 kmem_cache_t *sctp_chunk_cachep __read_mostly;
33611 kmem_cache_t *sctp_bucket_cachep __read_mostly;
33612
33613-extern int sctp_snmp_proc_init(void);
33614-extern int sctp_snmp_proc_exit(void);
33615-extern int sctp_eps_proc_init(void);
33616-extern int sctp_eps_proc_exit(void);
33617-extern int sctp_assocs_proc_init(void);
33618-extern int sctp_assocs_proc_exit(void);
33619-
33620 /* Return the address of the control sock. */
33621 struct sock *sctp_get_ctl_sock(void)
33622 {
33623@@ -1049,7 +1042,7 @@
33624 sctp_rto_beta = SCTP_RTO_BETA;
33625
33626 /* Valid.Cookie.Life - 60 seconds */
33627- sctp_valid_cookie_life = 60 * HZ;
33628+ sctp_valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE;
33629
33630 /* Whether Cookie Preservative is enabled(1) or not(0) */
33631 sctp_cookie_preserve_enable = 1;
33632diff -Nur linux-2.6.18-rc5/net/sctp/sm_statefuns.c linux-2.6.19/net/sctp/sm_statefuns.c
33633--- linux-2.6.18-rc5/net/sctp/sm_statefuns.c 2006-08-28 05:41:48.000000000 +0200
33634+++ linux-2.6.19/net/sctp/sm_statefuns.c 2006-09-22 10:04:59.000000000 +0200
33635@@ -187,10 +187,9 @@
33636 */
33637 ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP,
33638 0, 0, 0, GFP_ATOMIC);
33639- if (!ev)
33640- goto nomem;
33641-
33642- sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
33643+ if (ev)
33644+ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
33645+ SCTP_ULPEVENT(ev));
33646
33647 /* Upon reception of the SHUTDOWN COMPLETE chunk the endpoint
33648 * will verify that it is in SHUTDOWN-ACK-SENT state, if it is
33649@@ -215,9 +214,6 @@
33650 sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
33651
33652 return SCTP_DISPOSITION_DELETE_TCB;
33653-
33654-nomem:
33655- return SCTP_DISPOSITION_NOMEM;
33656 }
33657
33658 /*
33659@@ -347,8 +343,6 @@
33660 GFP_ATOMIC))
33661 goto nomem_init;
33662
33663- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
33664-
33665 /* B) "Z" shall respond immediately with an INIT ACK chunk. */
33666
33667 /* If there are errors need to be reported for unknown parameters,
33668@@ -360,11 +354,11 @@
33669 sizeof(sctp_chunkhdr_t);
33670
33671 if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0)
33672- goto nomem_ack;
33673+ goto nomem_init;
33674
33675 repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);
33676 if (!repl)
33677- goto nomem_ack;
33678+ goto nomem_init;
33679
33680 /* If there are errors need to be reported for unknown parameters,
33681 * include them in the outgoing INIT ACK as "Unrecognized parameter"
33682@@ -388,6 +382,8 @@
33683 sctp_chunk_free(err_chunk);
33684 }
33685
33686+ sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
33687+
33688 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
33689
33690 /*
33691@@ -400,12 +396,11 @@
33692
33693 return SCTP_DISPOSITION_DELETE_TCB;
33694
33695-nomem_ack:
33696- if (err_chunk)
33697- sctp_chunk_free(err_chunk);
33698 nomem_init:
33699 sctp_association_free(new_asoc);
33700 nomem:
33701+ if (err_chunk)
33702+ sctp_chunk_free(err_chunk);
33703 return SCTP_DISPOSITION_NOMEM;
33704 }
33705
33706@@ -600,7 +595,7 @@
33707 struct sctp_association *new_asoc;
33708 sctp_init_chunk_t *peer_init;
33709 struct sctp_chunk *repl;
33710- struct sctp_ulpevent *ev;
33711+ struct sctp_ulpevent *ev, *ai_ev = NULL;
33712 int error = 0;
33713 struct sctp_chunk *err_chk_p;
33714
33715@@ -659,20 +654,10 @@
33716 };
33717 }
33718
33719- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
33720- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
33721- SCTP_STATE(SCTP_STATE_ESTABLISHED));
33722- SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
33723- SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS);
33724- sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
33725
33726- if (new_asoc->autoclose)
33727- sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
33728- SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
33729-
33730- sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
33731-
33732- /* Re-build the bind address for the association is done in
33733+ /* Delay state machine commands until later.
33734+ *
33735+ * Re-build the bind address for the association is done in
33736 * the sctp_unpack_cookie() already.
33737 */
33738 /* This is a brand-new association, so these are not yet side
33739@@ -687,9 +672,7 @@
33740
33741 repl = sctp_make_cookie_ack(new_asoc, chunk);
33742 if (!repl)
33743- goto nomem_repl;
33744-
33745- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
33746+ goto nomem_init;
33747
33748 /* RFC 2960 5.1 Normal Establishment of an Association
33749 *
33750@@ -704,28 +687,53 @@
33751 if (!ev)
33752 goto nomem_ev;
33753
33754- sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
33755-
33756 /* Sockets API Draft Section 5.3.1.6
33757 * When a peer sends a Adaption Layer Indication parameter , SCTP
33758 * delivers this notification to inform the application that of the
33759 * peers requested adaption layer.
33760 */
33761 if (new_asoc->peer.adaption_ind) {
33762- ev = sctp_ulpevent_make_adaption_indication(new_asoc,
33763+ ai_ev = sctp_ulpevent_make_adaption_indication(new_asoc,
33764 GFP_ATOMIC);
33765- if (!ev)
33766- goto nomem_ev;
33767+ if (!ai_ev)
33768+ goto nomem_aiev;
33769+ }
33770+
33771+ /* Add all the state machine commands now since we've created
33772+ * everything. This way we don't introduce memory corruptions
33773+ * during side-effect processing and correclty count established
33774+ * associations.
33775+ */
33776+ sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
33777+ sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
33778+ SCTP_STATE(SCTP_STATE_ESTABLISHED));
33779+ SCTP_INC_STATS(SCTP_MIB_CURRESTAB);
33780+ SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS);
33781+ sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
33782+
33783+ if (new_asoc->autoclose)
33784+ sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
33785+ SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
33786
33787+ sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
33788+
33789+ /* This will send the COOKIE ACK */
33790+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
33791+
33792+ /* Queue the ASSOC_CHANGE event */
33793+ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
33794+
33795+ /* Send up the Adaptation Layer Indication event */
33796+ if (ai_ev)
33797 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
33798- SCTP_ULPEVENT(ev));
33799- }
33800+ SCTP_ULPEVENT(ai_ev));
33801
33802 return SCTP_DISPOSITION_CONSUME;
33803
33804+nomem_aiev:
33805+ sctp_ulpevent_free(ev);
33806 nomem_ev:
33807 sctp_chunk_free(repl);
33808-nomem_repl:
33809 nomem_init:
33810 sctp_association_free(new_asoc);
33811 nomem:
33812@@ -1360,10 +1368,8 @@
33813 if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type,
33814 sctp_source(chunk),
33815 (sctp_init_chunk_t *)chunk->chunk_hdr,
33816- GFP_ATOMIC)) {
33817- retval = SCTP_DISPOSITION_NOMEM;
33818- goto nomem_init;
33819- }
33820+ GFP_ATOMIC))
33821+ goto nomem;
33822
33823 /* Make sure no new addresses are being added during the
33824 * restart. Do not do this check for COOKIE-WAIT state,
33825@@ -1374,7 +1380,7 @@
33826 if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk,
33827 commands)) {
33828 retval = SCTP_DISPOSITION_CONSUME;
33829- goto cleanup_asoc;
33830+ goto nomem_retval;
33831 }
33832 }
33833
33834@@ -1430,17 +1436,17 @@
33835 sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
33836 retval = SCTP_DISPOSITION_CONSUME;
33837
33838+ return retval;
33839+
33840+nomem:
33841+ retval = SCTP_DISPOSITION_NOMEM;
33842+nomem_retval:
33843+ if (new_asoc)
33844+ sctp_association_free(new_asoc);
33845 cleanup:
33846 if (err_chunk)
33847 sctp_chunk_free(err_chunk);
33848 return retval;
33849-nomem:
33850- retval = SCTP_DISPOSITION_NOMEM;
33851- goto cleanup;
33852-nomem_init:
33853-cleanup_asoc:
33854- sctp_association_free(new_asoc);
33855- goto cleanup;
33856 }
33857
33858 /*
33859@@ -1611,15 +1617,10 @@
33860 */
33861 sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
33862
33863- /* Update the content of current association. */
33864- sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
33865-
33866 repl = sctp_make_cookie_ack(new_asoc, chunk);
33867 if (!repl)
33868 goto nomem;
33869
33870- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
33871-
33872 /* Report association restart to upper layer. */
33873 ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0,
33874 new_asoc->c.sinit_num_ostreams,
33875@@ -1628,6 +1629,9 @@
33876 if (!ev)
33877 goto nomem_ev;
33878
33879+ /* Update the content of current association. */
33880+ sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
33881+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
33882 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
33883 return SCTP_DISPOSITION_CONSUME;
33884
33885@@ -1751,7 +1755,7 @@
33886 sctp_cmd_seq_t *commands,
33887 struct sctp_association *new_asoc)
33888 {
33889- struct sctp_ulpevent *ev = NULL;
33890+ struct sctp_ulpevent *ev = NULL, *ai_ev = NULL;
33891 struct sctp_chunk *repl;
33892
33893 /* Clarification from Implementor's Guide:
33894@@ -1778,29 +1782,25 @@
33895 * SCTP user upon reception of a valid COOKIE
33896 * ECHO chunk.
33897 */
33898- ev = sctp_ulpevent_make_assoc_change(new_asoc, 0,
33899+ ev = sctp_ulpevent_make_assoc_change(asoc, 0,
33900 SCTP_COMM_UP, 0,
33901- new_asoc->c.sinit_num_ostreams,
33902- new_asoc->c.sinit_max_instreams,
33903+ asoc->c.sinit_num_ostreams,
33904+ asoc->c.sinit_max_instreams,
33905 GFP_ATOMIC);
33906 if (!ev)
33907 goto nomem;
33908- sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
33909- SCTP_ULPEVENT(ev));
33910
33911 /* Sockets API Draft Section 5.3.1.6
33912 * When a peer sends a Adaption Layer Indication parameter,
33913 * SCTP delivers this notification to inform the application
33914 * that of the peers requested adaption layer.
33915 */
33916- if (new_asoc->peer.adaption_ind) {
33917- ev = sctp_ulpevent_make_adaption_indication(new_asoc,
33918+ if (asoc->peer.adaption_ind) {
33919+ ai_ev = sctp_ulpevent_make_adaption_indication(asoc,
33920 GFP_ATOMIC);
33921- if (!ev)
33922+ if (!ai_ev)
33923 goto nomem;
33924
33925- sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
33926- SCTP_ULPEVENT(ev));
33927 }
33928 }
33929 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
33930@@ -1809,12 +1809,21 @@
33931 if (!repl)
33932 goto nomem;
33933
33934+ if (ev)
33935+ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
33936+ SCTP_ULPEVENT(ev));
33937+ if (ai_ev)
33938+ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
33939+ SCTP_ULPEVENT(ai_ev));
33940+
33941 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
33942 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
33943
33944 return SCTP_DISPOSITION_CONSUME;
33945
33946 nomem:
33947+ if (ai_ev)
33948+ sctp_ulpevent_free(ai_ev);
33949 if (ev)
33950 sctp_ulpevent_free(ev);
33951 return SCTP_DISPOSITION_NOMEM;
33952@@ -2663,9 +2672,11 @@
33953 break;
33954 case SCTP_IERROR_HIGH_TSN:
33955 case SCTP_IERROR_BAD_STREAM:
33956+ SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
33957 goto discard_noforce;
33958 case SCTP_IERROR_DUP_TSN:
33959 case SCTP_IERROR_IGNORE_TSN:
33960+ SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS);
33961 goto discard_force;
33962 case SCTP_IERROR_NO_DATA:
33963 goto consume;
33964@@ -3017,7 +3028,6 @@
33965 if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
33966 return sctp_sf_violation_chunklen(ep, asoc, type, arg,
33967 commands);
33968-
33969 /* 10.2 H) SHUTDOWN COMPLETE notification
33970 *
33971 * When SCTP completes the shutdown procedures (section 9.2) this
33972@@ -3028,6 +3038,14 @@
33973 if (!ev)
33974 goto nomem;
33975
33976+ /* ...send a SHUTDOWN COMPLETE chunk to its peer, */
33977+ reply = sctp_make_shutdown_complete(asoc, chunk);
33978+ if (!reply)
33979+ goto nomem_chunk;
33980+
33981+ /* Do all the commands now (after allocation), so that we
33982+ * have consistent state if memory allocation failes
33983+ */
33984 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
33985
33986 /* Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall
33987@@ -3039,11 +3057,6 @@
33988 sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
33989 SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
33990
33991- /* ...send a SHUTDOWN COMPLETE chunk to its peer, */
33992- reply = sctp_make_shutdown_complete(asoc, chunk);
33993- if (!reply)
33994- goto nomem;
33995-
33996 sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
33997 SCTP_STATE(SCTP_STATE_CLOSED));
33998 SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);
33999@@ -3054,6 +3067,8 @@
34000 sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
34001 return SCTP_DISPOSITION_DELETE_TCB;
34002
34003+nomem_chunk:
34004+ sctp_ulpevent_free(ev);
34005 nomem:
34006 return SCTP_DISPOSITION_NOMEM;
34007 }
34008@@ -3652,6 +3667,7 @@
34009 void *arg,
34010 sctp_cmd_seq_t *commands)
34011 {
34012+ SCTP_INC_STATS(SCTP_MIB_IN_PKT_DISCARDS);
34013 sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
34014
34015 return SCTP_DISPOSITION_CONSUME;
34016@@ -4548,6 +4564,8 @@
34017 {
34018 struct sctp_transport *transport = arg;
34019
34020+ SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS);
34021+
34022 if (asoc->overall_error_count >= asoc->max_retrans) {
34023 sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
34024 SCTP_ERROR(ETIMEDOUT));
34025@@ -4616,6 +4634,7 @@
34026 void *arg,
34027 sctp_cmd_seq_t *commands)
34028 {
34029+ SCTP_INC_STATS(SCTP_MIB_DELAY_SACK_EXPIREDS);
34030 sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE());
34031 return SCTP_DISPOSITION_CONSUME;
34032 }
34033@@ -4650,6 +4669,7 @@
34034 int attempts = asoc->init_err_counter + 1;
34035
34036 SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
34037+ SCTP_INC_STATS(SCTP_MIB_T1_INIT_EXPIREDS);
34038
34039 if (attempts <= asoc->max_init_attempts) {
34040 bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
34041@@ -4709,6 +4729,7 @@
34042 int attempts = asoc->init_err_counter + 1;
34043
34044 SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
34045+ SCTP_INC_STATS(SCTP_MIB_T1_COOKIE_EXPIREDS);
34046
34047 if (attempts <= asoc->max_init_attempts) {
34048 repl = sctp_make_cookie_echo(asoc, NULL);
34049@@ -4753,6 +4774,8 @@
34050 struct sctp_chunk *reply = NULL;
34051
34052 SCTP_DEBUG_PRINTK("Timer T2 expired.\n");
34053+ SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS);
34054+
34055 if (asoc->overall_error_count >= asoc->max_retrans) {
34056 sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
34057 SCTP_ERROR(ETIMEDOUT));
34058@@ -4814,6 +4837,8 @@
34059 struct sctp_chunk *chunk = asoc->addip_last_asconf;
34060 struct sctp_transport *transport = chunk->transport;
34061
34062+ SCTP_INC_STATS(SCTP_MIB_T4_RTO_EXPIREDS);
34063+
34064 /* ADDIP 4.1 B1) Increment the error counters and perform path failure
34065 * detection on the appropriate destination address as defined in
34066 * RFC2960 [5] section 8.1 and 8.2.
34067@@ -4880,6 +4905,7 @@
34068 struct sctp_chunk *reply = NULL;
34069
34070 SCTP_DEBUG_PRINTK("Timer T5 expired.\n");
34071+ SCTP_INC_STATS(SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS);
34072
34073 reply = sctp_make_abort(asoc, NULL, 0);
34074 if (!reply)
34075@@ -4910,6 +4936,8 @@
34076 {
34077 int disposition;
34078
34079+ SCTP_INC_STATS(SCTP_MIB_AUTOCLOSE_EXPIREDS);
34080+
34081 /* From 9.2 Shutdown of an Association
34082 * Upon receipt of the SHUTDOWN primitive from its upper
34083 * layer, the endpoint enters SHUTDOWN-PENDING state and
34084diff -Nur linux-2.6.18-rc5/net/sctp/sysctl.c linux-2.6.19/net/sctp/sysctl.c
34085--- linux-2.6.18-rc5/net/sctp/sysctl.c 2006-08-28 05:41:48.000000000 +0200
34086+++ linux-2.6.19/net/sctp/sysctl.c 2006-09-22 10:04:59.000000000 +0200
34087@@ -45,9 +45,10 @@
34088 #include <net/sctp/sctp.h>
34089 #include <linux/sysctl.h>
34090
34091-static ctl_handler sctp_sysctl_jiffies_ms;
34092-static long rto_timer_min = 1;
34093-static long rto_timer_max = 86400000; /* One day */
34094+static int zero = 0;
34095+static int one = 1;
34096+static int timer_max = 86400000; /* ms in one day */
34097+static int int_max = INT_MAX;
34098 static long sack_timer_min = 1;
34099 static long sack_timer_max = 500;
34100
34101@@ -56,45 +57,45 @@
34102 .ctl_name = NET_SCTP_RTO_INITIAL,
34103 .procname = "rto_initial",
34104 .data = &sctp_rto_initial,
34105- .maxlen = sizeof(long),
34106+ .maxlen = sizeof(unsigned int),
34107 .mode = 0644,
34108- .proc_handler = &proc_doulongvec_ms_jiffies_minmax,
34109- .strategy = &sctp_sysctl_jiffies_ms,
34110- .extra1 = &rto_timer_min,
34111- .extra2 = &rto_timer_max
34112+ .proc_handler = &proc_dointvec_minmax,
34113+ .strategy = &sysctl_intvec,
34114+ .extra1 = &one,
34115+ .extra2 = &timer_max
34116 },
34117 {
34118 .ctl_name = NET_SCTP_RTO_MIN,
34119 .procname = "rto_min",
34120 .data = &sctp_rto_min,
34121- .maxlen = sizeof(long),
34122+ .maxlen = sizeof(unsigned int),
34123 .mode = 0644,
34124- .proc_handler = &proc_doulongvec_ms_jiffies_minmax,
34125- .strategy = &sctp_sysctl_jiffies_ms,
34126- .extra1 = &rto_timer_min,
34127- .extra2 = &rto_timer_max
34128+ .proc_handler = &proc_dointvec_minmax,
34129+ .strategy = &sysctl_intvec,
34130+ .extra1 = &one,
34131+ .extra2 = &timer_max
34132 },
34133 {
34134 .ctl_name = NET_SCTP_RTO_MAX,
34135 .procname = "rto_max",
34136 .data = &sctp_rto_max,
34137- .maxlen = sizeof(long),
34138+ .maxlen = sizeof(unsigned int),
34139 .mode = 0644,
34140- .proc_handler = &proc_doulongvec_ms_jiffies_minmax,
34141- .strategy = &sctp_sysctl_jiffies_ms,
34142- .extra1 = &rto_timer_min,
34143- .extra2 = &rto_timer_max
34144+ .proc_handler = &proc_dointvec_minmax,
34145+ .strategy = &sysctl_intvec,
34146+ .extra1 = &one,
34147+ .extra2 = &timer_max
34148 },
34149 {
34150 .ctl_name = NET_SCTP_VALID_COOKIE_LIFE,
34151 .procname = "valid_cookie_life",
34152 .data = &sctp_valid_cookie_life,
34153- .maxlen = sizeof(long),
34154+ .maxlen = sizeof(unsigned int),
34155 .mode = 0644,
34156- .proc_handler = &proc_doulongvec_ms_jiffies_minmax,
34157- .strategy = &sctp_sysctl_jiffies_ms,
34158- .extra1 = &rto_timer_min,
34159- .extra2 = &rto_timer_max
34160+ .proc_handler = &proc_dointvec_minmax,
34161+ .strategy = &sysctl_intvec,
34162+ .extra1 = &one,
34163+ .extra2 = &timer_max
34164 },
34165 {
34166 .ctl_name = NET_SCTP_MAX_BURST,
34167@@ -102,7 +103,10 @@
34168 .data = &sctp_max_burst,
34169 .maxlen = sizeof(int),
34170 .mode = 0644,
34171- .proc_handler = &proc_dointvec
34172+ .proc_handler = &proc_dointvec_minmax,
34173+ .strategy = &sysctl_intvec,
34174+ .extra1 = &zero,
34175+ .extra2 = &int_max
34176 },
34177 {
34178 .ctl_name = NET_SCTP_ASSOCIATION_MAX_RETRANS,
34179@@ -110,7 +114,10 @@
34180 .data = &sctp_max_retrans_association,
34181 .maxlen = sizeof(int),
34182 .mode = 0644,
34183- .proc_handler = &proc_dointvec
34184+ .proc_handler = &proc_dointvec_minmax,
34185+ .strategy = &sysctl_intvec,
34186+ .extra1 = &one,
34187+ .extra2 = &int_max
34188 },
34189 {
34190 .ctl_name = NET_SCTP_SNDBUF_POLICY,
34191@@ -118,7 +125,8 @@
34192 .data = &sctp_sndbuf_policy,
34193 .maxlen = sizeof(int),
34194 .mode = 0644,
34195- .proc_handler = &proc_dointvec
34196+ .proc_handler = &proc_dointvec,
34197+ .strategy = &sysctl_intvec
34198 },
34199 {
34200 .ctl_name = NET_SCTP_RCVBUF_POLICY,
34201@@ -126,7 +134,8 @@
34202 .data = &sctp_rcvbuf_policy,
34203 .maxlen = sizeof(int),
34204 .mode = 0644,
34205- .proc_handler = &proc_dointvec
34206+ .proc_handler = &proc_dointvec,
34207+ .strategy = &sysctl_intvec
34208 },
34209 {
34210 .ctl_name = NET_SCTP_PATH_MAX_RETRANS,
34211@@ -134,7 +143,10 @@
34212 .data = &sctp_max_retrans_path,
34213 .maxlen = sizeof(int),
34214 .mode = 0644,
34215- .proc_handler = &proc_dointvec
34216+ .proc_handler = &proc_dointvec_minmax,
34217+ .strategy = &sysctl_intvec,
34218+ .extra1 = &one,
34219+ .extra2 = &int_max
34220 },
34221 {
34222 .ctl_name = NET_SCTP_MAX_INIT_RETRANSMITS,
34223@@ -142,18 +154,21 @@
34224 .data = &sctp_max_retrans_init,
34225 .maxlen = sizeof(int),
34226 .mode = 0644,
34227- .proc_handler = &proc_dointvec
34228+ .proc_handler = &proc_dointvec_minmax,
34229+ .strategy = &sysctl_intvec,
34230+ .extra1 = &one,
34231+ .extra2 = &int_max
34232 },
34233 {
34234 .ctl_name = NET_SCTP_HB_INTERVAL,
34235 .procname = "hb_interval",
34236 .data = &sctp_hb_interval,
34237- .maxlen = sizeof(long),
34238+ .maxlen = sizeof(unsigned int),
34239 .mode = 0644,
34240- .proc_handler = &proc_doulongvec_ms_jiffies_minmax,
34241- .strategy = &sctp_sysctl_jiffies_ms,
34242- .extra1 = &rto_timer_min,
34243- .extra2 = &rto_timer_max
34244+ .proc_handler = &proc_dointvec_minmax,
34245+ .strategy = &sysctl_intvec,
34246+ .extra1 = &one,
34247+ .extra2 = &timer_max
34248 },
34249 {
34250 .ctl_name = NET_SCTP_PRESERVE_ENABLE,
34251@@ -161,23 +176,26 @@
34252 .data = &sctp_cookie_preserve_enable,
34253 .maxlen = sizeof(int),
34254 .mode = 0644,
34255- .proc_handler = &proc_dointvec
34256+ .proc_handler = &proc_dointvec,
34257+ .strategy = &sysctl_intvec
34258 },
34259 {
34260 .ctl_name = NET_SCTP_RTO_ALPHA,
34261 .procname = "rto_alpha_exp_divisor",
34262 .data = &sctp_rto_alpha,
34263 .maxlen = sizeof(int),
34264- .mode = 0644,
34265- .proc_handler = &proc_dointvec
34266+ .mode = 0444,
34267+ .proc_handler = &proc_dointvec,
34268+ .strategy = &sysctl_intvec
34269 },
34270 {
34271 .ctl_name = NET_SCTP_RTO_BETA,
34272 .procname = "rto_beta_exp_divisor",
34273 .data = &sctp_rto_beta,
34274 .maxlen = sizeof(int),
34275- .mode = 0644,
34276- .proc_handler = &proc_dointvec
34277+ .mode = 0444,
34278+ .proc_handler = &proc_dointvec,
34279+ .strategy = &sysctl_intvec
34280 },
34281 {
34282 .ctl_name = NET_SCTP_ADDIP_ENABLE,
34283@@ -185,7 +203,8 @@
34284 .data = &sctp_addip_enable,
34285 .maxlen = sizeof(int),
34286 .mode = 0644,
34287- .proc_handler = &proc_dointvec
34288+ .proc_handler = &proc_dointvec,
34289+ .strategy = &sysctl_intvec
34290 },
34291 {
34292 .ctl_name = NET_SCTP_PRSCTP_ENABLE,
34293@@ -193,7 +212,8 @@
34294 .data = &sctp_prsctp_enable,
34295 .maxlen = sizeof(int),
34296 .mode = 0644,
34297- .proc_handler = &proc_dointvec
34298+ .proc_handler = &proc_dointvec,
34299+ .strategy = &sysctl_intvec
34300 },
34301 {
34302 .ctl_name = NET_SCTP_SACK_TIMEOUT,
34303@@ -201,8 +221,8 @@
34304 .data = &sctp_sack_timeout,
34305 .maxlen = sizeof(long),
34306 .mode = 0644,
34307- .proc_handler = &proc_doulongvec_ms_jiffies_minmax,
34308- .strategy = &sctp_sysctl_jiffies_ms,
34309+ .proc_handler = &proc_dointvec_minmax,
34310+ .strategy = &sysctl_intvec,
34311 .extra1 = &sack_timer_min,
34312 .extra2 = &sack_timer_max,
34313 },
34314@@ -242,37 +262,3 @@
34315 {
34316 unregister_sysctl_table(sctp_sysctl_header);
34317 }
34318-
34319-/* Strategy function to convert jiffies to milliseconds. */
34320-static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen,
34321- void __user *oldval, size_t __user *oldlenp,
34322- void __user *newval, size_t newlen, void **context) {
34323-
34324- if (oldval) {
34325- size_t olen;
34326-
34327- if (oldlenp) {
34328- if (get_user(olen, oldlenp))
34329- return -EFAULT;
34330-
34331- if (olen != sizeof (int))
34332- return -EINVAL;
34333- }
34334- if (put_user((*(int *)(table->data) * 1000) / HZ,
34335- (int __user *)oldval) ||
34336- (oldlenp && put_user(sizeof (int), oldlenp)))
34337- return -EFAULT;
34338- }
34339- if (newval && newlen) {
34340- int new;
34341-
34342- if (newlen != sizeof (int))
34343- return -EINVAL;
34344-
34345- if (get_user(new, (int __user *)newval))
34346- return -EFAULT;
34347-
34348- *(int *)(table->data) = (new * HZ) / 1000;
34349- }
34350- return 1;
34351-}
34352diff -Nur linux-2.6.18-rc5/net/sctp/transport.c linux-2.6.19/net/sctp/transport.c
34353--- linux-2.6.18-rc5/net/sctp/transport.c 2006-08-28 05:41:48.000000000 +0200
34354+++ linux-2.6.19/net/sctp/transport.c 2006-09-22 10:04:59.000000000 +0200
34355@@ -75,7 +75,7 @@
34356 * parameter 'RTO.Initial'.
34357 */
34358 peer->rtt = 0;
34359- peer->rto = sctp_rto_initial;
34360+ peer->rto = msecs_to_jiffies(sctp_rto_initial);
34361 peer->rttvar = 0;
34362 peer->srtt = 0;
34363 peer->rto_pending = 0;
34364diff -Nur linux-2.6.18-rc5/net/socket.c linux-2.6.19/net/socket.c
34365--- linux-2.6.18-rc5/net/socket.c 2006-08-28 05:41:48.000000000 +0200
34366+++ linux-2.6.19/net/socket.c 2006-09-22 10:04:59.000000000 +0200
34367@@ -42,7 +42,7 @@
34368 * Andi Kleen : Some small cleanups, optimizations,
34369 * and fixed a copy_from_user() bug.
34370 * Tigran Aivazian : sys_send(args) calls sys_sendto(args, NULL, 0)
34371- * Tigran Aivazian : Made listen(2) backlog sanity checks
34372+ * Tigran Aivazian : Made listen(2) backlog sanity checks
34373 * protocol-independent
34374 *
34375 *
34376@@ -53,17 +53,17 @@
34377 *
34378 *
34379 * This module is effectively the top level interface to the BSD socket
34380- * paradigm.
34381+ * paradigm.
34382 *
34383 * Based upon Swansea University Computer Society NET3.039
34384 */
34385
34386 #include <linux/mm.h>
34387-#include <linux/smp_lock.h>
34388 #include <linux/socket.h>
34389 #include <linux/file.h>
34390 #include <linux/net.h>
34391 #include <linux/interrupt.h>
34392+#include <linux/rcupdate.h>
34393 #include <linux/netdevice.h>
34394 #include <linux/proc_fs.h>
34395 #include <linux/seq_file.h>
34396@@ -96,25 +96,24 @@
34397
34398 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
34399 static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf,
34400- size_t size, loff_t pos);
34401+ size_t size, loff_t pos);
34402 static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *buf,
34403- size_t size, loff_t pos);
34404-static int sock_mmap(struct file *file, struct vm_area_struct * vma);
34405+ size_t size, loff_t pos);
34406+static int sock_mmap(struct file *file, struct vm_area_struct *vma);
34407
34408 static int sock_close(struct inode *inode, struct file *file);
34409 static unsigned int sock_poll(struct file *file,
34410 struct poll_table_struct *wait);
34411-static long sock_ioctl(struct file *file,
34412- unsigned int cmd, unsigned long arg);
34413+static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
34414 #ifdef CONFIG_COMPAT
34415 static long compat_sock_ioctl(struct file *file,
34416- unsigned int cmd, unsigned long arg);
34417+ unsigned int cmd, unsigned long arg);
34418 #endif
34419 static int sock_fasync(int fd, struct file *filp, int on);
34420 static ssize_t sock_readv(struct file *file, const struct iovec *vector,
34421 unsigned long count, loff_t *ppos);
34422 static ssize_t sock_writev(struct file *file, const struct iovec *vector,
34423- unsigned long count, loff_t *ppos);
34424+ unsigned long count, loff_t *ppos);
34425 static ssize_t sock_sendpage(struct file *file, struct page *page,
34426 int offset, size_t size, loff_t *ppos, int more);
34427
34428@@ -147,52 +146,8 @@
34429 * The protocol list. Each protocol is registered in here.
34430 */
34431
34432-static struct net_proto_family *net_families[NPROTO];
34433-
34434-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
34435-static atomic_t net_family_lockct = ATOMIC_INIT(0);
34436 static DEFINE_SPINLOCK(net_family_lock);
34437-
34438-/* The strategy is: modifications net_family vector are short, do not
34439- sleep and veeery rare, but read access should be free of any exclusive
34440- locks.
34441- */
34442-
34443-static void net_family_write_lock(void)
34444-{
34445- spin_lock(&net_family_lock);
34446- while (atomic_read(&net_family_lockct) != 0) {
34447- spin_unlock(&net_family_lock);
34448-
34449- yield();
34450-
34451- spin_lock(&net_family_lock);
34452- }
34453-}
34454-
34455-static __inline__ void net_family_write_unlock(void)
34456-{
34457- spin_unlock(&net_family_lock);
34458-}
34459-
34460-static __inline__ void net_family_read_lock(void)
34461-{
34462- atomic_inc(&net_family_lockct);
34463- spin_unlock_wait(&net_family_lock);
34464-}
34465-
34466-static __inline__ void net_family_read_unlock(void)
34467-{
34468- atomic_dec(&net_family_lockct);
34469-}
34470-
34471-#else
34472-#define net_family_write_lock() do { } while(0)
34473-#define net_family_write_unlock() do { } while(0)
34474-#define net_family_read_lock() do { } while(0)
34475-#define net_family_read_unlock() do { } while(0)
34476-#endif
34477-
34478+static const struct net_proto_family *net_families[NPROTO] __read_mostly;
34479
34480 /*
34481 * Statistics counters of the socket lists
34482@@ -201,19 +156,20 @@
34483 static DEFINE_PER_CPU(int, sockets_in_use) = 0;
34484
34485 /*
34486- * Support routines. Move socket addresses back and forth across the kernel/user
34487- * divide and look after the messy bits.
34488+ * Support routines.
34489+ * Move socket addresses back and forth across the kernel/user
34490+ * divide and look after the messy bits.
34491 */
34492
34493-#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
34494+#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
34495 16 for IP, 16 for IPX,
34496 24 for IPv6,
34497- about 80 for AX.25
34498+ about 80 for AX.25
34499 must be at least one bigger than
34500 the AF_UNIX size (see net/unix/af_unix.c
34501- :unix_mkname()).
34502+ :unix_mkname()).
34503 */
34504-
34505+
34506 /**
34507 * move_addr_to_kernel - copy a socket address into kernel space
34508 * @uaddr: Address in user space
34509@@ -227,11 +183,11 @@
34510
34511 int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
34512 {
34513- if(ulen<0||ulen>MAX_SOCK_ADDR)
34514+ if (ulen < 0 || ulen > MAX_SOCK_ADDR)
34515 return -EINVAL;
34516- if(ulen==0)
34517+ if (ulen == 0)
34518 return 0;
34519- if(copy_from_user(kaddr,uaddr,ulen))
34520+ if (copy_from_user(kaddr, uaddr, ulen))
34521 return -EFAULT;
34522 return audit_sockaddr(ulen, kaddr);
34523 }
34524@@ -252,51 +208,52 @@
34525 * length of the data is written over the length limit the user
34526 * specified. Zero is returned for a success.
34527 */
34528-
34529-int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ulen)
34530+
34531+int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,
34532+ int __user *ulen)
34533 {
34534 int err;
34535 int len;
34536
34537- if((err=get_user(len, ulen)))
34538+ err = get_user(len, ulen);
34539+ if (err)
34540 return err;
34541- if(len>klen)
34542- len=klen;
34543- if(len<0 || len> MAX_SOCK_ADDR)
34544+ if (len > klen)
34545+ len = klen;
34546+ if (len < 0 || len > MAX_SOCK_ADDR)
34547 return -EINVAL;
34548- if(len)
34549- {
34550+ if (len) {
34551 if (audit_sockaddr(klen, kaddr))
34552 return -ENOMEM;
34553- if(copy_to_user(uaddr,kaddr,len))
34554+ if (copy_to_user(uaddr, kaddr, len))
34555 return -EFAULT;
34556 }
34557 /*
34558- * "fromlen shall refer to the value before truncation.."
34559- * 1003.1g
34560+ * "fromlen shall refer to the value before truncation.."
34561+ * 1003.1g
34562 */
34563 return __put_user(klen, ulen);
34564 }
34565
34566 #define SOCKFS_MAGIC 0x534F434B
34567
34568-static kmem_cache_t * sock_inode_cachep __read_mostly;
34569+static kmem_cache_t *sock_inode_cachep __read_mostly;
34570
34571 static struct inode *sock_alloc_inode(struct super_block *sb)
34572 {
34573 struct socket_alloc *ei;
34574- ei = (struct socket_alloc *)kmem_cache_alloc(sock_inode_cachep, SLAB_KERNEL);
34575+
34576+ ei = kmem_cache_alloc(sock_inode_cachep, SLAB_KERNEL);
34577 if (!ei)
34578 return NULL;
34579 init_waitqueue_head(&ei->socket.wait);
34580-
34581+
34582 ei->socket.fasync_list = NULL;
34583 ei->socket.state = SS_UNCONNECTED;
34584 ei->socket.flags = 0;
34585 ei->socket.ops = NULL;
34586 ei->socket.sk = NULL;
34587 ei->socket.file = NULL;
34588- ei->socket.flags = 0;
34589
34590 return &ei->vfs_inode;
34591 }
34592@@ -307,22 +264,25 @@
34593 container_of(inode, struct socket_alloc, vfs_inode));
34594 }
34595
34596-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
34597+static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
34598 {
34599- struct socket_alloc *ei = (struct socket_alloc *) foo;
34600+ struct socket_alloc *ei = (struct socket_alloc *)foo;
34601
34602- if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
34603- SLAB_CTOR_CONSTRUCTOR)
34604+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR))
34605+ == SLAB_CTOR_CONSTRUCTOR)
34606 inode_init_once(&ei->vfs_inode);
34607 }
34608-
34609+
34610 static int init_inodecache(void)
34611 {
34612 sock_inode_cachep = kmem_cache_create("sock_inode_cache",
34613- sizeof(struct socket_alloc),
34614- 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
34615- SLAB_MEM_SPREAD),
34616- init_once, NULL);
34617+ sizeof(struct socket_alloc),
34618+ 0,
34619+ (SLAB_HWCACHE_ALIGN |
34620+ SLAB_RECLAIM_ACCOUNT |
34621+ SLAB_MEM_SPREAD),
34622+ init_once,
34623+ NULL);
34624 if (sock_inode_cachep == NULL)
34625 return -ENOMEM;
34626 return 0;
34627@@ -335,7 +295,8 @@
34628 };
34629
34630 static int sockfs_get_sb(struct file_system_type *fs_type,
34631- int flags, const char *dev_name, void *data, struct vfsmount *mnt)
34632+ int flags, const char *dev_name, void *data,
34633+ struct vfsmount *mnt)
34634 {
34635 return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC,
34636 mnt);
34637@@ -348,12 +309,13 @@
34638 .get_sb = sockfs_get_sb,
34639 .kill_sb = kill_anon_super,
34640 };
34641+
34642 static int sockfs_delete_dentry(struct dentry *dentry)
34643 {
34644 return 1;
34645 }
34646 static struct dentry_operations sockfs_dentry_operations = {
34647- .d_delete = sockfs_delete_dentry,
34648+ .d_delete = sockfs_delete_dentry,
34649 };
34650
34651 /*
34652@@ -477,10 +439,12 @@
34653 struct file *file;
34654 struct socket *sock;
34655
34656- if (!(file = fget(fd))) {
34657+ file = fget(fd);
34658+ if (!file) {
34659 *err = -EBADF;
34660 return NULL;
34661 }
34662+
34663 sock = sock_from_file(file, err);
34664 if (!sock)
34665 fput(file);
34666@@ -505,7 +469,7 @@
34667
34668 /**
34669 * sock_alloc - allocate a socket
34670- *
34671+ *
34672 * Allocate a new inode and socket object. The two are bound together
34673 * and initialised. The socket is then returned. If we are out of inodes
34674 * NULL is returned.
34675@@ -513,8 +477,8 @@
34676
34677 static struct socket *sock_alloc(void)
34678 {
34679- struct inode * inode;
34680- struct socket * sock;
34681+ struct inode *inode;
34682+ struct socket *sock;
34683
34684 inode = new_inode(sock_mnt->mnt_sb);
34685 if (!inode)
34686@@ -522,7 +486,7 @@
34687
34688 sock = SOCKET_I(inode);
34689
34690- inode->i_mode = S_IFSOCK|S_IRWXUGO;
34691+ inode->i_mode = S_IFSOCK | S_IRWXUGO;
34692 inode->i_uid = current->fsuid;
34693 inode->i_gid = current->fsgid;
34694
34695@@ -536,7 +500,7 @@
34696 * a back door. Remember to keep it shut otherwise you'll let the
34697 * creepy crawlies in.
34698 */
34699-
34700+
34701 static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
34702 {
34703 return -ENXIO;
34704@@ -553,9 +517,9 @@
34705 *
34706 * The socket is released from the protocol stack if it has a release
34707 * callback, and the inode is then released if the socket is bound to
34708- * an inode not a file.
34709+ * an inode not a file.
34710 */
34711-
34712+
34713 void sock_release(struct socket *sock)
34714 {
34715 if (sock->ops) {
34716@@ -575,10 +539,10 @@
34717 iput(SOCK_INODE(sock));
34718 return;
34719 }
34720- sock->file=NULL;
34721+ sock->file = NULL;
34722 }
34723
34724-static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
34725+static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
34726 struct msghdr *msg, size_t size)
34727 {
34728 struct sock_iocb *si = kiocb_to_siocb(iocb);
34729@@ -621,14 +585,14 @@
34730 * the following is safe, since for compiler definitions of kvec and
34731 * iovec are identical, yielding the same in-core layout and alignment
34732 */
34733- msg->msg_iov = (struct iovec *)vec,
34734+ msg->msg_iov = (struct iovec *)vec;
34735 msg->msg_iovlen = num;
34736 result = sock_sendmsg(sock, msg, size);
34737 set_fs(oldfs);
34738 return result;
34739 }
34740
34741-static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
34742+static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
34743 struct msghdr *msg, size_t size, int flags)
34744 {
34745 int err;
34746@@ -647,14 +611,14 @@
34747 return sock->ops->recvmsg(iocb, sock, msg, size, flags);
34748 }
34749
34750-int sock_recvmsg(struct socket *sock, struct msghdr *msg,
34751+int sock_recvmsg(struct socket *sock, struct msghdr *msg,
34752 size_t size, int flags)
34753 {
34754 struct kiocb iocb;
34755 struct sock_iocb siocb;
34756 int ret;
34757
34758- init_sync_kiocb(&iocb, NULL);
34759+ init_sync_kiocb(&iocb, NULL);
34760 iocb.private = &siocb;
34761 ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
34762 if (-EIOCBQUEUED == ret)
34763@@ -662,9 +626,8 @@
34764 return ret;
34765 }
34766
34767-int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
34768- struct kvec *vec, size_t num,
34769- size_t size, int flags)
34770+int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
34771+ struct kvec *vec, size_t num, size_t size, int flags)
34772 {
34773 mm_segment_t oldfs = get_fs();
34774 int result;
34775@@ -674,8 +637,7 @@
34776 * the following is safe, since for compiler definitions of kvec and
34777 * iovec are identical, yielding the same in-core layout and alignment
34778 */
34779- msg->msg_iov = (struct iovec *)vec,
34780- msg->msg_iovlen = num;
34781+ msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
34782 result = sock_recvmsg(sock, msg, size, flags);
34783 set_fs(oldfs);
34784 return result;
34785@@ -702,7 +664,8 @@
34786 }
34787
34788 static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
34789- char __user *ubuf, size_t size, struct sock_iocb *siocb)
34790+ char __user *ubuf, size_t size,
34791+ struct sock_iocb *siocb)
34792 {
34793 if (!is_sync_kiocb(iocb)) {
34794 siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
34795@@ -720,20 +683,21 @@
34796 }
34797
34798 static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
34799- struct file *file, struct iovec *iov, unsigned long nr_segs)
34800+ struct file *file, struct iovec *iov,
34801+ unsigned long nr_segs)
34802 {
34803 struct socket *sock = file->private_data;
34804 size_t size = 0;
34805 int i;
34806
34807- for (i = 0 ; i < nr_segs ; i++)
34808- size += iov[i].iov_len;
34809+ for (i = 0; i < nr_segs; i++)
34810+ size += iov[i].iov_len;
34811
34812 msg->msg_name = NULL;
34813 msg->msg_namelen = 0;
34814 msg->msg_control = NULL;
34815 msg->msg_controllen = 0;
34816- msg->msg_iov = (struct iovec *) iov;
34817+ msg->msg_iov = (struct iovec *)iov;
34818 msg->msg_iovlen = nr_segs;
34819 msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
34820
34821@@ -748,7 +712,7 @@
34822 struct msghdr msg;
34823 int ret;
34824
34825- init_sync_kiocb(&iocb, NULL);
34826+ init_sync_kiocb(&iocb, NULL);
34827 iocb.private = &siocb;
34828
34829 ret = do_sock_read(&msg, &iocb, file, (struct iovec *)iov, nr_segs);
34830@@ -758,7 +722,7 @@
34831 }
34832
34833 static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
34834- size_t count, loff_t pos)
34835+ size_t count, loff_t pos)
34836 {
34837 struct sock_iocb siocb, *x;
34838
34839@@ -771,24 +735,25 @@
34840 if (!x)
34841 return -ENOMEM;
34842 return do_sock_read(&x->async_msg, iocb, iocb->ki_filp,
34843- &x->async_iov, 1);
34844+ &x->async_iov, 1);
34845 }
34846
34847 static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
34848- struct file *file, struct iovec *iov, unsigned long nr_segs)
34849+ struct file *file, struct iovec *iov,
34850+ unsigned long nr_segs)
34851 {
34852 struct socket *sock = file->private_data;
34853 size_t size = 0;
34854 int i;
34855
34856- for (i = 0 ; i < nr_segs ; i++)
34857- size += iov[i].iov_len;
34858+ for (i = 0; i < nr_segs; i++)
34859+ size += iov[i].iov_len;
34860
34861 msg->msg_name = NULL;
34862 msg->msg_namelen = 0;
34863 msg->msg_control = NULL;
34864 msg->msg_controllen = 0;
34865- msg->msg_iov = (struct iovec *) iov;
34866+ msg->msg_iov = (struct iovec *)iov;
34867 msg->msg_iovlen = nr_segs;
34868 msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
34869 if (sock->type == SOCK_SEQPACKET)
34870@@ -815,7 +780,7 @@
34871 }
34872
34873 static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
34874- size_t count, loff_t pos)
34875+ size_t count, loff_t pos)
34876 {
34877 struct sock_iocb siocb, *x;
34878
34879@@ -829,46 +794,48 @@
34880 return -ENOMEM;
34881
34882 return do_sock_write(&x->async_msg, iocb, iocb->ki_filp,
34883- &x->async_iov, 1);
34884+ &x->async_iov, 1);
34885 }
34886
34887-
34888 /*
34889 * Atomic setting of ioctl hooks to avoid race
34890 * with module unload.
34891 */
34892
34893 static DEFINE_MUTEX(br_ioctl_mutex);
34894-static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL;
34895+static int (*br_ioctl_hook) (unsigned int cmd, void __user *arg) = NULL;
34896
34897-void brioctl_set(int (*hook)(unsigned int, void __user *))
34898+void brioctl_set(int (*hook) (unsigned int, void __user *))
34899 {
34900 mutex_lock(&br_ioctl_mutex);
34901 br_ioctl_hook = hook;
34902 mutex_unlock(&br_ioctl_mutex);
34903 }
34904+
34905 EXPORT_SYMBOL(brioctl_set);
34906
34907 static DEFINE_MUTEX(vlan_ioctl_mutex);
34908-static int (*vlan_ioctl_hook)(void __user *arg);
34909+static int (*vlan_ioctl_hook) (void __user *arg);
34910
34911-void vlan_ioctl_set(int (*hook)(void __user *))
34912+void vlan_ioctl_set(int (*hook) (void __user *))
34913 {
34914 mutex_lock(&vlan_ioctl_mutex);
34915 vlan_ioctl_hook = hook;
34916 mutex_unlock(&vlan_ioctl_mutex);
34917 }
34918+
34919 EXPORT_SYMBOL(vlan_ioctl_set);
34920
34921 static DEFINE_MUTEX(dlci_ioctl_mutex);
34922-static int (*dlci_ioctl_hook)(unsigned int, void __user *);
34923+static int (*dlci_ioctl_hook) (unsigned int, void __user *);
34924
34925-void dlci_ioctl_set(int (*hook)(unsigned int, void __user *))
34926+void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
34927 {
34928 mutex_lock(&dlci_ioctl_mutex);
34929 dlci_ioctl_hook = hook;
34930 mutex_unlock(&dlci_ioctl_mutex);
34931 }
34932+
34933 EXPORT_SYMBOL(dlci_ioctl_set);
34934
34935 /*
34936@@ -890,8 +857,8 @@
34937 if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
34938 err = dev_ioctl(cmd, argp);
34939 } else
34940-#endif /* CONFIG_WIRELESS_EXT */
34941- switch (cmd) {
34942+#endif /* CONFIG_WIRELESS_EXT */
34943+ switch (cmd) {
34944 case FIOSETOWN:
34945 case SIOCSPGRP:
34946 err = -EFAULT;
34947@@ -901,7 +868,8 @@
34948 break;
34949 case FIOGETOWN:
34950 case SIOCGPGRP:
34951- err = put_user(sock->file->f_owner.pid, (int __user *)argp);
34952+ err = put_user(sock->file->f_owner.pid,
34953+ (int __user *)argp);
34954 break;
34955 case SIOCGIFBR:
34956 case SIOCSIFBR:
34957@@ -912,7 +880,7 @@
34958 request_module("bridge");
34959
34960 mutex_lock(&br_ioctl_mutex);
34961- if (br_ioctl_hook)
34962+ if (br_ioctl_hook)
34963 err = br_ioctl_hook(cmd, argp);
34964 mutex_unlock(&br_ioctl_mutex);
34965 break;
34966@@ -929,7 +897,7 @@
34967 break;
34968 case SIOCGIFDIVERT:
34969 case SIOCSIFDIVERT:
34970- /* Convert this to call through a hook */
34971+ /* Convert this to call through a hook */
34972 err = divert_ioctl(cmd, argp);
34973 break;
34974 case SIOCADDDLCI:
34975@@ -954,7 +922,7 @@
34976 if (err == -ENOIOCTLCMD)
34977 err = dev_ioctl(cmd, argp);
34978 break;
34979- }
34980+ }
34981 return err;
34982 }
34983
34984@@ -962,7 +930,7 @@
34985 {
34986 int err;
34987 struct socket *sock = NULL;
34988-
34989+
34990 err = security_socket_create(family, type, protocol, 1);
34991 if (err)
34992 goto out;
34993@@ -973,26 +941,33 @@
34994 goto out;
34995 }
34996
34997- security_socket_post_create(sock, family, type, protocol, 1);
34998 sock->type = type;
34999+ err = security_socket_post_create(sock, family, type, protocol, 1);
35000+ if (err)
35001+ goto out_release;
35002+
35003 out:
35004 *res = sock;
35005 return err;
35006+out_release:
35007+ sock_release(sock);
35008+ sock = NULL;
35009+ goto out;
35010 }
35011
35012 /* No kernel lock held - perfect */
35013-static unsigned int sock_poll(struct file *file, poll_table * wait)
35014+static unsigned int sock_poll(struct file *file, poll_table *wait)
35015 {
35016 struct socket *sock;
35017
35018 /*
35019- * We can't return errors to poll, so it's either yes or no.
35020+ * We can't return errors to poll, so it's either yes or no.
35021 */
35022 sock = file->private_data;
35023 return sock->ops->poll(file, sock, wait);
35024 }
35025
35026-static int sock_mmap(struct file * file, struct vm_area_struct * vma)
35027+static int sock_mmap(struct file *file, struct vm_area_struct *vma)
35028 {
35029 struct socket *sock = file->private_data;
35030
35031@@ -1002,12 +977,11 @@
35032 static int sock_close(struct inode *inode, struct file *filp)
35033 {
35034 /*
35035- * It was possible the inode is NULL we were
35036- * closing an unfinished socket.
35037+ * It was possible the inode is NULL we were
35038+ * closing an unfinished socket.
35039 */
35040
35041- if (!inode)
35042- {
35043+ if (!inode) {
35044 printk(KERN_DEBUG "sock_close: NULL inode\n");
35045 return 0;
35046 }
35047@@ -1033,57 +1007,52 @@
35048
35049 static int sock_fasync(int fd, struct file *filp, int on)
35050 {
35051- struct fasync_struct *fa, *fna=NULL, **prev;
35052+ struct fasync_struct *fa, *fna = NULL, **prev;
35053 struct socket *sock;
35054 struct sock *sk;
35055
35056- if (on)
35057- {
35058+ if (on) {
35059 fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
35060- if(fna==NULL)
35061+ if (fna == NULL)
35062 return -ENOMEM;
35063 }
35064
35065 sock = filp->private_data;
35066
35067- if ((sk=sock->sk) == NULL) {
35068+ sk = sock->sk;
35069+ if (sk == NULL) {
35070 kfree(fna);
35071 return -EINVAL;
35072 }
35073
35074 lock_sock(sk);
35075
35076- prev=&(sock->fasync_list);
35077+ prev = &(sock->fasync_list);
35078
35079- for (fa=*prev; fa!=NULL; prev=&fa->fa_next,fa=*prev)
35080- if (fa->fa_file==filp)
35081+ for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev)
35082+ if (fa->fa_file == filp)
35083 break;
35084
35085- if(on)
35086- {
35087- if(fa!=NULL)
35088- {
35089+ if (on) {
35090+ if (fa != NULL) {
35091 write_lock_bh(&sk->sk_callback_lock);
35092- fa->fa_fd=fd;
35093+ fa->fa_fd = fd;
35094 write_unlock_bh(&sk->sk_callback_lock);
35095
35096 kfree(fna);
35097 goto out;
35098 }
35099- fna->fa_file=filp;
35100- fna->fa_fd=fd;
35101- fna->magic=FASYNC_MAGIC;
35102- fna->fa_next=sock->fasync_list;
35103+ fna->fa_file = filp;
35104+ fna->fa_fd = fd;
35105+ fna->magic = FASYNC_MAGIC;
35106+ fna->fa_next = sock->fasync_list;
35107 write_lock_bh(&sk->sk_callback_lock);
35108- sock->fasync_list=fna;
35109+ sock->fasync_list = fna;
35110 write_unlock_bh(&sk->sk_callback_lock);
35111- }
35112- else
35113- {
35114- if (fa!=NULL)
35115- {
35116+ } else {
35117+ if (fa != NULL) {
35118 write_lock_bh(&sk->sk_callback_lock);
35119- *prev=fa->fa_next;
35120+ *prev = fa->fa_next;
35121 write_unlock_bh(&sk->sk_callback_lock);
35122 kfree(fa);
35123 }
35124@@ -1100,10 +1069,9 @@
35125 {
35126 if (!sock || !sock->fasync_list)
35127 return -1;
35128- switch (how)
35129- {
35130+ switch (how) {
35131 case 1:
35132-
35133+
35134 if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
35135 break;
35136 goto call_kill;
35137@@ -1112,7 +1080,7 @@
35138 break;
35139 /* fall through */
35140 case 0:
35141- call_kill:
35142+call_kill:
35143 __kill_fasync(sock->fasync_list, SIGIO, band);
35144 break;
35145 case 3:
35146@@ -1121,13 +1089,15 @@
35147 return 0;
35148 }
35149
35150-static int __sock_create(int family, int type, int protocol, struct socket **res, int kern)
35151+static int __sock_create(int family, int type, int protocol,
35152+ struct socket **res, int kern)
35153 {
35154 int err;
35155 struct socket *sock;
35156+ const struct net_proto_family *pf;
35157
35158 /*
35159- * Check protocol is in range
35160+ * Check protocol is in range
35161 */
35162 if (family < 0 || family >= NPROTO)
35163 return -EAFNOSUPPORT;
35164@@ -1140,10 +1110,11 @@
35165 deadlock in module load.
35166 */
35167 if (family == PF_INET && type == SOCK_PACKET) {
35168- static int warned;
35169+ static int warned;
35170 if (!warned) {
35171 warned = 1;
35172- printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm);
35173+ printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n",
35174+ current->comm);
35175 }
35176 family = PF_PACKET;
35177 }
35178@@ -1151,79 +1122,84 @@
35179 err = security_socket_create(family, type, protocol, kern);
35180 if (err)
35181 return err;
35182-
35183+
35184+ /*
35185+ * Allocate the socket and allow the family to set things up. if
35186+ * the protocol is 0, the family is instructed to select an appropriate
35187+ * default.
35188+ */
35189+ sock = sock_alloc();
35190+ if (!sock) {
35191+ if (net_ratelimit())
35192+ printk(KERN_WARNING "socket: no more sockets\n");
35193+ return -ENFILE; /* Not exactly a match, but its the
35194+ closest posix thing */
35195+ }
35196+
35197+ sock->type = type;
35198+
35199 #if defined(CONFIG_KMOD)
35200- /* Attempt to load a protocol module if the find failed.
35201- *
35202- * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
35203+ /* Attempt to load a protocol module if the find failed.
35204+ *
35205+ * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
35206 * requested real, full-featured networking support upon configuration.
35207 * Otherwise module support will break!
35208 */
35209- if (net_families[family]==NULL)
35210- {
35211- request_module("net-pf-%d",family);
35212- }
35213+ if (net_families[family] == NULL)
35214+ request_module("net-pf-%d", family);
35215 #endif
35216
35217- net_family_read_lock();
35218- if (net_families[family] == NULL) {
35219- err = -EAFNOSUPPORT;
35220- goto out;
35221- }
35222-
35223-/*
35224- * Allocate the socket and allow the family to set things up. if
35225- * the protocol is 0, the family is instructed to select an appropriate
35226- * default.
35227- */
35228-
35229- if (!(sock = sock_alloc())) {
35230- if (net_ratelimit())
35231- printk(KERN_WARNING "socket: no more sockets\n");
35232- err = -ENFILE; /* Not exactly a match, but its the
35233- closest posix thing */
35234- goto out;
35235- }
35236-
35237- sock->type = type;
35238+ rcu_read_lock();
35239+ pf = rcu_dereference(net_families[family]);
35240+ err = -EAFNOSUPPORT;
35241+ if (!pf)
35242+ goto out_release;
35243
35244 /*
35245 * We will call the ->create function, that possibly is in a loadable
35246 * module, so we have to bump that loadable module refcnt first.
35247 */
35248- err = -EAFNOSUPPORT;
35249- if (!try_module_get(net_families[family]->owner))
35250+ if (!try_module_get(pf->owner))
35251 goto out_release;
35252
35253- if ((err = net_families[family]->create(sock, protocol)) < 0) {
35254- sock->ops = NULL;
35255+ /* Now protected by module ref count */
35256+ rcu_read_unlock();
35257+
35258+ err = pf->create(sock, protocol);
35259+ if (err < 0)
35260 goto out_module_put;
35261- }
35262
35263 /*
35264 * Now to bump the refcnt of the [loadable] module that owns this
35265 * socket at sock_release time we decrement its refcnt.
35266 */
35267- if (!try_module_get(sock->ops->owner)) {
35268- sock->ops = NULL;
35269- goto out_module_put;
35270- }
35271+ if (!try_module_get(sock->ops->owner))
35272+ goto out_module_busy;
35273+
35274 /*
35275 * Now that we're done with the ->create function, the [loadable]
35276 * module can have its refcnt decremented
35277 */
35278- module_put(net_families[family]->owner);
35279+ module_put(pf->owner);
35280+ err = security_socket_post_create(sock, family, type, protocol, kern);
35281+ if (err)
35282+ goto out_release;
35283 *res = sock;
35284- security_socket_post_create(sock, family, type, protocol, kern);
35285
35286-out:
35287- net_family_read_unlock();
35288- return err;
35289+ return 0;
35290+
35291+out_module_busy:
35292+ err = -EAFNOSUPPORT;
35293 out_module_put:
35294- module_put(net_families[family]->owner);
35295-out_release:
35296+ sock->ops = NULL;
35297+ module_put(pf->owner);
35298+out_sock_release:
35299 sock_release(sock);
35300- goto out;
35301+ return err;
35302+
35303+out_release:
35304+ rcu_read_unlock();
35305+ goto out_sock_release;
35306 }
35307
35308 int sock_create(int family, int type, int protocol, struct socket **res)
35309@@ -1261,7 +1238,8 @@
35310 * Create a pair of connected sockets.
35311 */
35312
35313-asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec)
35314+asmlinkage long sys_socketpair(int family, int type, int protocol,
35315+ int __user *usockvec)
35316 {
35317 struct socket *sock1, *sock2;
35318 int fd1, fd2, err;
35319@@ -1280,7 +1258,7 @@
35320 goto out_release_1;
35321
35322 err = sock1->ops->socketpair(sock1, sock2);
35323- if (err < 0)
35324+ if (err < 0)
35325 goto out_release_both;
35326
35327 fd1 = fd2 = -1;
35328@@ -1299,7 +1277,7 @@
35329 * Not kernel problem.
35330 */
35331
35332- err = put_user(fd1, &usockvec[0]);
35333+ err = put_user(fd1, &usockvec[0]);
35334 if (!err)
35335 err = put_user(fd2, &usockvec[1]);
35336 if (!err)
35337@@ -1310,19 +1288,18 @@
35338 return err;
35339
35340 out_close_1:
35341- sock_release(sock2);
35342+ sock_release(sock2);
35343 sys_close(fd1);
35344 return err;
35345
35346 out_release_both:
35347- sock_release(sock2);
35348+ sock_release(sock2);
35349 out_release_1:
35350- sock_release(sock1);
35351+ sock_release(sock1);
35352 out:
35353 return err;
35354 }
35355
35356-
35357 /*
35358 * Bind a name to a socket. Nothing much to do here since it's
35359 * the protocol's responsibility to handle the local address.
35360@@ -1337,35 +1314,39 @@
35361 char address[MAX_SOCK_ADDR];
35362 int err, fput_needed;
35363
35364- if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
35365- {
35366- if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
35367- err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
35368+ sock = sockfd_lookup_light(fd, &err, &fput_needed);
35369+ if(sock) {
35370+ err = move_addr_to_kernel(umyaddr, addrlen, address);
35371+ if (err >= 0) {
35372+ err = security_socket_bind(sock,
35373+ (struct sockaddr *)address,
35374+ addrlen);
35375 if (!err)
35376 err = sock->ops->bind(sock,
35377- (struct sockaddr *)address, addrlen);
35378+ (struct sockaddr *)
35379+ address, addrlen);
35380 }
35381 fput_light(sock->file, fput_needed);
35382- }
35383+ }
35384 return err;
35385 }
35386
35387-
35388 /*
35389 * Perform a listen. Basically, we allow the protocol to do anything
35390 * necessary for a listen, and if that works, we mark the socket as
35391 * ready for listening.
35392 */
35393
35394-int sysctl_somaxconn = SOMAXCONN;
35395+int sysctl_somaxconn __read_mostly = SOMAXCONN;
35396
35397 asmlinkage long sys_listen(int fd, int backlog)
35398 {
35399 struct socket *sock;
35400 int err, fput_needed;
35401-
35402- if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
35403- if ((unsigned) backlog > sysctl_somaxconn)
35404+
35405+ sock = sockfd_lookup_light(fd, &err, &fput_needed);
35406+ if (sock) {
35407+ if ((unsigned)backlog > sysctl_somaxconn)
35408 backlog = sysctl_somaxconn;
35409
35410 err = security_socket_listen(sock, backlog);
35411@@ -1377,7 +1358,6 @@
35412 return err;
35413 }
35414
35415-
35416 /*
35417 * For accept, we attempt to create a new socket, set up the link
35418 * with the client, wake up the client, then return the new
35419@@ -1390,7 +1370,8 @@
35420 * clean when we restucture accept also.
35421 */
35422
35423-asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen)
35424+asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
35425+ int __user *upeer_addrlen)
35426 {
35427 struct socket *sock, *newsock;
35428 struct file *newfile;
35429@@ -1402,7 +1383,7 @@
35430 goto out;
35431
35432 err = -ENFILE;
35433- if (!(newsock = sock_alloc()))
35434+ if (!(newsock = sock_alloc()))
35435 goto out_put;
35436
35437 newsock->type = sock->type;
35438@@ -1434,11 +1415,13 @@
35439 goto out_fd;
35440
35441 if (upeer_sockaddr) {
35442- if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
35443+ if (newsock->ops->getname(newsock, (struct sockaddr *)address,
35444+ &len, 2) < 0) {
35445 err = -ECONNABORTED;
35446 goto out_fd;
35447 }
35448- err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen);
35449+ err = move_addr_to_user(address, len, upeer_sockaddr,
35450+ upeer_addrlen);
35451 if (err < 0)
35452 goto out_fd;
35453 }
35454@@ -1460,7 +1443,6 @@
35455 goto out_put;
35456 }
35457
35458-
35459 /*
35460 * Attempt to connect to a socket with the server address. The address
35461 * is in user space so we verify it is OK and move it to kernel space.
35462@@ -1473,7 +1455,8 @@
35463 * include the -EINPROGRESS status for such sockets.
35464 */
35465
35466-asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
35467+asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,
35468+ int addrlen)
35469 {
35470 struct socket *sock;
35471 char address[MAX_SOCK_ADDR];
35472@@ -1486,11 +1469,12 @@
35473 if (err < 0)
35474 goto out_put;
35475
35476- err = security_socket_connect(sock, (struct sockaddr *)address, addrlen);
35477+ err =
35478+ security_socket_connect(sock, (struct sockaddr *)address, addrlen);
35479 if (err)
35480 goto out_put;
35481
35482- err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
35483+ err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
35484 sock->file->f_flags);
35485 out_put:
35486 fput_light(sock->file, fput_needed);
35487@@ -1503,12 +1487,13 @@
35488 * name to user space.
35489 */
35490
35491-asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len)
35492+asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
35493+ int __user *usockaddr_len)
35494 {
35495 struct socket *sock;
35496 char address[MAX_SOCK_ADDR];
35497 int len, err, fput_needed;
35498-
35499+
35500 sock = sockfd_lookup_light(fd, &err, &fput_needed);
35501 if (!sock)
35502 goto out;
35503@@ -1533,22 +1518,27 @@
35504 * name to user space.
35505 */
35506
35507-asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len)
35508+asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
35509+ int __user *usockaddr_len)
35510 {
35511 struct socket *sock;
35512 char address[MAX_SOCK_ADDR];
35513 int len, err, fput_needed;
35514
35515- if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
35516+ sock = sockfd_lookup_light(fd, &err, &fput_needed);
35517+ if (sock != NULL) {
35518 err = security_socket_getpeername(sock);
35519 if (err) {
35520 fput_light(sock->file, fput_needed);
35521 return err;
35522 }
35523
35524- err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
35525+ err =
35526+ sock->ops->getname(sock, (struct sockaddr *)address, &len,
35527+ 1);
35528 if (!err)
35529- err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
35530+ err = move_addr_to_user(address, len, usockaddr,
35531+ usockaddr_len);
35532 fput_light(sock->file, fput_needed);
35533 }
35534 return err;
35535@@ -1560,8 +1550,9 @@
35536 * the protocol.
35537 */
35538
35539-asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags,
35540- struct sockaddr __user *addr, int addr_len)
35541+asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
35542+ unsigned flags, struct sockaddr __user *addr,
35543+ int addr_len)
35544 {
35545 struct socket *sock;
35546 char address[MAX_SOCK_ADDR];
35547@@ -1578,54 +1569,55 @@
35548 sock = sock_from_file(sock_file, &err);
35549 if (!sock)
35550 goto out_put;
35551- iov.iov_base=buff;
35552- iov.iov_len=len;
35553- msg.msg_name=NULL;
35554- msg.msg_iov=&iov;
35555- msg.msg_iovlen=1;
35556- msg.msg_control=NULL;
35557- msg.msg_controllen=0;
35558- msg.msg_namelen=0;
35559+ iov.iov_base = buff;
35560+ iov.iov_len = len;
35561+ msg.msg_name = NULL;
35562+ msg.msg_iov = &iov;
35563+ msg.msg_iovlen = 1;
35564+ msg.msg_control = NULL;
35565+ msg.msg_controllen = 0;
35566+ msg.msg_namelen = 0;
35567 if (addr) {
35568 err = move_addr_to_kernel(addr, addr_len, address);
35569 if (err < 0)
35570 goto out_put;
35571- msg.msg_name=address;
35572- msg.msg_namelen=addr_len;
35573+ msg.msg_name = address;
35574+ msg.msg_namelen = addr_len;
35575 }
35576 if (sock->file->f_flags & O_NONBLOCK)
35577 flags |= MSG_DONTWAIT;
35578 msg.msg_flags = flags;
35579 err = sock_sendmsg(sock, &msg, len);
35580
35581-out_put:
35582+out_put:
35583 fput_light(sock_file, fput_needed);
35584 return err;
35585 }
35586
35587 /*
35588- * Send a datagram down a socket.
35589+ * Send a datagram down a socket.
35590 */
35591
35592-asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags)
35593+asmlinkage long sys_send(int fd, void __user *buff, size_t len, unsigned flags)
35594 {
35595 return sys_sendto(fd, buff, len, flags, NULL, 0);
35596 }
35597
35598 /*
35599- * Receive a frame from the socket and optionally record the address of the
35600+ * Receive a frame from the socket and optionally record the address of the
35601 * sender. We verify the buffers are writable and if needed move the
35602 * sender address from kernel to user space.
35603 */
35604
35605-asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags,
35606- struct sockaddr __user *addr, int __user *addr_len)
35607+asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
35608+ unsigned flags, struct sockaddr __user *addr,
35609+ int __user *addr_len)
35610 {
35611 struct socket *sock;
35612 struct iovec iov;
35613 struct msghdr msg;
35614 char address[MAX_SOCK_ADDR];
35615- int err,err2;
35616+ int err, err2;
35617 struct file *sock_file;
35618 int fput_needed;
35619
35620@@ -1637,23 +1629,22 @@
35621 if (!sock)
35622 goto out;
35623
35624- msg.msg_control=NULL;
35625- msg.msg_controllen=0;
35626- msg.msg_iovlen=1;
35627- msg.msg_iov=&iov;
35628- iov.iov_len=size;
35629- iov.iov_base=ubuf;
35630- msg.msg_name=address;
35631- msg.msg_namelen=MAX_SOCK_ADDR;
35632+ msg.msg_control = NULL;
35633+ msg.msg_controllen = 0;
35634+ msg.msg_iovlen = 1;
35635+ msg.msg_iov = &iov;
35636+ iov.iov_len = size;
35637+ iov.iov_base = ubuf;
35638+ msg.msg_name = address;
35639+ msg.msg_namelen = MAX_SOCK_ADDR;
35640 if (sock->file->f_flags & O_NONBLOCK)
35641 flags |= MSG_DONTWAIT;
35642- err=sock_recvmsg(sock, &msg, size, flags);
35643+ err = sock_recvmsg(sock, &msg, size, flags);
35644
35645- if(err >= 0 && addr != NULL)
35646- {
35647- err2=move_addr_to_user(address, msg.msg_namelen, addr, addr_len);
35648- if(err2<0)
35649- err=err2;
35650+ if (err >= 0 && addr != NULL) {
35651+ err2 = move_addr_to_user(address, msg.msg_namelen, addr, addr_len);
35652+ if (err2 < 0)
35653+ err = err2;
35654 }
35655 out:
35656 fput_light(sock_file, fput_needed);
35657@@ -1661,10 +1652,11 @@
35658 }
35659
35660 /*
35661- * Receive a datagram from a socket.
35662+ * Receive a datagram from a socket.
35663 */
35664
35665-asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags)
35666+asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
35667+ unsigned flags)
35668 {
35669 return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
35670 }
35671@@ -1674,24 +1666,29 @@
35672 * to pass the user mode parameter for the protocols to sort out.
35673 */
35674
35675-asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen)
35676+asmlinkage long sys_setsockopt(int fd, int level, int optname,
35677+ char __user *optval, int optlen)
35678 {
35679 int err, fput_needed;
35680 struct socket *sock;
35681
35682 if (optlen < 0)
35683 return -EINVAL;
35684-
35685- if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL)
35686- {
35687- err = security_socket_setsockopt(sock,level,optname);
35688+
35689+ sock = sockfd_lookup_light(fd, &err, &fput_needed);
35690+ if (sock != NULL) {
35691+ err = security_socket_setsockopt(sock, level, optname);
35692 if (err)
35693 goto out_put;
35694
35695 if (level == SOL_SOCKET)
35696- err=sock_setsockopt(sock,level,optname,optval,optlen);
35697+ err =
35698+ sock_setsockopt(sock, level, optname, optval,
35699+ optlen);
35700 else
35701- err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
35702+ err =
35703+ sock->ops->setsockopt(sock, level, optname, optval,
35704+ optlen);
35705 out_put:
35706 fput_light(sock->file, fput_needed);
35707 }
35708@@ -1703,27 +1700,32 @@
35709 * to pass a user mode parameter for the protocols to sort out.
35710 */
35711
35712-asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen)
35713+asmlinkage long sys_getsockopt(int fd, int level, int optname,
35714+ char __user *optval, int __user *optlen)
35715 {
35716 int err, fput_needed;
35717 struct socket *sock;
35718
35719- if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
35720+ sock = sockfd_lookup_light(fd, &err, &fput_needed);
35721+ if (sock != NULL) {
35722 err = security_socket_getsockopt(sock, level, optname);
35723 if (err)
35724 goto out_put;
35725
35726 if (level == SOL_SOCKET)
35727- err=sock_getsockopt(sock,level,optname,optval,optlen);
35728+ err =
35729+ sock_getsockopt(sock, level, optname, optval,
35730+ optlen);
35731 else
35732- err=sock->ops->getsockopt(sock, level, optname, optval, optlen);
35733+ err =
35734+ sock->ops->getsockopt(sock, level, optname, optval,
35735+ optlen);
35736 out_put:
35737 fput_light(sock->file, fput_needed);
35738 }
35739 return err;
35740 }
35741
35742-
35743 /*
35744 * Shutdown a socket.
35745 */
35746@@ -1733,8 +1735,8 @@
35747 int err, fput_needed;
35748 struct socket *sock;
35749
35750- if ((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
35751- {
35752+ sock = sockfd_lookup_light(fd, &err, &fput_needed);
35753+ if (sock != NULL) {
35754 err = security_socket_shutdown(sock, how);
35755 if (!err)
35756 err = sock->ops->shutdown(sock, how);
35757@@ -1743,41 +1745,42 @@
35758 return err;
35759 }
35760
35761-/* A couple of helpful macros for getting the address of the 32/64 bit
35762+/* A couple of helpful macros for getting the address of the 32/64 bit
35763 * fields which are the same type (int / unsigned) on our platforms.
35764 */
35765 #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member)
35766 #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen)
35767 #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags)
35768
35769-
35770 /*
35771 * BSD sendmsg interface
35772 */
35773
35774 asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
35775 {
35776- struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg;
35777+ struct compat_msghdr __user *msg_compat =
35778+ (struct compat_msghdr __user *)msg;
35779 struct socket *sock;
35780 char address[MAX_SOCK_ADDR];
35781 struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
35782 unsigned char ctl[sizeof(struct cmsghdr) + 20]
35783- __attribute__ ((aligned (sizeof(__kernel_size_t))));
35784- /* 20 is size of ipv6_pktinfo */
35785+ __attribute__ ((aligned(sizeof(__kernel_size_t))));
35786+ /* 20 is size of ipv6_pktinfo */
35787 unsigned char *ctl_buf = ctl;
35788 struct msghdr msg_sys;
35789 int err, ctl_len, iov_size, total_len;
35790 int fput_needed;
35791-
35792+
35793 err = -EFAULT;
35794 if (MSG_CMSG_COMPAT & flags) {
35795 if (get_compat_msghdr(&msg_sys, msg_compat))
35796 return -EFAULT;
35797- } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
35798+ }
35799+ else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
35800 return -EFAULT;
35801
35802 sock = sockfd_lookup_light(fd, &err, &fput_needed);
35803- if (!sock)
35804+ if (!sock)
35805 goto out;
35806
35807 /* do not move before msg_sys is valid */
35808@@ -1785,7 +1788,7 @@
35809 if (msg_sys.msg_iovlen > UIO_MAXIOV)
35810 goto out_put;
35811
35812- /* Check whether to allocate the iovec area*/
35813+ /* Check whether to allocate the iovec area */
35814 err = -ENOMEM;
35815 iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
35816 if (msg_sys.msg_iovlen > UIO_FASTIOV) {
35817@@ -1799,7 +1802,7 @@
35818 err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ);
35819 } else
35820 err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
35821- if (err < 0)
35822+ if (err < 0)
35823 goto out_freeiov;
35824 total_len = err;
35825
35826@@ -1807,18 +1810,19 @@
35827
35828 if (msg_sys.msg_controllen > INT_MAX)
35829 goto out_freeiov;
35830- ctl_len = msg_sys.msg_controllen;
35831+ ctl_len = msg_sys.msg_controllen;
35832 if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
35833- err = cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl, sizeof(ctl));
35834+ err =
35835+ cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl,
35836+ sizeof(ctl));
35837 if (err)
35838 goto out_freeiov;
35839 ctl_buf = msg_sys.msg_control;
35840 ctl_len = msg_sys.msg_controllen;
35841 } else if (ctl_len) {
35842- if (ctl_len > sizeof(ctl))
35843- {
35844+ if (ctl_len > sizeof(ctl)) {
35845 ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
35846- if (ctl_buf == NULL)
35847+ if (ctl_buf == NULL)
35848 goto out_freeiov;
35849 }
35850 err = -EFAULT;
35851@@ -1827,7 +1831,8 @@
35852 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
35853 * checking falls down on this.
35854 */
35855- if (copy_from_user(ctl_buf, (void __user *) msg_sys.msg_control, ctl_len))
35856+ if (copy_from_user(ctl_buf, (void __user *)msg_sys.msg_control,
35857+ ctl_len))
35858 goto out_freectl;
35859 msg_sys.msg_control = ctl_buf;
35860 }
35861@@ -1838,14 +1843,14 @@
35862 err = sock_sendmsg(sock, &msg_sys, total_len);
35863
35864 out_freectl:
35865- if (ctl_buf != ctl)
35866+ if (ctl_buf != ctl)
35867 sock_kfree_s(sock->sk, ctl_buf, ctl_len);
35868 out_freeiov:
35869 if (iov != iovstack)
35870 sock_kfree_s(sock->sk, iov, iov_size);
35871 out_put:
35872 fput_light(sock->file, fput_needed);
35873-out:
35874+out:
35875 return err;
35876 }
35877
35878@@ -1853,12 +1858,14 @@
35879 * BSD recvmsg interface
35880 */
35881
35882-asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags)
35883+asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
35884+ unsigned int flags)
35885 {
35886- struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg;
35887+ struct compat_msghdr __user *msg_compat =
35888+ (struct compat_msghdr __user *)msg;
35889 struct socket *sock;
35890 struct iovec iovstack[UIO_FASTIOV];
35891- struct iovec *iov=iovstack;
35892+ struct iovec *iov = iovstack;
35893 struct msghdr msg_sys;
35894 unsigned long cmsg_ptr;
35895 int err, iov_size, total_len, len;
35896@@ -1870,13 +1877,13 @@
35897 /* user mode address pointers */
35898 struct sockaddr __user *uaddr;
35899 int __user *uaddr_len;
35900-
35901+
35902 if (MSG_CMSG_COMPAT & flags) {
35903 if (get_compat_msghdr(&msg_sys, msg_compat))
35904 return -EFAULT;
35905- } else
35906- if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
35907- return -EFAULT;
35908+ }
35909+ else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr)))
35910+ return -EFAULT;
35911
35912 sock = sockfd_lookup_light(fd, &err, &fput_needed);
35913 if (!sock)
35914@@ -1885,8 +1892,8 @@
35915 err = -EMSGSIZE;
35916 if (msg_sys.msg_iovlen > UIO_MAXIOV)
35917 goto out_put;
35918-
35919- /* Check whether to allocate the iovec area*/
35920+
35921+ /* Check whether to allocate the iovec area */
35922 err = -ENOMEM;
35923 iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
35924 if (msg_sys.msg_iovlen > UIO_FASTIOV) {
35925@@ -1896,11 +1903,11 @@
35926 }
35927
35928 /*
35929- * Save the user-mode address (verify_iovec will change the
35930- * kernel msghdr to use the kernel address space)
35931+ * Save the user-mode address (verify_iovec will change the
35932+ * kernel msghdr to use the kernel address space)
35933 */
35934-
35935- uaddr = (void __user *) msg_sys.msg_name;
35936+
35937+ uaddr = (void __user *)msg_sys.msg_name;
35938 uaddr_len = COMPAT_NAMELEN(msg);
35939 if (MSG_CMSG_COMPAT & flags) {
35940 err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
35941@@ -1908,13 +1915,13 @@
35942 err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
35943 if (err < 0)
35944 goto out_freeiov;
35945- total_len=err;
35946+ total_len = err;
35947
35948 cmsg_ptr = (unsigned long)msg_sys.msg_control;
35949 msg_sys.msg_flags = 0;
35950 if (MSG_CMSG_COMPAT & flags)
35951 msg_sys.msg_flags = MSG_CMSG_COMPAT;
35952-
35953+
35954 if (sock->file->f_flags & O_NONBLOCK)
35955 flags |= MSG_DONTWAIT;
35956 err = sock_recvmsg(sock, &msg_sys, total_len, flags);
35957@@ -1923,7 +1930,8 @@
35958 len = err;
35959
35960 if (uaddr != NULL) {
35961- err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
35962+ err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr,
35963+ uaddr_len);
35964 if (err < 0)
35965 goto out_freeiov;
35966 }
35967@@ -1932,10 +1940,10 @@
35968 if (err)
35969 goto out_freeiov;
35970 if (MSG_CMSG_COMPAT & flags)
35971- err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr,
35972+ err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
35973 &msg_compat->msg_controllen);
35974 else
35975- err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr,
35976+ err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr,
35977 &msg->msg_controllen);
35978 if (err)
35979 goto out_freeiov;
35980@@ -1954,163 +1962,187 @@
35981
35982 /* Argument list sizes for sys_socketcall */
35983 #define AL(x) ((x) * sizeof(unsigned long))
35984-static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
35985- AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
35986- AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
35987+static const unsigned char nargs[18]={
35988+ AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
35989+ AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
35990+ AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)
35991+};
35992+
35993 #undef AL
35994
35995 /*
35996- * System call vectors.
35997+ * System call vectors.
35998 *
35999 * Argument checking cleaned up. Saved 20% in size.
36000 * This function doesn't need to set the kernel lock because
36001- * it is set by the callees.
36002+ * it is set by the callees.
36003 */
36004
36005 asmlinkage long sys_socketcall(int call, unsigned long __user *args)
36006 {
36007 unsigned long a[6];
36008- unsigned long a0,a1;
36009+ unsigned long a0, a1;
36010 int err;
36011
36012- if(call<1||call>SYS_RECVMSG)
36013+ if (call < 1 || call > SYS_RECVMSG)
36014 return -EINVAL;
36015
36016 /* copy_from_user should be SMP safe. */
36017 if (copy_from_user(a, args, nargs[call]))
36018 return -EFAULT;
36019
36020- err = audit_socketcall(nargs[call]/sizeof(unsigned long), a);
36021+ err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
36022 if (err)
36023 return err;
36024
36025- a0=a[0];
36026- a1=a[1];
36027-
36028- switch(call)
36029- {
36030- case SYS_SOCKET:
36031- err = sys_socket(a0,a1,a[2]);
36032- break;
36033- case SYS_BIND:
36034- err = sys_bind(a0,(struct sockaddr __user *)a1, a[2]);
36035- break;
36036- case SYS_CONNECT:
36037- err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
36038- break;
36039- case SYS_LISTEN:
36040- err = sys_listen(a0,a1);
36041- break;
36042- case SYS_ACCEPT:
36043- err = sys_accept(a0,(struct sockaddr __user *)a1, (int __user *)a[2]);
36044- break;
36045- case SYS_GETSOCKNAME:
36046- err = sys_getsockname(a0,(struct sockaddr __user *)a1, (int __user *)a[2]);
36047- break;
36048- case SYS_GETPEERNAME:
36049- err = sys_getpeername(a0, (struct sockaddr __user *)a1, (int __user *)a[2]);
36050- break;
36051- case SYS_SOCKETPAIR:
36052- err = sys_socketpair(a0,a1, a[2], (int __user *)a[3]);
36053- break;
36054- case SYS_SEND:
36055- err = sys_send(a0, (void __user *)a1, a[2], a[3]);
36056- break;
36057- case SYS_SENDTO:
36058- err = sys_sendto(a0,(void __user *)a1, a[2], a[3],
36059- (struct sockaddr __user *)a[4], a[5]);
36060- break;
36061- case SYS_RECV:
36062- err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
36063- break;
36064- case SYS_RECVFROM:
36065- err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
36066- (struct sockaddr __user *)a[4], (int __user *)a[5]);
36067- break;
36068- case SYS_SHUTDOWN:
36069- err = sys_shutdown(a0,a1);
36070- break;
36071- case SYS_SETSOCKOPT:
36072- err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
36073- break;
36074- case SYS_GETSOCKOPT:
36075- err = sys_getsockopt(a0, a1, a[2], (char __user *)a[3], (int __user *)a[4]);
36076- break;
36077- case SYS_SENDMSG:
36078- err = sys_sendmsg(a0, (struct msghdr __user *) a1, a[2]);
36079- break;
36080- case SYS_RECVMSG:
36081- err = sys_recvmsg(a0, (struct msghdr __user *) a1, a[2]);
36082- break;
36083- default:
36084- err = -EINVAL;
36085- break;
36086+ a0 = a[0];
36087+ a1 = a[1];
36088+
36089+ switch (call) {
36090+ case SYS_SOCKET:
36091+ err = sys_socket(a0, a1, a[2]);
36092+ break;
36093+ case SYS_BIND:
36094+ err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
36095+ break;
36096+ case SYS_CONNECT:
36097+ err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
36098+ break;
36099+ case SYS_LISTEN:
36100+ err = sys_listen(a0, a1);
36101+ break;
36102+ case SYS_ACCEPT:
36103+ err =
36104+ sys_accept(a0, (struct sockaddr __user *)a1,
36105+ (int __user *)a[2]);
36106+ break;
36107+ case SYS_GETSOCKNAME:
36108+ err =
36109+ sys_getsockname(a0, (struct sockaddr __user *)a1,
36110+ (int __user *)a[2]);
36111+ break;
36112+ case SYS_GETPEERNAME:
36113+ err =
36114+ sys_getpeername(a0, (struct sockaddr __user *)a1,
36115+ (int __user *)a[2]);
36116+ break;
36117+ case SYS_SOCKETPAIR:
36118+ err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
36119+ break;
36120+ case SYS_SEND:
36121+ err = sys_send(a0, (void __user *)a1, a[2], a[3]);
36122+ break;
36123+ case SYS_SENDTO:
36124+ err = sys_sendto(a0, (void __user *)a1, a[2], a[3],
36125+ (struct sockaddr __user *)a[4], a[5]);
36126+ break;
36127+ case SYS_RECV:
36128+ err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
36129+ break;
36130+ case SYS_RECVFROM:
36131+ err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
36132+ (struct sockaddr __user *)a[4],
36133+ (int __user *)a[5]);
36134+ break;
36135+ case SYS_SHUTDOWN:
36136+ err = sys_shutdown(a0, a1);
36137+ break;
36138+ case SYS_SETSOCKOPT:
36139+ err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]);
36140+ break;
36141+ case SYS_GETSOCKOPT:
36142+ err =
36143+ sys_getsockopt(a0, a1, a[2], (char __user *)a[3],
36144+ (int __user *)a[4]);
36145+ break;
36146+ case SYS_SENDMSG:
36147+ err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
36148+ break;
36149+ case SYS_RECVMSG:
36150+ err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
36151+ break;
36152+ default:
36153+ err = -EINVAL;
36154+ break;
36155 }
36156 return err;
36157 }
36158
36159-#endif /* __ARCH_WANT_SYS_SOCKETCALL */
36160+#endif /* __ARCH_WANT_SYS_SOCKETCALL */
36161
36162-/*
36163+/**
36164+ * sock_register - add a socket protocol handler
36165+ * @ops: description of protocol
36166+ *
36167 * This function is called by a protocol handler that wants to
36168 * advertise its address family, and have it linked into the
36169- * SOCKET module.
36170+ * socket interface. The value ops->family coresponds to the
36171+ * socket system call protocol family.
36172 */
36173-
36174-int sock_register(struct net_proto_family *ops)
36175+int sock_register(const struct net_proto_family *ops)
36176 {
36177 int err;
36178
36179 if (ops->family >= NPROTO) {
36180- printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
36181+ printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family,
36182+ NPROTO);
36183 return -ENOBUFS;
36184 }
36185- net_family_write_lock();
36186- err = -EEXIST;
36187- if (net_families[ops->family] == NULL) {
36188- net_families[ops->family]=ops;
36189+
36190+ spin_lock(&net_family_lock);
36191+ if (net_families[ops->family])
36192+ err = -EEXIST;
36193+ else {
36194+ net_families[ops->family] = ops;
36195 err = 0;
36196 }
36197- net_family_write_unlock();
36198- printk(KERN_INFO "NET: Registered protocol family %d\n",
36199- ops->family);
36200+ spin_unlock(&net_family_lock);
36201+
36202+ printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
36203 return err;
36204 }
36205
36206-/*
36207+/**
36208+ * sock_unregister - remove a protocol handler
36209+ * @family: protocol family to remove
36210+ *
36211 * This function is called by a protocol handler that wants to
36212 * remove its address family, and have it unlinked from the
36213- * SOCKET module.
36214+ * new socket creation.
36215+ *
36216+ * If protocol handler is a module, then it can use module reference
36217+ * counts to protect against new references. If protocol handler is not
36218+ * a module then it needs to provide its own protection in
36219+ * the ops->create routine.
36220 */
36221-
36222-int sock_unregister(int family)
36223+void sock_unregister(int family)
36224 {
36225- if (family < 0 || family >= NPROTO)
36226- return -1;
36227+ BUG_ON(family < 0 || family >= NPROTO);
36228
36229- net_family_write_lock();
36230- net_families[family]=NULL;
36231- net_family_write_unlock();
36232- printk(KERN_INFO "NET: Unregistered protocol family %d\n",
36233- family);
36234- return 0;
36235+ spin_lock(&net_family_lock);
36236+ net_families[family] = NULL;
36237+ spin_unlock(&net_family_lock);
36238+
36239+ synchronize_rcu();
36240+
36241+ printk(KERN_INFO "NET: Unregistered protocol family %d\n", family);
36242 }
36243
36244 static int __init sock_init(void)
36245 {
36246 /*
36247- * Initialize sock SLAB cache.
36248+ * Initialize sock SLAB cache.
36249 */
36250-
36251+
36252 sk_init();
36253
36254 /*
36255- * Initialize skbuff SLAB cache
36256+ * Initialize skbuff SLAB cache
36257 */
36258 skb_init();
36259
36260 /*
36261- * Initialize the protocols module.
36262+ * Initialize the protocols module.
36263 */
36264
36265 init_inodecache();
36266@@ -2136,7 +2168,7 @@
36267 int counter = 0;
36268
36269 for_each_possible_cpu(cpu)
36270- counter += per_cpu(sockets_in_use, cpu);
36271+ counter += per_cpu(sockets_in_use, cpu);
36272
36273 /* It can be negative, by the way. 8) */
36274 if (counter < 0)
36275@@ -2144,11 +2176,11 @@
36276
36277 seq_printf(seq, "sockets: used %d\n", counter);
36278 }
36279-#endif /* CONFIG_PROC_FS */
36280+#endif /* CONFIG_PROC_FS */
36281
36282 #ifdef CONFIG_COMPAT
36283 static long compat_sock_ioctl(struct file *file, unsigned cmd,
36284- unsigned long arg)
36285+ unsigned long arg)
36286 {
36287 struct socket *sock = file->private_data;
36288 int ret = -ENOIOCTLCMD;
36289@@ -2160,6 +2192,109 @@
36290 }
36291 #endif
36292
36293+int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
36294+{
36295+ return sock->ops->bind(sock, addr, addrlen);
36296+}
36297+
36298+int kernel_listen(struct socket *sock, int backlog)
36299+{
36300+ return sock->ops->listen(sock, backlog);
36301+}
36302+
36303+int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
36304+{
36305+ struct sock *sk = sock->sk;
36306+ int err;
36307+
36308+ err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
36309+ newsock);
36310+ if (err < 0)
36311+ goto done;
36312+
36313+ err = sock->ops->accept(sock, *newsock, flags);
36314+ if (err < 0) {
36315+ sock_release(*newsock);
36316+ goto done;
36317+ }
36318+
36319+ (*newsock)->ops = sock->ops;
36320+
36321+done:
36322+ return err;
36323+}
36324+
36325+int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
36326+ int flags)
36327+{
36328+ return sock->ops->connect(sock, addr, addrlen, flags);
36329+}
36330+
36331+int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
36332+ int *addrlen)
36333+{
36334+ return sock->ops->getname(sock, addr, addrlen, 0);
36335+}
36336+
36337+int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
36338+ int *addrlen)
36339+{
36340+ return sock->ops->getname(sock, addr, addrlen, 1);
36341+}
36342+
36343+int kernel_getsockopt(struct socket *sock, int level, int optname,
36344+ char *optval, int *optlen)
36345+{
36346+ mm_segment_t oldfs = get_fs();
36347+ int err;
36348+
36349+ set_fs(KERNEL_DS);
36350+ if (level == SOL_SOCKET)
36351+ err = sock_getsockopt(sock, level, optname, optval, optlen);
36352+ else
36353+ err = sock->ops->getsockopt(sock, level, optname, optval,
36354+ optlen);
36355+ set_fs(oldfs);
36356+ return err;
36357+}
36358+
36359+int kernel_setsockopt(struct socket *sock, int level, int optname,
36360+ char *optval, int optlen)
36361+{
36362+ mm_segment_t oldfs = get_fs();
36363+ int err;
36364+
36365+ set_fs(KERNEL_DS);
36366+ if (level == SOL_SOCKET)
36367+ err = sock_setsockopt(sock, level, optname, optval, optlen);
36368+ else
36369+ err = sock->ops->setsockopt(sock, level, optname, optval,
36370+ optlen);
36371+ set_fs(oldfs);
36372+ return err;
36373+}
36374+
36375+int kernel_sendpage(struct socket *sock, struct page *page, int offset,
36376+ size_t size, int flags)
36377+{
36378+ if (sock->ops->sendpage)
36379+ return sock->ops->sendpage(sock, page, offset, size, flags);
36380+
36381+ return sock_no_sendpage(sock, page, offset, size, flags);
36382+}
36383+
36384+int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
36385+{
36386+ mm_segment_t oldfs = get_fs();
36387+ int err;
36388+
36389+ set_fs(KERNEL_DS);
36390+ err = sock->ops->ioctl(sock, cmd, arg);
36391+ set_fs(oldfs);
36392+
36393+ return err;
36394+}
36395+
36396 /* ABI emulation layers need these two */
36397 EXPORT_SYMBOL(move_addr_to_kernel);
36398 EXPORT_SYMBOL(move_addr_to_user);
36399@@ -2176,3 +2311,13 @@
36400 EXPORT_SYMBOL(sockfd_lookup);
36401 EXPORT_SYMBOL(kernel_sendmsg);
36402 EXPORT_SYMBOL(kernel_recvmsg);
36403+EXPORT_SYMBOL(kernel_bind);
36404+EXPORT_SYMBOL(kernel_listen);
36405+EXPORT_SYMBOL(kernel_accept);
36406+EXPORT_SYMBOL(kernel_connect);
36407+EXPORT_SYMBOL(kernel_getsockname);
36408+EXPORT_SYMBOL(kernel_getpeername);
36409+EXPORT_SYMBOL(kernel_getsockopt);
36410+EXPORT_SYMBOL(kernel_setsockopt);
36411+EXPORT_SYMBOL(kernel_sendpage);
36412+EXPORT_SYMBOL(kernel_sock_ioctl);
36413diff -Nur linux-2.6.18-rc5/net/sunrpc/socklib.c linux-2.6.19/net/sunrpc/socklib.c
36414--- linux-2.6.18-rc5/net/sunrpc/socklib.c 2006-08-28 05:41:48.000000000 +0200
36415+++ linux-2.6.19/net/sunrpc/socklib.c 2006-09-22 10:04:59.000000000 +0200
36416@@ -168,7 +168,7 @@
36417 return -1;
36418 if ((unsigned short)csum_fold(desc.csum))
36419 return -1;
36420- if (unlikely(skb->ip_summed == CHECKSUM_HW))
36421+ if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
36422 netdev_rx_csum_fault(skb->dev);
36423 return 0;
36424 no_checksum:
36425diff -Nur linux-2.6.18-rc5/net/sunrpc/svcsock.c linux-2.6.19/net/sunrpc/svcsock.c
36426--- linux-2.6.18-rc5/net/sunrpc/svcsock.c 2006-08-28 05:41:48.000000000 +0200
36427+++ linux-2.6.19/net/sunrpc/svcsock.c 2006-09-22 10:04:59.000000000 +0200
36428@@ -388,7 +388,7 @@
36429 /* send head */
36430 if (slen == xdr->head[0].iov_len)
36431 flags = 0;
36432- len = sock->ops->sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags);
36433+ len = kernel_sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags);
36434 if (len != xdr->head[0].iov_len)
36435 goto out;
36436 slen -= xdr->head[0].iov_len;
36437@@ -400,7 +400,7 @@
36438 while (pglen > 0) {
36439 if (slen == size)
36440 flags = 0;
36441- result = sock->ops->sendpage(sock, *ppage, base, size, flags);
36442+ result = kernel_sendpage(sock, *ppage, base, size, flags);
36443 if (result > 0)
36444 len += result;
36445 if (result != size)
36446@@ -413,7 +413,7 @@
36447 }
36448 /* send tail */
36449 if (xdr->tail[0].iov_len) {
36450- result = sock->ops->sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage],
36451+ result = kernel_sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage],
36452 ((unsigned long)xdr->tail[0].iov_base)& (PAGE_SIZE-1),
36453 xdr->tail[0].iov_len, 0);
36454
36455@@ -434,13 +434,10 @@
36456 static int
36457 svc_recv_available(struct svc_sock *svsk)
36458 {
36459- mm_segment_t oldfs;
36460 struct socket *sock = svsk->sk_sock;
36461 int avail, err;
36462
36463- oldfs = get_fs(); set_fs(KERNEL_DS);
36464- err = sock->ops->ioctl(sock, TIOCINQ, (unsigned long) &avail);
36465- set_fs(oldfs);
36466+ err = kernel_sock_ioctl(sock, TIOCINQ, (unsigned long) &avail);
36467
36468 return (err >= 0)? avail : err;
36469 }
36470@@ -472,7 +469,7 @@
36471 * at accept time. FIXME
36472 */
36473 alen = sizeof(rqstp->rq_addr);
36474- sock->ops->getname(sock, (struct sockaddr *)&rqstp->rq_addr, &alen, 1);
36475+ kernel_getpeername(sock, (struct sockaddr *)&rqstp->rq_addr, &alen);
36476
36477 dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
36478 rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
36479@@ -758,7 +755,6 @@
36480 struct svc_serv *serv = svsk->sk_server;
36481 struct socket *sock = svsk->sk_sock;
36482 struct socket *newsock;
36483- const struct proto_ops *ops;
36484 struct svc_sock *newsvsk;
36485 int err, slen;
36486
36487@@ -766,29 +762,23 @@
36488 if (!sock)
36489 return;
36490
36491- err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock);
36492- if (err) {
36493+ clear_bit(SK_CONN, &svsk->sk_flags);
36494+ err = kernel_accept(sock, &newsock, O_NONBLOCK);
36495+ if (err < 0) {
36496 if (err == -ENOMEM)
36497 printk(KERN_WARNING "%s: no more sockets!\n",
36498 serv->sv_name);
36499- return;
36500- }
36501-
36502- dprintk("svc: tcp_accept %p allocated\n", newsock);
36503- newsock->ops = ops = sock->ops;
36504-
36505- clear_bit(SK_CONN, &svsk->sk_flags);
36506- if ((err = ops->accept(sock, newsock, O_NONBLOCK)) < 0) {
36507- if (err != -EAGAIN && net_ratelimit())
36508+ else if (err != -EAGAIN && net_ratelimit())
36509 printk(KERN_WARNING "%s: accept failed (err %d)!\n",
36510 serv->sv_name, -err);
36511- goto failed; /* aborted connection or whatever */
36512+ return;
36513 }
36514+
36515 set_bit(SK_CONN, &svsk->sk_flags);
36516 svc_sock_enqueue(svsk);
36517
36518 slen = sizeof(sin);
36519- err = ops->getname(newsock, (struct sockaddr *) &sin, &slen, 1);
36520+ err = kernel_getpeername(newsock, (struct sockaddr *) &sin, &slen);
36521 if (err < 0) {
36522 if (net_ratelimit())
36523 printk(KERN_WARNING "%s: peername failed (err %d)!\n",
36524@@ -1406,14 +1396,14 @@
36525 if (sin != NULL) {
36526 if (type == SOCK_STREAM)
36527 sock->sk->sk_reuse = 1; /* allow address reuse */
36528- error = sock->ops->bind(sock, (struct sockaddr *) sin,
36529+ error = kernel_bind(sock, (struct sockaddr *) sin,
36530 sizeof(*sin));
36531 if (error < 0)
36532 goto bummer;
36533 }
36534
36535 if (protocol == IPPROTO_TCP) {
36536- if ((error = sock->ops->listen(sock, 64)) < 0)
36537+ if ((error = kernel_listen(sock, 64)) < 0)
36538 goto bummer;
36539 }
36540
36541diff -Nur linux-2.6.18-rc5/net/sunrpc/xprtsock.c linux-2.6.19/net/sunrpc/xprtsock.c
36542--- linux-2.6.18-rc5/net/sunrpc/xprtsock.c 2006-08-28 05:41:48.000000000 +0200
36543+++ linux-2.6.19/net/sunrpc/xprtsock.c 2006-09-22 10:04:59.000000000 +0200
36544@@ -174,7 +174,6 @@
36545 struct page **ppage = xdr->pages;
36546 unsigned int len, pglen = xdr->page_len;
36547 int err, ret = 0;
36548- ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
36549
36550 if (unlikely(!sock))
36551 return -ENOTCONN;
36552@@ -207,7 +206,6 @@
36553 base &= ~PAGE_CACHE_MASK;
36554 }
36555
36556- sendpage = sock->ops->sendpage ? : sock_no_sendpage;
36557 do {
36558 int flags = XS_SENDMSG_FLAGS;
36559
36560@@ -220,10 +218,7 @@
36561 if (pglen != len || xdr->tail[0].iov_len != 0)
36562 flags |= MSG_MORE;
36563
36564- /* Hmm... We might be dealing with highmem pages */
36565- if (PageHighMem(*ppage))
36566- sendpage = sock_no_sendpage;
36567- err = sendpage(sock, *ppage, base, len, flags);
36568+ err = kernel_sendpage(sock, *ppage, base, len, flags);
36569 if (ret == 0)
36570 ret = err;
36571 else if (err > 0)
36572@@ -986,7 +981,7 @@
36573
36574 do {
36575 myaddr.sin_port = htons(port);
36576- err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
36577+ err = kernel_bind(sock, (struct sockaddr *) &myaddr,
36578 sizeof(myaddr));
36579 if (err == 0) {
36580 xprt->port = port;
36581@@ -1081,7 +1076,7 @@
36582 */
36583 memset(&any, 0, sizeof(any));
36584 any.sa_family = AF_UNSPEC;
36585- result = sock->ops->connect(sock, &any, sizeof(any), 0);
36586+ result = kernel_connect(sock, &any, sizeof(any), 0);
36587 if (result)
36588 dprintk("RPC: AF_UNSPEC connect return code %d\n",
36589 result);
36590@@ -1151,7 +1146,7 @@
36591 /* Tell the socket layer to start connecting... */
36592 xprt->stat.connect_count++;
36593 xprt->stat.connect_start = jiffies;
36594- status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
36595+ status = kernel_connect(sock, (struct sockaddr *) &xprt->addr,
36596 sizeof(xprt->addr), O_NONBLOCK);
36597 dprintk("RPC: %p connect status %d connected %d sock state %d\n",
36598 xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
36599diff -Nur linux-2.6.18-rc5/net/unix/af_unix.c linux-2.6.19/net/unix/af_unix.c
36600--- linux-2.6.18-rc5/net/unix/af_unix.c 2006-08-28 05:41:48.000000000 +0200
36601+++ linux-2.6.19/net/unix/af_unix.c 2006-09-22 10:04:59.000000000 +0200
36602@@ -117,7 +117,7 @@
36603 #include <net/checksum.h>
36604 #include <linux/security.h>
36605
36606-int sysctl_unix_max_dgram_qlen = 10;
36607+int sysctl_unix_max_dgram_qlen __read_mostly = 10;
36608
36609 struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
36610 DEFINE_SPINLOCK(unix_table_lock);
36611@@ -2060,10 +2060,7 @@
36612 int rc = -1;
36613 struct sk_buff *dummy_skb;
36614
36615- if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)) {
36616- printk(KERN_CRIT "%s: panic\n", __FUNCTION__);
36617- goto out;
36618- }
36619+ BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb));
36620
36621 rc = proto_register(&unix_proto, 1);
36622 if (rc != 0) {
36623diff -Nur linux-2.6.18-rc5/net/xfrm/Kconfig linux-2.6.19/net/xfrm/Kconfig
36624--- linux-2.6.18-rc5/net/xfrm/Kconfig 2006-08-28 05:41:48.000000000 +0200
36625+++ linux-2.6.19/net/xfrm/Kconfig 2006-09-22 10:04:59.000000000 +0200
36626@@ -6,14 +6,24 @@
36627 depends on NET
36628
36629 config XFRM_USER
36630- tristate "IPsec user configuration interface"
36631+ tristate "Transformation user configuration interface"
36632 depends on INET && XFRM
36633 ---help---
36634- Support for IPsec user configuration interface used
36635- by native Linux tools.
36636+ Support for Transformation(XFRM) user configuration interface
36637+ like IPsec used by native Linux tools.
36638
36639 If unsure, say Y.
36640
36641+config XFRM_SUB_POLICY
36642+ bool "Transformation sub policy support (EXPERIMENTAL)"
36643+ depends on XFRM && EXPERIMENTAL
36644+ ---help---
36645+ Support sub policy for developers. By using sub policy with main
36646+ one, two policies can be applied to the same packet at once.
36647+ Policy which lives shorter time in kernel should be a sub.
36648+
36649+ If unsure, say N.
36650+
36651 config NET_KEY
36652 tristate "PF_KEY sockets"
36653 select XFRM
36654diff -Nur linux-2.6.18-rc5/net/xfrm/Makefile linux-2.6.19/net/xfrm/Makefile
36655--- linux-2.6.18-rc5/net/xfrm/Makefile 2006-08-28 05:41:48.000000000 +0200
36656+++ linux-2.6.19/net/xfrm/Makefile 2006-09-22 10:04:59.000000000 +0200
36657@@ -2,6 +2,7 @@
36658 # Makefile for the XFRM subsystem.
36659 #
36660
36661-obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o
36662+obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
36663+ xfrm_input.o xfrm_algo.o
36664 obj-$(CONFIG_XFRM_USER) += xfrm_user.o
36665
36666diff -Nur linux-2.6.18-rc5/net/xfrm/xfrm_hash.c linux-2.6.19/net/xfrm/xfrm_hash.c
36667--- linux-2.6.18-rc5/net/xfrm/xfrm_hash.c 1970-01-01 01:00:00.000000000 +0100
36668+++ linux-2.6.19/net/xfrm/xfrm_hash.c 2006-09-22 10:04:59.000000000 +0200
36669@@ -0,0 +1,41 @@
36670+/* xfrm_hash.c: Common hash table code.
36671+ *
36672+ * Copyright (C) 2006 David S. Miller (davem@davemloft.net)
36673+ */
36674+
36675+#include <linux/kernel.h>
36676+#include <linux/mm.h>
36677+#include <linux/bootmem.h>
36678+#include <linux/vmalloc.h>
36679+#include <linux/slab.h>
36680+#include <linux/xfrm.h>
36681+
36682+#include "xfrm_hash.h"
36683+
36684+struct hlist_head *xfrm_hash_alloc(unsigned int sz)
36685+{
36686+ struct hlist_head *n;
36687+
36688+ if (sz <= PAGE_SIZE)
36689+ n = kmalloc(sz, GFP_KERNEL);
36690+ else if (hashdist)
36691+ n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL);
36692+ else
36693+ n = (struct hlist_head *)
36694+ __get_free_pages(GFP_KERNEL, get_order(sz));
36695+
36696+ if (n)
36697+ memset(n, 0, sz);
36698+
36699+ return n;
36700+}
36701+
36702+void xfrm_hash_free(struct hlist_head *n, unsigned int sz)
36703+{
36704+ if (sz <= PAGE_SIZE)
36705+ kfree(n);
36706+ else if (hashdist)
36707+ vfree(n);
36708+ else
36709+ free_pages((unsigned long)n, get_order(sz));
36710+}
36711diff -Nur linux-2.6.18-rc5/net/xfrm/xfrm_hash.h linux-2.6.19/net/xfrm/xfrm_hash.h
36712--- linux-2.6.18-rc5/net/xfrm/xfrm_hash.h 1970-01-01 01:00:00.000000000 +0100
36713+++ linux-2.6.19/net/xfrm/xfrm_hash.h 2006-09-22 10:04:59.000000000 +0200
36714@@ -0,0 +1,128 @@
36715+#ifndef _XFRM_HASH_H
36716+#define _XFRM_HASH_H
36717+
36718+#include <linux/xfrm.h>
36719+#include <linux/socket.h>
36720+
36721+static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr)
36722+{
36723+ return ntohl(addr->a4);
36724+}
36725+
36726+static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr)
36727+{
36728+ return ntohl(addr->a6[2] ^ addr->a6[3]);
36729+}
36730+
36731+static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr)
36732+{
36733+ return ntohl(daddr->a4 ^ saddr->a4);
36734+}
36735+
36736+static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr)
36737+{
36738+ return ntohl(daddr->a6[2] ^ daddr->a6[3] ^
36739+ saddr->a6[2] ^ saddr->a6[3]);
36740+}
36741+
36742+static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr,
36743+ u32 reqid, unsigned short family,
36744+ unsigned int hmask)
36745+{
36746+ unsigned int h = family ^ reqid;
36747+ switch (family) {
36748+ case AF_INET:
36749+ h ^= __xfrm4_daddr_saddr_hash(daddr, saddr);
36750+ break;
36751+ case AF_INET6:
36752+ h ^= __xfrm6_daddr_saddr_hash(daddr, saddr);
36753+ break;
36754+ }
36755+ return (h ^ (h >> 16)) & hmask;
36756+}
36757+
36758+static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr,
36759+ unsigned short family,
36760+ unsigned int hmask)
36761+{
36762+ unsigned int h = family;
36763+ switch (family) {
36764+ case AF_INET:
36765+ h ^= __xfrm4_addr_hash(saddr);
36766+ break;
36767+ case AF_INET6:
36768+ h ^= __xfrm6_addr_hash(saddr);
36769+ break;
36770+ };
36771+ return (h ^ (h >> 16)) & hmask;
36772+}
36773+
36774+static inline unsigned int
36775+__xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family,
36776+ unsigned int hmask)
36777+{
36778+ unsigned int h = spi ^ proto;
36779+ switch (family) {
36780+ case AF_INET:
36781+ h ^= __xfrm4_addr_hash(daddr);
36782+ break;
36783+ case AF_INET6:
36784+ h ^= __xfrm6_addr_hash(daddr);
36785+ break;
36786+ }
36787+ return (h ^ (h >> 10) ^ (h >> 20)) & hmask;
36788+}
36789+
36790+static inline unsigned int __idx_hash(u32 index, unsigned int hmask)
36791+{
36792+ return (index ^ (index >> 8)) & hmask;
36793+}
36794+
36795+static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask)
36796+{
36797+ xfrm_address_t *daddr = &sel->daddr;
36798+ xfrm_address_t *saddr = &sel->saddr;
36799+ unsigned int h = 0;
36800+
36801+ switch (family) {
36802+ case AF_INET:
36803+ if (sel->prefixlen_d != 32 ||
36804+ sel->prefixlen_s != 32)
36805+ return hmask + 1;
36806+
36807+ h = __xfrm4_daddr_saddr_hash(daddr, saddr);
36808+ break;
36809+
36810+ case AF_INET6:
36811+ if (sel->prefixlen_d != 128 ||
36812+ sel->prefixlen_s != 128)
36813+ return hmask + 1;
36814+
36815+ h = __xfrm6_daddr_saddr_hash(daddr, saddr);
36816+ break;
36817+ };
36818+ h ^= (h >> 16);
36819+ return h & hmask;
36820+}
36821+
36822+static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask)
36823+{
36824+ unsigned int h = 0;
36825+
36826+ switch (family) {
36827+ case AF_INET:
36828+ h = __xfrm4_daddr_saddr_hash(daddr, saddr);
36829+ break;
36830+
36831+ case AF_INET6:
36832+ h = __xfrm6_daddr_saddr_hash(daddr, saddr);
36833+ break;
36834+ };
36835+ h ^= (h >> 16);
36836+ return h & hmask;
36837+}
36838+
36839+extern struct hlist_head *xfrm_hash_alloc(unsigned int sz);
36840+extern void xfrm_hash_free(struct hlist_head *n, unsigned int sz);
36841+
36842+#endif /* _XFRM_HASH_H */
36843diff -Nur linux-2.6.18-rc5/net/xfrm/xfrm_input.c linux-2.6.19/net/xfrm/xfrm_input.c
36844--- linux-2.6.18-rc5/net/xfrm/xfrm_input.c 2006-08-28 05:41:48.000000000 +0200
36845+++ linux-2.6.19/net/xfrm/xfrm_input.c 2006-09-22 10:04:59.000000000 +0200
36846@@ -82,8 +82,6 @@
36847 {
36848 secpath_cachep = kmem_cache_create("secpath_cache",
36849 sizeof(struct sec_path),
36850- 0, SLAB_HWCACHE_ALIGN,
36851+ 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
36852 NULL, NULL);
36853- if (!secpath_cachep)
36854- panic("XFRM: failed to allocate secpath_cache\n");
36855 }
36856diff -Nur linux-2.6.18-rc5/net/xfrm/xfrm_policy.c linux-2.6.19/net/xfrm/xfrm_policy.c
36857--- linux-2.6.18-rc5/net/xfrm/xfrm_policy.c 2006-08-28 05:41:48.000000000 +0200
36858+++ linux-2.6.19/net/xfrm/xfrm_policy.c 2006-09-22 10:04:59.000000000 +0200
36859@@ -22,16 +22,19 @@
36860 #include <linux/netdevice.h>
36861 #include <linux/netfilter.h>
36862 #include <linux/module.h>
36863+#include <linux/cache.h>
36864 #include <net/xfrm.h>
36865 #include <net/ip.h>
36866
36867+#include "xfrm_hash.h"
36868+
36869 DEFINE_MUTEX(xfrm_cfg_mutex);
36870 EXPORT_SYMBOL(xfrm_cfg_mutex);
36871
36872 static DEFINE_RWLOCK(xfrm_policy_lock);
36873
36874-struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
36875-EXPORT_SYMBOL(xfrm_policy_list);
36876+unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
36877+EXPORT_SYMBOL(xfrm_policy_count);
36878
36879 static DEFINE_RWLOCK(xfrm_policy_afinfo_lock);
36880 static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
36881@@ -39,8 +42,7 @@
36882 static kmem_cache_t *xfrm_dst_cache __read_mostly;
36883
36884 static struct work_struct xfrm_policy_gc_work;
36885-static struct list_head xfrm_policy_gc_list =
36886- LIST_HEAD_INIT(xfrm_policy_gc_list);
36887+static HLIST_HEAD(xfrm_policy_gc_list);
36888 static DEFINE_SPINLOCK(xfrm_policy_gc_lock);
36889
36890 static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
36891@@ -310,8 +312,10 @@
36892 policy = kzalloc(sizeof(struct xfrm_policy), gfp);
36893
36894 if (policy) {
36895- atomic_set(&policy->refcnt, 1);
36896+ INIT_HLIST_NODE(&policy->bydst);
36897+ INIT_HLIST_NODE(&policy->byidx);
36898 rwlock_init(&policy->lock);
36899+ atomic_set(&policy->refcnt, 1);
36900 init_timer(&policy->timer);
36901 policy->timer.data = (unsigned long)policy;
36902 policy->timer.function = xfrm_policy_timer;
36903@@ -357,17 +361,16 @@
36904 static void xfrm_policy_gc_task(void *data)
36905 {
36906 struct xfrm_policy *policy;
36907- struct list_head *entry, *tmp;
36908- struct list_head gc_list = LIST_HEAD_INIT(gc_list);
36909+ struct hlist_node *entry, *tmp;
36910+ struct hlist_head gc_list;
36911
36912 spin_lock_bh(&xfrm_policy_gc_lock);
36913- list_splice_init(&xfrm_policy_gc_list, &gc_list);
36914+ gc_list.first = xfrm_policy_gc_list.first;
36915+ INIT_HLIST_HEAD(&xfrm_policy_gc_list);
36916 spin_unlock_bh(&xfrm_policy_gc_lock);
36917
36918- list_for_each_safe(entry, tmp, &gc_list) {
36919- policy = list_entry(entry, struct xfrm_policy, list);
36920+ hlist_for_each_entry_safe(policy, entry, tmp, &gc_list, bydst)
36921 xfrm_policy_gc_kill(policy);
36922- }
36923 }
36924
36925 /* Rule must be locked. Release descentant resources, announce
36926@@ -389,70 +392,275 @@
36927 }
36928
36929 spin_lock(&xfrm_policy_gc_lock);
36930- list_add(&policy->list, &xfrm_policy_gc_list);
36931+ hlist_add_head(&policy->bydst, &xfrm_policy_gc_list);
36932 spin_unlock(&xfrm_policy_gc_lock);
36933
36934 schedule_work(&xfrm_policy_gc_work);
36935 }
36936
36937+struct xfrm_policy_hash {
36938+ struct hlist_head *table;
36939+ unsigned int hmask;
36940+};
36941+
36942+static struct hlist_head xfrm_policy_inexact[XFRM_POLICY_MAX*2];
36943+static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly;
36944+static struct hlist_head *xfrm_policy_byidx __read_mostly;
36945+static unsigned int xfrm_idx_hmask __read_mostly;
36946+static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024;
36947+
36948+static inline unsigned int idx_hash(u32 index)
36949+{
36950+ return __idx_hash(index, xfrm_idx_hmask);
36951+}
36952+
36953+static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir)
36954+{
36955+ unsigned int hmask = xfrm_policy_bydst[dir].hmask;
36956+ unsigned int hash = __sel_hash(sel, family, hmask);
36957+
36958+ return (hash == hmask + 1 ?
36959+ &xfrm_policy_inexact[dir] :
36960+ xfrm_policy_bydst[dir].table + hash);
36961+}
36962+
36963+static struct hlist_head *policy_hash_direct(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, int dir)
36964+{
36965+ unsigned int hmask = xfrm_policy_bydst[dir].hmask;
36966+ unsigned int hash = __addr_hash(daddr, saddr, family, hmask);
36967+
36968+ return xfrm_policy_bydst[dir].table + hash;
36969+}
36970+
36971+static void xfrm_dst_hash_transfer(struct hlist_head *list,
36972+ struct hlist_head *ndsttable,
36973+ unsigned int nhashmask)
36974+{
36975+ struct hlist_node *entry, *tmp;
36976+ struct xfrm_policy *pol;
36977+
36978+ hlist_for_each_entry_safe(pol, entry, tmp, list, bydst) {
36979+ unsigned int h;
36980+
36981+ h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr,
36982+ pol->family, nhashmask);
36983+ hlist_add_head(&pol->bydst, ndsttable+h);
36984+ }
36985+}
36986+
36987+static void xfrm_idx_hash_transfer(struct hlist_head *list,
36988+ struct hlist_head *nidxtable,
36989+ unsigned int nhashmask)
36990+{
36991+ struct hlist_node *entry, *tmp;
36992+ struct xfrm_policy *pol;
36993+
36994+ hlist_for_each_entry_safe(pol, entry, tmp, list, byidx) {
36995+ unsigned int h;
36996+
36997+ h = __idx_hash(pol->index, nhashmask);
36998+ hlist_add_head(&pol->byidx, nidxtable+h);
36999+ }
37000+}
37001+
37002+static unsigned long xfrm_new_hash_mask(unsigned int old_hmask)
37003+{
37004+ return ((old_hmask + 1) << 1) - 1;
37005+}
37006+
37007+static void xfrm_bydst_resize(int dir)
37008+{
37009+ unsigned int hmask = xfrm_policy_bydst[dir].hmask;
37010+ unsigned int nhashmask = xfrm_new_hash_mask(hmask);
37011+ unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head);
37012+ struct hlist_head *odst = xfrm_policy_bydst[dir].table;
37013+ struct hlist_head *ndst = xfrm_hash_alloc(nsize);
37014+ int i;
37015+
37016+ if (!ndst)
37017+ return;
37018+
37019+ write_lock_bh(&xfrm_policy_lock);
37020+
37021+ for (i = hmask; i >= 0; i--)
37022+ xfrm_dst_hash_transfer(odst + i, ndst, nhashmask);
37023+
37024+ xfrm_policy_bydst[dir].table = ndst;
37025+ xfrm_policy_bydst[dir].hmask = nhashmask;
37026+
37027+ write_unlock_bh(&xfrm_policy_lock);
37028+
37029+ xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head));
37030+}
37031+
37032+static void xfrm_byidx_resize(int total)
37033+{
37034+ unsigned int hmask = xfrm_idx_hmask;
37035+ unsigned int nhashmask = xfrm_new_hash_mask(hmask);
37036+ unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head);
37037+ struct hlist_head *oidx = xfrm_policy_byidx;
37038+ struct hlist_head *nidx = xfrm_hash_alloc(nsize);
37039+ int i;
37040+
37041+ if (!nidx)
37042+ return;
37043+
37044+ write_lock_bh(&xfrm_policy_lock);
37045+
37046+ for (i = hmask; i >= 0; i--)
37047+ xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask);
37048+
37049+ xfrm_policy_byidx = nidx;
37050+ xfrm_idx_hmask = nhashmask;
37051+
37052+ write_unlock_bh(&xfrm_policy_lock);
37053+
37054+ xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head));
37055+}
37056+
37057+static inline int xfrm_bydst_should_resize(int dir, int *total)
37058+{
37059+ unsigned int cnt = xfrm_policy_count[dir];
37060+ unsigned int hmask = xfrm_policy_bydst[dir].hmask;
37061+
37062+ if (total)
37063+ *total += cnt;
37064+
37065+ if ((hmask + 1) < xfrm_policy_hashmax &&
37066+ cnt > hmask)
37067+ return 1;
37068+
37069+ return 0;
37070+}
37071+
37072+static inline int xfrm_byidx_should_resize(int total)
37073+{
37074+ unsigned int hmask = xfrm_idx_hmask;
37075+
37076+ if ((hmask + 1) < xfrm_policy_hashmax &&
37077+ total > hmask)
37078+ return 1;
37079+
37080+ return 0;
37081+}
37082+
37083+static DEFINE_MUTEX(hash_resize_mutex);
37084+
37085+static void xfrm_hash_resize(void *__unused)
37086+{
37087+ int dir, total;
37088+
37089+ mutex_lock(&hash_resize_mutex);
37090+
37091+ total = 0;
37092+ for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {
37093+ if (xfrm_bydst_should_resize(dir, &total))
37094+ xfrm_bydst_resize(dir);
37095+ }
37096+ if (xfrm_byidx_should_resize(total))
37097+ xfrm_byidx_resize(total);
37098+
37099+ mutex_unlock(&hash_resize_mutex);
37100+}
37101+
37102+static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL);
37103+
37104 /* Generate new index... KAME seems to generate them ordered by cost
37105 * of an absolute inpredictability of ordering of rules. This will not pass. */
37106-static u32 xfrm_gen_index(int dir)
37107+static u32 xfrm_gen_index(u8 type, int dir)
37108 {
37109- u32 idx;
37110- struct xfrm_policy *p;
37111 static u32 idx_generator;
37112
37113 for (;;) {
37114+ struct hlist_node *entry;
37115+ struct hlist_head *list;
37116+ struct xfrm_policy *p;
37117+ u32 idx;
37118+ int found;
37119+
37120 idx = (idx_generator | dir);
37121 idx_generator += 8;
37122 if (idx == 0)
37123 idx = 8;
37124- for (p = xfrm_policy_list[dir]; p; p = p->next) {
37125- if (p->index == idx)
37126+ list = xfrm_policy_byidx + idx_hash(idx);
37127+ found = 0;
37128+ hlist_for_each_entry(p, entry, list, byidx) {
37129+ if (p->index == idx) {
37130+ found = 1;
37131 break;
37132+ }
37133 }
37134- if (!p)
37135+ if (!found)
37136 return idx;
37137 }
37138 }
37139
37140+static inline int selector_cmp(struct xfrm_selector *s1, struct xfrm_selector *s2)
37141+{
37142+ u32 *p1 = (u32 *) s1;
37143+ u32 *p2 = (u32 *) s2;
37144+ int len = sizeof(struct xfrm_selector) / sizeof(u32);
37145+ int i;
37146+
37147+ for (i = 0; i < len; i++) {
37148+ if (p1[i] != p2[i])
37149+ return 1;
37150+ }
37151+
37152+ return 0;
37153+}
37154+
37155 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
37156 {
37157- struct xfrm_policy *pol, **p;
37158- struct xfrm_policy *delpol = NULL;
37159- struct xfrm_policy **newpos = NULL;
37160+ struct xfrm_policy *pol;
37161+ struct xfrm_policy *delpol;
37162+ struct hlist_head *chain;
37163+ struct hlist_node *entry, *newpos, *last;
37164 struct dst_entry *gc_list;
37165
37166 write_lock_bh(&xfrm_policy_lock);
37167- for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) {
37168- if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0 &&
37169+ chain = policy_hash_bysel(&policy->selector, policy->family, dir);
37170+ delpol = NULL;
37171+ newpos = NULL;
37172+ last = NULL;
37173+ hlist_for_each_entry(pol, entry, chain, bydst) {
37174+ if (!delpol &&
37175+ pol->type == policy->type &&
37176+ !selector_cmp(&pol->selector, &policy->selector) &&
37177 xfrm_sec_ctx_match(pol->security, policy->security)) {
37178 if (excl) {
37179 write_unlock_bh(&xfrm_policy_lock);
37180 return -EEXIST;
37181 }
37182- *p = pol->next;
37183 delpol = pol;
37184 if (policy->priority > pol->priority)
37185 continue;
37186 } else if (policy->priority >= pol->priority) {
37187- p = &pol->next;
37188+ last = &pol->bydst;
37189 continue;
37190 }
37191 if (!newpos)
37192- newpos = p;
37193+ newpos = &pol->bydst;
37194 if (delpol)
37195 break;
37196- p = &pol->next;
37197+ last = &pol->bydst;
37198 }
37199+ if (!newpos)
37200+ newpos = last;
37201 if (newpos)
37202- p = newpos;
37203+ hlist_add_after(newpos, &policy->bydst);
37204+ else
37205+ hlist_add_head(&policy->bydst, chain);
37206 xfrm_pol_hold(policy);
37207- policy->next = *p;
37208- *p = policy;
37209+ xfrm_policy_count[dir]++;
37210 atomic_inc(&flow_cache_genid);
37211- policy->index = delpol ? delpol->index : xfrm_gen_index(dir);
37212+ if (delpol) {
37213+ hlist_del(&delpol->bydst);
37214+ hlist_del(&delpol->byidx);
37215+ xfrm_policy_count[dir]--;
37216+ }
37217+ policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir);
37218+ hlist_add_head(&policy->byidx, xfrm_policy_byidx+idx_hash(policy->index));
37219 policy->curlft.add_time = (unsigned long)xtime.tv_sec;
37220 policy->curlft.use_time = 0;
37221 if (!mod_timer(&policy->timer, jiffies + HZ))
37222@@ -461,10 +669,13 @@
37223
37224 if (delpol)
37225 xfrm_policy_kill(delpol);
37226+ else if (xfrm_bydst_should_resize(dir, NULL))
37227+ schedule_work(&xfrm_hash_work);
37228
37229 read_lock_bh(&xfrm_policy_lock);
37230 gc_list = NULL;
37231- for (policy = policy->next; policy; policy = policy->next) {
37232+ entry = &policy->bydst;
37233+ hlist_for_each_entry_continue(policy, entry, bydst) {
37234 struct dst_entry *dst;
37235
37236 write_lock(&policy->lock);
37237@@ -493,87 +704,146 @@
37238 }
37239 EXPORT_SYMBOL(xfrm_policy_insert);
37240
37241-struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel,
37242+struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
37243+ struct xfrm_selector *sel,
37244 struct xfrm_sec_ctx *ctx, int delete)
37245 {
37246- struct xfrm_policy *pol, **p;
37247+ struct xfrm_policy *pol, *ret;
37248+ struct hlist_head *chain;
37249+ struct hlist_node *entry;
37250
37251 write_lock_bh(&xfrm_policy_lock);
37252- for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
37253- if ((memcmp(sel, &pol->selector, sizeof(*sel)) == 0) &&
37254- (xfrm_sec_ctx_match(ctx, pol->security))) {
37255+ chain = policy_hash_bysel(sel, sel->family, dir);
37256+ ret = NULL;
37257+ hlist_for_each_entry(pol, entry, chain, bydst) {
37258+ if (pol->type == type &&
37259+ !selector_cmp(sel, &pol->selector) &&
37260+ xfrm_sec_ctx_match(ctx, pol->security)) {
37261 xfrm_pol_hold(pol);
37262- if (delete)
37263- *p = pol->next;
37264+ if (delete) {
37265+ hlist_del(&pol->bydst);
37266+ hlist_del(&pol->byidx);
37267+ xfrm_policy_count[dir]--;
37268+ }
37269+ ret = pol;
37270 break;
37271 }
37272 }
37273 write_unlock_bh(&xfrm_policy_lock);
37274
37275- if (pol && delete) {
37276+ if (ret && delete) {
37277 atomic_inc(&flow_cache_genid);
37278- xfrm_policy_kill(pol);
37279+ xfrm_policy_kill(ret);
37280 }
37281- return pol;
37282+ return ret;
37283 }
37284 EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
37285
37286-struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete)
37287+struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete)
37288 {
37289- struct xfrm_policy *pol, **p;
37290+ struct xfrm_policy *pol, *ret;
37291+ struct hlist_head *chain;
37292+ struct hlist_node *entry;
37293
37294 write_lock_bh(&xfrm_policy_lock);
37295- for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
37296- if (pol->index == id) {
37297+ chain = xfrm_policy_byidx + idx_hash(id);
37298+ ret = NULL;
37299+ hlist_for_each_entry(pol, entry, chain, byidx) {
37300+ if (pol->type == type && pol->index == id) {
37301 xfrm_pol_hold(pol);
37302- if (delete)
37303- *p = pol->next;
37304+ if (delete) {
37305+ hlist_del(&pol->bydst);
37306+ hlist_del(&pol->byidx);
37307+ xfrm_policy_count[dir]--;
37308+ }
37309+ ret = pol;
37310 break;
37311 }
37312 }
37313 write_unlock_bh(&xfrm_policy_lock);
37314
37315- if (pol && delete) {
37316+ if (ret && delete) {
37317 atomic_inc(&flow_cache_genid);
37318- xfrm_policy_kill(pol);
37319+ xfrm_policy_kill(ret);
37320 }
37321- return pol;
37322+ return ret;
37323 }
37324 EXPORT_SYMBOL(xfrm_policy_byid);
37325
37326-void xfrm_policy_flush(void)
37327+void xfrm_policy_flush(u8 type)
37328 {
37329- struct xfrm_policy *xp;
37330 int dir;
37331
37332 write_lock_bh(&xfrm_policy_lock);
37333 for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
37334- while ((xp = xfrm_policy_list[dir]) != NULL) {
37335- xfrm_policy_list[dir] = xp->next;
37336+ struct xfrm_policy *pol;
37337+ struct hlist_node *entry;
37338+ int i;
37339+
37340+ again1:
37341+ hlist_for_each_entry(pol, entry,
37342+ &xfrm_policy_inexact[dir], bydst) {
37343+ if (pol->type != type)
37344+ continue;
37345+ hlist_del(&pol->bydst);
37346+ hlist_del(&pol->byidx);
37347 write_unlock_bh(&xfrm_policy_lock);
37348
37349- xfrm_policy_kill(xp);
37350+ xfrm_policy_kill(pol);
37351
37352 write_lock_bh(&xfrm_policy_lock);
37353+ goto again1;
37354 }
37355+
37356+ for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
37357+ again2:
37358+ hlist_for_each_entry(pol, entry,
37359+ xfrm_policy_bydst[dir].table + i,
37360+ bydst) {
37361+ if (pol->type != type)
37362+ continue;
37363+ hlist_del(&pol->bydst);
37364+ hlist_del(&pol->byidx);
37365+ write_unlock_bh(&xfrm_policy_lock);
37366+
37367+ xfrm_policy_kill(pol);
37368+
37369+ write_lock_bh(&xfrm_policy_lock);
37370+ goto again2;
37371+ }
37372+ }
37373+
37374+ xfrm_policy_count[dir] = 0;
37375 }
37376 atomic_inc(&flow_cache_genid);
37377 write_unlock_bh(&xfrm_policy_lock);
37378 }
37379 EXPORT_SYMBOL(xfrm_policy_flush);
37380
37381-int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*),
37382+int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*),
37383 void *data)
37384 {
37385- struct xfrm_policy *xp;
37386- int dir;
37387- int count = 0;
37388- int error = 0;
37389+ struct xfrm_policy *pol;
37390+ struct hlist_node *entry;
37391+ int dir, count, error;
37392
37393 read_lock_bh(&xfrm_policy_lock);
37394+ count = 0;
37395 for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
37396- for (xp = xfrm_policy_list[dir]; xp; xp = xp->next)
37397- count++;
37398+ struct hlist_head *table = xfrm_policy_bydst[dir].table;
37399+ int i;
37400+
37401+ hlist_for_each_entry(pol, entry,
37402+ &xfrm_policy_inexact[dir], bydst) {
37403+ if (pol->type == type)
37404+ count++;
37405+ }
37406+ for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
37407+ hlist_for_each_entry(pol, entry, table + i, bydst) {
37408+ if (pol->type == type)
37409+ count++;
37410+ }
37411+ }
37412 }
37413
37414 if (count == 0) {
37415@@ -582,13 +852,28 @@
37416 }
37417
37418 for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) {
37419- for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) {
37420- error = func(xp, dir%XFRM_POLICY_MAX, --count, data);
37421+ struct hlist_head *table = xfrm_policy_bydst[dir].table;
37422+ int i;
37423+
37424+ hlist_for_each_entry(pol, entry,
37425+ &xfrm_policy_inexact[dir], bydst) {
37426+ if (pol->type != type)
37427+ continue;
37428+ error = func(pol, dir % XFRM_POLICY_MAX, --count, data);
37429 if (error)
37430 goto out;
37431 }
37432+ for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
37433+ hlist_for_each_entry(pol, entry, table + i, bydst) {
37434+ if (pol->type != type)
37435+ continue;
37436+ error = func(pol, dir % XFRM_POLICY_MAX, --count, data);
37437+ if (error)
37438+ goto out;
37439+ }
37440+ }
37441 }
37442-
37443+ error = 0;
37444 out:
37445 read_unlock_bh(&xfrm_policy_lock);
37446 return error;
37447@@ -597,29 +882,79 @@
37448
37449 /* Find policy to apply to this flow. */
37450
37451-static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir,
37452- void **objp, atomic_t **obj_refp)
37453+static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
37454+ u8 type, u16 family, int dir)
37455 {
37456- struct xfrm_policy *pol;
37457+ struct xfrm_selector *sel = &pol->selector;
37458+ int match;
37459
37460- read_lock_bh(&xfrm_policy_lock);
37461- for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) {
37462- struct xfrm_selector *sel = &pol->selector;
37463- int match;
37464+ if (pol->family != family ||
37465+ pol->type != type)
37466+ return 0;
37467
37468- if (pol->family != family)
37469- continue;
37470+ match = xfrm_selector_match(sel, fl, family);
37471+ if (match) {
37472+ if (!security_xfrm_policy_lookup(pol, fl->secid, dir))
37473+ return 1;
37474+ }
37475+
37476+ return 0;
37477+}
37478
37479- match = xfrm_selector_match(sel, fl, family);
37480+static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
37481+ u16 family, u8 dir)
37482+{
37483+ struct xfrm_policy *pol, *ret;
37484+ xfrm_address_t *daddr, *saddr;
37485+ struct hlist_node *entry;
37486+ struct hlist_head *chain;
37487+ u32 priority = ~0U;
37488+
37489+ daddr = xfrm_flowi_daddr(fl, family);
37490+ saddr = xfrm_flowi_saddr(fl, family);
37491+ if (unlikely(!daddr || !saddr))
37492+ return NULL;
37493
37494- if (match) {
37495- if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) {
37496- xfrm_pol_hold(pol);
37497- break;
37498- }
37499+ read_lock_bh(&xfrm_policy_lock);
37500+ chain = policy_hash_direct(daddr, saddr, family, dir);
37501+ ret = NULL;
37502+ hlist_for_each_entry(pol, entry, chain, bydst) {
37503+ if (xfrm_policy_match(pol, fl, type, family, dir)) {
37504+ ret = pol;
37505+ priority = ret->priority;
37506+ break;
37507 }
37508 }
37509+ chain = &xfrm_policy_inexact[dir];
37510+ hlist_for_each_entry(pol, entry, chain, bydst) {
37511+ if (xfrm_policy_match(pol, fl, type, family, dir) &&
37512+ pol->priority < priority) {
37513+ ret = pol;
37514+ break;
37515+ }
37516+ }
37517+ if (ret)
37518+ xfrm_pol_hold(ret);
37519 read_unlock_bh(&xfrm_policy_lock);
37520+
37521+ return ret;
37522+}
37523+
37524+static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
37525+ void **objp, atomic_t **obj_refp)
37526+{
37527+ struct xfrm_policy *pol;
37528+
37529+#ifdef CONFIG_XFRM_SUB_POLICY
37530+ pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir);
37531+ if (pol)
37532+ goto end;
37533+#endif
37534+ pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir);
37535+
37536+#ifdef CONFIG_XFRM_SUB_POLICY
37537+end:
37538+#endif
37539 if ((*objp = (void *) pol) != NULL)
37540 *obj_refp = &pol->refcnt;
37541 }
37542@@ -641,7 +976,7 @@
37543 };
37544 }
37545
37546-static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl, u32 sk_sid)
37547+static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl)
37548 {
37549 struct xfrm_policy *pol;
37550
37551@@ -652,7 +987,7 @@
37552 int err = 0;
37553
37554 if (match)
37555- err = security_xfrm_policy_lookup(pol, sk_sid, policy_to_flow_dir(dir));
37556+ err = security_xfrm_policy_lookup(pol, fl->secid, policy_to_flow_dir(dir));
37557
37558 if (match && !err)
37559 xfrm_pol_hold(pol);
37560@@ -665,24 +1000,29 @@
37561
37562 static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
37563 {
37564- pol->next = xfrm_policy_list[dir];
37565- xfrm_policy_list[dir] = pol;
37566+ struct hlist_head *chain = policy_hash_bysel(&pol->selector,
37567+ pol->family, dir);
37568+
37569+ hlist_add_head(&pol->bydst, chain);
37570+ hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index));
37571+ xfrm_policy_count[dir]++;
37572 xfrm_pol_hold(pol);
37573+
37574+ if (xfrm_bydst_should_resize(dir, NULL))
37575+ schedule_work(&xfrm_hash_work);
37576 }
37577
37578 static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
37579 int dir)
37580 {
37581- struct xfrm_policy **polp;
37582+ if (hlist_unhashed(&pol->bydst))
37583+ return NULL;
37584
37585- for (polp = &xfrm_policy_list[dir];
37586- *polp != NULL; polp = &(*polp)->next) {
37587- if (*polp == pol) {
37588- *polp = pol->next;
37589- return pol;
37590- }
37591- }
37592- return NULL;
37593+ hlist_del(&pol->bydst);
37594+ hlist_del(&pol->byidx);
37595+ xfrm_policy_count[dir]--;
37596+
37597+ return pol;
37598 }
37599
37600 int xfrm_policy_delete(struct xfrm_policy *pol, int dir)
37601@@ -704,12 +1044,17 @@
37602 {
37603 struct xfrm_policy *old_pol;
37604
37605+#ifdef CONFIG_XFRM_SUB_POLICY
37606+ if (pol && pol->type != XFRM_POLICY_TYPE_MAIN)
37607+ return -EINVAL;
37608+#endif
37609+
37610 write_lock_bh(&xfrm_policy_lock);
37611 old_pol = sk->sk_policy[dir];
37612 sk->sk_policy[dir] = pol;
37613 if (pol) {
37614 pol->curlft.add_time = (unsigned long)xtime.tv_sec;
37615- pol->index = xfrm_gen_index(XFRM_POLICY_MAX+dir);
37616+ pol->index = xfrm_gen_index(pol->type, XFRM_POLICY_MAX+dir);
37617 __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir);
37618 }
37619 if (old_pol)
37620@@ -738,6 +1083,7 @@
37621 newp->flags = old->flags;
37622 newp->xfrm_nr = old->xfrm_nr;
37623 newp->index = old->index;
37624+ newp->type = old->type;
37625 memcpy(newp->xfrm_vec, old->xfrm_vec,
37626 newp->xfrm_nr*sizeof(struct xfrm_tmpl));
37627 write_lock_bh(&xfrm_policy_lock);
37628@@ -761,17 +1107,32 @@
37629 return 0;
37630 }
37631
37632+static int
37633+xfrm_get_saddr(xfrm_address_t *local, xfrm_address_t *remote,
37634+ unsigned short family)
37635+{
37636+ int err;
37637+ struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
37638+
37639+ if (unlikely(afinfo == NULL))
37640+ return -EINVAL;
37641+ err = afinfo->get_saddr(local, remote);
37642+ xfrm_policy_put_afinfo(afinfo);
37643+ return err;
37644+}
37645+
37646 /* Resolve list of templates for the flow, given policy. */
37647
37648 static int
37649-xfrm_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl,
37650- struct xfrm_state **xfrm,
37651- unsigned short family)
37652+xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,
37653+ struct xfrm_state **xfrm,
37654+ unsigned short family)
37655 {
37656 int nx;
37657 int i, error;
37658 xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family);
37659 xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family);
37660+ xfrm_address_t tmp;
37661
37662 for (nx=0, i = 0; i < policy->xfrm_nr; i++) {
37663 struct xfrm_state *x;
37664@@ -779,9 +1140,15 @@
37665 xfrm_address_t *local = saddr;
37666 struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
37667
37668- if (tmpl->mode) {
37669+ if (tmpl->mode == XFRM_MODE_TUNNEL) {
37670 remote = &tmpl->id.daddr;
37671 local = &tmpl->saddr;
37672+ if (xfrm_addr_any(local, family)) {
37673+ error = xfrm_get_saddr(&tmp, remote, family);
37674+ if (error)
37675+ goto fail;
37676+ local = &tmp;
37677+ }
37678 }
37679
37680 x = xfrm_state_find(remote, local, fl, tmpl, policy, &error, family);
37681@@ -809,6 +1176,45 @@
37682 return error;
37683 }
37684
37685+static int
37686+xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
37687+ struct xfrm_state **xfrm,
37688+ unsigned short family)
37689+{
37690+ struct xfrm_state *tp[XFRM_MAX_DEPTH];
37691+ struct xfrm_state **tpp = (npols > 1) ? tp : xfrm;
37692+ int cnx = 0;
37693+ int error;
37694+ int ret;
37695+ int i;
37696+
37697+ for (i = 0; i < npols; i++) {
37698+ if (cnx + pols[i]->xfrm_nr >= XFRM_MAX_DEPTH) {
37699+ error = -ENOBUFS;
37700+ goto fail;
37701+ }
37702+
37703+ ret = xfrm_tmpl_resolve_one(pols[i], fl, &tpp[cnx], family);
37704+ if (ret < 0) {
37705+ error = ret;
37706+ goto fail;
37707+ } else
37708+ cnx += ret;
37709+ }
37710+
37711+ /* found states are sorted for outbound processing */
37712+ if (npols > 1)
37713+ xfrm_state_sort(xfrm, tpp, cnx, family);
37714+
37715+ return cnx;
37716+
37717+ fail:
37718+ for (cnx--; cnx>=0; cnx--)
37719+ xfrm_state_put(tpp[cnx]);
37720+ return error;
37721+
37722+}
37723+
37724 /* Check that the bundle accepts the flow and its components are
37725 * still valid.
37726 */
37727@@ -855,6 +1261,11 @@
37728 struct sock *sk, int flags)
37729 {
37730 struct xfrm_policy *policy;
37731+ struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
37732+ int npols;
37733+ int pol_dead;
37734+ int xfrm_nr;
37735+ int pi;
37736 struct xfrm_state *xfrm[XFRM_MAX_DEPTH];
37737 struct dst_entry *dst, *dst_orig = *dst_p;
37738 int nx = 0;
37739@@ -862,19 +1273,26 @@
37740 u32 genid;
37741 u16 family;
37742 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
37743- u32 sk_sid = security_sk_sid(sk, fl, dir);
37744+
37745 restart:
37746 genid = atomic_read(&flow_cache_genid);
37747 policy = NULL;
37748+ for (pi = 0; pi < ARRAY_SIZE(pols); pi++)
37749+ pols[pi] = NULL;
37750+ npols = 0;
37751+ pol_dead = 0;
37752+ xfrm_nr = 0;
37753+
37754 if (sk && sk->sk_policy[1])
37755- policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid);
37756+ policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
37757
37758 if (!policy) {
37759 /* To accelerate a bit... */
37760- if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
37761+ if ((dst_orig->flags & DST_NOXFRM) ||
37762+ !xfrm_policy_count[XFRM_POLICY_OUT])
37763 return 0;
37764
37765- policy = flow_cache_lookup(fl, sk_sid, dst_orig->ops->family,
37766+ policy = flow_cache_lookup(fl, dst_orig->ops->family,
37767 dir, xfrm_policy_lookup);
37768 }
37769
37770@@ -883,6 +1301,9 @@
37771
37772 family = dst_orig->ops->family;
37773 policy->curlft.use_time = (unsigned long)xtime.tv_sec;
37774+ pols[0] = policy;
37775+ npols ++;
37776+ xfrm_nr += pols[0]->xfrm_nr;
37777
37778 switch (policy->action) {
37779 case XFRM_POLICY_BLOCK:
37780@@ -891,11 +1312,13 @@
37781 goto error;
37782
37783 case XFRM_POLICY_ALLOW:
37784+#ifndef CONFIG_XFRM_SUB_POLICY
37785 if (policy->xfrm_nr == 0) {
37786 /* Flow passes not transformed. */
37787 xfrm_pol_put(policy);
37788 return 0;
37789 }
37790+#endif
37791
37792 /* Try to find matching bundle.
37793 *
37794@@ -911,7 +1334,36 @@
37795 if (dst)
37796 break;
37797
37798- nx = xfrm_tmpl_resolve(policy, fl, xfrm, family);
37799+#ifdef CONFIG_XFRM_SUB_POLICY
37800+ if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) {
37801+ pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN,
37802+ fl, family,
37803+ XFRM_POLICY_OUT);
37804+ if (pols[1]) {
37805+ if (pols[1]->action == XFRM_POLICY_BLOCK) {
37806+ err = -EPERM;
37807+ goto error;
37808+ }
37809+ npols ++;
37810+ xfrm_nr += pols[1]->xfrm_nr;
37811+ }
37812+ }
37813+
37814+ /*
37815+ * Because neither flowi nor bundle information knows about
37816+ * transformation template size. On more than one policy usage
37817+ * we can realize whether all of them is bypass or not after
37818+ * they are searched. See above not-transformed bypass
37819+ * is surrounded by non-sub policy configuration, too.
37820+ */
37821+ if (xfrm_nr == 0) {
37822+ /* Flow passes not transformed. */
37823+ xfrm_pols_put(pols, npols);
37824+ return 0;
37825+ }
37826+
37827+#endif
37828+ nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
37829
37830 if (unlikely(nx<0)) {
37831 err = nx;
37832@@ -924,7 +1376,7 @@
37833 set_current_state(TASK_RUNNING);
37834 remove_wait_queue(&km_waitq, &wait);
37835
37836- nx = xfrm_tmpl_resolve(policy, fl, xfrm, family);
37837+ nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
37838
37839 if (nx == -EAGAIN && signal_pending(current)) {
37840 err = -ERESTART;
37841@@ -932,7 +1384,7 @@
37842 }
37843 if (nx == -EAGAIN ||
37844 genid != atomic_read(&flow_cache_genid)) {
37845- xfrm_pol_put(policy);
37846+ xfrm_pols_put(pols, npols);
37847 goto restart;
37848 }
37849 err = nx;
37850@@ -942,7 +1394,7 @@
37851 }
37852 if (nx == 0) {
37853 /* Flow passes not transformed. */
37854- xfrm_pol_put(policy);
37855+ xfrm_pols_put(pols, npols);
37856 return 0;
37857 }
37858
37859@@ -956,8 +1408,14 @@
37860 goto error;
37861 }
37862
37863+ for (pi = 0; pi < npols; pi++) {
37864+ read_lock_bh(&pols[pi]->lock);
37865+ pol_dead |= pols[pi]->dead;
37866+ read_unlock_bh(&pols[pi]->lock);
37867+ }
37868+
37869 write_lock_bh(&policy->lock);
37870- if (unlikely(policy->dead || stale_bundle(dst))) {
37871+ if (unlikely(pol_dead || stale_bundle(dst))) {
37872 /* Wow! While we worked on resolving, this
37873 * policy has gone. Retry. It is not paranoia,
37874 * we just cannot enlist new bundle to dead object.
37875@@ -977,17 +1435,34 @@
37876 }
37877 *dst_p = dst;
37878 dst_release(dst_orig);
37879- xfrm_pol_put(policy);
37880+ xfrm_pols_put(pols, npols);
37881 return 0;
37882
37883 error:
37884 dst_release(dst_orig);
37885- xfrm_pol_put(policy);
37886+ xfrm_pols_put(pols, npols);
37887 *dst_p = NULL;
37888 return err;
37889 }
37890 EXPORT_SYMBOL(xfrm_lookup);
37891
37892+static inline int
37893+xfrm_secpath_reject(int idx, struct sk_buff *skb, struct flowi *fl)
37894+{
37895+ struct xfrm_state *x;
37896+ int err;
37897+
37898+ if (!skb->sp || idx < 0 || idx >= skb->sp->len)
37899+ return 0;
37900+ x = skb->sp->xvec[idx];
37901+ if (!x->type->reject)
37902+ return 0;
37903+ xfrm_state_hold(x);
37904+ err = x->type->reject(x, skb, fl);
37905+ xfrm_state_put(x);
37906+ return err;
37907+}
37908+
37909 /* When skb is transformed back to its "native" form, we have to
37910 * check policy restrictions. At the moment we make this in maximally
37911 * stupid way. Shame on me. :-) Of course, connected sockets must
37912@@ -1004,10 +1479,19 @@
37913 (x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
37914 (x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
37915 x->props.mode == tmpl->mode &&
37916- (tmpl->aalgos & (1<<x->props.aalgo)) &&
37917- !(x->props.mode && xfrm_state_addr_cmp(tmpl, x, family));
37918+ ((tmpl->aalgos & (1<<x->props.aalgo)) ||
37919+ !(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) &&
37920+ !(x->props.mode != XFRM_MODE_TRANSPORT &&
37921+ xfrm_state_addr_cmp(tmpl, x, family));
37922 }
37923
37924+/*
37925+ * 0 or more than 0 is returned when validation is succeeded (either bypass
37926+ * because of optional transport mode, or next index of the mathced secpath
37927+ * state with the template.
37928+ * -1 is returned when no matching template is found.
37929+ * Otherwise "-2 - errored_index" is returned.
37930+ */
37931 static inline int
37932 xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
37933 unsigned short family)
37934@@ -1015,15 +1499,18 @@
37935 int idx = start;
37936
37937 if (tmpl->optional) {
37938- if (!tmpl->mode)
37939+ if (tmpl->mode == XFRM_MODE_TRANSPORT)
37940 return start;
37941 } else
37942 start = -1;
37943 for (; idx < sp->len; idx++) {
37944 if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
37945 return ++idx;
37946- if (sp->xvec[idx]->props.mode)
37947+ if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
37948+ if (start == -1)
37949+ start = -2-idx;
37950 break;
37951+ }
37952 }
37953 return start;
37954 }
37955@@ -1032,21 +1519,25 @@
37956 xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
37957 {
37958 struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
37959+ int err;
37960
37961 if (unlikely(afinfo == NULL))
37962 return -EAFNOSUPPORT;
37963
37964 afinfo->decode_session(skb, fl);
37965+ err = security_xfrm_decode_session(skb, &fl->secid);
37966 xfrm_policy_put_afinfo(afinfo);
37967- return 0;
37968+ return err;
37969 }
37970 EXPORT_SYMBOL(xfrm_decode_session);
37971
37972-static inline int secpath_has_tunnel(struct sec_path *sp, int k)
37973+static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp)
37974 {
37975 for (; k < sp->len; k++) {
37976- if (sp->xvec[k]->props.mode)
37977+ if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT) {
37978+ *idxp = k;
37979 return 1;
37980+ }
37981 }
37982
37983 return 0;
37984@@ -1056,16 +1547,18 @@
37985 unsigned short family)
37986 {
37987 struct xfrm_policy *pol;
37988+ struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
37989+ int npols = 0;
37990+ int xfrm_nr;
37991+ int pi;
37992 struct flowi fl;
37993 u8 fl_dir = policy_to_flow_dir(dir);
37994- u32 sk_sid;
37995+ int xerr_idx = -1;
37996
37997 if (xfrm_decode_session(skb, &fl, family) < 0)
37998 return 0;
37999 nf_nat_decode_session(skb, &fl, family);
38000
38001- sk_sid = security_sk_sid(sk, &fl, fl_dir);
38002-
38003 /* First, check used SA against their selectors. */
38004 if (skb->sp) {
38005 int i;
38006@@ -1079,46 +1572,90 @@
38007
38008 pol = NULL;
38009 if (sk && sk->sk_policy[dir])
38010- pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid);
38011+ pol = xfrm_sk_policy_lookup(sk, dir, &fl);
38012
38013 if (!pol)
38014- pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir,
38015+ pol = flow_cache_lookup(&fl, family, fl_dir,
38016 xfrm_policy_lookup);
38017
38018- if (!pol)
38019- return !skb->sp || !secpath_has_tunnel(skb->sp, 0);
38020+ if (!pol) {
38021+ if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
38022+ xfrm_secpath_reject(xerr_idx, skb, &fl);
38023+ return 0;
38024+ }
38025+ return 1;
38026+ }
38027
38028 pol->curlft.use_time = (unsigned long)xtime.tv_sec;
38029
38030+ pols[0] = pol;
38031+ npols ++;
38032+#ifdef CONFIG_XFRM_SUB_POLICY
38033+ if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) {
38034+ pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN,
38035+ &fl, family,
38036+ XFRM_POLICY_IN);
38037+ if (pols[1]) {
38038+ pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec;
38039+ npols ++;
38040+ }
38041+ }
38042+#endif
38043+
38044 if (pol->action == XFRM_POLICY_ALLOW) {
38045 struct sec_path *sp;
38046 static struct sec_path dummy;
38047+ struct xfrm_tmpl *tp[XFRM_MAX_DEPTH];
38048+ struct xfrm_tmpl *stp[XFRM_MAX_DEPTH];
38049+ struct xfrm_tmpl **tpp = tp;
38050+ int ti = 0;
38051 int i, k;
38052
38053 if ((sp = skb->sp) == NULL)
38054 sp = &dummy;
38055
38056+ for (pi = 0; pi < npols; pi++) {
38057+ if (pols[pi] != pol &&
38058+ pols[pi]->action != XFRM_POLICY_ALLOW)
38059+ goto reject;
38060+ if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH)
38061+ goto reject_error;
38062+ for (i = 0; i < pols[pi]->xfrm_nr; i++)
38063+ tpp[ti++] = &pols[pi]->xfrm_vec[i];
38064+ }
38065+ xfrm_nr = ti;
38066+ if (npols > 1) {
38067+ xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
38068+ tpp = stp;
38069+ }
38070+
38071 /* For each tunnel xfrm, find the first matching tmpl.
38072 * For each tmpl before that, find corresponding xfrm.
38073 * Order is _important_. Later we will implement
38074 * some barriers, but at the moment barriers
38075 * are implied between each two transformations.
38076 */
38077- for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
38078- k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family);
38079- if (k < 0)
38080+ for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
38081+ k = xfrm_policy_ok(tpp[i], sp, k, family);
38082+ if (k < 0) {
38083+ if (k < -1)
38084+ /* "-2 - errored_index" returned */
38085+ xerr_idx = -(2+k);
38086 goto reject;
38087+ }
38088 }
38089
38090- if (secpath_has_tunnel(sp, k))
38091+ if (secpath_has_nontransport(sp, k, &xerr_idx))
38092 goto reject;
38093
38094- xfrm_pol_put(pol);
38095+ xfrm_pols_put(pols, npols);
38096 return 1;
38097 }
38098
38099 reject:
38100- xfrm_pol_put(pol);
38101+ xfrm_secpath_reject(xerr_idx, skb, &fl);
38102+reject_error:
38103+ xfrm_pols_put(pols, npols);
38104 return 0;
38105 }
38106 EXPORT_SYMBOL(__xfrm_policy_check);
38107@@ -1166,7 +1703,7 @@
38108
38109 static int stale_bundle(struct dst_entry *dst)
38110 {
38111- return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC);
38112+ return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
38113 }
38114
38115 void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
38116@@ -1196,33 +1733,50 @@
38117 return dst;
38118 }
38119
38120+static void prune_one_bundle(struct xfrm_policy *pol, int (*func)(struct dst_entry *), struct dst_entry **gc_list_p)
38121+{
38122+ struct dst_entry *dst, **dstp;
38123+
38124+ write_lock(&pol->lock);
38125+ dstp = &pol->bundles;
38126+ while ((dst=*dstp) != NULL) {
38127+ if (func(dst)) {
38128+ *dstp = dst->next;
38129+ dst->next = *gc_list_p;
38130+ *gc_list_p = dst;
38131+ } else {
38132+ dstp = &dst->next;
38133+ }
38134+ }
38135+ write_unlock(&pol->lock);
38136+}
38137+
38138 static void xfrm_prune_bundles(int (*func)(struct dst_entry *))
38139 {
38140- int i;
38141- struct xfrm_policy *pol;
38142- struct dst_entry *dst, **dstp, *gc_list = NULL;
38143+ struct dst_entry *gc_list = NULL;
38144+ int dir;
38145
38146 read_lock_bh(&xfrm_policy_lock);
38147- for (i=0; i<2*XFRM_POLICY_MAX; i++) {
38148- for (pol = xfrm_policy_list[i]; pol; pol = pol->next) {
38149- write_lock(&pol->lock);
38150- dstp = &pol->bundles;
38151- while ((dst=*dstp) != NULL) {
38152- if (func(dst)) {
38153- *dstp = dst->next;
38154- dst->next = gc_list;
38155- gc_list = dst;
38156- } else {
38157- dstp = &dst->next;
38158- }
38159- }
38160- write_unlock(&pol->lock);
38161+ for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {
38162+ struct xfrm_policy *pol;
38163+ struct hlist_node *entry;
38164+ struct hlist_head *table;
38165+ int i;
38166+
38167+ hlist_for_each_entry(pol, entry,
38168+ &xfrm_policy_inexact[dir], bydst)
38169+ prune_one_bundle(pol, func, &gc_list);
38170+
38171+ table = xfrm_policy_bydst[dir].table;
38172+ for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
38173+ hlist_for_each_entry(pol, entry, table + i, bydst)
38174+ prune_one_bundle(pol, func, &gc_list);
38175 }
38176 }
38177 read_unlock_bh(&xfrm_policy_lock);
38178
38179 while (gc_list) {
38180- dst = gc_list;
38181+ struct dst_entry *dst = gc_list;
38182 gc_list = dst->next;
38183 dst_free(dst);
38184 }
38185@@ -1238,22 +1792,12 @@
38186 xfrm_prune_bundles(unused_bundle);
38187 }
38188
38189-int xfrm_flush_bundles(void)
38190+static int xfrm_flush_bundles(void)
38191 {
38192 xfrm_prune_bundles(stale_bundle);
38193 return 0;
38194 }
38195
38196-static int always_true(struct dst_entry *dst)
38197-{
38198- return 1;
38199-}
38200-
38201-void xfrm_flush_all_bundles(void)
38202-{
38203- xfrm_prune_bundles(always_true);
38204-}
38205-
38206 void xfrm_init_pmtu(struct dst_entry *dst)
38207 {
38208 do {
38209@@ -1281,7 +1825,7 @@
38210 * still valid.
38211 */
38212
38213-int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
38214+int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict)
38215 {
38216 struct dst_entry *dst = &first->u.dst;
38217 struct xfrm_dst *last;
38218@@ -1298,8 +1842,16 @@
38219
38220 if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
38221 return 0;
38222+ if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm))
38223+ return 0;
38224 if (dst->xfrm->km.state != XFRM_STATE_VALID)
38225 return 0;
38226+ if (xdst->genid != dst->xfrm->genid)
38227+ return 0;
38228+
38229+ if (strict && fl && dst->xfrm->props.mode != XFRM_MODE_TUNNEL &&
38230+ !xfrm_state_addr_flow_check(dst->xfrm, fl, family))
38231+ return 0;
38232
38233 mtu = dst_mtu(dst->child);
38234 if (xdst->child_mtu_cached != mtu) {
38235@@ -1448,12 +2000,33 @@
38236
38237 static void __init xfrm_policy_init(void)
38238 {
38239+ unsigned int hmask, sz;
38240+ int dir;
38241+
38242 xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache",
38243 sizeof(struct xfrm_dst),
38244- 0, SLAB_HWCACHE_ALIGN,
38245+ 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
38246 NULL, NULL);
38247- if (!xfrm_dst_cache)
38248- panic("XFRM: failed to allocate xfrm_dst_cache\n");
38249+
38250+ hmask = 8 - 1;
38251+ sz = (hmask+1) * sizeof(struct hlist_head);
38252+
38253+ xfrm_policy_byidx = xfrm_hash_alloc(sz);
38254+ xfrm_idx_hmask = hmask;
38255+ if (!xfrm_policy_byidx)
38256+ panic("XFRM: failed to allocate byidx hash\n");
38257+
38258+ for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {
38259+ struct xfrm_policy_hash *htab;
38260+
38261+ INIT_HLIST_HEAD(&xfrm_policy_inexact[dir]);
38262+
38263+ htab = &xfrm_policy_bydst[dir];
38264+ htab->table = xfrm_hash_alloc(sz);
38265+ htab->hmask = hmask;
38266+ if (!htab->table)
38267+ panic("XFRM: failed to allocate bydst hash\n");
38268+ }
38269
38270 INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL);
38271 register_netdevice_notifier(&xfrm_dev_notifier);
38272diff -Nur linux-2.6.18-rc5/net/xfrm/xfrm_state.c linux-2.6.19/net/xfrm/xfrm_state.c
38273--- linux-2.6.18-rc5/net/xfrm/xfrm_state.c 2006-08-28 05:41:48.000000000 +0200
38274+++ linux-2.6.19/net/xfrm/xfrm_state.c 2006-09-22 10:04:59.000000000 +0200
38275@@ -18,8 +18,11 @@
38276 #include <linux/pfkeyv2.h>
38277 #include <linux/ipsec.h>
38278 #include <linux/module.h>
38279+#include <linux/cache.h>
38280 #include <asm/uaccess.h>
38281
38282+#include "xfrm_hash.h"
38283+
38284 struct sock *xfrm_nl;
38285 EXPORT_SYMBOL(xfrm_nl);
38286
38287@@ -32,7 +35,7 @@
38288 /* Each xfrm_state may be linked to two tables:
38289
38290 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
38291- 2. Hash table by daddr to find what SAs exist for given
38292+ 2. Hash table by (daddr,family,reqid) to find what SAs exist for given
38293 destination/tunnel endpoint. (output)
38294 */
38295
38296@@ -44,8 +47,123 @@
38297 * Main use is finding SA after policy selected tunnel or transport mode.
38298 * Also, it can be used by ah/esp icmp error handler to find offending SA.
38299 */
38300-static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE];
38301-static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE];
38302+static struct hlist_head *xfrm_state_bydst __read_mostly;
38303+static struct hlist_head *xfrm_state_bysrc __read_mostly;
38304+static struct hlist_head *xfrm_state_byspi __read_mostly;
38305+static unsigned int xfrm_state_hmask __read_mostly;
38306+static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
38307+static unsigned int xfrm_state_num;
38308+static unsigned int xfrm_state_genid;
38309+
38310+static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
38311+ xfrm_address_t *saddr,
38312+ u32 reqid,
38313+ unsigned short family)
38314+{
38315+ return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask);
38316+}
38317+
38318+static inline unsigned int xfrm_src_hash(xfrm_address_t *addr,
38319+ unsigned short family)
38320+{
38321+ return __xfrm_src_hash(addr, family, xfrm_state_hmask);
38322+}
38323+
38324+static inline unsigned int
38325+xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family)
38326+{
38327+ return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask);
38328+}
38329+
38330+static void xfrm_hash_transfer(struct hlist_head *list,
38331+ struct hlist_head *ndsttable,
38332+ struct hlist_head *nsrctable,
38333+ struct hlist_head *nspitable,
38334+ unsigned int nhashmask)
38335+{
38336+ struct hlist_node *entry, *tmp;
38337+ struct xfrm_state *x;
38338+
38339+ hlist_for_each_entry_safe(x, entry, tmp, list, bydst) {
38340+ unsigned int h;
38341+
38342+ h = __xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
38343+ x->props.reqid, x->props.family,
38344+ nhashmask);
38345+ hlist_add_head(&x->bydst, ndsttable+h);
38346+
38347+ h = __xfrm_src_hash(&x->props.saddr, x->props.family,
38348+ nhashmask);
38349+ hlist_add_head(&x->bysrc, nsrctable+h);
38350+
38351+ h = __xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
38352+ x->props.family, nhashmask);
38353+ hlist_add_head(&x->byspi, nspitable+h);
38354+ }
38355+}
38356+
38357+static unsigned long xfrm_hash_new_size(void)
38358+{
38359+ return ((xfrm_state_hmask + 1) << 1) *
38360+ sizeof(struct hlist_head);
38361+}
38362+
38363+static DEFINE_MUTEX(hash_resize_mutex);
38364+
38365+static void xfrm_hash_resize(void *__unused)
38366+{
38367+ struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi;
38368+ unsigned long nsize, osize;
38369+ unsigned int nhashmask, ohashmask;
38370+ int i;
38371+
38372+ mutex_lock(&hash_resize_mutex);
38373+
38374+ nsize = xfrm_hash_new_size();
38375+ ndst = xfrm_hash_alloc(nsize);
38376+ if (!ndst)
38377+ goto out_unlock;
38378+ nsrc = xfrm_hash_alloc(nsize);
38379+ if (!nsrc) {
38380+ xfrm_hash_free(ndst, nsize);
38381+ goto out_unlock;
38382+ }
38383+ nspi = xfrm_hash_alloc(nsize);
38384+ if (!nspi) {
38385+ xfrm_hash_free(ndst, nsize);
38386+ xfrm_hash_free(nsrc, nsize);
38387+ goto out_unlock;
38388+ }
38389+
38390+ spin_lock_bh(&xfrm_state_lock);
38391+
38392+ nhashmask = (nsize / sizeof(struct hlist_head)) - 1U;
38393+ for (i = xfrm_state_hmask; i >= 0; i--)
38394+ xfrm_hash_transfer(xfrm_state_bydst+i, ndst, nsrc, nspi,
38395+ nhashmask);
38396+
38397+ odst = xfrm_state_bydst;
38398+ osrc = xfrm_state_bysrc;
38399+ ospi = xfrm_state_byspi;
38400+ ohashmask = xfrm_state_hmask;
38401+
38402+ xfrm_state_bydst = ndst;
38403+ xfrm_state_bysrc = nsrc;
38404+ xfrm_state_byspi = nspi;
38405+ xfrm_state_hmask = nhashmask;
38406+
38407+ spin_unlock_bh(&xfrm_state_lock);
38408+
38409+ osize = (ohashmask + 1) * sizeof(struct hlist_head);
38410+ xfrm_hash_free(odst, osize);
38411+ xfrm_hash_free(osrc, osize);
38412+ xfrm_hash_free(ospi, osize);
38413+
38414+out_unlock:
38415+ mutex_unlock(&hash_resize_mutex);
38416+}
38417+
38418+static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL);
38419
38420 DECLARE_WAIT_QUEUE_HEAD(km_waitq);
38421 EXPORT_SYMBOL(km_waitq);
38422@@ -54,11 +172,9 @@
38423 static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
38424
38425 static struct work_struct xfrm_state_gc_work;
38426-static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list);
38427+static HLIST_HEAD(xfrm_state_gc_list);
38428 static DEFINE_SPINLOCK(xfrm_state_gc_lock);
38429
38430-static int xfrm_state_gc_flush_bundles;
38431-
38432 int __xfrm_state_delete(struct xfrm_state *x);
38433
38434 static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
38435@@ -69,14 +185,13 @@
38436
38437 static void xfrm_state_gc_destroy(struct xfrm_state *x)
38438 {
38439- if (del_timer(&x->timer))
38440- BUG();
38441- if (del_timer(&x->rtimer))
38442- BUG();
38443+ del_timer_sync(&x->timer);
38444+ del_timer_sync(&x->rtimer);
38445 kfree(x->aalg);
38446 kfree(x->ealg);
38447 kfree(x->calg);
38448 kfree(x->encap);
38449+ kfree(x->coaddr);
38450 if (x->mode)
38451 xfrm_put_mode(x->mode);
38452 if (x->type) {
38453@@ -90,22 +205,17 @@
38454 static void xfrm_state_gc_task(void *data)
38455 {
38456 struct xfrm_state *x;
38457- struct list_head *entry, *tmp;
38458- struct list_head gc_list = LIST_HEAD_INIT(gc_list);
38459-
38460- if (xfrm_state_gc_flush_bundles) {
38461- xfrm_state_gc_flush_bundles = 0;
38462- xfrm_flush_bundles();
38463- }
38464+ struct hlist_node *entry, *tmp;
38465+ struct hlist_head gc_list;
38466
38467 spin_lock_bh(&xfrm_state_gc_lock);
38468- list_splice_init(&xfrm_state_gc_list, &gc_list);
38469+ gc_list.first = xfrm_state_gc_list.first;
38470+ INIT_HLIST_HEAD(&xfrm_state_gc_list);
38471 spin_unlock_bh(&xfrm_state_gc_lock);
38472
38473- list_for_each_safe(entry, tmp, &gc_list) {
38474- x = list_entry(entry, struct xfrm_state, bydst);
38475+ hlist_for_each_entry_safe(x, entry, tmp, &gc_list, bydst)
38476 xfrm_state_gc_destroy(x);
38477- }
38478+
38479 wake_up(&km_waitq);
38480 }
38481
38482@@ -168,9 +278,9 @@
38483 if (warn)
38484 km_state_expired(x, 0, 0);
38485 resched:
38486- if (next != LONG_MAX &&
38487- !mod_timer(&x->timer, jiffies + make_jiffies(next)))
38488- xfrm_state_hold(x);
38489+ if (next != LONG_MAX)
38490+ mod_timer(&x->timer, jiffies + make_jiffies(next));
38491+
38492 goto out;
38493
38494 expired:
38495@@ -185,7 +295,6 @@
38496
38497 out:
38498 spin_unlock(&x->lock);
38499- xfrm_state_put(x);
38500 }
38501
38502 static void xfrm_replay_timer_handler(unsigned long data);
38503@@ -199,8 +308,9 @@
38504 if (x) {
38505 atomic_set(&x->refcnt, 1);
38506 atomic_set(&x->tunnel_users, 0);
38507- INIT_LIST_HEAD(&x->bydst);
38508- INIT_LIST_HEAD(&x->byspi);
38509+ INIT_HLIST_NODE(&x->bydst);
38510+ INIT_HLIST_NODE(&x->bysrc);
38511+ INIT_HLIST_NODE(&x->byspi);
38512 init_timer(&x->timer);
38513 x->timer.function = xfrm_timer_handler;
38514 x->timer.data = (unsigned long)x;
38515@@ -225,7 +335,7 @@
38516 BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
38517
38518 spin_lock_bh(&xfrm_state_gc_lock);
38519- list_add(&x->bydst, &xfrm_state_gc_list);
38520+ hlist_add_head(&x->bydst, &xfrm_state_gc_list);
38521 spin_unlock_bh(&xfrm_state_gc_lock);
38522 schedule_work(&xfrm_state_gc_work);
38523 }
38524@@ -238,27 +348,12 @@
38525 if (x->km.state != XFRM_STATE_DEAD) {
38526 x->km.state = XFRM_STATE_DEAD;
38527 spin_lock(&xfrm_state_lock);
38528- list_del(&x->bydst);
38529- __xfrm_state_put(x);
38530- if (x->id.spi) {
38531- list_del(&x->byspi);
38532- __xfrm_state_put(x);
38533- }
38534+ hlist_del(&x->bydst);
38535+ hlist_del(&x->bysrc);
38536+ if (x->id.spi)
38537+ hlist_del(&x->byspi);
38538+ xfrm_state_num--;
38539 spin_unlock(&xfrm_state_lock);
38540- if (del_timer(&x->timer))
38541- __xfrm_state_put(x);
38542- if (del_timer(&x->rtimer))
38543- __xfrm_state_put(x);
38544-
38545- /* The number two in this test is the reference
38546- * mentioned in the comment below plus the reference
38547- * our caller holds. A larger value means that
38548- * there are DSTs attached to this xfrm_state.
38549- */
38550- if (atomic_read(&x->refcnt) > 2) {
38551- xfrm_state_gc_flush_bundles = 1;
38552- schedule_work(&xfrm_state_gc_work);
38553- }
38554
38555 /* All xfrm_state objects are created by xfrm_state_alloc.
38556 * The xfrm_state_alloc call gives a reference, and that
38557@@ -287,14 +382,15 @@
38558 void xfrm_state_flush(u8 proto)
38559 {
38560 int i;
38561- struct xfrm_state *x;
38562
38563 spin_lock_bh(&xfrm_state_lock);
38564- for (i = 0; i < XFRM_DST_HSIZE; i++) {
38565+ for (i = 0; i <= xfrm_state_hmask; i++) {
38566+ struct hlist_node *entry;
38567+ struct xfrm_state *x;
38568 restart:
38569- list_for_each_entry(x, xfrm_state_bydst+i, bydst) {
38570+ hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
38571 if (!xfrm_state_kern(x) &&
38572- (proto == IPSEC_PROTO_ANY || x->id.proto == proto)) {
38573+ xfrm_id_proto_match(x->id.proto, proto)) {
38574 xfrm_state_hold(x);
38575 spin_unlock_bh(&xfrm_state_lock);
38576
38577@@ -325,29 +421,103 @@
38578 return 0;
38579 }
38580
38581+static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family)
38582+{
38583+ unsigned int h = xfrm_spi_hash(daddr, spi, proto, family);
38584+ struct xfrm_state *x;
38585+ struct hlist_node *entry;
38586+
38587+ hlist_for_each_entry(x, entry, xfrm_state_byspi+h, byspi) {
38588+ if (x->props.family != family ||
38589+ x->id.spi != spi ||
38590+ x->id.proto != proto)
38591+ continue;
38592+
38593+ switch (family) {
38594+ case AF_INET:
38595+ if (x->id.daddr.a4 != daddr->a4)
38596+ continue;
38597+ break;
38598+ case AF_INET6:
38599+ if (!ipv6_addr_equal((struct in6_addr *)daddr,
38600+ (struct in6_addr *)
38601+ x->id.daddr.a6))
38602+ continue;
38603+ break;
38604+ };
38605+
38606+ xfrm_state_hold(x);
38607+ return x;
38608+ }
38609+
38610+ return NULL;
38611+}
38612+
38613+static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
38614+{
38615+ unsigned int h = xfrm_src_hash(saddr, family);
38616+ struct xfrm_state *x;
38617+ struct hlist_node *entry;
38618+
38619+ hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) {
38620+ if (x->props.family != family ||
38621+ x->id.proto != proto)
38622+ continue;
38623+
38624+ switch (family) {
38625+ case AF_INET:
38626+ if (x->id.daddr.a4 != daddr->a4 ||
38627+ x->props.saddr.a4 != saddr->a4)
38628+ continue;
38629+ break;
38630+ case AF_INET6:
38631+ if (!ipv6_addr_equal((struct in6_addr *)daddr,
38632+ (struct in6_addr *)
38633+ x->id.daddr.a6) ||
38634+ !ipv6_addr_equal((struct in6_addr *)saddr,
38635+ (struct in6_addr *)
38636+ x->props.saddr.a6))
38637+ continue;
38638+ break;
38639+ };
38640+
38641+ xfrm_state_hold(x);
38642+ return x;
38643+ }
38644+
38645+ return NULL;
38646+}
38647+
38648+static inline struct xfrm_state *
38649+__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family)
38650+{
38651+ if (use_spi)
38652+ return __xfrm_state_lookup(&x->id.daddr, x->id.spi,
38653+ x->id.proto, family);
38654+ else
38655+ return __xfrm_state_lookup_byaddr(&x->id.daddr,
38656+ &x->props.saddr,
38657+ x->id.proto, family);
38658+}
38659+
38660 struct xfrm_state *
38661 xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
38662 struct flowi *fl, struct xfrm_tmpl *tmpl,
38663 struct xfrm_policy *pol, int *err,
38664 unsigned short family)
38665 {
38666- unsigned h = xfrm_dst_hash(daddr, family);
38667+ unsigned int h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family);
38668+ struct hlist_node *entry;
38669 struct xfrm_state *x, *x0;
38670 int acquire_in_progress = 0;
38671 int error = 0;
38672 struct xfrm_state *best = NULL;
38673- struct xfrm_state_afinfo *afinfo;
38674
38675- afinfo = xfrm_state_get_afinfo(family);
38676- if (afinfo == NULL) {
38677- *err = -EAFNOSUPPORT;
38678- return NULL;
38679- }
38680-
38681 spin_lock_bh(&xfrm_state_lock);
38682- list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
38683+ hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
38684 if (x->props.family == family &&
38685 x->props.reqid == tmpl->reqid &&
38686+ !(x->props.flags & XFRM_STATE_WILDRECV) &&
38687 xfrm_state_addr_check(x, daddr, saddr, family) &&
38688 tmpl->mode == x->props.mode &&
38689 tmpl->id.proto == x->id.proto &&
38690@@ -367,7 +537,7 @@
38691 */
38692 if (x->km.state == XFRM_STATE_VALID) {
38693 if (!xfrm_selector_match(&x->sel, fl, family) ||
38694- !xfrm_sec_ctx_match(pol->security, x->security))
38695+ !security_xfrm_state_pol_flow_match(x, pol, fl))
38696 continue;
38697 if (!best ||
38698 best->km.dying > x->km.dying ||
38699@@ -379,7 +549,7 @@
38700 } else if (x->km.state == XFRM_STATE_ERROR ||
38701 x->km.state == XFRM_STATE_EXPIRED) {
38702 if (xfrm_selector_match(&x->sel, fl, family) &&
38703- xfrm_sec_ctx_match(pol->security, x->security))
38704+ security_xfrm_state_pol_flow_match(x, pol, fl))
38705 error = -ESRCH;
38706 }
38707 }
38708@@ -388,8 +558,8 @@
38709 x = best;
38710 if (!x && !error && !acquire_in_progress) {
38711 if (tmpl->id.spi &&
38712- (x0 = afinfo->state_lookup(daddr, tmpl->id.spi,
38713- tmpl->id.proto)) != NULL) {
38714+ (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi,
38715+ tmpl->id.proto, family)) != NULL) {
38716 xfrm_state_put(x0);
38717 error = -EEXIST;
38718 goto out;
38719@@ -403,17 +573,24 @@
38720 * to current session. */
38721 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
38722
38723+ error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
38724+ if (error) {
38725+ x->km.state = XFRM_STATE_DEAD;
38726+ xfrm_state_put(x);
38727+ x = NULL;
38728+ goto out;
38729+ }
38730+
38731 if (km_query(x, tmpl, pol) == 0) {
38732 x->km.state = XFRM_STATE_ACQ;
38733- list_add_tail(&x->bydst, xfrm_state_bydst+h);
38734- xfrm_state_hold(x);
38735+ hlist_add_head(&x->bydst, xfrm_state_bydst+h);
38736+ h = xfrm_src_hash(saddr, family);
38737+ hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
38738 if (x->id.spi) {
38739 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
38740- list_add(&x->byspi, xfrm_state_byspi+h);
38741- xfrm_state_hold(x);
38742+ hlist_add_head(&x->byspi, xfrm_state_byspi+h);
38743 }
38744 x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
38745- xfrm_state_hold(x);
38746 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
38747 add_timer(&x->timer);
38748 } else {
38749@@ -429,59 +606,167 @@
38750 else
38751 *err = acquire_in_progress ? -EAGAIN : error;
38752 spin_unlock_bh(&xfrm_state_lock);
38753- xfrm_state_put_afinfo(afinfo);
38754 return x;
38755 }
38756
38757 static void __xfrm_state_insert(struct xfrm_state *x)
38758 {
38759- unsigned h = xfrm_dst_hash(&x->id.daddr, x->props.family);
38760+ unsigned int h;
38761
38762- list_add(&x->bydst, xfrm_state_bydst+h);
38763- xfrm_state_hold(x);
38764+ x->genid = ++xfrm_state_genid;
38765
38766- h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);
38767+ h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
38768+ x->props.reqid, x->props.family);
38769+ hlist_add_head(&x->bydst, xfrm_state_bydst+h);
38770
38771- list_add(&x->byspi, xfrm_state_byspi+h);
38772- xfrm_state_hold(x);
38773+ h = xfrm_src_hash(&x->props.saddr, x->props.family);
38774+ hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
38775
38776- if (!mod_timer(&x->timer, jiffies + HZ))
38777- xfrm_state_hold(x);
38778+ if (xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY)) {
38779+ h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
38780+ x->props.family);
38781
38782- if (x->replay_maxage &&
38783- !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
38784- xfrm_state_hold(x);
38785+ hlist_add_head(&x->byspi, xfrm_state_byspi+h);
38786+ }
38787+
38788+ mod_timer(&x->timer, jiffies + HZ);
38789+ if (x->replay_maxage)
38790+ mod_timer(&x->rtimer, jiffies + x->replay_maxage);
38791
38792 wake_up(&km_waitq);
38793+
38794+ xfrm_state_num++;
38795+
38796+ if (x->bydst.next != NULL &&
38797+ (xfrm_state_hmask + 1) < xfrm_state_hashmax &&
38798+ xfrm_state_num > xfrm_state_hmask)
38799+ schedule_work(&xfrm_hash_work);
38800+}
38801+
38802+/* xfrm_state_lock is held */
38803+static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
38804+{
38805+ unsigned short family = xnew->props.family;
38806+ u32 reqid = xnew->props.reqid;
38807+ struct xfrm_state *x;
38808+ struct hlist_node *entry;
38809+ unsigned int h;
38810+
38811+ h = xfrm_dst_hash(&xnew->id.daddr, &xnew->props.saddr, reqid, family);
38812+ hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
38813+ if (x->props.family == family &&
38814+ x->props.reqid == reqid &&
38815+ !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) &&
38816+ !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family))
38817+ x->genid = xfrm_state_genid;
38818+ }
38819 }
38820
38821 void xfrm_state_insert(struct xfrm_state *x)
38822 {
38823 spin_lock_bh(&xfrm_state_lock);
38824+ __xfrm_state_bump_genids(x);
38825 __xfrm_state_insert(x);
38826 spin_unlock_bh(&xfrm_state_lock);
38827-
38828- xfrm_flush_all_bundles();
38829 }
38830 EXPORT_SYMBOL(xfrm_state_insert);
38831
38832+/* xfrm_state_lock is held */
38833+static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create)
38834+{
38835+ unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family);
38836+ struct hlist_node *entry;
38837+ struct xfrm_state *x;
38838+
38839+ hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
38840+ if (x->props.reqid != reqid ||
38841+ x->props.mode != mode ||
38842+ x->props.family != family ||
38843+ x->km.state != XFRM_STATE_ACQ ||
38844+ x->id.spi != 0)
38845+ continue;
38846+
38847+ switch (family) {
38848+ case AF_INET:
38849+ if (x->id.daddr.a4 != daddr->a4 ||
38850+ x->props.saddr.a4 != saddr->a4)
38851+ continue;
38852+ break;
38853+ case AF_INET6:
38854+ if (!ipv6_addr_equal((struct in6_addr *)x->id.daddr.a6,
38855+ (struct in6_addr *)daddr) ||
38856+ !ipv6_addr_equal((struct in6_addr *)
38857+ x->props.saddr.a6,
38858+ (struct in6_addr *)saddr))
38859+ continue;
38860+ break;
38861+ };
38862+
38863+ xfrm_state_hold(x);
38864+ return x;
38865+ }
38866+
38867+ if (!create)
38868+ return NULL;
38869+
38870+ x = xfrm_state_alloc();
38871+ if (likely(x)) {
38872+ switch (family) {
38873+ case AF_INET:
38874+ x->sel.daddr.a4 = daddr->a4;
38875+ x->sel.saddr.a4 = saddr->a4;
38876+ x->sel.prefixlen_d = 32;
38877+ x->sel.prefixlen_s = 32;
38878+ x->props.saddr.a4 = saddr->a4;
38879+ x->id.daddr.a4 = daddr->a4;
38880+ break;
38881+
38882+ case AF_INET6:
38883+ ipv6_addr_copy((struct in6_addr *)x->sel.daddr.a6,
38884+ (struct in6_addr *)daddr);
38885+ ipv6_addr_copy((struct in6_addr *)x->sel.saddr.a6,
38886+ (struct in6_addr *)saddr);
38887+ x->sel.prefixlen_d = 128;
38888+ x->sel.prefixlen_s = 128;
38889+ ipv6_addr_copy((struct in6_addr *)x->props.saddr.a6,
38890+ (struct in6_addr *)saddr);
38891+ ipv6_addr_copy((struct in6_addr *)x->id.daddr.a6,
38892+ (struct in6_addr *)daddr);
38893+ break;
38894+ };
38895+
38896+ x->km.state = XFRM_STATE_ACQ;
38897+ x->id.proto = proto;
38898+ x->props.family = family;
38899+ x->props.mode = mode;
38900+ x->props.reqid = reqid;
38901+ x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
38902+ xfrm_state_hold(x);
38903+ x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
38904+ add_timer(&x->timer);
38905+ hlist_add_head(&x->bydst, xfrm_state_bydst+h);
38906+ h = xfrm_src_hash(saddr, family);
38907+ hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
38908+ wake_up(&km_waitq);
38909+ }
38910+
38911+ return x;
38912+}
38913+
38914 static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);
38915
38916 int xfrm_state_add(struct xfrm_state *x)
38917 {
38918- struct xfrm_state_afinfo *afinfo;
38919 struct xfrm_state *x1;
38920 int family;
38921 int err;
38922+ int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
38923
38924 family = x->props.family;
38925- afinfo = xfrm_state_get_afinfo(family);
38926- if (unlikely(afinfo == NULL))
38927- return -EAFNOSUPPORT;
38928
38929 spin_lock_bh(&xfrm_state_lock);
38930
38931- x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
38932+ x1 = __xfrm_state_locate(x, use_spi, family);
38933 if (x1) {
38934 xfrm_state_put(x1);
38935 x1 = NULL;
38936@@ -489,7 +774,7 @@
38937 goto out;
38938 }
38939
38940- if (x->km.seq) {
38941+ if (use_spi && x->km.seq) {
38942 x1 = __xfrm_find_acq_byseq(x->km.seq);
38943 if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) {
38944 xfrm_state_put(x1);
38945@@ -497,20 +782,17 @@
38946 }
38947 }
38948
38949- if (!x1)
38950- x1 = afinfo->find_acq(
38951- x->props.mode, x->props.reqid, x->id.proto,
38952- &x->id.daddr, &x->props.saddr, 0);
38953+ if (use_spi && !x1)
38954+ x1 = __find_acq_core(family, x->props.mode, x->props.reqid,
38955+ x->id.proto,
38956+ &x->id.daddr, &x->props.saddr, 0);
38957
38958+ __xfrm_state_bump_genids(x);
38959 __xfrm_state_insert(x);
38960 err = 0;
38961
38962 out:
38963 spin_unlock_bh(&xfrm_state_lock);
38964- xfrm_state_put_afinfo(afinfo);
38965-
38966- if (!err)
38967- xfrm_flush_all_bundles();
38968
38969 if (x1) {
38970 xfrm_state_delete(x1);
38971@@ -523,16 +805,12 @@
38972
38973 int xfrm_state_update(struct xfrm_state *x)
38974 {
38975- struct xfrm_state_afinfo *afinfo;
38976 struct xfrm_state *x1;
38977 int err;
38978-
38979- afinfo = xfrm_state_get_afinfo(x->props.family);
38980- if (unlikely(afinfo == NULL))
38981- return -EAFNOSUPPORT;
38982+ int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
38983
38984 spin_lock_bh(&xfrm_state_lock);
38985- x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
38986+ x1 = __xfrm_state_locate(x, use_spi, x->props.family);
38987
38988 err = -ESRCH;
38989 if (!x1)
38990@@ -552,7 +830,6 @@
38991
38992 out:
38993 spin_unlock_bh(&xfrm_state_lock);
38994- xfrm_state_put_afinfo(afinfo);
38995
38996 if (err)
38997 return err;
38998@@ -568,11 +845,15 @@
38999 if (likely(x1->km.state == XFRM_STATE_VALID)) {
39000 if (x->encap && x1->encap)
39001 memcpy(x1->encap, x->encap, sizeof(*x1->encap));
39002+ if (x->coaddr && x1->coaddr) {
39003+ memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr));
39004+ }
39005+ if (!use_spi && memcmp(&x1->sel, &x->sel, sizeof(x1->sel)))
39006+ memcpy(&x1->sel, &x->sel, sizeof(x1->sel));
39007 memcpy(&x1->lft, &x->lft, sizeof(x1->lft));
39008 x1->km.dying = 0;
39009
39010- if (!mod_timer(&x1->timer, jiffies + HZ))
39011- xfrm_state_hold(x1);
39012+ mod_timer(&x1->timer, jiffies + HZ);
39013 if (x1->curlft.use_time)
39014 xfrm_state_check_expire(x1);
39015
39016@@ -597,8 +878,7 @@
39017 if (x->curlft.bytes >= x->lft.hard_byte_limit ||
39018 x->curlft.packets >= x->lft.hard_packet_limit) {
39019 x->km.state = XFRM_STATE_EXPIRED;
39020- if (!mod_timer(&x->timer, jiffies))
39021- xfrm_state_hold(x);
39022+ mod_timer(&x->timer, jiffies);
39023 return -EINVAL;
39024 }
39025
39026@@ -640,46 +920,93 @@
39027 unsigned short family)
39028 {
39029 struct xfrm_state *x;
39030- struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
39031- if (!afinfo)
39032- return NULL;
39033
39034 spin_lock_bh(&xfrm_state_lock);
39035- x = afinfo->state_lookup(daddr, spi, proto);
39036+ x = __xfrm_state_lookup(daddr, spi, proto, family);
39037 spin_unlock_bh(&xfrm_state_lock);
39038- xfrm_state_put_afinfo(afinfo);
39039 return x;
39040 }
39041 EXPORT_SYMBOL(xfrm_state_lookup);
39042
39043 struct xfrm_state *
39044+xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr,
39045+ u8 proto, unsigned short family)
39046+{
39047+ struct xfrm_state *x;
39048+
39049+ spin_lock_bh(&xfrm_state_lock);
39050+ x = __xfrm_state_lookup_byaddr(daddr, saddr, proto, family);
39051+ spin_unlock_bh(&xfrm_state_lock);
39052+ return x;
39053+}
39054+EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
39055+
39056+struct xfrm_state *
39057 xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
39058 xfrm_address_t *daddr, xfrm_address_t *saddr,
39059 int create, unsigned short family)
39060 {
39061 struct xfrm_state *x;
39062+
39063+ spin_lock_bh(&xfrm_state_lock);
39064+ x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create);
39065+ spin_unlock_bh(&xfrm_state_lock);
39066+
39067+ return x;
39068+}
39069+EXPORT_SYMBOL(xfrm_find_acq);
39070+
39071+#ifdef CONFIG_XFRM_SUB_POLICY
39072+int
39073+xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
39074+ unsigned short family)
39075+{
39076+ int err = 0;
39077 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
39078 if (!afinfo)
39079- return NULL;
39080+ return -EAFNOSUPPORT;
39081
39082 spin_lock_bh(&xfrm_state_lock);
39083- x = afinfo->find_acq(mode, reqid, proto, daddr, saddr, create);
39084+ if (afinfo->tmpl_sort)
39085+ err = afinfo->tmpl_sort(dst, src, n);
39086 spin_unlock_bh(&xfrm_state_lock);
39087 xfrm_state_put_afinfo(afinfo);
39088- return x;
39089+ return err;
39090 }
39091-EXPORT_SYMBOL(xfrm_find_acq);
39092+EXPORT_SYMBOL(xfrm_tmpl_sort);
39093+
39094+int
39095+xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
39096+ unsigned short family)
39097+{
39098+ int err = 0;
39099+ struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
39100+ if (!afinfo)
39101+ return -EAFNOSUPPORT;
39102+
39103+ spin_lock_bh(&xfrm_state_lock);
39104+ if (afinfo->state_sort)
39105+ err = afinfo->state_sort(dst, src, n);
39106+ spin_unlock_bh(&xfrm_state_lock);
39107+ xfrm_state_put_afinfo(afinfo);
39108+ return err;
39109+}
39110+EXPORT_SYMBOL(xfrm_state_sort);
39111+#endif
39112
39113 /* Silly enough, but I'm lazy to build resolution list */
39114
39115 static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq)
39116 {
39117 int i;
39118- struct xfrm_state *x;
39119
39120- for (i = 0; i < XFRM_DST_HSIZE; i++) {
39121- list_for_each_entry(x, xfrm_state_bydst+i, bydst) {
39122- if (x->km.seq == seq && x->km.state == XFRM_STATE_ACQ) {
39123+ for (i = 0; i <= xfrm_state_hmask; i++) {
39124+ struct hlist_node *entry;
39125+ struct xfrm_state *x;
39126+
39127+ hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
39128+ if (x->km.seq == seq &&
39129+ x->km.state == XFRM_STATE_ACQ) {
39130 xfrm_state_hold(x);
39131 return x;
39132 }
39133@@ -715,7 +1042,7 @@
39134 void
39135 xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
39136 {
39137- u32 h;
39138+ unsigned int h;
39139 struct xfrm_state *x0;
39140
39141 if (x->id.spi)
39142@@ -745,8 +1072,7 @@
39143 if (x->id.spi) {
39144 spin_lock_bh(&xfrm_state_lock);
39145 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);
39146- list_add(&x->byspi, xfrm_state_byspi+h);
39147- xfrm_state_hold(x);
39148+ hlist_add_head(&x->byspi, xfrm_state_byspi+h);
39149 spin_unlock_bh(&xfrm_state_lock);
39150 wake_up(&km_waitq);
39151 }
39152@@ -758,13 +1084,14 @@
39153 {
39154 int i;
39155 struct xfrm_state *x;
39156+ struct hlist_node *entry;
39157 int count = 0;
39158 int err = 0;
39159
39160 spin_lock_bh(&xfrm_state_lock);
39161- for (i = 0; i < XFRM_DST_HSIZE; i++) {
39162- list_for_each_entry(x, xfrm_state_bydst+i, bydst) {
39163- if (proto == IPSEC_PROTO_ANY || x->id.proto == proto)
39164+ for (i = 0; i <= xfrm_state_hmask; i++) {
39165+ hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
39166+ if (xfrm_id_proto_match(x->id.proto, proto))
39167 count++;
39168 }
39169 }
39170@@ -773,9 +1100,9 @@
39171 goto out;
39172 }
39173
39174- for (i = 0; i < XFRM_DST_HSIZE; i++) {
39175- list_for_each_entry(x, xfrm_state_bydst+i, bydst) {
39176- if (proto != IPSEC_PROTO_ANY && x->id.proto != proto)
39177+ for (i = 0; i <= xfrm_state_hmask; i++) {
39178+ hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
39179+ if (!xfrm_id_proto_match(x->id.proto, proto))
39180 continue;
39181 err = func(x, --count, data);
39182 if (err)
39183@@ -832,10 +1159,8 @@
39184 km_state_notify(x, &c);
39185
39186 if (x->replay_maxage &&
39187- !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) {
39188- xfrm_state_hold(x);
39189+ !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
39190 x->xflags &= ~XFRM_TIME_DEFER;
39191- }
39192 }
39193 EXPORT_SYMBOL(xfrm_replay_notify);
39194
39195@@ -853,7 +1178,6 @@
39196 }
39197
39198 spin_unlock(&x->lock);
39199- xfrm_state_put(x);
39200 }
39201
39202 int xfrm_replay_check(struct xfrm_state *x, u32 seq)
39203@@ -997,6 +1321,25 @@
39204 }
39205 EXPORT_SYMBOL(km_policy_expired);
39206
39207+int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr)
39208+{
39209+ int err = -EINVAL;
39210+ int ret;
39211+ struct xfrm_mgr *km;
39212+
39213+ read_lock(&xfrm_km_lock);
39214+ list_for_each_entry(km, &xfrm_km_list, list) {
39215+ if (km->report) {
39216+ ret = km->report(proto, sel, addr);
39217+ if (!ret)
39218+ err = ret;
39219+ }
39220+ }
39221+ read_unlock(&xfrm_km_lock);
39222+ return err;
39223+}
39224+EXPORT_SYMBOL(km_report);
39225+
39226 int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
39227 {
39228 int err;
39229@@ -1018,7 +1361,7 @@
39230 err = -EINVAL;
39231 read_lock(&xfrm_km_lock);
39232 list_for_each_entry(km, &xfrm_km_list, list) {
39233- pol = km->compile_policy(sk->sk_family, optname, data,
39234+ pol = km->compile_policy(sk, optname, data,
39235 optlen, &err);
39236 if (err >= 0)
39237 break;
39238@@ -1065,11 +1408,8 @@
39239 write_lock_bh(&xfrm_state_afinfo_lock);
39240 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
39241 err = -ENOBUFS;
39242- else {
39243- afinfo->state_bydst = xfrm_state_bydst;
39244- afinfo->state_byspi = xfrm_state_byspi;
39245+ else
39246 xfrm_state_afinfo[afinfo->family] = afinfo;
39247- }
39248 write_unlock_bh(&xfrm_state_afinfo_lock);
39249 return err;
39250 }
39251@@ -1086,11 +1426,8 @@
39252 if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
39253 if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
39254 err = -EINVAL;
39255- else {
39256+ else
39257 xfrm_state_afinfo[afinfo->family] = NULL;
39258- afinfo->state_byspi = NULL;
39259- afinfo->state_bydst = NULL;
39260- }
39261 }
39262 write_unlock_bh(&xfrm_state_afinfo_lock);
39263 return err;
39264@@ -1206,12 +1543,17 @@
39265
39266 void __init xfrm_state_init(void)
39267 {
39268- int i;
39269+ unsigned int sz;
39270+
39271+ sz = sizeof(struct hlist_head) * 8;
39272+
39273+ xfrm_state_bydst = xfrm_hash_alloc(sz);
39274+ xfrm_state_bysrc = xfrm_hash_alloc(sz);
39275+ xfrm_state_byspi = xfrm_hash_alloc(sz);
39276+ if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi)
39277+ panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes.");
39278+ xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1);
39279
39280- for (i=0; i<XFRM_DST_HSIZE; i++) {
39281- INIT_LIST_HEAD(&xfrm_state_bydst[i]);
39282- INIT_LIST_HEAD(&xfrm_state_byspi[i]);
39283- }
39284 INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);
39285 }
39286
39287diff -Nur linux-2.6.18-rc5/net/xfrm/xfrm_user.c linux-2.6.19/net/xfrm/xfrm_user.c
39288--- linux-2.6.18-rc5/net/xfrm/xfrm_user.c 2006-08-28 05:41:48.000000000 +0200
39289+++ linux-2.6.19/net/xfrm/xfrm_user.c 2006-09-22 10:04:59.000000000 +0200
39290@@ -27,6 +27,9 @@
39291 #include <net/xfrm.h>
39292 #include <net/netlink.h>
39293 #include <asm/uaccess.h>
39294+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
39295+#include <linux/in6.h>
39296+#endif
39297
39298 static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
39299 {
39300@@ -86,6 +89,22 @@
39301 return 0;
39302 }
39303
39304+static int verify_one_addr(struct rtattr **xfrma, enum xfrm_attr_type_t type,
39305+ xfrm_address_t **addrp)
39306+{
39307+ struct rtattr *rt = xfrma[type - 1];
39308+
39309+ if (!rt)
39310+ return 0;
39311+
39312+ if ((rt->rta_len - sizeof(*rt)) < sizeof(**addrp))
39313+ return -EINVAL;
39314+
39315+ if (addrp)
39316+ *addrp = RTA_DATA(rt);
39317+
39318+ return 0;
39319+}
39320
39321 static inline int verify_sec_ctx_len(struct rtattr **xfrma)
39322 {
39323@@ -156,6 +175,19 @@
39324 goto out;
39325 break;
39326
39327+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
39328+ case IPPROTO_DSTOPTS:
39329+ case IPPROTO_ROUTING:
39330+ if (xfrma[XFRMA_ALG_COMP-1] ||
39331+ xfrma[XFRMA_ALG_AUTH-1] ||
39332+ xfrma[XFRMA_ALG_CRYPT-1] ||
39333+ xfrma[XFRMA_ENCAP-1] ||
39334+ xfrma[XFRMA_SEC_CTX-1] ||
39335+ !xfrma[XFRMA_COADDR-1])
39336+ goto out;
39337+ break;
39338+#endif
39339+
39340 default:
39341 goto out;
39342 };
39343@@ -170,11 +202,14 @@
39344 goto out;
39345 if ((err = verify_sec_ctx_len(xfrma)))
39346 goto out;
39347+ if ((err = verify_one_addr(xfrma, XFRMA_COADDR, NULL)))
39348+ goto out;
39349
39350 err = -EINVAL;
39351 switch (p->mode) {
39352- case 0:
39353- case 1:
39354+ case XFRM_MODE_TRANSPORT:
39355+ case XFRM_MODE_TUNNEL:
39356+ case XFRM_MODE_ROUTEOPTIMIZATION:
39357 break;
39358
39359 default:
39360@@ -258,6 +293,24 @@
39361 return security_xfrm_state_alloc(x, uctx);
39362 }
39363
39364+static int attach_one_addr(xfrm_address_t **addrpp, struct rtattr *u_arg)
39365+{
39366+ struct rtattr *rta = u_arg;
39367+ xfrm_address_t *p, *uaddrp;
39368+
39369+ if (!rta)
39370+ return 0;
39371+
39372+ uaddrp = RTA_DATA(rta);
39373+ p = kmalloc(sizeof(*p), GFP_KERNEL);
39374+ if (!p)
39375+ return -ENOMEM;
39376+
39377+ memcpy(p, uaddrp, sizeof(*p));
39378+ *addrpp = p;
39379+ return 0;
39380+}
39381+
39382 static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
39383 {
39384 memcpy(&x->id, &p->id, sizeof(x->id));
39385@@ -347,7 +400,8 @@
39386 goto error;
39387 if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
39388 goto error;
39389-
39390+ if ((err = attach_one_addr(&x->coaddr, xfrma[XFRMA_COADDR-1])))
39391+ goto error;
39392 err = xfrm_init_state(x);
39393 if (err)
39394 goto error;
39395@@ -416,16 +470,48 @@
39396 return err;
39397 }
39398
39399+static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p,
39400+ struct rtattr **xfrma,
39401+ int *errp)
39402+{
39403+ struct xfrm_state *x = NULL;
39404+ int err;
39405+
39406+ if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
39407+ err = -ESRCH;
39408+ x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
39409+ } else {
39410+ xfrm_address_t *saddr = NULL;
39411+
39412+ err = verify_one_addr(xfrma, XFRMA_SRCADDR, &saddr);
39413+ if (err)
39414+ goto out;
39415+
39416+ if (!saddr) {
39417+ err = -EINVAL;
39418+ goto out;
39419+ }
39420+
39421+ x = xfrm_state_lookup_byaddr(&p->daddr, saddr, p->proto,
39422+ p->family);
39423+ }
39424+
39425+ out:
39426+ if (!x && errp)
39427+ *errp = err;
39428+ return x;
39429+}
39430+
39431 static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
39432 {
39433 struct xfrm_state *x;
39434- int err;
39435+ int err = -ESRCH;
39436 struct km_event c;
39437 struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
39438
39439- x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
39440+ x = xfrm_user_state_lookup(p, (struct rtattr **)xfrma, &err);
39441 if (x == NULL)
39442- return -ESRCH;
39443+ return err;
39444
39445 if ((err = security_xfrm_state_delete(x)) != 0)
39446 goto out;
39447@@ -519,6 +605,13 @@
39448 uctx->ctx_len = x->security->ctx_len;
39449 memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len);
39450 }
39451+
39452+ if (x->coaddr)
39453+ RTA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr);
39454+
39455+ if (x->lastused)
39456+ RTA_PUT(skb, XFRMA_LASTUSED, sizeof(x->lastused), &x->lastused);
39457+
39458 nlh->nlmsg_len = skb->tail - b;
39459 out:
39460 sp->this_idx++;
39461@@ -540,7 +633,7 @@
39462 info.nlmsg_flags = NLM_F_MULTI;
39463 info.this_idx = 0;
39464 info.start_idx = cb->args[0];
39465- (void) xfrm_state_walk(IPSEC_PROTO_ANY, dump_one_state, &info);
39466+ (void) xfrm_state_walk(0, dump_one_state, &info);
39467 cb->args[0] = info.this_idx;
39468
39469 return skb->len;
39470@@ -576,10 +669,9 @@
39471 struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
39472 struct xfrm_state *x;
39473 struct sk_buff *resp_skb;
39474- int err;
39475+ int err = -ESRCH;
39476
39477- x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
39478- err = -ESRCH;
39479+ x = xfrm_user_state_lookup(p, (struct rtattr **)xfrma, &err);
39480 if (x == NULL)
39481 goto out_noput;
39482
39483@@ -692,6 +784,22 @@
39484 return 0;
39485 }
39486
39487+static int verify_policy_type(__u8 type)
39488+{
39489+ switch (type) {
39490+ case XFRM_POLICY_TYPE_MAIN:
39491+#ifdef CONFIG_XFRM_SUB_POLICY
39492+ case XFRM_POLICY_TYPE_SUB:
39493+#endif
39494+ break;
39495+
39496+ default:
39497+ return -EINVAL;
39498+ };
39499+
39500+ return 0;
39501+}
39502+
39503 static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
39504 {
39505 switch (p->share) {
39506@@ -785,6 +893,29 @@
39507 return 0;
39508 }
39509
39510+static int copy_from_user_policy_type(u8 *tp, struct rtattr **xfrma)
39511+{
39512+ struct rtattr *rt = xfrma[XFRMA_POLICY_TYPE-1];
39513+ struct xfrm_userpolicy_type *upt;
39514+ __u8 type = XFRM_POLICY_TYPE_MAIN;
39515+ int err;
39516+
39517+ if (rt) {
39518+ if (rt->rta_len < sizeof(*upt))
39519+ return -EINVAL;
39520+
39521+ upt = RTA_DATA(rt);
39522+ type = upt->type;
39523+ }
39524+
39525+ err = verify_policy_type(type);
39526+ if (err)
39527+ return err;
39528+
39529+ *tp = type;
39530+ return 0;
39531+}
39532+
39533 static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p)
39534 {
39535 xp->priority = p->priority;
39536@@ -823,16 +954,20 @@
39537
39538 copy_from_user_policy(xp, p);
39539
39540+ err = copy_from_user_policy_type(&xp->type, xfrma);
39541+ if (err)
39542+ goto error;
39543+
39544 if (!(err = copy_from_user_tmpl(xp, xfrma)))
39545 err = copy_from_user_sec_ctx(xp, xfrma);
39546-
39547- if (err) {
39548- *errp = err;
39549- kfree(xp);
39550- xp = NULL;
39551- }
39552+ if (err)
39553+ goto error;
39554
39555 return xp;
39556+ error:
39557+ *errp = err;
39558+ kfree(xp);
39559+ return NULL;
39560 }
39561
39562 static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
39563@@ -909,27 +1044,63 @@
39564 return -1;
39565 }
39566
39567-static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb)
39568+static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb)
39569 {
39570- if (xp->security) {
39571- int ctx_size = sizeof(struct xfrm_sec_ctx) +
39572- xp->security->ctx_len;
39573- struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size);
39574- struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
39575+ int ctx_size = sizeof(struct xfrm_sec_ctx) + s->ctx_len;
39576+ struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size);
39577+ struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
39578+
39579+ uctx->exttype = XFRMA_SEC_CTX;
39580+ uctx->len = ctx_size;
39581+ uctx->ctx_doi = s->ctx_doi;
39582+ uctx->ctx_alg = s->ctx_alg;
39583+ uctx->ctx_len = s->ctx_len;
39584+ memcpy(uctx + 1, s->ctx_str, s->ctx_len);
39585+ return 0;
39586
39587- uctx->exttype = XFRMA_SEC_CTX;
39588- uctx->len = ctx_size;
39589- uctx->ctx_doi = xp->security->ctx_doi;
39590- uctx->ctx_alg = xp->security->ctx_alg;
39591- uctx->ctx_len = xp->security->ctx_len;
39592- memcpy(uctx + 1, xp->security->ctx_str, xp->security->ctx_len);
39593+ rtattr_failure:
39594+ return -1;
39595+}
39596+
39597+static inline int copy_to_user_state_sec_ctx(struct xfrm_state *x, struct sk_buff *skb)
39598+{
39599+ if (x->security) {
39600+ return copy_sec_ctx(x->security, skb);
39601 }
39602 return 0;
39603+}
39604
39605- rtattr_failure:
39606+static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb)
39607+{
39608+ if (xp->security) {
39609+ return copy_sec_ctx(xp->security, skb);
39610+ }
39611+ return 0;
39612+}
39613+
39614+#ifdef CONFIG_XFRM_SUB_POLICY
39615+static int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb)
39616+{
39617+ struct xfrm_userpolicy_type upt;
39618+
39619+ memset(&upt, 0, sizeof(upt));
39620+ upt.type = xp->type;
39621+
39622+ RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt);
39623+
39624+ return 0;
39625+
39626+rtattr_failure:
39627 return -1;
39628 }
39629
39630+#else
39631+static inline int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb)
39632+{
39633+ return 0;
39634+}
39635+#endif
39636+
39637 static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr)
39638 {
39639 struct xfrm_dump_info *sp = ptr;
39640@@ -953,6 +1124,8 @@
39641 goto nlmsg_failure;
39642 if (copy_to_user_sec_ctx(xp, skb))
39643 goto nlmsg_failure;
39644+ if (copy_to_user_policy_type(xp, skb) < 0)
39645+ goto nlmsg_failure;
39646
39647 nlh->nlmsg_len = skb->tail - b;
39648 out:
39649@@ -974,7 +1147,10 @@
39650 info.nlmsg_flags = NLM_F_MULTI;
39651 info.this_idx = 0;
39652 info.start_idx = cb->args[0];
39653- (void) xfrm_policy_walk(dump_one_policy, &info);
39654+ (void) xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_one_policy, &info);
39655+#ifdef CONFIG_XFRM_SUB_POLICY
39656+ (void) xfrm_policy_walk(XFRM_POLICY_TYPE_SUB, dump_one_policy, &info);
39657+#endif
39658 cb->args[0] = info.this_idx;
39659
39660 return skb->len;
39661@@ -1010,6 +1186,7 @@
39662 {
39663 struct xfrm_policy *xp;
39664 struct xfrm_userpolicy_id *p;
39665+ __u8 type = XFRM_POLICY_TYPE_MAIN;
39666 int err;
39667 struct km_event c;
39668 int delete;
39669@@ -1017,12 +1194,16 @@
39670 p = NLMSG_DATA(nlh);
39671 delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY;
39672
39673+ err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
39674+ if (err)
39675+ return err;
39676+
39677 err = verify_policy_dir(p->dir);
39678 if (err)
39679 return err;
39680
39681 if (p->index)
39682- xp = xfrm_policy_byid(p->dir, p->index, delete);
39683+ xp = xfrm_policy_byid(type, p->dir, p->index, delete);
39684 else {
39685 struct rtattr **rtattrs = (struct rtattr **)xfrma;
39686 struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
39687@@ -1039,7 +1220,7 @@
39688 if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
39689 return err;
39690 }
39691- xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, delete);
39692+ xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete);
39693 security_xfrm_policy_free(&tmp);
39694 }
39695 if (xp == NULL)
39696@@ -1222,9 +1403,16 @@
39697
39698 static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
39699 {
39700-struct km_event c;
39701+ struct km_event c;
39702+ __u8 type = XFRM_POLICY_TYPE_MAIN;
39703+ int err;
39704+
39705+ err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
39706+ if (err)
39707+ return err;
39708
39709- xfrm_policy_flush();
39710+ xfrm_policy_flush(type);
39711+ c.data.type = type;
39712 c.event = nlh->nlmsg_type;
39713 c.seq = nlh->nlmsg_seq;
39714 c.pid = nlh->nlmsg_pid;
39715@@ -1237,10 +1425,15 @@
39716 struct xfrm_policy *xp;
39717 struct xfrm_user_polexpire *up = NLMSG_DATA(nlh);
39718 struct xfrm_userpolicy_info *p = &up->pol;
39719+ __u8 type = XFRM_POLICY_TYPE_MAIN;
39720 int err = -ENOENT;
39721
39722+ err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
39723+ if (err)
39724+ return err;
39725+
39726 if (p->index)
39727- xp = xfrm_policy_byid(p->dir, p->index, 0);
39728+ xp = xfrm_policy_byid(type, p->dir, p->index, 0);
39729 else {
39730 struct rtattr **rtattrs = (struct rtattr **)xfrma;
39731 struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
39732@@ -1257,7 +1450,7 @@
39733 if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
39734 return err;
39735 }
39736- xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, 0);
39737+ xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, 0);
39738 security_xfrm_policy_free(&tmp);
39739 }
39740
39741@@ -1384,6 +1577,7 @@
39742 [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0),
39743 [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
39744 [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
39745+ [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report),
39746 };
39747
39748 #undef XMSGSIZE
39749@@ -1708,7 +1902,9 @@
39750
39751 if (copy_to_user_tmpl(xp, skb) < 0)
39752 goto nlmsg_failure;
39753- if (copy_to_user_sec_ctx(xp, skb))
39754+ if (copy_to_user_state_sec_ctx(x, skb))
39755+ goto nlmsg_failure;
39756+ if (copy_to_user_policy_type(xp, skb) < 0)
39757 goto nlmsg_failure;
39758
39759 nlh->nlmsg_len = skb->tail - b;
39760@@ -1742,7 +1938,7 @@
39761 /* User gives us xfrm_user_policy_info followed by an array of 0
39762 * or more templates.
39763 */
39764-static struct xfrm_policy *xfrm_compile_policy(u16 family, int opt,
39765+static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
39766 u8 *data, int len, int *dir)
39767 {
39768 struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data;
39769@@ -1750,7 +1946,7 @@
39770 struct xfrm_policy *xp;
39771 int nr;
39772
39773- switch (family) {
39774+ switch (sk->sk_family) {
39775 case AF_INET:
39776 if (opt != IP_XFRM_POLICY) {
39777 *dir = -EOPNOTSUPP;
39778@@ -1790,8 +1986,18 @@
39779 }
39780
39781 copy_from_user_policy(xp, p);
39782+ xp->type = XFRM_POLICY_TYPE_MAIN;
39783 copy_templates(xp, ut, nr);
39784
39785+ if (!xp->security) {
39786+ int err = security_xfrm_sock_policy_alloc(xp, sk);
39787+ if (err) {
39788+ kfree(xp);
39789+ *dir = err;
39790+ return NULL;
39791+ }
39792+ }
39793+
39794 *dir = p->dir;
39795
39796 return xp;
39797@@ -1814,6 +2020,8 @@
39798 goto nlmsg_failure;
39799 if (copy_to_user_sec_ctx(xp, skb))
39800 goto nlmsg_failure;
39801+ if (copy_to_user_policy_type(xp, skb) < 0)
39802+ goto nlmsg_failure;
39803 upe->hard = !!hard;
39804
39805 nlh->nlmsg_len = skb->tail - b;
39806@@ -1885,6 +2093,8 @@
39807 copy_to_user_policy(xp, p, dir);
39808 if (copy_to_user_tmpl(xp, skb) < 0)
39809 goto nlmsg_failure;
39810+ if (copy_to_user_policy_type(xp, skb) < 0)
39811+ goto nlmsg_failure;
39812
39813 nlh->nlmsg_len = skb->tail - b;
39814
39815@@ -1902,6 +2112,9 @@
39816 struct nlmsghdr *nlh;
39817 struct sk_buff *skb;
39818 unsigned char *b;
39819+#ifdef CONFIG_XFRM_SUB_POLICY
39820+ struct xfrm_userpolicy_type upt;
39821+#endif
39822 int len = NLMSG_LENGTH(0);
39823
39824 skb = alloc_skb(len, GFP_ATOMIC);
39825@@ -1911,6 +2124,13 @@
39826
39827
39828 nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0);
39829+ nlh->nlmsg_flags = 0;
39830+
39831+#ifdef CONFIG_XFRM_SUB_POLICY
39832+ memset(&upt, 0, sizeof(upt));
39833+ upt.type = c->data.type;
39834+ RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt);
39835+#endif
39836
39837 nlh->nlmsg_len = skb->tail - b;
39838
39839@@ -1918,6 +2138,9 @@
39840 return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC);
39841
39842 nlmsg_failure:
39843+#ifdef CONFIG_XFRM_SUB_POLICY
39844+rtattr_failure:
39845+#endif
39846 kfree_skb(skb);
39847 return -1;
39848 }
39849@@ -1942,19 +2165,64 @@
39850
39851 }
39852
39853+static int build_report(struct sk_buff *skb, u8 proto,
39854+ struct xfrm_selector *sel, xfrm_address_t *addr)
39855+{
39856+ struct xfrm_user_report *ur;
39857+ struct nlmsghdr *nlh;
39858+ unsigned char *b = skb->tail;
39859+
39860+ nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_REPORT, sizeof(*ur));
39861+ ur = NLMSG_DATA(nlh);
39862+ nlh->nlmsg_flags = 0;
39863+
39864+ ur->proto = proto;
39865+ memcpy(&ur->sel, sel, sizeof(ur->sel));
39866+
39867+ if (addr)
39868+ RTA_PUT(skb, XFRMA_COADDR, sizeof(*addr), addr);
39869+
39870+ nlh->nlmsg_len = skb->tail - b;
39871+ return skb->len;
39872+
39873+nlmsg_failure:
39874+rtattr_failure:
39875+ skb_trim(skb, b - skb->data);
39876+ return -1;
39877+}
39878+
39879+static int xfrm_send_report(u8 proto, struct xfrm_selector *sel,
39880+ xfrm_address_t *addr)
39881+{
39882+ struct sk_buff *skb;
39883+ size_t len;
39884+
39885+ len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct xfrm_user_report)));
39886+ skb = alloc_skb(len, GFP_ATOMIC);
39887+ if (skb == NULL)
39888+ return -ENOMEM;
39889+
39890+ if (build_report(skb, proto, sel, addr) < 0)
39891+ BUG();
39892+
39893+ NETLINK_CB(skb).dst_group = XFRMNLGRP_REPORT;
39894+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC);
39895+}
39896+
39897 static struct xfrm_mgr netlink_mgr = {
39898 .id = "netlink",
39899 .notify = xfrm_send_state_notify,
39900 .acquire = xfrm_send_acquire,
39901 .compile_policy = xfrm_compile_policy,
39902 .notify_policy = xfrm_send_policy_notify,
39903+ .report = xfrm_send_report,
39904 };
39905
39906 static int __init xfrm_user_init(void)
39907 {
39908 struct sock *nlsk;
39909
39910- printk(KERN_INFO "Initializing IPsec netlink socket\n");
39911+ printk(KERN_INFO "Initializing XFRM netlink socket\n");
39912
39913 nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
39914 xfrm_netlink_rcv, THIS_MODULE);
39915diff -Nur linux-2.6.18-rc5/include/linux/bootmem.h linux-2.6.19/include/linux/bootmem.h
39916--- linux-2.6.18-rc5/include/linux/bootmem.h 2006-08-28 05:41:48.000000000 +0200
39917+++ linux-2.6.19/include/linux/bootmem.h 2006-09-22 10:04:55.000000000 +0200
39918@@ -114,7 +114,7 @@
39919 #else
39920 #define HASHDIST_DEFAULT 0
39921 #endif
39922-extern int __initdata hashdist; /* Distribute hashes across NUMA nodes? */
39923+extern int hashdist; /* Distribute hashes across NUMA nodes? */
39924
39925
39926 #endif /* _LINUX_BOOTMEM_H */
39927diff -Nur linux-2.6.18-rc5/include/linux/dccp.h linux-2.6.19/include/linux/dccp.h
39928--- linux-2.6.18-rc5/include/linux/dccp.h 2006-08-28 05:41:48.000000000 +0200
39929+++ linux-2.6.19/include/linux/dccp.h 2006-09-22 10:04:56.000000000 +0200
39930@@ -438,6 +438,7 @@
39931 * @dccps_role - Role of this sock, one of %dccp_role
39932 * @dccps_ndp_count - number of Non Data Packets since last data packet
39933 * @dccps_hc_rx_ackvec - rx half connection ack vector
39934+ * @dccps_xmit_timer - timer for when CCID is not ready to send
39935 */
39936 struct dccp_sock {
39937 /* inet_connection_sock has to be the first member of dccp_sock */
39938@@ -470,6 +471,7 @@
39939 enum dccp_role dccps_role:2;
39940 __u8 dccps_hc_rx_insert_options:1;
39941 __u8 dccps_hc_tx_insert_options:1;
39942+ struct timer_list dccps_xmit_timer;
39943 };
39944
39945 static inline struct dccp_sock *dccp_sk(const struct sock *sk)
39946diff -Nur linux-2.6.18-rc5/include/linux/fib_rules.h linux-2.6.19/include/linux/fib_rules.h
39947--- linux-2.6.18-rc5/include/linux/fib_rules.h 1970-01-01 01:00:00.000000000 +0100
39948+++ linux-2.6.19/include/linux/fib_rules.h 2006-09-22 10:04:56.000000000 +0200
39949@@ -0,0 +1,65 @@
39950+#ifndef __LINUX_FIB_RULES_H
39951+#define __LINUX_FIB_RULES_H
39952+
39953+#include <linux/types.h>
39954+#include <linux/rtnetlink.h>
39955+
39956+/* rule is permanent, and cannot be deleted */
39957+#define FIB_RULE_PERMANENT 1
39958+
39959+struct fib_rule_hdr
39960+{
39961+ __u8 family;
39962+ __u8 dst_len;
39963+ __u8 src_len;
39964+ __u8 tos;
39965+
39966+ __u8 table;
39967+ __u8 res1; /* reserved */
39968+ __u8 res2; /* reserved */
39969+ __u8 action;
39970+
39971+ __u32 flags;
39972+};
39973+
39974+enum
39975+{
39976+ FRA_UNSPEC,
39977+ FRA_DST, /* destination address */
39978+ FRA_SRC, /* source address */
39979+ FRA_IFNAME, /* interface name */
39980+ FRA_UNUSED1,
39981+ FRA_UNUSED2,
39982+ FRA_PRIORITY, /* priority/preference */
39983+ FRA_UNUSED3,
39984+ FRA_UNUSED4,
39985+ FRA_UNUSED5,
39986+ FRA_FWMARK, /* netfilter mark */
39987+ FRA_FLOW, /* flow/class id */
39988+ FRA_UNUSED6,
39989+ FRA_UNUSED7,
39990+ FRA_UNUSED8,
39991+ FRA_TABLE, /* Extended table id */
39992+ FRA_FWMASK, /* mask for netfilter mark */
39993+ __FRA_MAX
39994+};
39995+
39996+#define FRA_MAX (__FRA_MAX - 1)
39997+
39998+enum
39999+{
40000+ FR_ACT_UNSPEC,
40001+ FR_ACT_TO_TBL, /* Pass to fixed table */
40002+ FR_ACT_RES1,
40003+ FR_ACT_RES2,
40004+ FR_ACT_RES3,
40005+ FR_ACT_RES4,
40006+ FR_ACT_BLACKHOLE, /* Drop without notification */
40007+ FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */
40008+ FR_ACT_PROHIBIT, /* Drop with EACCES */
40009+ __FR_ACT_MAX,
40010+};
40011+
40012+#define FR_ACT_MAX (__FR_ACT_MAX - 1)
40013+
40014+#endif
40015diff -Nur linux-2.6.18-rc5/include/linux/filter.h linux-2.6.19/include/linux/filter.h
40016--- linux-2.6.18-rc5/include/linux/filter.h 2006-08-28 05:41:48.000000000 +0200
40017+++ linux-2.6.19/include/linux/filter.h 2006-09-22 10:04:56.000000000 +0200
40018@@ -25,10 +25,10 @@
40019
40020 struct sock_filter /* Filter block */
40021 {
40022- __u16 code; /* Actual filter code */
40023- __u8 jt; /* Jump true */
40024- __u8 jf; /* Jump false */
40025- __u32 k; /* Generic multiuse field */
40026+ __u16 code; /* Actual filter code */
40027+ __u8 jt; /* Jump true */
40028+ __u8 jf; /* Jump false */
40029+ __u32 k; /* Generic multiuse field */
40030 };
40031
40032 struct sock_fprog /* Required for SO_ATTACH_FILTER. */
40033@@ -41,8 +41,9 @@
40034 struct sk_filter
40035 {
40036 atomic_t refcnt;
40037- unsigned int len; /* Number of filter blocks */
40038- struct sock_filter insns[0];
40039+ unsigned int len; /* Number of filter blocks */
40040+ struct rcu_head rcu;
40041+ struct sock_filter insns[0];
40042 };
40043
40044 static inline unsigned int sk_filter_len(struct sk_filter *fp)
40045diff -Nur linux-2.6.18-rc5/include/linux/genetlink.h linux-2.6.19/include/linux/genetlink.h
40046--- linux-2.6.18-rc5/include/linux/genetlink.h 2006-08-28 05:41:48.000000000 +0200
40047+++ linux-2.6.19/include/linux/genetlink.h 2006-09-22 10:04:56.000000000 +0200
40048@@ -16,6 +16,8 @@
40049
40050 #define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
40051
40052+#define GENL_ADMIN_PERM 0x01
40053+
40054 /*
40055 * List of reserved static generic netlink identifiers:
40056 */
40057@@ -43,9 +45,25 @@
40058 CTRL_ATTR_UNSPEC,
40059 CTRL_ATTR_FAMILY_ID,
40060 CTRL_ATTR_FAMILY_NAME,
40061+ CTRL_ATTR_VERSION,
40062+ CTRL_ATTR_HDRSIZE,
40063+ CTRL_ATTR_MAXATTR,
40064+ CTRL_ATTR_OPS,
40065 __CTRL_ATTR_MAX,
40066 };
40067
40068 #define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
40069
40070+enum {
40071+ CTRL_ATTR_OP_UNSPEC,
40072+ CTRL_ATTR_OP_ID,
40073+ CTRL_ATTR_OP_FLAGS,
40074+ CTRL_ATTR_OP_POLICY,
40075+ CTRL_ATTR_OP_DOIT,
40076+ CTRL_ATTR_OP_DUMPIT,
40077+ __CTRL_ATTR_OP_MAX,
40078+};
40079+
40080+#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
40081+
40082 #endif /* __LINUX_GENERIC_NETLINK_H */
40083diff -Nur linux-2.6.18-rc5/include/linux/if.h linux-2.6.19/include/linux/if.h
40084--- linux-2.6.18-rc5/include/linux/if.h 2006-08-28 05:41:48.000000000 +0200
40085+++ linux-2.6.19/include/linux/if.h 2006-09-22 10:04:56.000000000 +0200
40086@@ -212,5 +212,134 @@
40087 #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
40088 #define ifc_req ifc_ifcu.ifcu_req /* array of structures */
40089
40090+/* The struct should be in sync with struct net_device_stats */
40091+struct rtnl_link_stats
40092+{
40093+ __u32 rx_packets; /* total packets received */
40094+ __u32 tx_packets; /* total packets transmitted */
40095+ __u32 rx_bytes; /* total bytes received */
40096+ __u32 tx_bytes; /* total bytes transmitted */
40097+ __u32 rx_errors; /* bad packets received */
40098+ __u32 tx_errors; /* packet transmit problems */
40099+ __u32 rx_dropped; /* no space in linux buffers */
40100+ __u32 tx_dropped; /* no space available in linux */
40101+ __u32 multicast; /* multicast packets received */
40102+ __u32 collisions;
40103+
40104+ /* detailed rx_errors: */
40105+ __u32 rx_length_errors;
40106+ __u32 rx_over_errors; /* receiver ring buff overflow */
40107+ __u32 rx_crc_errors; /* recved pkt with crc error */
40108+ __u32 rx_frame_errors; /* recv'd frame alignment error */
40109+ __u32 rx_fifo_errors; /* recv'r fifo overrun */
40110+ __u32 rx_missed_errors; /* receiver missed packet */
40111+
40112+ /* detailed tx_errors */
40113+ __u32 tx_aborted_errors;
40114+ __u32 tx_carrier_errors;
40115+ __u32 tx_fifo_errors;
40116+ __u32 tx_heartbeat_errors;
40117+ __u32 tx_window_errors;
40118+
40119+ /* for cslip etc */
40120+ __u32 rx_compressed;
40121+ __u32 tx_compressed;
40122+};
40123+
40124+/* The struct should be in sync with struct ifmap */
40125+struct rtnl_link_ifmap
40126+{
40127+ __u64 mem_start;
40128+ __u64 mem_end;
40129+ __u64 base_addr;
40130+ __u16 irq;
40131+ __u8 dma;
40132+ __u8 port;
40133+};
40134+
40135+enum
40136+{
40137+ IFLA_UNSPEC,
40138+ IFLA_ADDRESS,
40139+ IFLA_BROADCAST,
40140+ IFLA_IFNAME,
40141+ IFLA_MTU,
40142+ IFLA_LINK,
40143+ IFLA_QDISC,
40144+ IFLA_STATS,
40145+ IFLA_COST,
40146+#define IFLA_COST IFLA_COST
40147+ IFLA_PRIORITY,
40148+#define IFLA_PRIORITY IFLA_PRIORITY
40149+ IFLA_MASTER,
40150+#define IFLA_MASTER IFLA_MASTER
40151+ IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
40152+#define IFLA_WIRELESS IFLA_WIRELESS
40153+ IFLA_PROTINFO, /* Protocol specific information for a link */
40154+#define IFLA_PROTINFO IFLA_PROTINFO
40155+ IFLA_TXQLEN,
40156+#define IFLA_TXQLEN IFLA_TXQLEN
40157+ IFLA_MAP,
40158+#define IFLA_MAP IFLA_MAP
40159+ IFLA_WEIGHT,
40160+#define IFLA_WEIGHT IFLA_WEIGHT
40161+ IFLA_OPERSTATE,
40162+ IFLA_LINKMODE,
40163+ __IFLA_MAX
40164+};
40165+
40166+
40167+#define IFLA_MAX (__IFLA_MAX - 1)
40168+
40169+/* ifi_flags.
40170+
40171+ IFF_* flags.
40172+
40173+ The only change is:
40174+ IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
40175+ more not changeable by user. They describe link media
40176+ characteristics and set by device driver.
40177+
40178+ Comments:
40179+ - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
40180+ - If neither of these three flags are set;
40181+ the interface is NBMA.
40182+
40183+ - IFF_MULTICAST does not mean anything special:
40184+ multicasts can be used on all not-NBMA links.
40185+ IFF_MULTICAST means that this media uses special encapsulation
40186+ for multicast frames. Apparently, all IFF_POINTOPOINT and
40187+ IFF_BROADCAST devices are able to use multicasts too.
40188+ */
40189+
40190+/* IFLA_LINK.
40191+ For usual devices it is equal ifi_index.
40192+ If it is a "virtual interface" (f.e. tunnel), ifi_link
40193+ can point to real physical interface (f.e. for bandwidth calculations),
40194+ or maybe 0, what means, that real media is unknown (usual
40195+ for IPIP tunnels, when route to endpoint is allowed to change)
40196+ */
40197+
40198+/* Subtype attributes for IFLA_PROTINFO */
40199+enum
40200+{
40201+ IFLA_INET6_UNSPEC,
40202+ IFLA_INET6_FLAGS, /* link flags */
40203+ IFLA_INET6_CONF, /* sysctl parameters */
40204+ IFLA_INET6_STATS, /* statistics */
40205+ IFLA_INET6_MCAST, /* MC things. What of them? */
40206+ IFLA_INET6_CACHEINFO, /* time values and max reasm size */
40207+ __IFLA_INET6_MAX
40208+};
40209+
40210+#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
40211+
40212+struct ifla_cacheinfo
40213+{
40214+ __u32 max_reasm_len;
40215+ __u32 tstamp; /* ipv6InterfaceTable updated timestamp */
40216+ __u32 reachable_time;
40217+ __u32 retrans_time;
40218+};
40219
40220 #endif /* _LINUX_IF_H */
40221diff -Nur linux-2.6.18-rc5/include/linux/if_addr.h linux-2.6.19/include/linux/if_addr.h
40222--- linux-2.6.18-rc5/include/linux/if_addr.h 1970-01-01 01:00:00.000000000 +0100
40223+++ linux-2.6.19/include/linux/if_addr.h 2006-09-22 10:04:56.000000000 +0200
40224@@ -0,0 +1,53 @@
40225+#ifndef __LINUX_IF_ADDR_H
40226+#define __LINUX_IF_ADDR_H
40227+
40228+#include <linux/netlink.h>
40229+
40230+struct ifaddrmsg
40231+{
40232+ __u8 ifa_family;
40233+ __u8 ifa_prefixlen; /* The prefix length */
40234+ __u8 ifa_flags; /* Flags */
40235+ __u8 ifa_scope; /* Address scope */
40236+ __u32 ifa_index; /* Link index */
40237+};
40238+
40239+/*
40240+ * Important comment:
40241+ * IFA_ADDRESS is prefix address, rather than local interface address.
40242+ * It makes no difference for normally configured broadcast interfaces,
40243+ * but for point-to-point IFA_ADDRESS is DESTINATION address,
40244+ * local address is supplied in IFA_LOCAL attribute.
40245+ */
40246+enum
40247+{
40248+ IFA_UNSPEC,
40249+ IFA_ADDRESS,
40250+ IFA_LOCAL,
40251+ IFA_LABEL,
40252+ IFA_BROADCAST,
40253+ IFA_ANYCAST,
40254+ IFA_CACHEINFO,
40255+ IFA_MULTICAST,
40256+ __IFA_MAX,
40257+};
40258+
40259+#define IFA_MAX (__IFA_MAX - 1)
40260+
40261+/* ifa_flags */
40262+#define IFA_F_SECONDARY 0x01
40263+#define IFA_F_TEMPORARY IFA_F_SECONDARY
40264+
40265+#define IFA_F_DEPRECATED 0x20
40266+#define IFA_F_TENTATIVE 0x40
40267+#define IFA_F_PERMANENT 0x80
40268+
40269+struct ifa_cacheinfo
40270+{
40271+ __u32 ifa_prefered;
40272+ __u32 ifa_valid;
40273+ __u32 cstamp; /* created timestamp, hundredths of seconds */
40274+ __u32 tstamp; /* updated timestamp, hundredths of seconds */
40275+};
40276+
40277+#endif
40278diff -Nur linux-2.6.18-rc5/include/linux/in.h linux-2.6.19/include/linux/in.h
40279--- linux-2.6.18-rc5/include/linux/in.h 2006-08-28 05:41:48.000000000 +0200
40280+++ linux-2.6.19/include/linux/in.h 2006-09-22 10:04:56.000000000 +0200
40281@@ -52,7 +52,7 @@
40282
40283 /* Internet address. */
40284 struct in_addr {
40285- __u32 s_addr;
40286+ __be32 s_addr;
40287 };
40288
40289 #define IP_TOS 1
40290@@ -177,7 +177,7 @@
40291 #define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
40292 struct sockaddr_in {
40293 sa_family_t sin_family; /* Address family */
40294- unsigned short int sin_port; /* Port number */
40295+ __be16 sin_port; /* Port number */
40296 struct in_addr sin_addr; /* Internet address */
40297
40298 /* Pad to size of `struct sockaddr'. */
40299diff -Nur linux-2.6.18-rc5/include/linux/in6.h linux-2.6.19/include/linux/in6.h
40300--- linux-2.6.18-rc5/include/linux/in6.h 2006-08-28 05:41:48.000000000 +0200
40301+++ linux-2.6.19/include/linux/in6.h 2006-09-22 10:04:56.000000000 +0200
40302@@ -134,6 +134,7 @@
40303 #define IPPROTO_ICMPV6 58 /* ICMPv6 */
40304 #define IPPROTO_NONE 59 /* IPv6 no next header */
40305 #define IPPROTO_DSTOPTS 60 /* IPv6 destination options */
40306+#define IPPROTO_MH 135 /* IPv6 mobility header */
40307
40308 /*
40309 * IPv6 TLV options.
40310@@ -142,6 +143,7 @@
40311 #define IPV6_TLV_PADN 1
40312 #define IPV6_TLV_ROUTERALERT 5
40313 #define IPV6_TLV_JUMBO 194
40314+#define IPV6_TLV_HAO 201 /* home address option */
40315
40316 /*
40317 * IPV6 socket options
40318diff -Nur linux-2.6.18-rc5/include/linux/inet.h linux-2.6.19/include/linux/inet.h
40319--- linux-2.6.18-rc5/include/linux/inet.h 2006-08-28 05:41:48.000000000 +0200
40320+++ linux-2.6.19/include/linux/inet.h 2006-09-22 10:04:56.000000000 +0200
40321@@ -46,5 +46,7 @@
40322 #include <linux/types.h>
40323
40324 extern __be32 in_aton(const char *str);
40325+extern int in4_pton(const char *src, int srclen, u8 *dst, char delim, const char **end);
40326+extern int in6_pton(const char *src, int srclen, u8 *dst, char delim, const char **end);
40327 #endif
40328 #endif /* _LINUX_INET_H */
40329diff -Nur linux-2.6.18-rc5/include/linux/ip.h linux-2.6.19/include/linux/ip.h
40330--- linux-2.6.18-rc5/include/linux/ip.h 2006-08-28 05:41:48.000000000 +0200
40331+++ linux-2.6.19/include/linux/ip.h 2006-09-22 10:04:56.000000000 +0200
40332@@ -57,6 +57,7 @@
40333 #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
40334 #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
40335 #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
40336+#define IPOPT_CIPSO (6 |IPOPT_CONTROL|IPOPT_COPY)
40337 #define IPOPT_RR (7 |IPOPT_CONTROL)
40338 #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
40339 #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
40340diff -Nur linux-2.6.18-rc5/include/linux/ipv6.h linux-2.6.19/include/linux/ipv6.h
40341--- linux-2.6.18-rc5/include/linux/ipv6.h 2006-08-28 05:41:48.000000000 +0200
40342+++ linux-2.6.19/include/linux/ipv6.h 2006-09-22 10:04:56.000000000 +0200
40343@@ -29,6 +29,7 @@
40344
40345 #define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */
40346 #define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */
40347+#define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */
40348
40349 /*
40350 * routing header
40351@@ -73,6 +74,28 @@
40352 #define rt0_type rt_hdr.type
40353 };
40354
40355+/*
40356+ * routing header type 2
40357+ */
40358+
40359+struct rt2_hdr {
40360+ struct ipv6_rt_hdr rt_hdr;
40361+ __u32 reserved;
40362+ struct in6_addr addr;
40363+
40364+#define rt2_type rt_hdr.type
40365+};
40366+
40367+/*
40368+ * home address option in destination options header
40369+ */
40370+
40371+struct ipv6_destopt_hao {
40372+ __u8 type;
40373+ __u8 length;
40374+ struct in6_addr addr;
40375+} __attribute__ ((__packed__));
40376+
40377 struct ipv6_auth_hdr {
40378 __u8 nexthdr;
40379 __u8 hdrlen; /* This one is measured in 32 bit units! */
40380@@ -206,6 +229,9 @@
40381 __u16 lastopt;
40382 __u32 nhoff;
40383 __u16 flags;
40384+#ifdef CONFIG_IPV6_MIP6
40385+ __u16 dsthao;
40386+#endif
40387
40388 #define IP6SKB_XFRM_TRANSFORMED 1
40389 };
40390@@ -242,6 +268,9 @@
40391 struct in6_addr rcv_saddr;
40392 struct in6_addr daddr;
40393 struct in6_addr *daddr_cache;
40394+#ifdef CONFIG_IPV6_SUBTREES
40395+ struct in6_addr *saddr_cache;
40396+#endif
40397
40398 __u32 flow_label;
40399 __u32 frag_size;
40400diff -Nur linux-2.6.18-rc5/include/linux/neighbour.h linux-2.6.19/include/linux/neighbour.h
40401--- linux-2.6.18-rc5/include/linux/neighbour.h 1970-01-01 01:00:00.000000000 +0100
40402+++ linux-2.6.19/include/linux/neighbour.h 2006-09-22 10:04:56.000000000 +0200
40403@@ -0,0 +1,159 @@
40404+#ifndef __LINUX_NEIGHBOUR_H
40405+#define __LINUX_NEIGHBOUR_H
40406+
40407+#include <linux/netlink.h>
40408+
40409+struct ndmsg
40410+{
40411+ __u8 ndm_family;
40412+ __u8 ndm_pad1;
40413+ __u16 ndm_pad2;
40414+ __s32 ndm_ifindex;
40415+ __u16 ndm_state;
40416+ __u8 ndm_flags;
40417+ __u8 ndm_type;
40418+};
40419+
40420+enum
40421+{
40422+ NDA_UNSPEC,
40423+ NDA_DST,
40424+ NDA_LLADDR,
40425+ NDA_CACHEINFO,
40426+ NDA_PROBES,
40427+ __NDA_MAX
40428+};
40429+
40430+#define NDA_MAX (__NDA_MAX - 1)
40431+
40432+/*
40433+ * Neighbor Cache Entry Flags
40434+ */
40435+
40436+#define NTF_PROXY 0x08 /* == ATF_PUBL */
40437+#define NTF_ROUTER 0x80
40438+
40439+/*
40440+ * Neighbor Cache Entry States.
40441+ */
40442+
40443+#define NUD_INCOMPLETE 0x01
40444+#define NUD_REACHABLE 0x02
40445+#define NUD_STALE 0x04
40446+#define NUD_DELAY 0x08
40447+#define NUD_PROBE 0x10
40448+#define NUD_FAILED 0x20
40449+
40450+/* Dummy states */
40451+#define NUD_NOARP 0x40
40452+#define NUD_PERMANENT 0x80
40453+#define NUD_NONE 0x00
40454+
40455+/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
40456+ and make no address resolution or NUD.
40457+ NUD_PERMANENT is also cannot be deleted by garbage collectors.
40458+ */
40459+
40460+struct nda_cacheinfo
40461+{
40462+ __u32 ndm_confirmed;
40463+ __u32 ndm_used;
40464+ __u32 ndm_updated;
40465+ __u32 ndm_refcnt;
40466+};
40467+
40468+/*****************************************************************
40469+ * Neighbour tables specific messages.
40470+ *
40471+ * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
40472+ * NLM_F_DUMP flag set. Every neighbour table configuration is
40473+ * spread over multiple messages to avoid running into message
40474+ * size limits on systems with many interfaces. The first message
40475+ * in the sequence transports all not device specific data such as
40476+ * statistics, configuration, and the default parameter set.
40477+ * This message is followed by 0..n messages carrying device
40478+ * specific parameter sets.
40479+ * Although the ordering should be sufficient, NDTA_NAME can be
40480+ * used to identify sequences. The initial message can be identified
40481+ * by checking for NDTA_CONFIG. The device specific messages do
40482+ * not contain this TLV but have NDTPA_IFINDEX set to the
40483+ * corresponding interface index.
40484+ *
40485+ * To change neighbour table attributes, send RTM_SETNEIGHTBL
40486+ * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
40487+ * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
40488+ * otherwise. Device specific parameter sets can be changed by
40489+ * setting NDTPA_IFINDEX to the interface index of the corresponding
40490+ * device.
40491+ ****/
40492+
40493+struct ndt_stats
40494+{
40495+ __u64 ndts_allocs;
40496+ __u64 ndts_destroys;
40497+ __u64 ndts_hash_grows;
40498+ __u64 ndts_res_failed;
40499+ __u64 ndts_lookups;
40500+ __u64 ndts_hits;
40501+ __u64 ndts_rcv_probes_mcast;
40502+ __u64 ndts_rcv_probes_ucast;
40503+ __u64 ndts_periodic_gc_runs;
40504+ __u64 ndts_forced_gc_runs;
40505+};
40506+
40507+enum {
40508+ NDTPA_UNSPEC,
40509+ NDTPA_IFINDEX, /* u32, unchangeable */
40510+ NDTPA_REFCNT, /* u32, read-only */
40511+ NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */
40512+ NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */
40513+ NDTPA_RETRANS_TIME, /* u64, msecs */
40514+ NDTPA_GC_STALETIME, /* u64, msecs */
40515+ NDTPA_DELAY_PROBE_TIME, /* u64, msecs */
40516+ NDTPA_QUEUE_LEN, /* u32 */
40517+ NDTPA_APP_PROBES, /* u32 */
40518+ NDTPA_UCAST_PROBES, /* u32 */
40519+ NDTPA_MCAST_PROBES, /* u32 */
40520+ NDTPA_ANYCAST_DELAY, /* u64, msecs */
40521+ NDTPA_PROXY_DELAY, /* u64, msecs */
40522+ NDTPA_PROXY_QLEN, /* u32 */
40523+ NDTPA_LOCKTIME, /* u64, msecs */
40524+ __NDTPA_MAX
40525+};
40526+#define NDTPA_MAX (__NDTPA_MAX - 1)
40527+
40528+struct ndtmsg
40529+{
40530+ __u8 ndtm_family;
40531+ __u8 ndtm_pad1;
40532+ __u16 ndtm_pad2;
40533+};
40534+
40535+struct ndt_config
40536+{
40537+ __u16 ndtc_key_len;
40538+ __u16 ndtc_entry_size;
40539+ __u32 ndtc_entries;
40540+ __u32 ndtc_last_flush; /* delta to now in msecs */
40541+ __u32 ndtc_last_rand; /* delta to now in msecs */
40542+ __u32 ndtc_hash_rnd;
40543+ __u32 ndtc_hash_mask;
40544+ __u32 ndtc_hash_chain_gc;
40545+ __u32 ndtc_proxy_qlen;
40546+};
40547+
40548+enum {
40549+ NDTA_UNSPEC,
40550+ NDTA_NAME, /* char *, unchangeable */
40551+ NDTA_THRESH1, /* u32 */
40552+ NDTA_THRESH2, /* u32 */
40553+ NDTA_THRESH3, /* u32 */
40554+ NDTA_CONFIG, /* struct ndt_config, read-only */
40555+ NDTA_PARMS, /* nested TLV NDTPA_* */
40556+ NDTA_STATS, /* struct ndt_stats, read-only */
40557+ NDTA_GC_INTERVAL, /* u64, msecs */
40558+ __NDTA_MAX
40559+};
40560+#define NDTA_MAX (__NDTA_MAX - 1)
40561+
40562+#endif
40563diff -Nur linux-2.6.18-rc5/include/linux/net.h linux-2.6.19/include/linux/net.h
40564--- linux-2.6.18-rc5/include/linux/net.h 2006-08-28 05:41:48.000000000 +0200
40565+++ linux-2.6.19/include/linux/net.h 2006-09-22 10:04:56.000000000 +0200
40566@@ -169,11 +169,6 @@
40567 struct net_proto_family {
40568 int family;
40569 int (*create)(struct socket *sock, int protocol);
40570- /* These are counters for the number of different methods of
40571- each we support */
40572- short authentication;
40573- short encryption;
40574- short encrypt_net;
40575 struct module *owner;
40576 };
40577
40578@@ -181,8 +176,8 @@
40579 struct kvec;
40580
40581 extern int sock_wake_async(struct socket *sk, int how, int band);
40582-extern int sock_register(struct net_proto_family *fam);
40583-extern int sock_unregister(int family);
40584+extern int sock_register(const struct net_proto_family *fam);
40585+extern void sock_unregister(int family);
40586 extern int sock_create(int family, int type, int proto,
40587 struct socket **res);
40588 extern int sock_create_kern(int family, int type, int proto,
40589@@ -208,6 +203,25 @@
40590 struct kvec *vec, size_t num,
40591 size_t len, int flags);
40592
40593+extern int kernel_bind(struct socket *sock, struct sockaddr *addr,
40594+ int addrlen);
40595+extern int kernel_listen(struct socket *sock, int backlog);
40596+extern int kernel_accept(struct socket *sock, struct socket **newsock,
40597+ int flags);
40598+extern int kernel_connect(struct socket *sock, struct sockaddr *addr,
40599+ int addrlen, int flags);
40600+extern int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
40601+ int *addrlen);
40602+extern int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
40603+ int *addrlen);
40604+extern int kernel_getsockopt(struct socket *sock, int level, int optname,
40605+ char *optval, int *optlen);
40606+extern int kernel_setsockopt(struct socket *sock, int level, int optname,
40607+ char *optval, int optlen);
40608+extern int kernel_sendpage(struct socket *sock, struct page *page, int offset,
40609+ size_t size, int flags);
40610+extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
40611+
40612 #ifndef CONFIG_SMP
40613 #define SOCKOPS_WRAPPED(name) name
40614 #define SOCKOPS_WRAP(name, fam)
40615diff -Nur linux-2.6.18-rc5/include/linux/netdevice.h linux-2.6.19/include/linux/netdevice.h
40616--- linux-2.6.18-rc5/include/linux/netdevice.h 2006-08-28 05:41:48.000000000 +0200
40617+++ linux-2.6.19/include/linux/netdevice.h 2006-09-22 10:04:56.000000000 +0200
40618@@ -976,7 +976,7 @@
40619 extern int netdev_max_backlog;
40620 extern int weight_p;
40621 extern int netdev_set_master(struct net_device *dev, struct net_device *master);
40622-extern int skb_checksum_help(struct sk_buff *skb, int inward);
40623+extern int skb_checksum_help(struct sk_buff *skb);
40624 extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features);
40625 #ifdef CONFIG_BUG
40626 extern void netdev_rx_csum_fault(struct net_device *dev);
40627@@ -1012,7 +1012,7 @@
40628 {
40629 return skb_is_gso(skb) &&
40630 (!skb_gso_ok(skb, dev->features) ||
40631- unlikely(skb->ip_summed != CHECKSUM_HW));
40632+ unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
40633 }
40634
40635 /* On bonding slaves other than the currently active slave, suppress
40636diff -Nur linux-2.6.18-rc5/include/linux/netfilter/nf_conntrack_common.h linux-2.6.19/include/linux/netfilter/nf_conntrack_common.h
40637--- linux-2.6.18-rc5/include/linux/netfilter/nf_conntrack_common.h 2006-08-28 05:41:48.000000000 +0200
40638+++ linux-2.6.19/include/linux/netfilter/nf_conntrack_common.h 2006-09-22 10:04:56.000000000 +0200
40639@@ -125,6 +125,10 @@
40640 /* Counter highest bit has been set */
40641 IPCT_COUNTER_FILLING_BIT = 11,
40642 IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
40643+
40644+ /* Mark is set */
40645+ IPCT_MARK_BIT = 12,
40646+ IPCT_MARK = (1 << IPCT_MARK_BIT),
40647 };
40648
40649 enum ip_conntrack_expect_events {
40650diff -Nur linux-2.6.18-rc5/include/linux/netfilter/nfnetlink.h linux-2.6.19/include/linux/netfilter/nfnetlink.h
40651--- linux-2.6.18-rc5/include/linux/netfilter/nfnetlink.h 2006-08-28 05:41:48.000000000 +0200
40652+++ linux-2.6.19/include/linux/netfilter/nfnetlink.h 2006-09-22 10:04:56.000000000 +0200
40653@@ -43,7 +43,7 @@
40654 u_int16_t nfa_len;
40655 u_int16_t nfa_type; /* we use 15 bits for the type, and the highest
40656 * bit to indicate whether the payload is nested */
40657-} __attribute__ ((packed));
40658+};
40659
40660 /* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from
40661 * rtnetlink.h, it's time to put this in a generic file */
40662@@ -79,7 +79,7 @@
40663 u_int8_t nfgen_family; /* AF_xxx */
40664 u_int8_t version; /* nfnetlink version */
40665 u_int16_t res_id; /* resource id */
40666-} __attribute__ ((packed));
40667+};
40668
40669 #define NFNETLINK_V0 0
40670
40671diff -Nur linux-2.6.18-rc5/include/linux/netfilter/nfnetlink_log.h linux-2.6.19/include/linux/netfilter/nfnetlink_log.h
40672--- linux-2.6.18-rc5/include/linux/netfilter/nfnetlink_log.h 2006-08-28 05:41:48.000000000 +0200
40673+++ linux-2.6.19/include/linux/netfilter/nfnetlink_log.h 2006-09-22 10:04:56.000000000 +0200
40674@@ -19,18 +19,18 @@
40675 u_int16_t hw_protocol; /* hw protocol (network order) */
40676 u_int8_t hook; /* netfilter hook */
40677 u_int8_t _pad;
40678-} __attribute__ ((packed));
40679+};
40680
40681 struct nfulnl_msg_packet_hw {
40682 u_int16_t hw_addrlen;
40683 u_int16_t _pad;
40684 u_int8_t hw_addr[8];
40685-} __attribute__ ((packed));
40686+};
40687
40688 struct nfulnl_msg_packet_timestamp {
40689 aligned_u64 sec;
40690 aligned_u64 usec;
40691-} __attribute__ ((packed));
40692+};
40693
40694 #define NFULNL_PREFIXLEN 30 /* just like old log target */
40695
40696diff -Nur linux-2.6.18-rc5/include/linux/netfilter/nfnetlink_queue.h linux-2.6.19/include/linux/netfilter/nfnetlink_queue.h
40697--- linux-2.6.18-rc5/include/linux/netfilter/nfnetlink_queue.h 2006-08-28 05:41:48.000000000 +0200
40698+++ linux-2.6.19/include/linux/netfilter/nfnetlink_queue.h 2006-09-22 10:04:56.000000000 +0200
40699@@ -22,12 +22,12 @@
40700 u_int16_t hw_addrlen;
40701 u_int16_t _pad;
40702 u_int8_t hw_addr[8];
40703-} __attribute__ ((packed));
40704+};
40705
40706 struct nfqnl_msg_packet_timestamp {
40707 aligned_u64 sec;
40708 aligned_u64 usec;
40709-} __attribute__ ((packed));
40710+};
40711
40712 enum nfqnl_attr_type {
40713 NFQA_UNSPEC,
40714@@ -49,7 +49,7 @@
40715 struct nfqnl_msg_verdict_hdr {
40716 u_int32_t verdict;
40717 u_int32_t id;
40718-} __attribute__ ((packed));
40719+};
40720
40721
40722 enum nfqnl_msg_config_cmds {
40723@@ -64,7 +64,7 @@
40724 u_int8_t command; /* nfqnl_msg_config_cmds */
40725 u_int8_t _pad;
40726 u_int16_t pf; /* AF_xxx for PF_[UN]BIND */
40727-} __attribute__ ((packed));
40728+};
40729
40730 enum nfqnl_config_mode {
40731 NFQNL_COPY_NONE,
40732diff -Nur linux-2.6.18-rc5/include/linux/netfilter/x_tables.h linux-2.6.19/include/linux/netfilter/x_tables.h
40733--- linux-2.6.18-rc5/include/linux/netfilter/x_tables.h 2006-08-28 05:41:48.000000000 +0200
40734+++ linux-2.6.19/include/linux/netfilter/x_tables.h 2006-09-22 10:04:56.000000000 +0200
40735@@ -174,12 +174,10 @@
40736 const void *ip,
40737 const struct xt_match *match,
40738 void *matchinfo,
40739- unsigned int matchinfosize,
40740 unsigned int hook_mask);
40741
40742 /* Called when entry of this type deleted. */
40743- void (*destroy)(const struct xt_match *match, void *matchinfo,
40744- unsigned int matchinfosize);
40745+ void (*destroy)(const struct xt_match *match, void *matchinfo);
40746
40747 /* Called when userspace align differs from kernel space one */
40748 int (*compat)(void *match, void **dstptr, int *size, int convert);
40749@@ -187,6 +185,9 @@
40750 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
40751 struct module *me;
40752
40753+ /* Free to use by each match */
40754+ unsigned long data;
40755+
40756 char *table;
40757 unsigned int matchsize;
40758 unsigned int hooks;
40759@@ -211,8 +212,7 @@
40760 const struct net_device *out,
40761 unsigned int hooknum,
40762 const struct xt_target *target,
40763- const void *targinfo,
40764- void *userdata);
40765+ const void *targinfo);
40766
40767 /* Called when user tries to insert an entry of this type:
40768 hook_mask is a bitmask of hooks from which it can be
40769@@ -222,12 +222,10 @@
40770 const void *entry,
40771 const struct xt_target *target,
40772 void *targinfo,
40773- unsigned int targinfosize,
40774 unsigned int hook_mask);
40775
40776 /* Called when entry of this type deleted. */
40777- void (*destroy)(const struct xt_target *target, void *targinfo,
40778- unsigned int targinfosize);
40779+ void (*destroy)(const struct xt_target *target, void *targinfo);
40780
40781 /* Called when userspace align differs from kernel space one */
40782 int (*compat)(void *target, void **dstptr, int *size, int convert);
40783@@ -290,8 +288,13 @@
40784
40785 extern int xt_register_target(struct xt_target *target);
40786 extern void xt_unregister_target(struct xt_target *target);
40787+extern int xt_register_targets(struct xt_target *target, unsigned int n);
40788+extern void xt_unregister_targets(struct xt_target *target, unsigned int n);
40789+
40790 extern int xt_register_match(struct xt_match *target);
40791 extern void xt_unregister_match(struct xt_match *target);
40792+extern int xt_register_matches(struct xt_match *match, unsigned int n);
40793+extern void xt_unregister_matches(struct xt_match *match, unsigned int n);
40794
40795 extern int xt_check_match(const struct xt_match *match, unsigned short family,
40796 unsigned int size, const char *table, unsigned int hook,
40797diff -Nur linux-2.6.18-rc5/include/linux/netfilter/xt_DSCP.h linux-2.6.19/include/linux/netfilter/xt_DSCP.h
40798--- linux-2.6.18-rc5/include/linux/netfilter/xt_DSCP.h 1970-01-01 01:00:00.000000000 +0100
40799+++ linux-2.6.19/include/linux/netfilter/xt_DSCP.h 2006-09-22 10:04:56.000000000 +0200
40800@@ -0,0 +1,20 @@
40801+/* x_tables module for setting the IPv4/IPv6 DSCP field
40802+ *
40803+ * (C) 2002 Harald Welte <laforge@gnumonks.org>
40804+ * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com>
40805+ * This software is distributed under GNU GPL v2, 1991
40806+ *
40807+ * See RFC2474 for a description of the DSCP field within the IP Header.
40808+ *
40809+ * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp
40810+*/
40811+#ifndef _XT_DSCP_TARGET_H
40812+#define _XT_DSCP_TARGET_H
40813+#include <linux/netfilter/xt_dscp.h>
40814+
40815+/* target info */
40816+struct xt_DSCP_info {
40817+ u_int8_t dscp;
40818+};
40819+
40820+#endif /* _XT_DSCP_TARGET_H */
40821diff -Nur linux-2.6.18-rc5/include/linux/netfilter/xt_dscp.h linux-2.6.19/include/linux/netfilter/xt_dscp.h
40822--- linux-2.6.18-rc5/include/linux/netfilter/xt_dscp.h 1970-01-01 01:00:00.000000000 +0100
40823+++ linux-2.6.19/include/linux/netfilter/xt_dscp.h 2006-09-22 10:04:56.000000000 +0200
40824@@ -0,0 +1,23 @@
40825+/* x_tables module for matching the IPv4/IPv6 DSCP field
40826+ *
40827+ * (C) 2002 Harald Welte <laforge@gnumonks.org>
40828+ * This software is distributed under GNU GPL v2, 1991
40829+ *
40830+ * See RFC2474 for a description of the DSCP field within the IP Header.
40831+ *
40832+ * xt_dscp.h,v 1.3 2002/08/05 19:00:21 laforge Exp
40833+*/
40834+#ifndef _XT_DSCP_H
40835+#define _XT_DSCP_H
40836+
40837+#define XT_DSCP_MASK 0xfc /* 11111100 */
40838+#define XT_DSCP_SHIFT 2
40839+#define XT_DSCP_MAX 0x3f /* 00111111 */
40840+
40841+/* match info */
40842+struct xt_dscp_info {
40843+ u_int8_t dscp;
40844+ u_int8_t invert;
40845+};
40846+
40847+#endif /* _XT_DSCP_H */
40848diff -Nur linux-2.6.18-rc5/include/linux/netfilter.h linux-2.6.19/include/linux/netfilter.h
40849--- linux-2.6.18-rc5/include/linux/netfilter.h 2006-08-28 05:41:48.000000000 +0200
40850+++ linux-2.6.19/include/linux/netfilter.h 2006-09-22 10:04:56.000000000 +0200
40851@@ -282,6 +282,12 @@
40852 Returns true or false. */
40853 extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
40854
40855+extern u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval,
40856+ u_int32_t csum);
40857+extern u_int16_t nf_proto_csum_update(struct sk_buff *skb,
40858+ u_int32_t oldval, u_int32_t newval,
40859+ u_int16_t csum, int pseudohdr);
40860+
40861 struct nf_afinfo {
40862 unsigned short family;
40863 unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook,
40864diff -Nur linux-2.6.18-rc5/include/linux/netfilter_arp/arp_tables.h linux-2.6.19/include/linux/netfilter_arp/arp_tables.h
40865--- linux-2.6.18-rc5/include/linux/netfilter_arp/arp_tables.h 2006-08-28 05:41:48.000000000 +0200
40866+++ linux-2.6.19/include/linux/netfilter_arp/arp_tables.h 2006-09-22 10:04:56.000000000 +0200
40867@@ -248,8 +248,7 @@
40868 unsigned int hook,
40869 const struct net_device *in,
40870 const struct net_device *out,
40871- struct arpt_table *table,
40872- void *userdata);
40873+ struct arpt_table *table);
40874
40875 #define ARPT_ALIGN(s) (((s) + (__alignof__(struct arpt_entry)-1)) & ~(__alignof__(struct arpt_entry)-1))
40876 #endif /*__KERNEL__*/
40877diff -Nur linux-2.6.18-rc5/include/linux/netfilter_bridge.h linux-2.6.19/include/linux/netfilter_bridge.h
40878--- linux-2.6.18-rc5/include/linux/netfilter_bridge.h 2006-08-28 05:41:48.000000000 +0200
40879+++ linux-2.6.19/include/linux/netfilter_bridge.h 2006-09-22 10:04:56.000000000 +0200
40880@@ -5,9 +5,8 @@
40881 */
40882
40883 #include <linux/netfilter.h>
40884-#if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER)
40885 #include <linux/if_ether.h>
40886-#endif
40887+#include <linux/if_vlan.h>
40888
40889 /* Bridge Hooks */
40890 /* After promisc drops, checksum checks. */
40891@@ -47,40 +46,20 @@
40892
40893
40894 /* Only used in br_forward.c */
40895-static inline
40896-int nf_bridge_maybe_copy_header(struct sk_buff *skb)
40897+extern int nf_bridge_copy_header(struct sk_buff *skb);
40898+static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb)
40899 {
40900- int err;
40901-
40902- if (skb->nf_bridge) {
40903- if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
40904- err = skb_cow(skb, 18);
40905- if (err)
40906- return err;
40907- memcpy(skb->data - 18, skb->nf_bridge->data, 18);
40908- skb_push(skb, 4);
40909- } else {
40910- err = skb_cow(skb, 16);
40911- if (err)
40912- return err;
40913- memcpy(skb->data - 16, skb->nf_bridge->data, 16);
40914- }
40915- }
40916- return 0;
40917+ if (skb->nf_bridge)
40918+ return nf_bridge_copy_header(skb);
40919+ return 0;
40920 }
40921
40922 /* This is called by the IP fragmenting code and it ensures there is
40923 * enough room for the encapsulating header (if there is one). */
40924-static inline
40925-int nf_bridge_pad(struct sk_buff *skb)
40926+static inline int nf_bridge_pad(const struct sk_buff *skb)
40927 {
40928- if (skb->protocol == __constant_htons(ETH_P_IP))
40929- return 0;
40930- if (skb->nf_bridge) {
40931- if (skb->protocol == __constant_htons(ETH_P_8021Q))
40932- return 4;
40933- }
40934- return 0;
40935+ return (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q))
40936+ ? VLAN_HLEN : 0;
40937 }
40938
40939 struct bridge_skb_cb {
40940@@ -90,6 +69,9 @@
40941 };
40942
40943 extern int brnf_deferred_hooks;
40944+#else
40945+#define nf_bridge_maybe_copy_header(skb) (0)
40946+#define nf_bridge_pad(skb) (0)
40947 #endif /* CONFIG_BRIDGE_NETFILTER */
40948
40949 #endif /* __KERNEL__ */
40950diff -Nur linux-2.6.18-rc5/include/linux/netfilter_ipv4/ip_nat.h linux-2.6.19/include/linux/netfilter_ipv4/ip_nat.h
40951--- linux-2.6.18-rc5/include/linux/netfilter_ipv4/ip_nat.h 2006-08-28 05:41:48.000000000 +0200
40952+++ linux-2.6.19/include/linux/netfilter_ipv4/ip_nat.h 2006-09-22 10:04:56.000000000 +0200
40953@@ -72,10 +72,6 @@
40954 extern int ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
40955 const struct ip_conntrack *ignored_conntrack);
40956
40957-/* Calculate relative checksum. */
40958-extern u_int16_t ip_nat_cheat_check(u_int32_t oldvalinv,
40959- u_int32_t newval,
40960- u_int16_t oldcheck);
40961 #else /* !__KERNEL__: iptables wants this to compile. */
40962 #define ip_nat_multi_range ip_nat_multi_range_compat
40963 #endif /*__KERNEL__*/
40964diff -Nur linux-2.6.18-rc5/include/linux/netfilter_ipv4/ip_nat_core.h linux-2.6.19/include/linux/netfilter_ipv4/ip_nat_core.h
40965--- linux-2.6.18-rc5/include/linux/netfilter_ipv4/ip_nat_core.h 2006-08-28 05:41:48.000000000 +0200
40966+++ linux-2.6.19/include/linux/netfilter_ipv4/ip_nat_core.h 2006-09-22 10:04:56.000000000 +0200
40967@@ -11,8 +11,8 @@
40968 unsigned int hooknum,
40969 struct sk_buff **pskb);
40970
40971-extern int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
40972- struct ip_conntrack *ct,
40973- enum ip_nat_manip_type manip,
40974- enum ip_conntrack_dir dir);
40975+extern int ip_nat_icmp_reply_translation(struct ip_conntrack *ct,
40976+ enum ip_conntrack_info ctinfo,
40977+ unsigned int hooknum,
40978+ struct sk_buff **pskb);
40979 #endif /* _IP_NAT_CORE_H */
40980diff -Nur linux-2.6.18-rc5/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.19/include/linux/netfilter_ipv4/ip_tables.h
40981--- linux-2.6.18-rc5/include/linux/netfilter_ipv4/ip_tables.h 2006-08-28 05:41:48.000000000 +0200
40982+++ linux-2.6.19/include/linux/netfilter_ipv4/ip_tables.h 2006-09-22 10:04:56.000000000 +0200
40983@@ -312,8 +312,7 @@
40984 unsigned int hook,
40985 const struct net_device *in,
40986 const struct net_device *out,
40987- struct ipt_table *table,
40988- void *userdata);
40989+ struct ipt_table *table);
40990
40991 #define IPT_ALIGN(s) XT_ALIGN(s)
40992
40993diff -Nur linux-2.6.18-rc5/include/linux/netfilter_ipv4/ipt_DSCP.h linux-2.6.19/include/linux/netfilter_ipv4/ipt_DSCP.h
40994--- linux-2.6.18-rc5/include/linux/netfilter_ipv4/ipt_DSCP.h 2006-08-28 05:41:48.000000000 +0200
40995+++ linux-2.6.19/include/linux/netfilter_ipv4/ipt_DSCP.h 2006-09-22 10:04:56.000000000 +0200
40996@@ -11,10 +11,8 @@
40997 #ifndef _IPT_DSCP_TARGET_H
40998 #define _IPT_DSCP_TARGET_H
40999 #include <linux/netfilter_ipv4/ipt_dscp.h>
41000+#include <linux/netfilter/xt_DSCP.h>
41001
41002-/* target info */
41003-struct ipt_DSCP_info {
41004- u_int8_t dscp;
41005-};
41006+#define ipt_DSCP_info xt_DSCP_info
41007
41008 #endif /* _IPT_DSCP_TARGET_H */
41009diff -Nur linux-2.6.18-rc5/include/linux/netfilter_ipv4/ipt_dscp.h linux-2.6.19/include/linux/netfilter_ipv4/ipt_dscp.h
41010--- linux-2.6.18-rc5/include/linux/netfilter_ipv4/ipt_dscp.h 2006-08-28 05:41:48.000000000 +0200
41011+++ linux-2.6.19/include/linux/netfilter_ipv4/ipt_dscp.h 2006-09-22 10:04:56.000000000 +0200
41012@@ -10,14 +10,12 @@
41013 #ifndef _IPT_DSCP_H
41014 #define _IPT_DSCP_H
41015
41016-#define IPT_DSCP_MASK 0xfc /* 11111100 */
41017-#define IPT_DSCP_SHIFT 2
41018-#define IPT_DSCP_MAX 0x3f /* 00111111 */
41019+#include <linux/netfilter/xt_dscp.h>
41020
41021-/* match info */
41022-struct ipt_dscp_info {
41023- u_int8_t dscp;
41024- u_int8_t invert;
41025-};
41026+#define IPT_DSCP_MASK XT_DSCP_MASK
41027+#define IPT_DSCP_SHIFT XT_DSCP_SHIFT
41028+#define IPT_DSCP_MAX XT_DSCP_MAX
41029+
41030+#define ipt_dscp_info xt_dscp_info
41031
41032 #endif /* _IPT_DSCP_H */
41033diff -Nur linux-2.6.18-rc5/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.19/include/linux/netfilter_ipv6/ip6_tables.h
41034--- linux-2.6.18-rc5/include/linux/netfilter_ipv6/ip6_tables.h 2006-08-28 05:41:48.000000000 +0200
41035+++ linux-2.6.19/include/linux/netfilter_ipv6/ip6_tables.h 2006-09-22 10:04:56.000000000 +0200
41036@@ -300,8 +300,7 @@
41037 unsigned int hook,
41038 const struct net_device *in,
41039 const struct net_device *out,
41040- struct ip6t_table *table,
41041- void *userdata);
41042+ struct ip6t_table *table);
41043
41044 /* Check for an extension */
41045 extern int ip6t_ext_hdr(u8 nexthdr);
41046diff -Nur linux-2.6.18-rc5/include/linux/pkt_cls.h linux-2.6.19/include/linux/pkt_cls.h
41047--- linux-2.6.18-rc5/include/linux/pkt_cls.h 2006-08-28 05:41:48.000000000 +0200
41048+++ linux-2.6.19/include/linux/pkt_cls.h 2006-09-22 10:04:56.000000000 +0200
41049@@ -305,6 +305,7 @@
41050 TCA_FW_POLICE,
41051 TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */
41052 TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
41053+ TCA_FW_MASK,
41054 __TCA_FW_MAX
41055 };
41056
41057diff -Nur linux-2.6.18-rc5/include/linux/rtnetlink.h linux-2.6.19/include/linux/rtnetlink.h
41058--- linux-2.6.18-rc5/include/linux/rtnetlink.h 2006-08-28 05:41:48.000000000 +0200
41059+++ linux-2.6.19/include/linux/rtnetlink.h 2006-09-22 10:04:56.000000000 +0200
41060@@ -2,6 +2,7 @@
41061 #define __LINUX_RTNETLINK_H
41062
41063 #include <linux/netlink.h>
41064+#include <linux/if.h>
41065
41066 /****
41067 * Routing/neighbour discovery messages.
41068@@ -238,10 +239,8 @@
41069 RT_TABLE_DEFAULT=253,
41070 RT_TABLE_MAIN=254,
41071 RT_TABLE_LOCAL=255,
41072- __RT_TABLE_MAX
41073+ RT_TABLE_MAX=0xFFFFFFFF
41074 };
41075-#define RT_TABLE_MAX (__RT_TABLE_MAX - 1)
41076-
41077
41078
41079 /* Routing message attributes */
41080@@ -263,6 +262,7 @@
41081 RTA_CACHEINFO,
41082 RTA_SESSION,
41083 RTA_MP_ALGO,
41084+ RTA_TABLE,
41085 __RTA_MAX
41086 };
41087
41088@@ -383,226 +383,6 @@
41089 } u;
41090 };
41091
41092-
41093-/*********************************************************
41094- * Interface address.
41095- ****/
41096-
41097-struct ifaddrmsg
41098-{
41099- unsigned char ifa_family;
41100- unsigned char ifa_prefixlen; /* The prefix length */
41101- unsigned char ifa_flags; /* Flags */
41102- unsigned char ifa_scope; /* See above */
41103- int ifa_index; /* Link index */
41104-};
41105-
41106-enum
41107-{
41108- IFA_UNSPEC,
41109- IFA_ADDRESS,
41110- IFA_LOCAL,
41111- IFA_LABEL,
41112- IFA_BROADCAST,
41113- IFA_ANYCAST,
41114- IFA_CACHEINFO,
41115- IFA_MULTICAST,
41116- __IFA_MAX
41117-};
41118-
41119-#define IFA_MAX (__IFA_MAX - 1)
41120-
41121-/* ifa_flags */
41122-
41123-#define IFA_F_SECONDARY 0x01
41124-#define IFA_F_TEMPORARY IFA_F_SECONDARY
41125-
41126-#define IFA_F_DEPRECATED 0x20
41127-#define IFA_F_TENTATIVE 0x40
41128-#define IFA_F_PERMANENT 0x80
41129-
41130-struct ifa_cacheinfo
41131-{
41132- __u32 ifa_prefered;
41133- __u32 ifa_valid;
41134- __u32 cstamp; /* created timestamp, hundredths of seconds */
41135- __u32 tstamp; /* updated timestamp, hundredths of seconds */
41136-};
41137-
41138-
41139-#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
41140-#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
41141-
41142-/*
41143- Important comment:
41144- IFA_ADDRESS is prefix address, rather than local interface address.
41145- It makes no difference for normally configured broadcast interfaces,
41146- but for point-to-point IFA_ADDRESS is DESTINATION address,
41147- local address is supplied in IFA_LOCAL attribute.
41148- */
41149-
41150-/**************************************************************
41151- * Neighbour discovery.
41152- ****/
41153-
41154-struct ndmsg
41155-{
41156- unsigned char ndm_family;
41157- unsigned char ndm_pad1;
41158- unsigned short ndm_pad2;
41159- int ndm_ifindex; /* Link index */
41160- __u16 ndm_state;
41161- __u8 ndm_flags;
41162- __u8 ndm_type;
41163-};
41164-
41165-enum
41166-{
41167- NDA_UNSPEC,
41168- NDA_DST,
41169- NDA_LLADDR,
41170- NDA_CACHEINFO,
41171- NDA_PROBES,
41172- __NDA_MAX
41173-};
41174-
41175-#define NDA_MAX (__NDA_MAX - 1)
41176-
41177-#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
41178-#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
41179-
41180-/*
41181- * Neighbor Cache Entry Flags
41182- */
41183-
41184-#define NTF_PROXY 0x08 /* == ATF_PUBL */
41185-#define NTF_ROUTER 0x80
41186-
41187-/*
41188- * Neighbor Cache Entry States.
41189- */
41190-
41191-#define NUD_INCOMPLETE 0x01
41192-#define NUD_REACHABLE 0x02
41193-#define NUD_STALE 0x04
41194-#define NUD_DELAY 0x08
41195-#define NUD_PROBE 0x10
41196-#define NUD_FAILED 0x20
41197-
41198-/* Dummy states */
41199-#define NUD_NOARP 0x40
41200-#define NUD_PERMANENT 0x80
41201-#define NUD_NONE 0x00
41202-
41203-
41204-struct nda_cacheinfo
41205-{
41206- __u32 ndm_confirmed;
41207- __u32 ndm_used;
41208- __u32 ndm_updated;
41209- __u32 ndm_refcnt;
41210-};
41211-
41212-
41213-/*****************************************************************
41214- * Neighbour tables specific messages.
41215- *
41216- * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
41217- * NLM_F_DUMP flag set. Every neighbour table configuration is
41218- * spread over multiple messages to avoid running into message
41219- * size limits on systems with many interfaces. The first message
41220- * in the sequence transports all not device specific data such as
41221- * statistics, configuration, and the default parameter set.
41222- * This message is followed by 0..n messages carrying device
41223- * specific parameter sets.
41224- * Although the ordering should be sufficient, NDTA_NAME can be
41225- * used to identify sequences. The initial message can be identified
41226- * by checking for NDTA_CONFIG. The device specific messages do
41227- * not contain this TLV but have NDTPA_IFINDEX set to the
41228- * corresponding interface index.
41229- *
41230- * To change neighbour table attributes, send RTM_SETNEIGHTBL
41231- * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
41232- * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
41233- * otherwise. Device specific parameter sets can be changed by
41234- * setting NDTPA_IFINDEX to the interface index of the corresponding
41235- * device.
41236- ****/
41237-
41238-struct ndt_stats
41239-{
41240- __u64 ndts_allocs;
41241- __u64 ndts_destroys;
41242- __u64 ndts_hash_grows;
41243- __u64 ndts_res_failed;
41244- __u64 ndts_lookups;
41245- __u64 ndts_hits;
41246- __u64 ndts_rcv_probes_mcast;
41247- __u64 ndts_rcv_probes_ucast;
41248- __u64 ndts_periodic_gc_runs;
41249- __u64 ndts_forced_gc_runs;
41250-};
41251-
41252-enum {
41253- NDTPA_UNSPEC,
41254- NDTPA_IFINDEX, /* u32, unchangeable */
41255- NDTPA_REFCNT, /* u32, read-only */
41256- NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */
41257- NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */
41258- NDTPA_RETRANS_TIME, /* u64, msecs */
41259- NDTPA_GC_STALETIME, /* u64, msecs */
41260- NDTPA_DELAY_PROBE_TIME, /* u64, msecs */
41261- NDTPA_QUEUE_LEN, /* u32 */
41262- NDTPA_APP_PROBES, /* u32 */
41263- NDTPA_UCAST_PROBES, /* u32 */
41264- NDTPA_MCAST_PROBES, /* u32 */
41265- NDTPA_ANYCAST_DELAY, /* u64, msecs */
41266- NDTPA_PROXY_DELAY, /* u64, msecs */
41267- NDTPA_PROXY_QLEN, /* u32 */
41268- NDTPA_LOCKTIME, /* u64, msecs */
41269- __NDTPA_MAX
41270-};
41271-#define NDTPA_MAX (__NDTPA_MAX - 1)
41272-
41273-struct ndtmsg
41274-{
41275- __u8 ndtm_family;
41276- __u8 ndtm_pad1;
41277- __u16 ndtm_pad2;
41278-};
41279-
41280-struct ndt_config
41281-{
41282- __u16 ndtc_key_len;
41283- __u16 ndtc_entry_size;
41284- __u32 ndtc_entries;
41285- __u32 ndtc_last_flush; /* delta to now in msecs */
41286- __u32 ndtc_last_rand; /* delta to now in msecs */
41287- __u32 ndtc_hash_rnd;
41288- __u32 ndtc_hash_mask;
41289- __u32 ndtc_hash_chain_gc;
41290- __u32 ndtc_proxy_qlen;
41291-};
41292-
41293-enum {
41294- NDTA_UNSPEC,
41295- NDTA_NAME, /* char *, unchangeable */
41296- NDTA_THRESH1, /* u32 */
41297- NDTA_THRESH2, /* u32 */
41298- NDTA_THRESH3, /* u32 */
41299- NDTA_CONFIG, /* struct ndt_config, read-only */
41300- NDTA_PARMS, /* nested TLV NDTPA_* */
41301- NDTA_STATS, /* struct ndt_stats, read-only */
41302- NDTA_GC_INTERVAL, /* u64, msecs */
41303- __NDTA_MAX
41304-};
41305-#define NDTA_MAX (__NDTA_MAX - 1)
41306-
41307-#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \
41308- NLMSG_ALIGN(sizeof(struct ndtmsg))))
41309-#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
41310-
41311-
41312 /****
41313 * General form of address family dependent message.
41314 ****/
41315@@ -663,138 +443,6 @@
41316 __u32 valid_time;
41317 };
41318
41319-/* The struct should be in sync with struct net_device_stats */
41320-struct rtnl_link_stats
41321-{
41322- __u32 rx_packets; /* total packets received */
41323- __u32 tx_packets; /* total packets transmitted */
41324- __u32 rx_bytes; /* total bytes received */
41325- __u32 tx_bytes; /* total bytes transmitted */
41326- __u32 rx_errors; /* bad packets received */
41327- __u32 tx_errors; /* packet transmit problems */
41328- __u32 rx_dropped; /* no space in linux buffers */
41329- __u32 tx_dropped; /* no space available in linux */
41330- __u32 multicast; /* multicast packets received */
41331- __u32 collisions;
41332-
41333- /* detailed rx_errors: */
41334- __u32 rx_length_errors;
41335- __u32 rx_over_errors; /* receiver ring buff overflow */
41336- __u32 rx_crc_errors; /* recved pkt with crc error */
41337- __u32 rx_frame_errors; /* recv'd frame alignment error */
41338- __u32 rx_fifo_errors; /* recv'r fifo overrun */
41339- __u32 rx_missed_errors; /* receiver missed packet */
41340-
41341- /* detailed tx_errors */
41342- __u32 tx_aborted_errors;
41343- __u32 tx_carrier_errors;
41344- __u32 tx_fifo_errors;
41345- __u32 tx_heartbeat_errors;
41346- __u32 tx_window_errors;
41347-
41348- /* for cslip etc */
41349- __u32 rx_compressed;
41350- __u32 tx_compressed;
41351-};
41352-
41353-/* The struct should be in sync with struct ifmap */
41354-struct rtnl_link_ifmap
41355-{
41356- __u64 mem_start;
41357- __u64 mem_end;
41358- __u64 base_addr;
41359- __u16 irq;
41360- __u8 dma;
41361- __u8 port;
41362-};
41363-
41364-enum
41365-{
41366- IFLA_UNSPEC,
41367- IFLA_ADDRESS,
41368- IFLA_BROADCAST,
41369- IFLA_IFNAME,
41370- IFLA_MTU,
41371- IFLA_LINK,
41372- IFLA_QDISC,
41373- IFLA_STATS,
41374- IFLA_COST,
41375-#define IFLA_COST IFLA_COST
41376- IFLA_PRIORITY,
41377-#define IFLA_PRIORITY IFLA_PRIORITY
41378- IFLA_MASTER,
41379-#define IFLA_MASTER IFLA_MASTER
41380- IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
41381-#define IFLA_WIRELESS IFLA_WIRELESS
41382- IFLA_PROTINFO, /* Protocol specific information for a link */
41383-#define IFLA_PROTINFO IFLA_PROTINFO
41384- IFLA_TXQLEN,
41385-#define IFLA_TXQLEN IFLA_TXQLEN
41386- IFLA_MAP,
41387-#define IFLA_MAP IFLA_MAP
41388- IFLA_WEIGHT,
41389-#define IFLA_WEIGHT IFLA_WEIGHT
41390- IFLA_OPERSTATE,
41391- IFLA_LINKMODE,
41392- __IFLA_MAX
41393-};
41394-
41395-
41396-#define IFLA_MAX (__IFLA_MAX - 1)
41397-
41398-#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
41399-#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
41400-
41401-/* ifi_flags.
41402-
41403- IFF_* flags.
41404-
41405- The only change is:
41406- IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
41407- more not changeable by user. They describe link media
41408- characteristics and set by device driver.
41409-
41410- Comments:
41411- - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
41412- - If neither of these three flags are set;
41413- the interface is NBMA.
41414-
41415- - IFF_MULTICAST does not mean anything special:
41416- multicasts can be used on all not-NBMA links.
41417- IFF_MULTICAST means that this media uses special encapsulation
41418- for multicast frames. Apparently, all IFF_POINTOPOINT and
41419- IFF_BROADCAST devices are able to use multicasts too.
41420- */
41421-
41422-/* IFLA_LINK.
41423- For usual devices it is equal ifi_index.
41424- If it is a "virtual interface" (f.e. tunnel), ifi_link
41425- can point to real physical interface (f.e. for bandwidth calculations),
41426- or maybe 0, what means, that real media is unknown (usual
41427- for IPIP tunnels, when route to endpoint is allowed to change)
41428- */
41429-
41430-/* Subtype attributes for IFLA_PROTINFO */
41431-enum
41432-{
41433- IFLA_INET6_UNSPEC,
41434- IFLA_INET6_FLAGS, /* link flags */
41435- IFLA_INET6_CONF, /* sysctl parameters */
41436- IFLA_INET6_STATS, /* statistics */
41437- IFLA_INET6_MCAST, /* MC things. What of them? */
41438- IFLA_INET6_CACHEINFO, /* time values and max reasm size */
41439- __IFLA_INET6_MAX
41440-};
41441-
41442-#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
41443-
41444-struct ifla_cacheinfo
41445-{
41446- __u32 max_reasm_len;
41447- __u32 tstamp; /* ipv6InterfaceTable updated timestamp */
41448- __u32 reachable_time;
41449- __u32 retrans_time;
41450-};
41451
41452 /*****************************************************************
41453 * Traffic control messages.
41454@@ -885,10 +533,13 @@
41455 RTNLGRP_NOP2,
41456 RTNLGRP_DECnet_ROUTE,
41457 #define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE
41458- RTNLGRP_NOP3,
41459+ RTNLGRP_DECnet_RULE,
41460+#define RTNLGRP_DECnet_RULE RTNLGRP_DECnet_RULE
41461 RTNLGRP_NOP4,
41462 RTNLGRP_IPV6_PREFIX,
41463 #define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX
41464+ RTNLGRP_IPV6_RULE,
41465+#define RTNLGRP_IPV6_RULE RTNLGRP_IPV6_RULE
41466 __RTNLGRP_MAX
41467 };
41468 #define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
41469@@ -923,8 +574,6 @@
41470 #define rtattr_parse_nested(tb, max, rta) \
41471 rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
41472
41473-extern struct sock *rtnl;
41474-
41475 struct rtnetlink_link
41476 {
41477 int (*doit)(struct sk_buff *, struct nlmsghdr*, void *attr);
41478@@ -933,6 +582,10 @@
41479
41480 extern struct rtnetlink_link * rtnetlink_links[NPROTO];
41481 extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
41482+extern int rtnl_unicast(struct sk_buff *skb, u32 pid);
41483+extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
41484+ struct nlmsghdr *nlh, gfp_t flags);
41485+extern void rtnl_set_sk_err(u32 group, int error);
41486 extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics);
41487
41488 extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data);
41489@@ -1065,6 +718,13 @@
41490 } \
41491 } while(0)
41492
41493+static inline u32 rtm_get_table(struct rtattr **rta, u8 table)
41494+{
41495+ return RTA_GET_U32(rta[RTA_TABLE-1]);
41496+rtattr_failure:
41497+ return table;
41498+}
41499+
41500 #endif /* __KERNEL__ */
41501
41502
6b10f65d 41503diff -Nur linux-2.6.18-rc5/include/linux/skbuff.h linux-2.6.19/include/linux/skbuff.h
41504--- linux-2.6.18-rc5/include/linux/skbuff.h 2006-08-28 05:41:48.000000000 +0200
41505+++ linux-2.6.19/include/linux/skbuff.h 2006-09-22 10:04:56.000000000 +0200
41506@@ -34,8 +34,9 @@
41507 #define HAVE_ALIGNABLE_SKB /* Ditto 8) */
41508
41509 #define CHECKSUM_NONE 0
41510-#define CHECKSUM_HW 1
41511+#define CHECKSUM_PARTIAL 1
41512 #define CHECKSUM_UNNECESSARY 2
41513+#define CHECKSUM_COMPLETE 3
41514
41515 #define SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES - 1)) & \
41516 ~(SMP_CACHE_BYTES - 1))
41517@@ -56,17 +57,17 @@
41518 * Apparently with secret goal to sell you new device, when you
41519 * will add new protocol to your host. F.e. IPv6. 8)
41520 *
41521- * HW: the most generic way. Device supplied checksum of _all_
41522+ * COMPLETE: the most generic way. Device supplied checksum of _all_
41523 * the packet as seen by netif_rx in skb->csum.
41524 * NOTE: Even if device supports only some protocols, but
41525- * is able to produce some skb->csum, it MUST use HW,
41526+ * is able to produce some skb->csum, it MUST use COMPLETE,
41527 * not UNNECESSARY.
41528 *
41529 * B. Checksumming on output.
41530 *
41531 * NONE: skb is checksummed by protocol or csum is not required.
41532 *
41533- * HW: device is required to csum packet as seen by hard_start_xmit
41534+ * PARTIAL: device is required to csum packet as seen by hard_start_xmit
41535 * from skb->h.raw to the end and to record the checksum
41536 * at skb->h.raw+skb->csum.
41537 *
41538@@ -1261,14 +1262,14 @@
41539 * @len: length of data pulled
41540 *
41541 * After doing a pull on a received packet, you need to call this to
41542- * update the CHECKSUM_HW checksum, or set ip_summed to CHECKSUM_NONE
41543- * so that it can be recomputed from scratch.
41544+ * update the CHECKSUM_COMPLETE checksum, or set ip_summed to
41545+ * CHECKSUM_NONE so that it can be recomputed from scratch.
41546 */
41547
41548 static inline void skb_postpull_rcsum(struct sk_buff *skb,
41549 const void *start, unsigned int len)
41550 {
41551- if (skb->ip_summed == CHECKSUM_HW)
41552+ if (skb->ip_summed == CHECKSUM_COMPLETE)
41553 skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0));
41554 }
41555
41556@@ -1287,7 +1288,7 @@
41557 {
41558 if (likely(len >= skb->len))
41559 return 0;
41560- if (skb->ip_summed == CHECKSUM_HW)
41561+ if (skb->ip_summed == CHECKSUM_COMPLETE)
41562 skb->ip_summed = CHECKSUM_NONE;
41563 return __pskb_trim(skb, len);
41564 }
41565diff -Nur linux-2.6.18-rc5/include/linux/snmp.h linux-2.6.19/include/linux/snmp.h
41566--- linux-2.6.18-rc5/include/linux/snmp.h 2006-08-28 05:41:48.000000000 +0200
41567+++ linux-2.6.19/include/linux/snmp.h 2006-09-22 10:04:56.000000000 +0200
41568@@ -155,42 +155,11 @@
41569 UDP_MIB_NOPORTS, /* NoPorts */
41570 UDP_MIB_INERRORS, /* InErrors */
41571 UDP_MIB_OUTDATAGRAMS, /* OutDatagrams */
41572+ UDP_MIB_RCVBUFERRORS, /* RcvbufErrors */
41573+ UDP_MIB_SNDBUFERRORS, /* SndbufErrors */
41574 __UDP_MIB_MAX
41575 };
41576
41577-/* sctp mib definitions */
41578-/*
41579- * draft-ietf-sigtran-sctp-mib-07.txt
41580- */
41581-enum
41582-{
41583- SCTP_MIB_NUM = 0,
41584- SCTP_MIB_CURRESTAB, /* CurrEstab */
41585- SCTP_MIB_ACTIVEESTABS, /* ActiveEstabs */
41586- SCTP_MIB_PASSIVEESTABS, /* PassiveEstabs */
41587- SCTP_MIB_ABORTEDS, /* Aborteds */
41588- SCTP_MIB_SHUTDOWNS, /* Shutdowns */
41589- SCTP_MIB_OUTOFBLUES, /* OutOfBlues */
41590- SCTP_MIB_CHECKSUMERRORS, /* ChecksumErrors */
41591- SCTP_MIB_OUTCTRLCHUNKS, /* OutCtrlChunks */
41592- SCTP_MIB_OUTORDERCHUNKS, /* OutOrderChunks */
41593- SCTP_MIB_OUTUNORDERCHUNKS, /* OutUnorderChunks */
41594- SCTP_MIB_INCTRLCHUNKS, /* InCtrlChunks */
41595- SCTP_MIB_INORDERCHUNKS, /* InOrderChunks */
41596- SCTP_MIB_INUNORDERCHUNKS, /* InUnorderChunks */
41597- SCTP_MIB_FRAGUSRMSGS, /* FragUsrMsgs */
41598- SCTP_MIB_REASMUSRMSGS, /* ReasmUsrMsgs */
41599- SCTP_MIB_OUTSCTPPACKS, /* OutSCTPPacks */
41600- SCTP_MIB_INSCTPPACKS, /* InSCTPPacks */
41601- SCTP_MIB_RTOALGORITHM, /* RtoAlgorithm */
41602- SCTP_MIB_RTOMIN, /* RtoMin */
41603- SCTP_MIB_RTOMAX, /* RtoMax */
41604- SCTP_MIB_RTOINITIAL, /* RtoInitial */
41605- SCTP_MIB_VALCOOKIELIFE, /* ValCookieLife */
41606- SCTP_MIB_MAXINITRETR, /* MaxInitRetr */
41607- __SCTP_MIB_MAX
41608-};
41609-
41610 /* linux mib definitions */
41611 enum
41612 {
41613diff -Nur linux-2.6.18-rc5/include/linux/sysctl.h linux-2.6.19/include/linux/sysctl.h
41614--- linux-2.6.18-rc5/include/linux/sysctl.h 2006-08-28 05:41:48.000000000 +0200
41615+++ linux-2.6.19/include/linux/sysctl.h 2006-09-22 10:04:56.000000000 +0200
41616@@ -411,6 +411,10 @@
41617 NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115,
41618 NET_TCP_DMA_COPYBREAK=116,
41619 NET_TCP_SLOW_START_AFTER_IDLE=117,
41620+ NET_CIPSOV4_CACHE_ENABLE=118,
41621+ NET_CIPSOV4_CACHE_BUCKET_SIZE=119,
41622+ NET_CIPSOV4_RBM_OPTFMT=120,
41623+ NET_CIPSOV4_RBM_STRICTVALID=121,
41624 };
41625
41626 enum {
41627diff -Nur linux-2.6.18-rc5/include/linux/xfrm.h linux-2.6.19/include/linux/xfrm.h
41628--- linux-2.6.18-rc5/include/linux/xfrm.h 2006-08-28 05:41:48.000000000 +0200
41629+++ linux-2.6.19/include/linux/xfrm.h 2006-09-22 10:04:57.000000000 +0200
41630@@ -104,6 +104,13 @@
41631
41632 enum
41633 {
41634+ XFRM_POLICY_TYPE_MAIN = 0,
41635+ XFRM_POLICY_TYPE_SUB = 1,
41636+ XFRM_POLICY_TYPE_MAX = 2
41637+};
41638+
41639+enum
41640+{
41641 XFRM_POLICY_IN = 0,
41642 XFRM_POLICY_OUT = 1,
41643 XFRM_POLICY_FWD = 2,
41644@@ -120,7 +127,9 @@
41645
41646 #define XFRM_MODE_TRANSPORT 0
41647 #define XFRM_MODE_TUNNEL 1
41648-#define XFRM_MODE_MAX 2
41649+#define XFRM_MODE_ROUTEOPTIMIZATION 2
41650+#define XFRM_MODE_IN_TRIGGER 3
41651+#define XFRM_MODE_MAX 4
41652
41653 /* Netlink configuration messages. */
41654 enum {
41655@@ -164,6 +173,10 @@
41656 #define XFRM_MSG_NEWAE XFRM_MSG_NEWAE
41657 XFRM_MSG_GETAE,
41658 #define XFRM_MSG_GETAE XFRM_MSG_GETAE
41659+
41660+ XFRM_MSG_REPORT,
41661+#define XFRM_MSG_REPORT XFRM_MSG_REPORT
41662+
41663 __XFRM_MSG_MAX
41664 };
41665 #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
41666@@ -217,6 +230,12 @@
41667 #define XFRM_AE_MAX (__XFRM_AE_MAX - 1)
41668 };
41669
41670+struct xfrm_userpolicy_type {
41671+ __u8 type;
41672+ __u16 reserved1;
41673+ __u8 reserved2;
41674+};
41675+
41676 /* Netlink message attributes. */
41677 enum xfrm_attr_type_t {
41678 XFRMA_UNSPEC,
41679@@ -232,6 +251,10 @@
41680 XFRMA_REPLAY_VAL,
41681 XFRMA_REPLAY_THRESH,
41682 XFRMA_ETIMER_THRESH,
41683+ XFRMA_SRCADDR, /* xfrm_address_t */
41684+ XFRMA_COADDR, /* xfrm_address_t */
41685+ XFRMA_LASTUSED,
41686+ XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */
41687 __XFRMA_MAX
41688
41689 #define XFRMA_MAX (__XFRMA_MAX - 1)
41690@@ -247,12 +270,13 @@
41691 __u32 seq;
41692 __u32 reqid;
41693 __u16 family;
41694- __u8 mode; /* 0=transport,1=tunnel */
41695+ __u8 mode; /* XFRM_MODE_xxx */
41696 __u8 replay_window;
41697 __u8 flags;
41698 #define XFRM_STATE_NOECN 1
41699 #define XFRM_STATE_DECAP_DSCP 2
41700 #define XFRM_STATE_NOPMTUDISC 4
41701+#define XFRM_STATE_WILDRECV 8
41702 };
41703
41704 struct xfrm_usersa_id {
41705@@ -319,12 +343,18 @@
41706 __u8 proto;
41707 };
41708
41709+struct xfrm_user_report {
41710+ __u8 proto;
41711+ struct xfrm_selector sel;
41712+};
41713+
41714 #ifndef __KERNEL__
41715 /* backwards compatibility for userspace */
41716 #define XFRMGRP_ACQUIRE 1
41717 #define XFRMGRP_EXPIRE 2
41718 #define XFRMGRP_SA 4
41719 #define XFRMGRP_POLICY 8
41720+#define XFRMGRP_REPORT 0x10
41721 #endif
41722
41723 enum xfrm_nlgroups {
41724@@ -340,6 +370,8 @@
41725 #define XFRMNLGRP_POLICY XFRMNLGRP_POLICY
41726 XFRMNLGRP_AEVENTS,
41727 #define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS
41728+ XFRMNLGRP_REPORT,
41729+#define XFRMNLGRP_REPORT XFRMNLGRP_REPORT
41730 __XFRMNLGRP_MAX
41731 };
41732 #define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1)
c771f314 41733diff -Nur linux-2.6.18-rc5/include/net/act_api.h linux-2.6.19/include/net/act_api.h
41734--- linux-2.6.18-rc5/include/net/act_api.h 2006-08-28 05:41:48.000000000 +0200
41735+++ linux-2.6.19/include/net/act_api.h 2006-09-22 10:04:57.000000000 +0200
41736@@ -8,70 +8,110 @@
41737 #include <net/sch_generic.h>
41738 #include <net/pkt_sched.h>
41739
41740-#define tca_gen(name) \
41741-struct tcf_##name *next; \
41742- u32 index; \
41743- int refcnt; \
41744- int bindcnt; \
41745- u32 capab; \
41746- int action; \
41747- struct tcf_t tm; \
41748- struct gnet_stats_basic bstats; \
41749- struct gnet_stats_queue qstats; \
41750- struct gnet_stats_rate_est rate_est; \
41751- spinlock_t *stats_lock; \
41752- spinlock_t lock
41753+struct tcf_common {
41754+ struct tcf_common *tcfc_next;
41755+ u32 tcfc_index;
41756+ int tcfc_refcnt;
41757+ int tcfc_bindcnt;
41758+ u32 tcfc_capab;
41759+ int tcfc_action;
41760+ struct tcf_t tcfc_tm;
41761+ struct gnet_stats_basic tcfc_bstats;
41762+ struct gnet_stats_queue tcfc_qstats;
41763+ struct gnet_stats_rate_est tcfc_rate_est;
41764+ spinlock_t *tcfc_stats_lock;
41765+ spinlock_t tcfc_lock;
41766+};
41767+#define tcf_next common.tcfc_next
41768+#define tcf_index common.tcfc_index
41769+#define tcf_refcnt common.tcfc_refcnt
41770+#define tcf_bindcnt common.tcfc_bindcnt
41771+#define tcf_capab common.tcfc_capab
41772+#define tcf_action common.tcfc_action
41773+#define tcf_tm common.tcfc_tm
41774+#define tcf_bstats common.tcfc_bstats
41775+#define tcf_qstats common.tcfc_qstats
41776+#define tcf_rate_est common.tcfc_rate_est
41777+#define tcf_stats_lock common.tcfc_stats_lock
41778+#define tcf_lock common.tcfc_lock
41779+
41780+struct tcf_police {
41781+ struct tcf_common common;
41782+ int tcfp_result;
41783+ u32 tcfp_ewma_rate;
41784+ u32 tcfp_burst;
41785+ u32 tcfp_mtu;
41786+ u32 tcfp_toks;
41787+ u32 tcfp_ptoks;
41788+ psched_time_t tcfp_t_c;
41789+ struct qdisc_rate_table *tcfp_R_tab;
41790+ struct qdisc_rate_table *tcfp_P_tab;
41791+};
41792+#define to_police(pc) \
41793+ container_of(pc, struct tcf_police, common)
41794
41795-struct tcf_police
41796-{
41797- tca_gen(police);
41798- int result;
41799- u32 ewma_rate;
41800- u32 burst;
41801- u32 mtu;
41802- u32 toks;
41803- u32 ptoks;
41804- psched_time_t t_c;
41805- struct qdisc_rate_table *R_tab;
41806- struct qdisc_rate_table *P_tab;
41807+struct tcf_hashinfo {
41808+ struct tcf_common **htab;
41809+ unsigned int hmask;
41810+ rwlock_t *lock;
41811 };
41812
41813+static inline unsigned int tcf_hash(u32 index, unsigned int hmask)
41814+{
41815+ return index & hmask;
41816+}
41817+
41818 #ifdef CONFIG_NET_CLS_ACT
41819
41820 #define ACT_P_CREATED 1
41821 #define ACT_P_DELETED 1
41822
41823-struct tcf_act_hdr
41824-{
41825- tca_gen(act_hdr);
41826+struct tcf_act_hdr {
41827+ struct tcf_common common;
41828 };
41829
41830-struct tc_action
41831-{
41832- void *priv;
41833- struct tc_action_ops *ops;
41834- __u32 type; /* for backward compat(TCA_OLD_COMPAT) */
41835- __u32 order;
41836- struct tc_action *next;
41837+struct tc_action {
41838+ void *priv;
41839+ struct tc_action_ops *ops;
41840+ __u32 type; /* for backward compat(TCA_OLD_COMPAT) */
41841+ __u32 order;
41842+ struct tc_action *next;
41843 };
41844
41845 #define TCA_CAP_NONE 0
41846-struct tc_action_ops
41847-{
41848+struct tc_action_ops {
41849 struct tc_action_ops *next;
41850+ struct tcf_hashinfo *hinfo;
41851 char kind[IFNAMSIZ];
41852 __u32 type; /* TBD to match kind */
41853 __u32 capab; /* capabilities includes 4 bit version */
41854 struct module *owner;
41855 int (*act)(struct sk_buff *, struct tc_action *, struct tcf_result *);
41856 int (*get_stats)(struct sk_buff *, struct tc_action *);
41857- int (*dump)(struct sk_buff *, struct tc_action *,int , int);
41858+ int (*dump)(struct sk_buff *, struct tc_action *, int, int);
41859 int (*cleanup)(struct tc_action *, int bind);
41860- int (*lookup)(struct tc_action *, u32 );
41861- int (*init)(struct rtattr *,struct rtattr *,struct tc_action *, int , int );
41862- int (*walk)(struct sk_buff *, struct netlink_callback *, int , struct tc_action *);
41863+ int (*lookup)(struct tc_action *, u32);
41864+ int (*init)(struct rtattr *, struct rtattr *, struct tc_action *, int , int);
41865+ int (*walk)(struct sk_buff *, struct netlink_callback *, int, struct tc_action *);
41866 };
41867
41868+extern struct tcf_common *tcf_hash_lookup(u32 index,
41869+ struct tcf_hashinfo *hinfo);
41870+extern void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo);
41871+extern int tcf_hash_release(struct tcf_common *p, int bind,
41872+ struct tcf_hashinfo *hinfo);
41873+extern int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
41874+ int type, struct tc_action *a);
41875+extern u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo);
41876+extern int tcf_hash_search(struct tc_action *a, u32 index);
41877+extern struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a,
41878+ int bind, struct tcf_hashinfo *hinfo);
41879+extern struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est,
41880+ struct tc_action *a, int size,
41881+ int bind, u32 *idx_gen,
41882+ struct tcf_hashinfo *hinfo);
41883+extern void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo);
41884+
41885 extern int tcf_register_action(struct tc_action_ops *a);
41886 extern int tcf_unregister_action(struct tc_action_ops *a);
41887 extern void tcf_action_destroy(struct tc_action *a, int bind);
41888@@ -96,17 +136,17 @@
41889 int ret = 0;
41890 #ifdef CONFIG_NET_CLS_ACT
41891 if (p) {
41892- if (bind) {
41893- p->bindcnt--;
41894- }
41895- p->refcnt--;
41896- if (p->refcnt <= 0 && !p->bindcnt) {
41897+ if (bind)
41898+ p->tcf_bindcnt--;
41899+
41900+ p->tcf_refcnt--;
41901+ if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) {
41902 tcf_police_destroy(p);
41903 ret = 1;
41904 }
41905 }
41906 #else
41907- if (p && --p->refcnt == 0)
41908+ if (p && --p->tcf_refcnt == 0)
41909 tcf_police_destroy(p);
41910
41911 #endif /* CONFIG_NET_CLS_ACT */
41912diff -Nur linux-2.6.18-rc5/include/net/act_generic.h linux-2.6.19/include/net/act_generic.h
41913--- linux-2.6.18-rc5/include/net/act_generic.h 2006-08-28 05:41:48.000000000 +0200
41914+++ linux-2.6.19/include/net/act_generic.h 1970-01-01 01:00:00.000000000 +0100
41915@@ -1,142 +0,0 @@
41916-/*
41917- * include/net/act_generic.h
41918- *
41919-*/
41920-#ifndef _NET_ACT_GENERIC_H
41921-#define _NET_ACT_GENERIC_H
41922-static inline int tcf_defact_release(struct tcf_defact *p, int bind)
41923-{
41924- int ret = 0;
41925- if (p) {
41926- if (bind) {
41927- p->bindcnt--;
41928- }
41929- p->refcnt--;
41930- if (p->bindcnt <= 0 && p->refcnt <= 0) {
41931- kfree(p->defdata);
41932- tcf_hash_destroy(p);
41933- ret = 1;
41934- }
41935- }
41936- return ret;
41937-}
41938-
41939-static inline int
41940-alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
41941-{
41942- p->defdata = kmalloc(datalen, GFP_KERNEL);
41943- if (p->defdata == NULL)
41944- return -ENOMEM;
41945- p->datalen = datalen;
41946- memcpy(p->defdata, defdata, datalen);
41947- return 0;
41948-}
41949-
41950-static inline int
41951-realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
41952-{
41953- /* safer to be just brute force for now */
41954- kfree(p->defdata);
41955- return alloc_defdata(p, datalen, defdata);
41956-}
41957-
41958-static inline int
41959-tcf_defact_init(struct rtattr *rta, struct rtattr *est,
41960- struct tc_action *a, int ovr, int bind)
41961-{
41962- struct rtattr *tb[TCA_DEF_MAX];
41963- struct tc_defact *parm;
41964- struct tcf_defact *p;
41965- void *defdata;
41966- u32 datalen = 0;
41967- int ret = 0;
41968-
41969- if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
41970- return -EINVAL;
41971-
41972- if (tb[TCA_DEF_PARMS - 1] == NULL ||
41973- RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm))
41974- return -EINVAL;
41975-
41976- parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);
41977- defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]);
41978- if (defdata == NULL)
41979- return -EINVAL;
41980-
41981- datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]);
41982- if (datalen <= 0)
41983- return -EINVAL;
41984-
41985- p = tcf_hash_check(parm->index, a, ovr, bind);
41986- if (p == NULL) {
41987- p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
41988- if (p == NULL)
41989- return -ENOMEM;
41990-
41991- ret = alloc_defdata(p, datalen, defdata);
41992- if (ret < 0) {
41993- kfree(p);
41994- return ret;
41995- }
41996- ret = ACT_P_CREATED;
41997- } else {
41998- if (!ovr) {
41999- tcf_defact_release(p, bind);
42000- return -EEXIST;
42001- }
42002- realloc_defdata(p, datalen, defdata);
42003- }
42004-
42005- spin_lock_bh(&p->lock);
42006- p->action = parm->action;
42007- spin_unlock_bh(&p->lock);
42008- if (ret == ACT_P_CREATED)
42009- tcf_hash_insert(p);
42010- return ret;
42011-}
42012-
42013-static inline int tcf_defact_cleanup(struct tc_action *a, int bind)
42014-{
42015- struct tcf_defact *p = PRIV(a, defact);
42016-
42017- if (p != NULL)
42018- return tcf_defact_release(p, bind);
42019- return 0;
42020-}
42021-
42022-static inline int
42023-tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
42024-{
42025- unsigned char *b = skb->tail;
42026- struct tc_defact opt;
42027- struct tcf_defact *p = PRIV(a, defact);
42028- struct tcf_t t;
42029-
42030- opt.index = p->index;
42031- opt.refcnt = p->refcnt - ref;
42032- opt.bindcnt = p->bindcnt - bind;
42033- opt.action = p->action;
42034- RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
42035- RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata);
42036- t.install = jiffies_to_clock_t(jiffies - p->tm.install);
42037- t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
42038- t.expires = jiffies_to_clock_t(p->tm.expires);
42039- RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
42040- return skb->len;
42041-
42042-rtattr_failure:
42043- skb_trim(skb, b - skb->data);
42044- return -1;
42045-}
42046-
42047-#define tca_use_default_ops \
42048- .dump = tcf_defact_dump, \
42049- .cleanup = tcf_defact_cleanup, \
42050- .init = tcf_defact_init, \
42051- .walk = tcf_generic_walker, \
42052-
42053-#define tca_use_default_defines(name) \
42054- static u32 idx_gen; \
42055- static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \
42056- static DEFINE_RWLOCK(##name_lock);
42057-#endif /* _NET_ACT_GENERIC_H */
42058diff -Nur linux-2.6.18-rc5/include/net/addrconf.h linux-2.6.19/include/net/addrconf.h
42059--- linux-2.6.18-rc5/include/net/addrconf.h 2006-08-28 05:41:48.000000000 +0200
42060+++ linux-2.6.19/include/net/addrconf.h 2006-09-22 10:04:57.000000000 +0200
42061@@ -61,6 +61,13 @@
42062 extern int ipv6_chk_addr(struct in6_addr *addr,
42063 struct net_device *dev,
42064 int strict);
42065+/* XXX: this is a placeholder till addrconf supports */
42066+#ifdef CONFIG_IPV6_MIP6
42067+static inline int ipv6_chk_home_addr(struct in6_addr *addr)
42068+{
42069+ return 0;
42070+}
42071+#endif
42072 extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
42073 struct net_device *dev,
42074 int strict);
42075diff -Nur linux-2.6.18-rc5/include/net/cipso_ipv4.h linux-2.6.19/include/net/cipso_ipv4.h
42076--- linux-2.6.18-rc5/include/net/cipso_ipv4.h 1970-01-01 01:00:00.000000000 +0100
42077+++ linux-2.6.19/include/net/cipso_ipv4.h 2006-09-22 10:04:57.000000000 +0200
42078@@ -0,0 +1,246 @@
42079+/*
42080+ * CIPSO - Commercial IP Security Option
42081+ *
42082+ * This is an implementation of the CIPSO 2.2 protocol as specified in
42083+ * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
42084+ * FIPS-188, copies of both documents can be found in the Documentation
42085+ * directory. While CIPSO never became a full IETF RFC standard many vendors
42086+ * have chosen to adopt the protocol and over the years it has become a
42087+ * de-facto standard for labeled networking.
42088+ *
42089+ * Author: Paul Moore <paul.moore@hp.com>
42090+ *
42091+ */
42092+
42093+/*
42094+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
42095+ *
42096+ * This program is free software; you can redistribute it and/or modify
42097+ * it under the terms of the GNU General Public License as published by
42098+ * the Free Software Foundation; either version 2 of the License, or
42099+ * (at your option) any later version.
42100+ *
42101+ * This program is distributed in the hope that it will be useful,
42102+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
42103+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
42104+ * the GNU General Public License for more details.
42105+ *
42106+ * You should have received a copy of the GNU General Public License
42107+ * along with this program; if not, write to the Free Software
42108+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42109+ *
42110+ */
42111+
42112+#ifndef _CIPSO_IPV4_H
42113+#define _CIPSO_IPV4_H
42114+
42115+#include <linux/types.h>
42116+#include <linux/rcupdate.h>
42117+#include <linux/list.h>
42118+#include <linux/net.h>
42119+#include <linux/skbuff.h>
42120+#include <net/netlabel.h>
42121+
42122+/* known doi values */
42123+#define CIPSO_V4_DOI_UNKNOWN 0x00000000
42124+
42125+/* tag types */
42126+#define CIPSO_V4_TAG_INVALID 0
42127+#define CIPSO_V4_TAG_RBITMAP 1
42128+#define CIPSO_V4_TAG_ENUM 2
42129+#define CIPSO_V4_TAG_RANGE 5
42130+#define CIPSO_V4_TAG_PBITMAP 6
42131+#define CIPSO_V4_TAG_FREEFORM 7
42132+
42133+/* doi mapping types */
42134+#define CIPSO_V4_MAP_UNKNOWN 0
42135+#define CIPSO_V4_MAP_STD 1
42136+#define CIPSO_V4_MAP_PASS 2
42137+
42138+/* limits */
42139+#define CIPSO_V4_MAX_REM_LVLS 256
42140+#define CIPSO_V4_INV_LVL 0x80000000
42141+#define CIPSO_V4_MAX_LOC_LVLS (CIPSO_V4_INV_LVL - 1)
42142+#define CIPSO_V4_MAX_REM_CATS 65536
42143+#define CIPSO_V4_INV_CAT 0x80000000
42144+#define CIPSO_V4_MAX_LOC_CATS (CIPSO_V4_INV_CAT - 1)
42145+
42146+/*
42147+ * CIPSO DOI definitions
42148+ */
42149+
42150+/* DOI definition struct */
42151+#define CIPSO_V4_TAG_MAXCNT 5
42152+struct cipso_v4_doi {
42153+ u32 doi;
42154+ u32 type;
42155+ union {
42156+ struct cipso_v4_std_map_tbl *std;
42157+ } map;
42158+ u8 tags[CIPSO_V4_TAG_MAXCNT];
42159+
42160+ u32 valid;
42161+ struct list_head list;
42162+ struct rcu_head rcu;
42163+ struct list_head dom_list;
42164+};
42165+
42166+/* Standard CIPSO mapping table */
42167+/* NOTE: the highest order bit (i.e. 0x80000000) is an 'invalid' flag, if the
42168+ * bit is set then consider that value as unspecified, meaning the
42169+ * mapping for that particular level/category is invalid */
42170+struct cipso_v4_std_map_tbl {
42171+ struct {
42172+ u32 *cipso;
42173+ u32 *local;
42174+ u32 cipso_size;
42175+ u32 local_size;
42176+ } lvl;
42177+ struct {
42178+ u32 *cipso;
42179+ u32 *local;
42180+ u32 cipso_size;
42181+ u32 local_size;
42182+ } cat;
42183+};
42184+
42185+/*
42186+ * Sysctl Variables
42187+ */
42188+
42189+#ifdef CONFIG_NETLABEL
42190+extern int cipso_v4_cache_enabled;
42191+extern int cipso_v4_cache_bucketsize;
42192+extern int cipso_v4_rbm_optfmt;
42193+extern int cipso_v4_rbm_strictvalid;
42194+#endif
42195+
42196+/*
42197+ * Helper Functions
42198+ */
42199+
42200+#define CIPSO_V4_OPTEXIST(x) (IPCB(x)->opt.cipso != 0)
42201+#define CIPSO_V4_OPTPTR(x) ((x)->nh.raw + IPCB(x)->opt.cipso)
42202+
42203+/*
42204+ * DOI List Functions
42205+ */
42206+
42207+#ifdef CONFIG_NETLABEL
42208+int cipso_v4_doi_add(struct cipso_v4_doi *doi_def);
42209+int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head));
42210+struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
42211+struct sk_buff *cipso_v4_doi_dump_all(size_t headroom);
42212+struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom);
42213+int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain);
42214+int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
42215+ const char *domain);
42216+#else
42217+static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
42218+{
42219+ return -ENOSYS;
42220+}
42221+
42222+static inline int cipso_v4_doi_remove(u32 doi,
42223+ void (*callback) (struct rcu_head * head))
42224+{
42225+ return 0;
42226+}
42227+
42228+static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
42229+{
42230+ return NULL;
42231+}
42232+
42233+static inline struct sk_buff *cipso_v4_doi_dump_all(size_t headroom)
42234+{
42235+ return NULL;
42236+}
42237+
42238+static inline struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom)
42239+{
42240+ return NULL;
42241+}
42242+
42243+static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def,
42244+ const char *domain)
42245+{
42246+ return -ENOSYS;
42247+}
42248+
42249+static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
42250+ const char *domain)
42251+{
42252+ return 0;
42253+}
42254+#endif /* CONFIG_NETLABEL */
42255+
42256+/*
42257+ * Label Mapping Cache Functions
42258+ */
42259+
42260+#ifdef CONFIG_NETLABEL
42261+void cipso_v4_cache_invalidate(void);
42262+int cipso_v4_cache_add(const struct sk_buff *skb,
42263+ const struct netlbl_lsm_secattr *secattr);
42264+#else
42265+static inline void cipso_v4_cache_invalidate(void)
42266+{
42267+ return;
42268+}
42269+
42270+static inline int cipso_v4_cache_add(const struct sk_buff *skb,
42271+ const struct netlbl_lsm_secattr *secattr)
42272+{
42273+ return 0;
42274+}
42275+#endif /* CONFIG_NETLABEL */
42276+
42277+/*
42278+ * Protocol Handling Functions
42279+ */
42280+
42281+#ifdef CONFIG_NETLABEL
42282+void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
42283+int cipso_v4_socket_setattr(const struct socket *sock,
42284+ const struct cipso_v4_doi *doi_def,
42285+ const struct netlbl_lsm_secattr *secattr);
42286+int cipso_v4_socket_getattr(const struct socket *sock,
42287+ struct netlbl_lsm_secattr *secattr);
42288+int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
42289+ struct netlbl_lsm_secattr *secattr);
42290+int cipso_v4_validate(unsigned char **option);
42291+#else
42292+static inline void cipso_v4_error(struct sk_buff *skb,
42293+ int error,
42294+ u32 gateway)
42295+{
42296+ return;
42297+}
42298+
42299+static inline int cipso_v4_socket_setattr(const struct socket *sock,
42300+ const struct cipso_v4_doi *doi_def,
42301+ const struct netlbl_lsm_secattr *secattr)
42302+{
42303+ return -ENOSYS;
42304+}
42305+
42306+static inline int cipso_v4_socket_getattr(const struct socket *sock,
42307+ struct netlbl_lsm_secattr *secattr)
42308+{
42309+ return -ENOSYS;
42310+}
42311+
42312+static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
42313+ struct netlbl_lsm_secattr *secattr)
42314+{
42315+ return -ENOSYS;
42316+}
42317+
42318+static inline int cipso_v4_validate(unsigned char **option)
42319+{
42320+ return -ENOSYS;
42321+}
42322+#endif /* CONFIG_NETLABEL */
42323+
42324+#endif /* _CIPSO_IPV4_H */
42325diff -Nur linux-2.6.18-rc5/include/net/dn_fib.h linux-2.6.19/include/net/dn_fib.h
42326--- linux-2.6.18-rc5/include/net/dn_fib.h 2006-08-28 05:41:48.000000000 +0200
42327+++ linux-2.6.19/include/net/dn_fib.h 2006-09-22 10:04:57.000000000 +0200
42328@@ -22,7 +22,7 @@
42329 };
42330
42331 struct dn_fib_res {
42332- struct dn_fib_rule *r;
42333+ struct fib_rule *r;
42334 struct dn_fib_info *fi;
42335 unsigned char prefixlen;
42336 unsigned char nh_sel;
42337@@ -94,7 +94,8 @@
42338
42339
42340 struct dn_fib_table {
42341- int n;
42342+ struct hlist_node hlist;
42343+ u32 n;
42344
42345 int (*insert)(struct dn_fib_table *t, struct rtmsg *r,
42346 struct dn_kern_rta *rta, struct nlmsghdr *n,
42347@@ -130,14 +131,11 @@
42348 extern void dn_fib_flush(void);
42349 extern void dn_fib_select_multipath(const struct flowi *fl,
42350 struct dn_fib_res *res);
42351-extern int dn_fib_sync_down(__le16 local, struct net_device *dev,
42352- int force);
42353-extern int dn_fib_sync_up(struct net_device *dev);
42354
42355 /*
42356 * dn_tables.c
42357 */
42358-extern struct dn_fib_table *dn_fib_get_table(int n, int creat);
42359+extern struct dn_fib_table *dn_fib_get_table(u32 n, int creat);
42360 extern struct dn_fib_table *dn_fib_empty_table(void);
42361 extern void dn_fib_table_init(void);
42362 extern void dn_fib_table_cleanup(void);
42363@@ -147,10 +145,8 @@
42364 */
42365 extern void dn_fib_rules_init(void);
42366 extern void dn_fib_rules_cleanup(void);
42367-extern void dn_fib_rule_put(struct dn_fib_rule *);
42368-extern __le16 dn_fib_rules_policy(__le16 saddr, struct dn_fib_res *res, unsigned *flags);
42369 extern unsigned dnet_addr_type(__le16 addr);
42370-extern int dn_fib_lookup(const struct flowi *fl, struct dn_fib_res *res);
42371+extern int dn_fib_lookup(struct flowi *fl, struct dn_fib_res *res);
42372
42373 /*
42374 * rtnetlink interface
42375@@ -176,11 +172,9 @@
42376 if (res->fi)
42377 dn_fib_info_put(res->fi);
42378 if (res->r)
42379- dn_fib_rule_put(res->r);
42380+ fib_rule_put(res->r);
42381 }
42382
42383-extern struct dn_fib_table *dn_fib_tables[];
42384-
42385 #else /* Endnode */
42386
42387 #define dn_fib_init() do { } while(0)
42388diff -Nur linux-2.6.18-rc5/include/net/dst.h linux-2.6.19/include/net/dst.h
42389--- linux-2.6.18-rc5/include/net/dst.h 2006-08-28 05:41:48.000000000 +0200
42390+++ linux-2.6.19/include/net/dst.h 2006-09-22 10:04:57.000000000 +0200
42391@@ -54,6 +54,7 @@
42392 unsigned long expires;
42393
42394 unsigned short header_len; /* more space at head required */
42395+ unsigned short nfheader_len; /* more non-fragment space at head required */
42396 unsigned short trailer_len; /* space to reserve at tail */
42397
42398 u32 metrics[RTAX_MAX];
42399diff -Nur linux-2.6.18-rc5/include/net/esp.h linux-2.6.19/include/net/esp.h
42400--- linux-2.6.18-rc5/include/net/esp.h 2006-08-28 05:41:48.000000000 +0200
42401+++ linux-2.6.19/include/net/esp.h 2006-09-22 10:04:57.000000000 +0200
42402@@ -14,13 +14,14 @@
42403 struct {
42404 u8 *key; /* Key */
42405 int key_len; /* Key length */
42406- u8 *ivec; /* ivec buffer */
42407+ int padlen; /* 0..255 */
42408 /* ivlen is offset from enc_data, where encrypted data start.
42409 * It is logically different of crypto_tfm_alg_ivsize(tfm).
42410 * We assume that it is either zero (no ivec), or
42411 * >= crypto_tfm_alg_ivsize(tfm). */
42412 int ivlen;
42413- int padlen; /* 0..255 */
42414+ int ivinitted;
42415+ u8 *ivec; /* ivec buffer */
42416 struct crypto_tfm *tfm; /* crypto handle */
42417 } conf;
42418
42419diff -Nur linux-2.6.18-rc5/include/net/fib_rules.h linux-2.6.19/include/net/fib_rules.h
42420--- linux-2.6.18-rc5/include/net/fib_rules.h 1970-01-01 01:00:00.000000000 +0100
42421+++ linux-2.6.19/include/net/fib_rules.h 2006-09-22 10:04:57.000000000 +0200
42422@@ -0,0 +1,97 @@
42423+#ifndef __NET_FIB_RULES_H
42424+#define __NET_FIB_RULES_H
42425+
42426+#include <linux/types.h>
42427+#include <linux/netdevice.h>
42428+#include <linux/fib_rules.h>
42429+#include <net/flow.h>
42430+#include <net/netlink.h>
42431+
42432+struct fib_rule
42433+{
42434+ struct list_head list;
42435+ atomic_t refcnt;
42436+ int ifindex;
42437+ char ifname[IFNAMSIZ];
42438+ u32 pref;
42439+ u32 flags;
42440+ u32 table;
42441+ u8 action;
42442+ struct rcu_head rcu;
42443+};
42444+
42445+struct fib_lookup_arg
42446+{
42447+ void *lookup_ptr;
42448+ void *result;
42449+ struct fib_rule *rule;
42450+};
42451+
42452+struct fib_rules_ops
42453+{
42454+ int family;
42455+ struct list_head list;
42456+ int rule_size;
42457+
42458+ int (*action)(struct fib_rule *,
42459+ struct flowi *, int,
42460+ struct fib_lookup_arg *);
42461+ int (*match)(struct fib_rule *,
42462+ struct flowi *, int);
42463+ int (*configure)(struct fib_rule *,
42464+ struct sk_buff *,
42465+ struct nlmsghdr *,
42466+ struct fib_rule_hdr *,
42467+ struct nlattr **);
42468+ int (*compare)(struct fib_rule *,
42469+ struct fib_rule_hdr *,
42470+ struct nlattr **);
42471+ int (*fill)(struct fib_rule *, struct sk_buff *,
42472+ struct nlmsghdr *,
42473+ struct fib_rule_hdr *);
42474+ u32 (*default_pref)(void);
42475+
42476+ int nlgroup;
42477+ struct nla_policy *policy;
42478+ struct list_head *rules_list;
42479+ struct module *owner;
42480+};
42481+
42482+static inline void fib_rule_get(struct fib_rule *rule)
42483+{
42484+ atomic_inc(&rule->refcnt);
42485+}
42486+
42487+static inline void fib_rule_put_rcu(struct rcu_head *head)
42488+{
42489+ struct fib_rule *rule = container_of(head, struct fib_rule, rcu);
42490+ kfree(rule);
42491+}
42492+
42493+static inline void fib_rule_put(struct fib_rule *rule)
42494+{
42495+ if (atomic_dec_and_test(&rule->refcnt))
42496+ call_rcu(&rule->rcu, fib_rule_put_rcu);
42497+}
42498+
42499+static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
42500+{
42501+ if (nla[FRA_TABLE])
42502+ return nla_get_u32(nla[FRA_TABLE]);
42503+ return frh->table;
42504+}
42505+
42506+extern int fib_rules_register(struct fib_rules_ops *);
42507+extern int fib_rules_unregister(struct fib_rules_ops *);
42508+
42509+extern int fib_rules_lookup(struct fib_rules_ops *,
42510+ struct flowi *, int flags,
42511+ struct fib_lookup_arg *);
42512+
42513+extern int fib_nl_newrule(struct sk_buff *,
42514+ struct nlmsghdr *, void *);
42515+extern int fib_nl_delrule(struct sk_buff *,
42516+ struct nlmsghdr *, void *);
42517+extern int fib_rules_dump(struct sk_buff *,
42518+ struct netlink_callback *, int);
42519+#endif
42520diff -Nur linux-2.6.18-rc5/include/net/flow.h linux-2.6.19/include/net/flow.h
42521--- linux-2.6.18-rc5/include/net/flow.h 2006-08-28 05:41:48.000000000 +0200
42522+++ linux-2.6.19/include/net/flow.h 2006-09-22 10:04:57.000000000 +0200
42523@@ -26,6 +26,7 @@
42524 struct {
42525 struct in6_addr daddr;
42526 struct in6_addr saddr;
42527+ __u32 fwmark;
42528 __u32 flowlabel;
42529 } ip6_u;
42530
42531@@ -42,6 +43,7 @@
42532 #define fld_scope nl_u.dn_u.scope
42533 #define fl6_dst nl_u.ip6_u.daddr
42534 #define fl6_src nl_u.ip6_u.saddr
42535+#define fl6_fwmark nl_u.ip6_u.fwmark
42536 #define fl6_flowlabel nl_u.ip6_u.flowlabel
42537 #define fl4_dst nl_u.ip4_u.daddr
42538 #define fl4_src nl_u.ip4_u.saddr
42539@@ -72,12 +74,22 @@
42540 } dnports;
42541
42542 __u32 spi;
42543+
42544+#ifdef CONFIG_IPV6_MIP6
42545+ struct {
42546+ __u8 type;
42547+ } mht;
42548+#endif
42549 } uli_u;
42550 #define fl_ip_sport uli_u.ports.sport
42551 #define fl_ip_dport uli_u.ports.dport
42552 #define fl_icmp_type uli_u.icmpt.type
42553 #define fl_icmp_code uli_u.icmpt.code
42554 #define fl_ipsec_spi uli_u.spi
42555+#ifdef CONFIG_IPV6_MIP6
42556+#define fl_mh_type uli_u.mht.type
42557+#endif
42558+ __u32 secid; /* used by xfrm; see secid.txt */
42559 } __attribute__((__aligned__(BITS_PER_LONG/8)));
42560
42561 #define FLOW_DIR_IN 0
42562@@ -85,10 +97,10 @@
42563 #define FLOW_DIR_FWD 2
42564
42565 struct sock;
42566-typedef void (*flow_resolve_t)(struct flowi *key, u32 sk_sid, u16 family, u8 dir,
42567+typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
42568 void **objp, atomic_t **obj_refp);
42569
42570-extern void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir,
42571+extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
42572 flow_resolve_t resolver);
42573 extern void flow_cache_flush(void);
42574 extern atomic_t flow_cache_genid;
42575diff -Nur linux-2.6.18-rc5/include/net/genetlink.h linux-2.6.19/include/net/genetlink.h
42576--- linux-2.6.18-rc5/include/net/genetlink.h 2006-08-28 05:41:48.000000000 +0200
42577+++ linux-2.6.19/include/net/genetlink.h 2006-09-22 10:04:57.000000000 +0200
42578@@ -27,8 +27,6 @@
42579 struct list_head family_list; /* private */
42580 };
42581
42582-#define GENL_ADMIN_PERM 0x01
42583-
42584 /**
42585 * struct genl_info - receiving information
42586 * @snd_seq: sending sequence number
42587@@ -133,11 +131,12 @@
42588 * @skb: netlink message as socket buffer
42589 * @pid: own netlink pid to avoid sending to yourself
42590 * @group: multicast group id
42591+ * @flags: allocation flags
42592 */
42593 static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid,
42594- unsigned int group)
42595+ unsigned int group, gfp_t flags)
42596 {
42597- return nlmsg_multicast(genl_sock, skb, pid, group);
42598+ return nlmsg_multicast(genl_sock, skb, pid, group, flags);
42599 }
42600
42601 /**
42602diff -Nur linux-2.6.18-rc5/include/net/inet_connection_sock.h linux-2.6.19/include/net/inet_connection_sock.h
42603--- linux-2.6.18-rc5/include/net/inet_connection_sock.h 2006-08-28 05:41:48.000000000 +0200
42604+++ linux-2.6.19/include/net/inet_connection_sock.h 2006-09-22 10:04:57.000000000 +0200
42605@@ -147,7 +147,8 @@
42606 enum inet_csk_ack_state_t {
42607 ICSK_ACK_SCHED = 1,
42608 ICSK_ACK_TIMER = 2,
42609- ICSK_ACK_PUSHED = 4
42610+ ICSK_ACK_PUSHED = 4,
42611+ ICSK_ACK_PUSHED2 = 8
42612 };
42613
42614 extern void inet_csk_init_xmit_timers(struct sock *sk,
42615diff -Nur linux-2.6.18-rc5/include/net/inet_hashtables.h linux-2.6.19/include/net/inet_hashtables.h
42616--- linux-2.6.18-rc5/include/net/inet_hashtables.h 2006-08-28 05:41:48.000000000 +0200
42617+++ linux-2.6.19/include/net/inet_hashtables.h 2006-09-22 10:04:57.000000000 +0200
42618@@ -271,38 +271,15 @@
42619 return ((struct rtable *)skb->dst)->rt_iif;
42620 }
42621
42622-extern struct sock *__inet_lookup_listener(const struct hlist_head *head,
42623+extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
42624 const u32 daddr,
42625 const unsigned short hnum,
42626 const int dif);
42627
42628-/* Optimize the common listener case. */
42629-static inline struct sock *
42630- inet_lookup_listener(struct inet_hashinfo *hashinfo,
42631- const u32 daddr,
42632- const unsigned short hnum, const int dif)
42633+static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo,
42634+ u32 daddr, u16 dport, int dif)
42635 {
42636- struct sock *sk = NULL;
42637- const struct hlist_head *head;
42638-
42639- read_lock(&hashinfo->lhash_lock);
42640- head = &hashinfo->listening_hash[inet_lhashfn(hnum)];
42641- if (!hlist_empty(head)) {
42642- const struct inet_sock *inet = inet_sk((sk = __sk_head(head)));
42643-
42644- if (inet->num == hnum && !sk->sk_node.next &&
42645- (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
42646- (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
42647- !sk->sk_bound_dev_if)
42648- goto sherry_cache;
42649- sk = __inet_lookup_listener(head, daddr, hnum, dif);
42650- }
42651- if (sk) {
42652-sherry_cache:
42653- sock_hold(sk);
42654- }
42655- read_unlock(&hashinfo->lhash_lock);
42656- return sk;
42657+ return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif);
42658 }
42659
42660 /* Socket demux engine toys. */
42661@@ -391,14 +368,25 @@
42662 goto out;
42663 }
42664
42665+static inline struct sock *
42666+ inet_lookup_established(struct inet_hashinfo *hashinfo,
42667+ const u32 saddr, const u16 sport,
42668+ const u32 daddr, const u16 dport,
42669+ const int dif)
42670+{
42671+ return __inet_lookup_established(hashinfo, saddr, sport, daddr,
42672+ ntohs(dport), dif);
42673+}
42674+
42675 static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo,
42676 const u32 saddr, const u16 sport,
42677- const u32 daddr, const u16 hnum,
42678+ const u32 daddr, const u16 dport,
42679 const int dif)
42680 {
42681+ u16 hnum = ntohs(dport);
42682 struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr,
42683 hnum, dif);
42684- return sk ? : inet_lookup_listener(hashinfo, daddr, hnum, dif);
42685+ return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif);
42686 }
42687
42688 static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
42689@@ -409,7 +397,7 @@
42690 struct sock *sk;
42691
42692 local_bh_disable();
42693- sk = __inet_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif);
42694+ sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif);
42695 local_bh_enable();
42696
42697 return sk;
42698diff -Nur linux-2.6.18-rc5/include/net/inet_sock.h linux-2.6.19/include/net/inet_sock.h
42699--- linux-2.6.18-rc5/include/net/inet_sock.h 2006-08-28 05:41:48.000000000 +0200
42700+++ linux-2.6.19/include/net/inet_sock.h 2006-09-22 10:04:57.000000000 +0200
42701@@ -27,7 +27,6 @@
42702 /** struct ip_options - IP Options
42703 *
42704 * @faddr - Saved first hop address
42705- * @is_setbyuser - Set by setsockopt?
42706 * @is_data - Options in __data, rather than skb
42707 * @is_strictroute - Strict source route
42708 * @srr_is_hit - Packet destination addr was our one
42709@@ -42,8 +41,7 @@
42710 unsigned char srr;
42711 unsigned char rr;
42712 unsigned char ts;
42713- unsigned char is_setbyuser:1,
42714- is_data:1,
42715+ unsigned char is_data:1,
42716 is_strictroute:1,
42717 srr_is_hit:1,
42718 is_changed:1,
42719@@ -51,7 +49,7 @@
42720 ts_needtime:1,
42721 ts_needaddr:1;
42722 unsigned char router_alert;
42723- unsigned char __pad1;
42724+ unsigned char cipso;
42725 unsigned char __pad2;
42726 unsigned char __data[0];
42727 };
42728diff -Nur linux-2.6.18-rc5/include/net/ip6_fib.h linux-2.6.19/include/net/ip6_fib.h
42729--- linux-2.6.18-rc5/include/net/ip6_fib.h 2006-08-28 05:41:48.000000000 +0200
42730+++ linux-2.6.19/include/net/ip6_fib.h 2006-09-22 10:04:57.000000000 +0200
42731@@ -16,14 +16,35 @@
42732 #ifdef __KERNEL__
42733
42734 #include <linux/ipv6_route.h>
42735-
42736-#include <net/dst.h>
42737-#include <net/flow.h>
42738 #include <linux/rtnetlink.h>
42739 #include <linux/spinlock.h>
42740+#include <net/dst.h>
42741+#include <net/flow.h>
42742+#include <net/netlink.h>
42743
42744 struct rt6_info;
42745
42746+struct fib6_config
42747+{
42748+ u32 fc_table;
42749+ u32 fc_metric;
42750+ int fc_dst_len;
42751+ int fc_src_len;
42752+ int fc_ifindex;
42753+ u32 fc_flags;
42754+ u32 fc_protocol;
42755+
42756+ struct in6_addr fc_dst;
42757+ struct in6_addr fc_src;
42758+ struct in6_addr fc_gateway;
42759+
42760+ unsigned long fc_expires;
42761+ struct nlattr *fc_mx;
42762+ int fc_mx_len;
42763+
42764+ struct nl_info fc_nlinfo;
42765+};
42766+
42767 struct fib6_node
42768 {
42769 struct fib6_node *parent;
42770@@ -39,6 +60,11 @@
42771 __u32 fn_sernum;
42772 };
42773
42774+#ifndef CONFIG_IPV6_SUBTREES
42775+#define FIB6_SUBTREE(fn) NULL
42776+#else
42777+#define FIB6_SUBTREE(fn) ((fn)->subtree)
42778+#endif
42779
42780 /*
42781 * routing information
42782@@ -51,6 +77,8 @@
42783 int plen;
42784 };
42785
42786+struct fib6_table;
42787+
42788 struct rt6_info
42789 {
42790 union {
42791@@ -71,6 +99,7 @@
42792 u32 rt6i_flags;
42793 u32 rt6i_metric;
42794 atomic_t rt6i_ref;
42795+ struct fib6_table *rt6i_table;
42796
42797 struct rt6key rt6i_dst;
42798 struct rt6key rt6i_src;
42799@@ -89,28 +118,6 @@
42800 void *args;
42801 };
42802
42803-extern struct fib6_walker_t fib6_walker_list;
42804-extern rwlock_t fib6_walker_lock;
42805-
42806-static inline void fib6_walker_link(struct fib6_walker_t *w)
42807-{
42808- write_lock_bh(&fib6_walker_lock);
42809- w->next = fib6_walker_list.next;
42810- w->prev = &fib6_walker_list;
42811- w->next->prev = w;
42812- w->prev->next = w;
42813- write_unlock_bh(&fib6_walker_lock);
42814-}
42815-
42816-static inline void fib6_walker_unlink(struct fib6_walker_t *w)
42817-{
42818- write_lock_bh(&fib6_walker_lock);
42819- w->next->prev = w->prev;
42820- w->prev->next = w->next;
42821- w->prev = w->next = w;
42822- write_unlock_bh(&fib6_walker_lock);
42823-}
42824-
42825 struct rt6_statistics {
42826 __u32 fib_nodes;
42827 __u32 fib_route_nodes;
42828@@ -143,12 +150,41 @@
42829
42830 typedef void (*f_pnode)(struct fib6_node *fn, void *);
42831
42832-extern struct fib6_node ip6_routing_table;
42833+struct fib6_table {
42834+ struct hlist_node tb6_hlist;
42835+ u32 tb6_id;
42836+ rwlock_t tb6_lock;
42837+ struct fib6_node tb6_root;
42838+};
42839+
42840+#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC
42841+#define RT6_TABLE_MAIN RT_TABLE_MAIN
42842+#define RT6_TABLE_DFLT RT6_TABLE_MAIN
42843+#define RT6_TABLE_INFO RT6_TABLE_MAIN
42844+#define RT6_TABLE_PREFIX RT6_TABLE_MAIN
42845+
42846+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
42847+#define FIB6_TABLE_MIN 1
42848+#define FIB6_TABLE_MAX RT_TABLE_MAX
42849+#define RT6_TABLE_LOCAL RT_TABLE_LOCAL
42850+#else
42851+#define FIB6_TABLE_MIN RT_TABLE_MAIN
42852+#define FIB6_TABLE_MAX FIB6_TABLE_MIN
42853+#define RT6_TABLE_LOCAL RT6_TABLE_MAIN
42854+#endif
42855+
42856+typedef struct rt6_info *(*pol_lookup_t)(struct fib6_table *,
42857+ struct flowi *, int);
42858
42859 /*
42860 * exported functions
42861 */
42862
42863+extern struct fib6_table * fib6_get_table(u32 id);
42864+extern struct fib6_table * fib6_new_table(u32 id);
42865+extern struct dst_entry * fib6_rule_lookup(struct flowi *fl, int flags,
42866+ pol_lookup_t lookup);
42867+
42868 extern struct fib6_node *fib6_lookup(struct fib6_node *root,
42869 struct in6_addr *daddr,
42870 struct in6_addr *saddr);
42871@@ -157,32 +193,29 @@
42872 struct in6_addr *daddr, int dst_len,
42873 struct in6_addr *saddr, int src_len);
42874
42875-extern void fib6_clean_tree(struct fib6_node *root,
42876- int (*func)(struct rt6_info *, void *arg),
42877- int prune, void *arg);
42878-
42879-extern int fib6_walk(struct fib6_walker_t *w);
42880-extern int fib6_walk_continue(struct fib6_walker_t *w);
42881+extern void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
42882+ int prune, void *arg);
42883
42884 extern int fib6_add(struct fib6_node *root,
42885 struct rt6_info *rt,
42886- struct nlmsghdr *nlh,
42887- void *rtattr,
42888- struct netlink_skb_parms *req);
42889+ struct nl_info *info);
42890
42891 extern int fib6_del(struct rt6_info *rt,
42892- struct nlmsghdr *nlh,
42893- void *rtattr,
42894- struct netlink_skb_parms *req);
42895+ struct nl_info *info);
42896
42897 extern void inet6_rt_notify(int event, struct rt6_info *rt,
42898- struct nlmsghdr *nlh,
42899- struct netlink_skb_parms *req);
42900+ struct nl_info *info);
42901
42902 extern void fib6_run_gc(unsigned long dummy);
42903
42904 extern void fib6_gc_cleanup(void);
42905
42906 extern void fib6_init(void);
42907+
42908+extern void fib6_rules_init(void);
42909+extern void fib6_rules_cleanup(void);
42910+extern int fib6_rules_dump(struct sk_buff *,
42911+ struct netlink_callback *);
42912+
42913 #endif
42914 #endif
42915diff -Nur linux-2.6.18-rc5/include/net/ip6_route.h linux-2.6.19/include/net/ip6_route.h
42916--- linux-2.6.18-rc5/include/net/ip6_route.h 2006-08-28 05:41:48.000000000 +0200
42917+++ linux-2.6.19/include/net/ip6_route.h 2006-09-22 10:04:57.000000000 +0200
42918@@ -32,6 +32,10 @@
42919 #include <linux/ip.h>
42920 #include <linux/ipv6.h>
42921
42922+#define RT6_LOOKUP_F_IFACE 0x1
42923+#define RT6_LOOKUP_F_REACHABLE 0x2
42924+#define RT6_LOOKUP_F_HAS_SADDR 0x4
42925+
42926 struct pol_chain {
42927 int type;
42928 int priority;
42929@@ -41,6 +45,11 @@
42930
42931 extern struct rt6_info ip6_null_entry;
42932
42933+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
42934+extern struct rt6_info ip6_prohibit_entry;
42935+extern struct rt6_info ip6_blk_hole_entry;
42936+#endif
42937+
42938 extern int ip6_rt_gc_interval;
42939
42940 extern void ip6_route_input(struct sk_buff *skb);
42941@@ -55,18 +64,9 @@
42942
42943 extern int ipv6_route_ioctl(unsigned int cmd, void __user *arg);
42944
42945-extern int ip6_route_add(struct in6_rtmsg *rtmsg,
42946- struct nlmsghdr *,
42947- void *rtattr,
42948- struct netlink_skb_parms *req);
42949-extern int ip6_ins_rt(struct rt6_info *,
42950- struct nlmsghdr *,
42951- void *rtattr,
42952- struct netlink_skb_parms *req);
42953-extern int ip6_del_rt(struct rt6_info *,
42954- struct nlmsghdr *,
42955- void *rtattr,
42956- struct netlink_skb_parms *req);
42957+extern int ip6_route_add(struct fib6_config *cfg);
42958+extern int ip6_ins_rt(struct rt6_info *);
42959+extern int ip6_del_rt(struct rt6_info *);
42960
42961 extern int ip6_rt_addr_add(struct in6_addr *addr,
42962 struct net_device *dev,
42963@@ -114,6 +114,7 @@
42964 struct in6_addr *gwaddr);
42965
42966 extern void rt6_redirect(struct in6_addr *dest,
42967+ struct in6_addr *src,
42968 struct in6_addr *saddr,
42969 struct neighbour *neigh,
42970 u8 *lladdr,
42971@@ -131,6 +132,13 @@
42972 extern int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
42973 extern int inet6_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
42974
42975+struct rt6_rtnl_dump_arg
42976+{
42977+ struct sk_buff *skb;
42978+ struct netlink_callback *cb;
42979+};
42980+
42981+extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
42982 extern void rt6_ifdown(struct net_device *dev);
42983 extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
42984
42985@@ -140,21 +148,24 @@
42986 * Store a destination cache entry in a socket
42987 */
42988 static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst,
42989- struct in6_addr *daddr)
42990+ struct in6_addr *daddr, struct in6_addr *saddr)
42991 {
42992 struct ipv6_pinfo *np = inet6_sk(sk);
42993 struct rt6_info *rt = (struct rt6_info *) dst;
42994
42995 sk_setup_caps(sk, dst);
42996 np->daddr_cache = daddr;
42997+#ifdef CONFIG_IPV6_SUBTREES
42998+ np->saddr_cache = saddr;
42999+#endif
43000 np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
43001 }
43002
43003 static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
43004- struct in6_addr *daddr)
43005+ struct in6_addr *daddr, struct in6_addr *saddr)
43006 {
43007 write_lock(&sk->sk_dst_lock);
43008- __ip6_dst_store(sk, dst, daddr);
43009+ __ip6_dst_store(sk, dst, daddr, saddr);
43010 write_unlock(&sk->sk_dst_lock);
43011 }
43012
43013diff -Nur linux-2.6.18-rc5/include/net/ip_fib.h linux-2.6.19/include/net/ip_fib.h
43014--- linux-2.6.18-rc5/include/net/ip_fib.h 2006-08-28 05:41:48.000000000 +0200
43015+++ linux-2.6.19/include/net/ip_fib.h 2006-09-22 10:04:57.000000000 +0200
43016@@ -18,26 +18,34 @@
43017
43018 #include <net/flow.h>
43019 #include <linux/seq_file.h>
43020+#include <net/fib_rules.h>
43021
43022-/* WARNING: The ordering of these elements must match ordering
43023- * of RTA_* rtnetlink attribute numbers.
43024- */
43025-struct kern_rta {
43026- void *rta_dst;
43027- void *rta_src;
43028- int *rta_iif;
43029- int *rta_oif;
43030- void *rta_gw;
43031- u32 *rta_priority;
43032- void *rta_prefsrc;
43033- struct rtattr *rta_mx;
43034- struct rtattr *rta_mp;
43035- unsigned char *rta_protoinfo;
43036- u32 *rta_flow;
43037- struct rta_cacheinfo *rta_ci;
43038- struct rta_session *rta_sess;
43039- u32 *rta_mp_alg;
43040-};
43041+struct fib_config {
43042+ u8 fc_family;
43043+ u8 fc_dst_len;
43044+ u8 fc_src_len;
43045+ u8 fc_tos;
43046+ u8 fc_protocol;
43047+ u8 fc_scope;
43048+ u8 fc_type;
43049+ /* 1 byte unused */
43050+ u32 fc_table;
43051+ u32 fc_dst;
43052+ u32 fc_src;
43053+ u32 fc_gw;
43054+ int fc_oif;
43055+ u32 fc_flags;
43056+ u32 fc_priority;
43057+ u32 fc_prefsrc;
43058+ struct nlattr *fc_mx;
43059+ struct rtnexthop *fc_mp;
43060+ int fc_mx_len;
43061+ int fc_mp_len;
43062+ u32 fc_flow;
43063+ u32 fc_mp_alg;
43064+ u32 fc_nlflags;
43065+ struct nl_info fc_nlinfo;
43066+ };
43067
43068 struct fib_info;
43069
43070@@ -149,15 +157,12 @@
43071 #endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */
43072
43073 struct fib_table {
43074- unsigned char tb_id;
43075+ struct hlist_node tb_hlist;
43076+ u32 tb_id;
43077 unsigned tb_stamp;
43078 int (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);
43079- int (*tb_insert)(struct fib_table *table, struct rtmsg *r,
43080- struct kern_rta *rta, struct nlmsghdr *n,
43081- struct netlink_skb_parms *req);
43082- int (*tb_delete)(struct fib_table *table, struct rtmsg *r,
43083- struct kern_rta *rta, struct nlmsghdr *n,
43084- struct netlink_skb_parms *req);
43085+ int (*tb_insert)(struct fib_table *, struct fib_config *);
43086+ int (*tb_delete)(struct fib_table *, struct fib_config *);
43087 int (*tb_dump)(struct fib_table *table, struct sk_buff *skb,
43088 struct netlink_callback *cb);
43089 int (*tb_flush)(struct fib_table *table);
43090@@ -172,14 +177,14 @@
43091 extern struct fib_table *ip_fib_local_table;
43092 extern struct fib_table *ip_fib_main_table;
43093
43094-static inline struct fib_table *fib_get_table(int id)
43095+static inline struct fib_table *fib_get_table(u32 id)
43096 {
43097 if (id != RT_TABLE_LOCAL)
43098 return ip_fib_main_table;
43099 return ip_fib_local_table;
43100 }
43101
43102-static inline struct fib_table *fib_new_table(int id)
43103+static inline struct fib_table *fib_new_table(u32 id)
43104 {
43105 return fib_get_table(id);
43106 }
43107@@ -199,35 +204,19 @@
43108 }
43109
43110 #else /* CONFIG_IP_MULTIPLE_TABLES */
43111-#define ip_fib_local_table (fib_tables[RT_TABLE_LOCAL])
43112-#define ip_fib_main_table (fib_tables[RT_TABLE_MAIN])
43113-
43114-extern struct fib_table * fib_tables[RT_TABLE_MAX+1];
43115-extern int fib_lookup(const struct flowi *flp, struct fib_result *res);
43116-extern struct fib_table *__fib_new_table(int id);
43117-extern void fib_rule_put(struct fib_rule *r);
43118-
43119-static inline struct fib_table *fib_get_table(int id)
43120-{
43121- if (id == 0)
43122- id = RT_TABLE_MAIN;
43123-
43124- return fib_tables[id];
43125-}
43126-
43127-static inline struct fib_table *fib_new_table(int id)
43128-{
43129- if (id == 0)
43130- id = RT_TABLE_MAIN;
43131+#define ip_fib_local_table fib_get_table(RT_TABLE_LOCAL)
43132+#define ip_fib_main_table fib_get_table(RT_TABLE_MAIN)
43133
43134- return fib_tables[id] ? : __fib_new_table(id);
43135-}
43136+extern int fib_lookup(struct flowi *flp, struct fib_result *res);
43137
43138+extern struct fib_table *fib_new_table(u32 id);
43139+extern struct fib_table *fib_get_table(u32 id);
43140 extern void fib_select_default(const struct flowi *flp, struct fib_result *res);
43141
43142 #endif /* CONFIG_IP_MULTIPLE_TABLES */
43143
43144 /* Exported by fib_frontend.c */
43145+extern struct nla_policy rtm_ipv4_policy[];
43146 extern void ip_fib_init(void);
43147 extern int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
43148 extern int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
43149@@ -243,23 +232,20 @@
43150 extern int ip_fib_check_default(u32 gw, struct net_device *dev);
43151 extern int fib_sync_down(u32 local, struct net_device *dev, int force);
43152 extern int fib_sync_up(struct net_device *dev);
43153-extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
43154- struct kern_rta *rta, struct rtentry *r);
43155 extern u32 __fib_res_prefsrc(struct fib_result *res);
43156
43157 /* Exported by fib_hash.c */
43158-extern struct fib_table *fib_hash_init(int id);
43159+extern struct fib_table *fib_hash_init(u32 id);
43160
43161 #ifdef CONFIG_IP_MULTIPLE_TABLES
43162-/* Exported by fib_rules.c */
43163+extern int fib4_rules_dump(struct sk_buff *skb, struct netlink_callback *cb);
43164+
43165+extern void __init fib4_rules_init(void);
43166
43167-extern int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
43168-extern int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
43169-extern int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb);
43170 #ifdef CONFIG_NET_CLS_ROUTE
43171 extern u32 fib_rules_tclass(struct fib_result *res);
43172 #endif
43173-extern void fib_rules_init(void);
43174+
43175 #endif
43176
43177 static inline void fib_combine_itag(u32 *itag, struct fib_result *res)
43178diff -Nur linux-2.6.18-rc5/include/net/ipv6.h linux-2.6.19/include/net/ipv6.h
43179--- linux-2.6.18-rc5/include/net/ipv6.h 2006-08-28 05:41:48.000000000 +0200
43180+++ linux-2.6.19/include/net/ipv6.h 2006-09-22 10:04:57.000000000 +0200
43181@@ -40,6 +40,7 @@
43182 #define NEXTHDR_ICMP 58 /* ICMP for IPv6. */
43183 #define NEXTHDR_NONE 59 /* No next header */
43184 #define NEXTHDR_DEST 60 /* Destination options header. */
43185+#define NEXTHDR_MOBILITY 135 /* Mobility header. */
43186
43187 #define NEXTHDR_MAX 255
43188
43189@@ -229,7 +230,7 @@
43190 void (*destructor)(struct sock *));
43191
43192
43193-extern int ipv6_parse_hopopts(struct sk_buff *skb);
43194+extern int ipv6_parse_hopopts(struct sk_buff **skbp);
43195
43196 extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
43197 extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
43198@@ -506,6 +507,8 @@
43199
43200 extern int ipv6_ext_hdr(u8 nexthdr);
43201
43202+extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
43203+
43204 extern struct ipv6_txoptions * ipv6_invert_rthdr(struct sock *sk,
43205 struct ipv6_rt_hdr *hdr);
43206
43207diff -Nur linux-2.6.18-rc5/include/net/mip6.h linux-2.6.19/include/net/mip6.h
43208--- linux-2.6.18-rc5/include/net/mip6.h 1970-01-01 01:00:00.000000000 +0100
43209+++ linux-2.6.19/include/net/mip6.h 2006-09-22 10:04:57.000000000 +0200
43210@@ -0,0 +1,61 @@
43211+/*
43212+ * Copyright (C)2003-2006 Helsinki University of Technology
43213+ * Copyright (C)2003-2006 USAGI/WIDE Project
43214+ *
43215+ * This program is free software; you can redistribute it and/or modify
43216+ * it under the terms of the GNU General Public License as published by
43217+ * the Free Software Foundation; either version 2 of the License, or
43218+ * (at your option) any later version.
43219+ *
43220+ * This program is distributed in the hope that it will be useful,
43221+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
43222+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43223+ * GNU General Public License for more details.
43224+ *
43225+ * You should have received a copy of the GNU General Public License
43226+ * along with this program; if not, write to the Free Software
43227+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43228+ */
43229+/*
43230+ * Authors:
43231+ * Noriaki TAKAMIYA @USAGI
43232+ * Masahide NAKAMURA @USAGI
43233+ * YOSHIFUJI Hideaki @USAGI
43234+ */
43235+#ifndef _NET_MIP6_H
43236+#define _NET_MIP6_H
43237+
43238+#include <linux/skbuff.h>
43239+#include <net/sock.h>
43240+
43241+#define MIP6_OPT_PAD_1 0
43242+#define MIP6_OPT_PAD_N 1
43243+
43244+/*
43245+ * Mobility Header
43246+ */
43247+struct ip6_mh {
43248+ __u8 ip6mh_proto;
43249+ __u8 ip6mh_hdrlen;
43250+ __u8 ip6mh_type;
43251+ __u8 ip6mh_reserved;
43252+ __u16 ip6mh_cksum;
43253+ /* Followed by type specific messages */
43254+ __u8 data[0];
43255+} __attribute__ ((__packed__));
43256+
43257+#define IP6_MH_TYPE_BRR 0 /* Binding Refresh Request */
43258+#define IP6_MH_TYPE_HOTI 1 /* HOTI Message */
43259+#define IP6_MH_TYPE_COTI 2 /* COTI Message */
43260+#define IP6_MH_TYPE_HOT 3 /* HOT Message */
43261+#define IP6_MH_TYPE_COT 4 /* COT Message */
43262+#define IP6_MH_TYPE_BU 5 /* Binding Update */
43263+#define IP6_MH_TYPE_BACK 6 /* Binding ACK */
43264+#define IP6_MH_TYPE_BERROR 7 /* Binding Error */
43265+#define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR
43266+
43267+extern int mip6_init(void);
43268+extern void mip6_fini(void);
43269+extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb);
43270+
43271+#endif
43272diff -Nur linux-2.6.18-rc5/include/net/neighbour.h linux-2.6.19/include/net/neighbour.h
43273--- linux-2.6.18-rc5/include/net/neighbour.h 2006-08-28 05:41:48.000000000 +0200
43274+++ linux-2.6.19/include/net/neighbour.h 2006-09-22 10:04:57.000000000 +0200
43275@@ -1,6 +1,8 @@
43276 #ifndef _NET_NEIGHBOUR_H
43277 #define _NET_NEIGHBOUR_H
43278
43279+#include <linux/neighbour.h>
43280+
43281 /*
43282 * Generic neighbour manipulation
43283 *
43284@@ -14,40 +16,6 @@
43285 * - Add neighbour cache statistics like rtstat
43286 */
43287
43288-/* The following flags & states are exported to user space,
43289- so that they should be moved to include/linux/ directory.
43290- */
43291-
43292-/*
43293- * Neighbor Cache Entry Flags
43294- */
43295-
43296-#define NTF_PROXY 0x08 /* == ATF_PUBL */
43297-#define NTF_ROUTER 0x80
43298-
43299-/*
43300- * Neighbor Cache Entry States.
43301- */
43302-
43303-#define NUD_INCOMPLETE 0x01
43304-#define NUD_REACHABLE 0x02
43305-#define NUD_STALE 0x04
43306-#define NUD_DELAY 0x08
43307-#define NUD_PROBE 0x10
43308-#define NUD_FAILED 0x20
43309-
43310-/* Dummy states */
43311-#define NUD_NOARP 0x40
43312-#define NUD_PERMANENT 0x80
43313-#define NUD_NONE 0x00
43314-
43315-/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
43316- and make no address resolution or NUD.
43317- NUD_PERMANENT is also cannot be deleted by garbage collectors.
43318- */
43319-
43320-#ifdef __KERNEL__
43321-
43322 #include <asm/atomic.h>
43323 #include <linux/netdevice.h>
43324 #include <linux/skbuff.h>
43325@@ -133,7 +101,7 @@
43326 __u8 dead;
43327 atomic_t probes;
43328 rwlock_t lock;
43329- unsigned char ha[(MAX_ADDR_LEN+sizeof(unsigned long)-1)&~(sizeof(unsigned long)-1)];
43330+ unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
43331 struct hh_cache *hh;
43332 atomic_t refcnt;
43333 int (*output)(struct sk_buff *skb);
43334@@ -374,6 +342,3 @@
43335 #define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb)
43336
43337 #endif
43338-#endif
43339-
43340-
43341diff -Nur linux-2.6.18-rc5/include/net/netlabel.h linux-2.6.19/include/net/netlabel.h
43342--- linux-2.6.18-rc5/include/net/netlabel.h 1970-01-01 01:00:00.000000000 +0100
43343+++ linux-2.6.19/include/net/netlabel.h 2006-09-22 10:04:57.000000000 +0200
43344@@ -0,0 +1,292 @@
43345+/*
43346+ * NetLabel System
43347+ *
43348+ * The NetLabel system manages static and dynamic label mappings for network
43349+ * protocols such as CIPSO and RIPSO.
43350+ *
43351+ * Author: Paul Moore <paul.moore@hp.com>
43352+ *
43353+ */
43354+
43355+/*
43356+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
43357+ *
43358+ * This program is free software; you can redistribute it and/or modify
43359+ * it under the terms of the GNU General Public License as published by
43360+ * the Free Software Foundation; either version 2 of the License, or
43361+ * (at your option) any later version.
43362+ *
43363+ * This program is distributed in the hope that it will be useful,
43364+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
43365+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
43366+ * the GNU General Public License for more details.
43367+ *
43368+ * You should have received a copy of the GNU General Public License
43369+ * along with this program; if not, write to the Free Software
43370+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43371+ *
43372+ */
43373+
43374+#ifndef _NETLABEL_H
43375+#define _NETLABEL_H
43376+
43377+#include <linux/types.h>
43378+#include <linux/net.h>
43379+#include <linux/skbuff.h>
43380+#include <net/netlink.h>
43381+
43382+/*
43383+ * NetLabel - A management interface for maintaining network packet label
43384+ * mapping tables for explicit packet labling protocols.
43385+ *
43386+ * Network protocols such as CIPSO and RIPSO require a label translation layer
43387+ * to convert the label on the packet into something meaningful on the host
43388+ * machine. In the current Linux implementation these mapping tables live
43389+ * inside the kernel; NetLabel provides a mechanism for user space applications
43390+ * to manage these mapping tables.
43391+ *
43392+ * NetLabel makes use of the Generic NETLINK mechanism as a transport layer to
43393+ * send messages between kernel and user space. The general format of a
43394+ * NetLabel message is shown below:
43395+ *
43396+ * +-----------------+-------------------+--------- --- -- -
43397+ * | struct nlmsghdr | struct genlmsghdr | payload
43398+ * +-----------------+-------------------+--------- --- -- -
43399+ *
43400+ * The 'nlmsghdr' and 'genlmsghdr' structs should be dealt with like normal.
43401+ * The payload is dependent on the subsystem specified in the
43402+ * 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions
43403+ * should be defined in the corresponding net/netlabel/netlabel_<subsys>.h|c
43404+ * file. All of the fields in the NetLabel payload are NETLINK attributes, the
43405+ * length of each field is the length of the NETLINK attribute payload, see
43406+ * include/net/netlink.h for more information on NETLINK attributes.
43407+ *
43408+ */
43409+
43410+/*
43411+ * NetLabel NETLINK protocol
43412+ */
43413+
43414+#define NETLBL_PROTO_VERSION 1
43415+
43416+/* NetLabel NETLINK types/families */
43417+#define NETLBL_NLTYPE_NONE 0
43418+#define NETLBL_NLTYPE_MGMT 1
43419+#define NETLBL_NLTYPE_MGMT_NAME "NLBL_MGMT"
43420+#define NETLBL_NLTYPE_RIPSO 2
43421+#define NETLBL_NLTYPE_RIPSO_NAME "NLBL_RIPSO"
43422+#define NETLBL_NLTYPE_CIPSOV4 3
43423+#define NETLBL_NLTYPE_CIPSOV4_NAME "NLBL_CIPSOv4"
43424+#define NETLBL_NLTYPE_CIPSOV6 4
43425+#define NETLBL_NLTYPE_CIPSOV6_NAME "NLBL_CIPSOv6"
43426+#define NETLBL_NLTYPE_UNLABELED 5
43427+#define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL"
43428+
43429+/* NetLabel return codes */
43430+#define NETLBL_E_OK 0
43431+
43432+/*
43433+ * Helper functions
43434+ */
43435+
43436+#define NETLBL_LEN_U8 nla_total_size(sizeof(u8))
43437+#define NETLBL_LEN_U16 nla_total_size(sizeof(u16))
43438+#define NETLBL_LEN_U32 nla_total_size(sizeof(u32))
43439+
43440+/**
43441+ * netlbl_netlink_alloc_skb - Allocate a NETLINK message buffer
43442+ * @head: the amount of headroom in bytes
43443+ * @body: the desired size (minus headroom) in bytes
43444+ * @gfp_flags: the alloc flags to pass to alloc_skb()
43445+ *
43446+ * Description:
43447+ * Allocate a NETLINK message buffer based on the sizes given in @head and
43448+ * @body. If @head is greater than zero skb_reserve() is called to reserve
43449+ * @head bytes at the start of the buffer. Returns a valid sk_buff pointer on
43450+ * success, NULL on failure.
43451+ *
43452+ */
43453+static inline struct sk_buff *netlbl_netlink_alloc_skb(size_t head,
43454+ size_t body,
43455+ int gfp_flags)
43456+{
43457+ struct sk_buff *skb;
43458+
43459+ skb = alloc_skb(NLMSG_ALIGN(head + body), gfp_flags);
43460+ if (skb == NULL)
43461+ return NULL;
43462+ if (head > 0) {
43463+ skb_reserve(skb, head);
43464+ if (skb_tailroom(skb) < body) {
43465+ kfree_skb(skb);
43466+ return NULL;
43467+ }
43468+ }
43469+
43470+ return skb;
43471+}
43472+
43473+/*
43474+ * NetLabel - Kernel API for accessing the network packet label mappings.
43475+ *
43476+ * The following functions are provided for use by other kernel modules,
43477+ * specifically kernel LSM modules, to provide a consistent, transparent API
43478+ * for dealing with explicit packet labeling protocols such as CIPSO and
43479+ * RIPSO. The functions defined here are implemented in the
43480+ * net/netlabel/netlabel_kapi.c file.
43481+ *
43482+ */
43483+
43484+/* Domain mapping definition struct */
43485+struct netlbl_dom_map;
43486+
43487+/* Domain mapping operations */
43488+int netlbl_domhsh_remove(const char *domain);
43489+
43490+/* LSM security attributes */
43491+struct netlbl_lsm_cache {
43492+ void (*free) (const void *data);
43493+ void *data;
43494+};
43495+struct netlbl_lsm_secattr {
43496+ char *domain;
43497+
43498+ u32 mls_lvl;
43499+ u32 mls_lvl_vld;
43500+ unsigned char *mls_cat;
43501+ size_t mls_cat_len;
43502+
43503+ struct netlbl_lsm_cache cache;
43504+};
43505+
43506+/*
43507+ * LSM security attribute operations
43508+ */
43509+
43510+
43511+/**
43512+ * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct
43513+ * @secattr: the struct to initialize
43514+ *
43515+ * Description:
43516+ * Initialize an already allocated netlbl_lsm_secattr struct. Returns zero on
43517+ * success, negative values on error.
43518+ *
43519+ */
43520+static inline int netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
43521+{
43522+ memset(secattr, 0, sizeof(*secattr));
43523+ return 0;
43524+}
43525+
43526+/**
43527+ * netlbl_secattr_destroy - Clears a netlbl_lsm_secattr struct
43528+ * @secattr: the struct to clear
43529+ * @clear_cache: cache clear flag
43530+ *
43531+ * Description:
43532+ * Destroys the @secattr struct, including freeing all of the internal buffers.
43533+ * If @clear_cache is true then free the cache fields, otherwise leave them
43534+ * intact. The struct must be reset with a call to netlbl_secattr_init()
43535+ * before reuse.
43536+ *
43537+ */
43538+static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr,
43539+ u32 clear_cache)
43540+{
43541+ if (clear_cache && secattr->cache.data != NULL && secattr->cache.free)
43542+ secattr->cache.free(secattr->cache.data);
43543+ kfree(secattr->domain);
43544+ kfree(secattr->mls_cat);
43545+}
43546+
43547+/**
43548+ * netlbl_secattr_alloc - Allocate and initialize a netlbl_lsm_secattr struct
43549+ * @flags: the memory allocation flags
43550+ *
43551+ * Description:
43552+ * Allocate and initialize a netlbl_lsm_secattr struct. Returns a valid
43553+ * pointer on success, or NULL on failure.
43554+ *
43555+ */
43556+static inline struct netlbl_lsm_secattr *netlbl_secattr_alloc(int flags)
43557+{
43558+ return kzalloc(sizeof(struct netlbl_lsm_secattr), flags);
43559+}
43560+
43561+/**
43562+ * netlbl_secattr_free - Frees a netlbl_lsm_secattr struct
43563+ * @secattr: the struct to free
43564+ * @clear_cache: cache clear flag
43565+ *
43566+ * Description:
43567+ * Frees @secattr including all of the internal buffers. If @clear_cache is
43568+ * true then free the cache fields, otherwise leave them intact.
43569+ *
43570+ */
43571+static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr,
43572+ u32 clear_cache)
43573+{
43574+ netlbl_secattr_destroy(secattr, clear_cache);
43575+ kfree(secattr);
43576+}
43577+
43578+/*
43579+ * LSM protocol operations
43580+ */
43581+
43582+#ifdef CONFIG_NETLABEL
43583+int netlbl_socket_setattr(const struct socket *sock,
43584+ const struct netlbl_lsm_secattr *secattr);
43585+int netlbl_socket_getattr(const struct socket *sock,
43586+ struct netlbl_lsm_secattr *secattr);
43587+int netlbl_skbuff_getattr(const struct sk_buff *skb,
43588+ struct netlbl_lsm_secattr *secattr);
43589+void netlbl_skbuff_err(struct sk_buff *skb, int error);
43590+#else
43591+static inline int netlbl_socket_setattr(const struct socket *sock,
43592+ const struct netlbl_lsm_secattr *secattr)
43593+{
43594+ return -ENOSYS;
43595+}
43596+
43597+static inline int netlbl_socket_getattr(const struct socket *sock,
43598+ struct netlbl_lsm_secattr *secattr)
43599+{
43600+ return -ENOSYS;
43601+}
43602+
43603+static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
43604+ struct netlbl_lsm_secattr *secattr)
43605+{
43606+ return -ENOSYS;
43607+}
43608+
43609+static inline void netlbl_skbuff_err(struct sk_buff *skb, int error)
43610+{
43611+ return;
43612+}
43613+#endif /* CONFIG_NETLABEL */
43614+
43615+/*
43616+ * LSM label mapping cache operations
43617+ */
43618+
43619+#ifdef CONFIG_NETLABEL
43620+void netlbl_cache_invalidate(void);
43621+int netlbl_cache_add(const struct sk_buff *skb,
43622+ const struct netlbl_lsm_secattr *secattr);
43623+#else
43624+static inline void netlbl_cache_invalidate(void)
43625+{
43626+ return;
43627+}
43628+
43629+static inline int netlbl_cache_add(const struct sk_buff *skb,
43630+ const struct netlbl_lsm_secattr *secattr)
43631+{
43632+ return 0;
43633+}
43634+#endif /* CONFIG_NETLABEL */
43635+
43636+#endif /* _NETLABEL_H */
43637diff -Nur linux-2.6.18-rc5/include/net/netlink.h linux-2.6.19/include/net/netlink.h
43638--- linux-2.6.18-rc5/include/net/netlink.h 2006-08-28 05:41:48.000000000 +0200
43639+++ linux-2.6.19/include/net/netlink.h 2006-09-22 10:04:57.000000000 +0200
43640@@ -35,12 +35,15 @@
43641 * nlmsg_put() add a netlink message to an skb
43642 * nlmsg_put_answer() callback based nlmsg_put()
43643 * nlmsg_end() finanlize netlink message
43644+ * nlmsg_get_pos() return current position in message
43645+ * nlmsg_trim() trim part of message
43646 * nlmsg_cancel() cancel message construction
43647 * nlmsg_free() free a netlink message
43648 *
43649 * Message Sending:
43650 * nlmsg_multicast() multicast message to several groups
43651 * nlmsg_unicast() unicast a message to a single socket
43652+ * nlmsg_notify() send notification message
43653 *
43654 * Message Length Calculations:
43655 * nlmsg_msg_size(payload) length of message w/o padding
43656@@ -62,6 +65,9 @@
43657 * nlmsg_validate() validate netlink message incl. attrs
43658 * nlmsg_for_each_attr() loop over all attributes
43659 *
43660+ * Misc:
43661+ * nlmsg_report() report back to application?
43662+ *
43663 * ------------------------------------------------------------------------
43664 * Attributes Interface
43665 * ------------------------------------------------------------------------
43666@@ -80,8 +86,10 @@
43667 * struct nlattr netlink attribtue header
43668 *
43669 * Attribute Construction:
43670- * nla_reserve(skb, type, len) reserve skb tailroom for an attribute
43671+ * nla_reserve(skb, type, len) reserve room for an attribute
43672+ * nla_reserve_nohdr(skb, len) reserve room for an attribute w/o hdr
43673 * nla_put(skb, type, len, data) add attribute to skb
43674+ * nla_put_nohdr(skb, len, data) add attribute w/o hdr
43675 *
43676 * Attribute Construction for Basic Types:
43677 * nla_put_u8(skb, type, value) add u8 attribute to skb
43678@@ -139,6 +147,7 @@
43679 * nla_next(nla, remaining) get next netlink attribute
43680 * nla_validate() validate a stream of attributes
43681 * nla_find() find attribute in stream of attributes
43682+ * nla_find_nested() find attribute in nested attributes
43683 * nla_parse() parse and validate stream of attrs
43684 * nla_parse_nested() parse nested attribuets
43685 * nla_for_each_attr() loop over all attributes
43686@@ -158,6 +167,7 @@
43687 NLA_FLAG,
43688 NLA_MSECS,
43689 NLA_NESTED,
43690+ NLA_NUL_STRING,
43691 __NLA_TYPE_MAX,
43692 };
43693
43694@@ -166,21 +176,37 @@
43695 /**
43696 * struct nla_policy - attribute validation policy
43697 * @type: Type of attribute or NLA_UNSPEC
43698- * @minlen: Minimal length of payload required to be available
43699+ * @len: Type specific length of payload
43700 *
43701 * Policies are defined as arrays of this struct, the array must be
43702 * accessible by attribute type up to the highest identifier to be expected.
43703 *
43704+ * Meaning of `len' field:
43705+ * NLA_STRING Maximum length of string
43706+ * NLA_NUL_STRING Maximum length of string (excluding NUL)
43707+ * NLA_FLAG Unused
43708+ * All other Exact length of attribute payload
43709+ *
43710 * Example:
43711 * static struct nla_policy my_policy[ATTR_MAX+1] __read_mostly = {
43712 * [ATTR_FOO] = { .type = NLA_U16 },
43713- * [ATTR_BAR] = { .type = NLA_STRING },
43714- * [ATTR_BAZ] = { .minlen = sizeof(struct mystruct) },
43715+ * [ATTR_BAR] = { .type = NLA_STRING, len = BARSIZ },
43716+ * [ATTR_BAZ] = { .len = sizeof(struct mystruct) },
43717 * };
43718 */
43719 struct nla_policy {
43720 u16 type;
43721- u16 minlen;
43722+ u16 len;
43723+};
43724+
43725+/**
43726+ * struct nl_info - netlink source information
43727+ * @nlh: Netlink message header of original request
43728+ * @pid: Netlink PID of requesting application
43729+ */
43730+struct nl_info {
43731+ struct nlmsghdr *nlh;
43732+ u32 pid;
43733 };
43734
43735 extern void netlink_run_queue(struct sock *sk, unsigned int *qlen,
43736@@ -188,6 +214,9 @@
43737 struct nlmsghdr *, int *));
43738 extern void netlink_queue_skip(struct nlmsghdr *nlh,
43739 struct sk_buff *skb);
43740+extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb,
43741+ u32 pid, unsigned int group, int report,
43742+ gfp_t flags);
43743
43744 extern int nla_validate(struct nlattr *head, int len, int maxtype,
43745 struct nla_policy *policy);
43746@@ -203,12 +232,18 @@
43747 extern int nla_strcmp(const struct nlattr *nla, const char *str);
43748 extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype,
43749 int attrlen);
43750+extern void * __nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
43751 extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype,
43752 int attrlen);
43753+extern void * nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
43754 extern void __nla_put(struct sk_buff *skb, int attrtype,
43755 int attrlen, const void *data);
43756+extern void __nla_put_nohdr(struct sk_buff *skb, int attrlen,
43757+ const void *data);
43758 extern int nla_put(struct sk_buff *skb, int attrtype,
43759 int attrlen, const void *data);
43760+extern int nla_put_nohdr(struct sk_buff *skb, int attrlen,
43761+ const void *data);
43762
43763 /**************************************************************************
43764 * Netlink Messages
43765@@ -364,6 +399,17 @@
43766 }
43767
43768 /**
43769+ * nlmsg_report - need to report back to application?
43770+ * @nlh: netlink message header
43771+ *
43772+ * Returns 1 if a report back to the application is requested.
43773+ */
43774+static inline int nlmsg_report(struct nlmsghdr *nlh)
43775+{
43776+ return !!(nlh->nlmsg_flags & NLM_F_ECHO);
43777+}
43778+
43779+/**
43780 * nlmsg_for_each_attr - iterate over a stream of attributes
43781 * @pos: loop counter, set to current attribute
43782 * @nlh: netlink message header
43783@@ -453,12 +499,13 @@
43784 /**
43785 * nlmsg_new - Allocate a new netlink message
43786 * @size: maximum size of message
43787+ * @flags: the type of memory to allocate.
43788 *
43789 * Use NLMSG_GOODSIZE if size isn't know and you need a good default size.
43790 */
43791-static inline struct sk_buff *nlmsg_new(int size)
43792+static inline struct sk_buff *nlmsg_new(int size, gfp_t flags)
43793 {
43794- return alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
43795+ return alloc_skb(size, flags);
43796 }
43797
43798 /**
43799@@ -480,6 +527,32 @@
43800 }
43801
43802 /**
43803+ * nlmsg_get_pos - return current position in netlink message
43804+ * @skb: socket buffer the message is stored in
43805+ *
43806+ * Returns a pointer to the current tail of the message.
43807+ */
43808+static inline void *nlmsg_get_pos(struct sk_buff *skb)
43809+{
43810+ return skb->tail;
43811+}
43812+
43813+/**
43814+ * nlmsg_trim - Trim message to a mark
43815+ * @skb: socket buffer the message is stored in
43816+ * @mark: mark to trim to
43817+ *
43818+ * Trims the message to the provided mark. Returns -1.
43819+ */
43820+static inline int nlmsg_trim(struct sk_buff *skb, void *mark)
43821+{
43822+ if (mark)
43823+ skb_trim(skb, (unsigned char *) mark - skb->data);
43824+
43825+ return -1;
43826+}
43827+
43828+/**
43829 * nlmsg_cancel - Cancel construction of a netlink message
43830 * @skb: socket buffer the message is stored in
43831 * @nlh: netlink message header
43832@@ -489,9 +562,7 @@
43833 */
43834 static inline int nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh)
43835 {
43836- skb_trim(skb, (unsigned char *) nlh - skb->data);
43837-
43838- return -1;
43839+ return nlmsg_trim(skb, nlh);
43840 }
43841
43842 /**
43843@@ -509,15 +580,16 @@
43844 * @skb: netlink message as socket buffer
43845 * @pid: own netlink pid to avoid sending to yourself
43846 * @group: multicast group id
43847+ * @flags: allocation flags
43848 */
43849 static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb,
43850- u32 pid, unsigned int group)
43851+ u32 pid, unsigned int group, gfp_t flags)
43852 {
43853 int err;
43854
43855 NETLINK_CB(skb).dst_group = group;
43856
43857- err = netlink_broadcast(sk, skb, pid, group, GFP_KERNEL);
43858+ err = netlink_broadcast(sk, skb, pid, group, flags);
43859 if (err > 0)
43860 err = 0;
43861
43862@@ -631,6 +703,18 @@
43863 }
43864
43865 /**
43866+ * nla_find_nested - find attribute in a set of nested attributes
43867+ * @nla: attribute containing the nested attributes
43868+ * @attrtype: type of attribute to look for
43869+ *
43870+ * Returns the first attribute which matches the specified type.
43871+ */
43872+static inline struct nlattr *nla_find_nested(struct nlattr *nla, int attrtype)
43873+{
43874+ return nla_find(nla_data(nla), nla_len(nla), attrtype);
43875+}
43876+
43877+/**
43878 * nla_parse_nested - parse nested attributes
43879 * @tb: destination array with maxtype+1 elements
43880 * @maxtype: maximum attribute type to be expected
43881@@ -751,7 +835,7 @@
43882 #define NLA_PUT_STRING(skb, attrtype, value) \
43883 NLA_PUT(skb, attrtype, strlen(value) + 1, value)
43884
43885-#define NLA_PUT_FLAG(skb, attrtype, value) \
43886+#define NLA_PUT_FLAG(skb, attrtype) \
43887 NLA_PUT(skb, attrtype, 0, NULL)
43888
43889 #define NLA_PUT_MSECS(skb, attrtype, jiffies) \
43890@@ -862,10 +946,7 @@
43891 */
43892 static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
43893 {
43894- if (start)
43895- skb_trim(skb, (unsigned char *) start - skb->data);
43896-
43897- return -1;
43898+ return nlmsg_trim(skb, start);
43899 }
43900
43901 /**
43902@@ -880,4 +961,13 @@
43903 nla_ok(pos, rem); \
43904 pos = nla_next(pos, &(rem)))
43905
43906+/**
43907+ * nla_for_each_nested - iterate over nested attributes
43908+ * @pos: loop counter, set to current attribute
43909+ * @nla: attribute containing the nested attributes
43910+ * @rem: initialized to len, holds bytes currently remaining in stream
43911+ */
43912+#define nla_for_each_nested(pos, nla, rem) \
43913+ nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem)
43914+
43915 #endif
43916diff -Nur linux-2.6.18-rc5/include/net/nexthop.h linux-2.6.19/include/net/nexthop.h
43917--- linux-2.6.18-rc5/include/net/nexthop.h 1970-01-01 01:00:00.000000000 +0100
43918+++ linux-2.6.19/include/net/nexthop.h 2006-09-22 10:04:57.000000000 +0200
43919@@ -0,0 +1,33 @@
43920+#ifndef __NET_NEXTHOP_H
43921+#define __NET_NEXTHOP_H
43922+
43923+#include <linux/rtnetlink.h>
43924+#include <net/netlink.h>
43925+
43926+static inline int rtnh_ok(const struct rtnexthop *rtnh, int remaining)
43927+{
43928+ return remaining >= sizeof(*rtnh) &&
43929+ rtnh->rtnh_len >= sizeof(*rtnh) &&
43930+ rtnh->rtnh_len <= remaining;
43931+}
43932+
43933+static inline struct rtnexthop *rtnh_next(const struct rtnexthop *rtnh,
43934+ int *remaining)
43935+{
43936+ int totlen = NLA_ALIGN(rtnh->rtnh_len);
43937+
43938+ *remaining -= totlen;
43939+ return (struct rtnexthop *) ((char *) rtnh + totlen);
43940+}
43941+
43942+static inline struct nlattr *rtnh_attrs(const struct rtnexthop *rtnh)
43943+{
43944+ return (struct nlattr *) ((char *) rtnh + NLA_ALIGN(sizeof(*rtnh)));
43945+}
43946+
43947+static inline int rtnh_attrlen(const struct rtnexthop *rtnh)
43948+{
43949+ return rtnh->rtnh_len - NLA_ALIGN(sizeof(*rtnh));
43950+}
43951+
43952+#endif
43953diff -Nur linux-2.6.18-rc5/include/net/pkt_act.h linux-2.6.19/include/net/pkt_act.h
43954--- linux-2.6.18-rc5/include/net/pkt_act.h 2006-08-28 05:41:48.000000000 +0200
43955+++ linux-2.6.19/include/net/pkt_act.h 1970-01-01 01:00:00.000000000 +0100
43956@@ -1,273 +0,0 @@
43957-#ifndef __NET_PKT_ACT_H
43958-#define __NET_PKT_ACT_H
43959-
43960-#include <asm/uaccess.h>
43961-#include <asm/system.h>
43962-#include <linux/bitops.h>
43963-#include <linux/types.h>
43964-#include <linux/kernel.h>
43965-#include <linux/sched.h>
43966-#include <linux/string.h>
43967-#include <linux/mm.h>
43968-#include <linux/socket.h>
43969-#include <linux/sockios.h>
43970-#include <linux/in.h>
43971-#include <linux/errno.h>
43972-#include <linux/interrupt.h>
43973-#include <linux/skbuff.h>
43974-#include <linux/rtnetlink.h>
43975-#include <linux/module.h>
43976-#include <linux/init.h>
43977-#include <linux/proc_fs.h>
43978-#include <net/sock.h>
43979-#include <net/pkt_sched.h>
43980-
43981-#define tca_st(val) (struct tcf_##val *)
43982-#define PRIV(a,name) ( tca_st(name) (a)->priv)
43983-
43984-#if 0 /* control */
43985-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
43986-#else
43987-#define DPRINTK(format,args...)
43988-#endif
43989-
43990-#if 0 /* data */
43991-#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
43992-#else
43993-#define D2PRINTK(format,args...)
43994-#endif
43995-
43996-static __inline__ unsigned
43997-tcf_hash(u32 index)
43998-{
43999- return index & MY_TAB_MASK;
44000-}
44001-
44002-/* probably move this from being inline
44003- * and put into act_generic
44004-*/
44005-static inline void
44006-tcf_hash_destroy(struct tcf_st *p)
44007-{
44008- unsigned h = tcf_hash(p->index);
44009- struct tcf_st **p1p;
44010-
44011- for (p1p = &tcf_ht[h]; *p1p; p1p = &(*p1p)->next) {
44012- if (*p1p == p) {
44013- write_lock_bh(&tcf_t_lock);
44014- *p1p = p->next;
44015- write_unlock_bh(&tcf_t_lock);
44016-#ifdef CONFIG_NET_ESTIMATOR
44017- gen_kill_estimator(&p->bstats, &p->rate_est);
44018-#endif
44019- kfree(p);
44020- return;
44021- }
44022- }
44023- BUG_TRAP(0);
44024-}
44025-
44026-static inline int
44027-tcf_hash_release(struct tcf_st *p, int bind )
44028-{
44029- int ret = 0;
44030- if (p) {
44031- if (bind) {
44032- p->bindcnt--;
44033- }
44034- p->refcnt--;
44035- if(p->bindcnt <=0 && p->refcnt <= 0) {
44036- tcf_hash_destroy(p);
44037- ret = 1;
44038- }
44039- }
44040- return ret;
44041-}
44042-
44043-static __inline__ int
44044-tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
44045- struct tc_action *a)
44046-{
44047- struct tcf_st *p;
44048- int err =0, index = -1,i= 0, s_i = 0, n_i = 0;
44049- struct rtattr *r ;
44050-
44051- read_lock(&tcf_t_lock);
44052-
44053- s_i = cb->args[0];
44054-
44055- for (i = 0; i < MY_TAB_SIZE; i++) {
44056- p = tcf_ht[tcf_hash(i)];
44057-
44058- for (; p; p = p->next) {
44059- index++;
44060- if (index < s_i)
44061- continue;
44062- a->priv = p;
44063- a->order = n_i;
44064- r = (struct rtattr*) skb->tail;
44065- RTA_PUT(skb, a->order, 0, NULL);
44066- err = tcf_action_dump_1(skb, a, 0, 0);
44067- if (0 > err) {
44068- index--;
44069- skb_trim(skb, (u8*)r - skb->data);
44070- goto done;
44071- }
44072- r->rta_len = skb->tail - (u8*)r;
44073- n_i++;
44074- if (n_i >= TCA_ACT_MAX_PRIO) {
44075- goto done;
44076- }
44077- }
44078- }
44079-done:
44080- read_unlock(&tcf_t_lock);
44081- if (n_i)
44082- cb->args[0] += n_i;
44083- return n_i;
44084-
44085-rtattr_failure:
44086- skb_trim(skb, (u8*)r - skb->data);
44087- goto done;
44088-}
44089-
44090-static __inline__ int
44091-tcf_del_walker(struct sk_buff *skb, struct tc_action *a)
44092-{
44093- struct tcf_st *p, *s_p;
44094- struct rtattr *r ;
44095- int i= 0, n_i = 0;
44096-
44097- r = (struct rtattr*) skb->tail;
44098- RTA_PUT(skb, a->order, 0, NULL);
44099- RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
44100- for (i = 0; i < MY_TAB_SIZE; i++) {
44101- p = tcf_ht[tcf_hash(i)];
44102-
44103- while (p != NULL) {
44104- s_p = p->next;
44105- if (ACT_P_DELETED == tcf_hash_release(p, 0)) {
44106- module_put(a->ops->owner);
44107- }
44108- n_i++;
44109- p = s_p;
44110- }
44111- }
44112- RTA_PUT(skb, TCA_FCNT, 4, &n_i);
44113- r->rta_len = skb->tail - (u8*)r;
44114-
44115- return n_i;
44116-rtattr_failure:
44117- skb_trim(skb, (u8*)r - skb->data);
44118- return -EINVAL;
44119-}
44120-
44121-static __inline__ int
44122-tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, int type,
44123- struct tc_action *a)
44124-{
44125- if (type == RTM_DELACTION) {
44126- return tcf_del_walker(skb,a);
44127- } else if (type == RTM_GETACTION) {
44128- return tcf_dump_walker(skb,cb,a);
44129- } else {
44130- printk("tcf_generic_walker: unknown action %d\n",type);
44131- return -EINVAL;
44132- }
44133-}
44134-
44135-static __inline__ struct tcf_st *
44136-tcf_hash_lookup(u32 index)
44137-{
44138- struct tcf_st *p;
44139-
44140- read_lock(&tcf_t_lock);
44141- for (p = tcf_ht[tcf_hash(index)]; p; p = p->next) {
44142- if (p->index == index)
44143- break;
44144- }
44145- read_unlock(&tcf_t_lock);
44146- return p;
44147-}
44148-
44149-static __inline__ u32
44150-tcf_hash_new_index(void)
44151-{
44152- do {
44153- if (++idx_gen == 0)
44154- idx_gen = 1;
44155- } while (tcf_hash_lookup(idx_gen));
44156-
44157- return idx_gen;
44158-}
44159-
44160-
44161-static inline int
44162-tcf_hash_search(struct tc_action *a, u32 index)
44163-{
44164- struct tcf_st *p = tcf_hash_lookup(index);
44165-
44166- if (p != NULL) {
44167- a->priv = p;
44168- return 1;
44169- }
44170- return 0;
44171-}
44172-
44173-#ifdef CONFIG_NET_ACT_INIT
44174-static inline struct tcf_st *
44175-tcf_hash_check(u32 index, struct tc_action *a, int ovr, int bind)
44176-{
44177- struct tcf_st *p = NULL;
44178- if (index && (p = tcf_hash_lookup(index)) != NULL) {
44179- if (bind) {
44180- p->bindcnt++;
44181- p->refcnt++;
44182- }
44183- a->priv = p;
44184- }
44185- return p;
44186-}
44187-
44188-static inline struct tcf_st *
44189-tcf_hash_create(u32 index, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind)
44190-{
44191- struct tcf_st *p = NULL;
44192-
44193- p = kmalloc(size, GFP_KERNEL);
44194- if (p == NULL)
44195- return p;
44196-
44197- memset(p, 0, size);
44198- p->refcnt = 1;
44199-
44200- if (bind) {
44201- p->bindcnt = 1;
44202- }
44203-
44204- spin_lock_init(&p->lock);
44205- p->stats_lock = &p->lock;
44206- p->index = index ? : tcf_hash_new_index();
44207- p->tm.install = jiffies;
44208- p->tm.lastuse = jiffies;
44209-#ifdef CONFIG_NET_ESTIMATOR
44210- if (est)
44211- gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est);
44212-#endif
44213- a->priv = (void *) p;
44214- return p;
44215-}
44216-
44217-static inline void tcf_hash_insert(struct tcf_st *p)
44218-{
44219- unsigned h = tcf_hash(p->index);
44220-
44221- write_lock_bh(&tcf_t_lock);
44222- p->next = tcf_ht[h];
44223- tcf_ht[h] = p;
44224- write_unlock_bh(&tcf_t_lock);
44225-}
44226-
44227-#endif
44228-
44229-#endif
44230diff -Nur linux-2.6.18-rc5/include/net/request_sock.h linux-2.6.19/include/net/request_sock.h
44231--- linux-2.6.18-rc5/include/net/request_sock.h 2006-08-28 05:41:48.000000000 +0200
44232+++ linux-2.6.19/include/net/request_sock.h 2006-09-22 10:04:57.000000000 +0200
44233@@ -53,6 +53,7 @@
44234 unsigned long expires;
44235 struct request_sock_ops *rsk_ops;
44236 struct sock *sk;
44237+ u32 secid;
44238 };
44239
44240 static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops)
44241diff -Nur linux-2.6.18-rc5/include/net/route.h linux-2.6.19/include/net/route.h
44242--- linux-2.6.18-rc5/include/net/route.h 2006-08-28 05:41:48.000000000 +0200
44243+++ linux-2.6.19/include/net/route.h 2006-09-22 10:04:57.000000000 +0200
44244@@ -32,6 +32,7 @@
44245 #include <linux/route.h>
44246 #include <linux/ip.h>
44247 #include <linux/cache.h>
44248+#include <linux/security.h>
44249
44250 #ifndef __KERNEL__
44251 #warning This file is not supposed to be used outside of kernel.
44252@@ -166,6 +167,7 @@
44253 ip_rt_put(*rp);
44254 *rp = NULL;
44255 }
44256+ security_sk_classify_flow(sk, &fl);
44257 return ip_route_output_flow(rp, &fl, sk, 0);
44258 }
44259
44260@@ -182,6 +184,7 @@
44261 fl.proto = protocol;
44262 ip_rt_put(*rp);
44263 *rp = NULL;
44264+ security_sk_classify_flow(sk, &fl);
44265 return ip_route_output_flow(rp, &fl, sk, 0);
44266 }
44267 return 0;
44268diff -Nur linux-2.6.18-rc5/include/net/sctp/constants.h linux-2.6.19/include/net/sctp/constants.h
44269--- linux-2.6.18-rc5/include/net/sctp/constants.h 2006-08-28 05:41:48.000000000 +0200
44270+++ linux-2.6.19/include/net/sctp/constants.h 2006-09-22 10:04:57.000000000 +0200
44271@@ -264,10 +264,10 @@
44272 enum { SCTP_MAX_GABS = 16 };
44273
44274 /* Heartbeat interval - 30 secs */
44275-#define SCTP_DEFAULT_TIMEOUT_HEARTBEAT (30 * HZ)
44276+#define SCTP_DEFAULT_TIMEOUT_HEARTBEAT (30*1000)
44277
44278 /* Delayed sack timer - 200ms */
44279-#define SCTP_DEFAULT_TIMEOUT_SACK ((200 * HZ) / 1000)
44280+#define SCTP_DEFAULT_TIMEOUT_SACK (200)
44281
44282 /* RTO.Initial - 3 seconds
44283 * RTO.Min - 1 second
44284@@ -275,9 +275,9 @@
44285 * RTO.Alpha - 1/8
44286 * RTO.Beta - 1/4
44287 */
44288-#define SCTP_RTO_INITIAL (3 * HZ)
44289-#define SCTP_RTO_MIN (1 * HZ)
44290-#define SCTP_RTO_MAX (60 * HZ)
44291+#define SCTP_RTO_INITIAL (3 * 1000)
44292+#define SCTP_RTO_MIN (1 * 1000)
44293+#define SCTP_RTO_MAX (60 * 1000)
44294
44295 #define SCTP_RTO_ALPHA 3 /* 1/8 when converted to right shifts. */
44296 #define SCTP_RTO_BETA 2 /* 1/4 when converted to right shifts. */
44297@@ -290,8 +290,7 @@
44298 #define SCTP_DEF_MAX_INIT 6
44299 #define SCTP_DEF_MAX_SEND 10
44300
44301-#define SCTP_DEFAULT_COOKIE_LIFE_SEC 60 /* seconds */
44302-#define SCTP_DEFAULT_COOKIE_LIFE_USEC 0 /* microseconds */
44303+#define SCTP_DEFAULT_COOKIE_LIFE (60 * 1000) /* 60 seconds */
44304
44305 #define SCTP_DEFAULT_MINWINDOW 1500 /* default minimum rwnd size */
44306 #define SCTP_DEFAULT_MAXWINDOW 65535 /* default rwnd size */
44307diff -Nur linux-2.6.18-rc5/include/net/sctp/sctp.h linux-2.6.19/include/net/sctp/sctp.h
44308--- linux-2.6.18-rc5/include/net/sctp/sctp.h 2006-08-28 05:41:48.000000000 +0200
44309+++ linux-2.6.19/include/net/sctp/sctp.h 2006-09-22 10:04:57.000000000 +0200
44310@@ -128,6 +128,8 @@
44311 int flags);
44312 extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
44313 extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
44314+int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
44315+ void *ptr);
44316
44317 /*
44318 * sctp/socket.c
44319@@ -178,6 +180,17 @@
44320 struct sock *oldsk, struct sock *newsk);
44321
44322 /*
44323+ * sctp/proc.c
44324+ */
44325+int sctp_snmp_proc_init(void);
44326+void sctp_snmp_proc_exit(void);
44327+int sctp_eps_proc_init(void);
44328+void sctp_eps_proc_exit(void);
44329+int sctp_assocs_proc_init(void);
44330+void sctp_assocs_proc_exit(void);
44331+
44332+
44333+/*
44334 * Section: Macros, externs, and inlines
44335 */
44336
44337@@ -216,6 +229,50 @@
44338
44339 #endif /* !TEST_FRAME */
44340
44341+/* sctp mib definitions */
44342+enum
44343+{
44344+ SCTP_MIB_NUM = 0,
44345+ SCTP_MIB_CURRESTAB, /* CurrEstab */
44346+ SCTP_MIB_ACTIVEESTABS, /* ActiveEstabs */
44347+ SCTP_MIB_PASSIVEESTABS, /* PassiveEstabs */
44348+ SCTP_MIB_ABORTEDS, /* Aborteds */
44349+ SCTP_MIB_SHUTDOWNS, /* Shutdowns */
44350+ SCTP_MIB_OUTOFBLUES, /* OutOfBlues */
44351+ SCTP_MIB_CHECKSUMERRORS, /* ChecksumErrors */
44352+ SCTP_MIB_OUTCTRLCHUNKS, /* OutCtrlChunks */
44353+ SCTP_MIB_OUTORDERCHUNKS, /* OutOrderChunks */
44354+ SCTP_MIB_OUTUNORDERCHUNKS, /* OutUnorderChunks */
44355+ SCTP_MIB_INCTRLCHUNKS, /* InCtrlChunks */
44356+ SCTP_MIB_INORDERCHUNKS, /* InOrderChunks */
44357+ SCTP_MIB_INUNORDERCHUNKS, /* InUnorderChunks */
44358+ SCTP_MIB_FRAGUSRMSGS, /* FragUsrMsgs */
44359+ SCTP_MIB_REASMUSRMSGS, /* ReasmUsrMsgs */
44360+ SCTP_MIB_OUTSCTPPACKS, /* OutSCTPPacks */
44361+ SCTP_MIB_INSCTPPACKS, /* InSCTPPacks */
44362+ SCTP_MIB_T1_INIT_EXPIREDS,
44363+ SCTP_MIB_T1_COOKIE_EXPIREDS,
44364+ SCTP_MIB_T2_SHUTDOWN_EXPIREDS,
44365+ SCTP_MIB_T3_RTX_EXPIREDS,
44366+ SCTP_MIB_T4_RTO_EXPIREDS,
44367+ SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS,
44368+ SCTP_MIB_DELAY_SACK_EXPIREDS,
44369+ SCTP_MIB_AUTOCLOSE_EXPIREDS,
44370+ SCTP_MIB_T3_RETRANSMITS,
44371+ SCTP_MIB_PMTUD_RETRANSMITS,
44372+ SCTP_MIB_FAST_RETRANSMITS,
44373+ SCTP_MIB_IN_PKT_SOFTIRQ,
44374+ SCTP_MIB_IN_PKT_BACKLOG,
44375+ SCTP_MIB_IN_PKT_DISCARDS,
44376+ SCTP_MIB_IN_DATA_CHUNK_DISCARDS,
44377+ __SCTP_MIB_MAX
44378+};
44379+
44380+#define SCTP_MIB_MAX __SCTP_MIB_MAX
44381+struct sctp_mib {
44382+ unsigned long mibs[SCTP_MIB_MAX];
44383+} __SNMP_MIB_ALIGN__;
44384+
44385
44386 /* Print debugging messages. */
44387 #if SCTP_DEBUG
44388diff -Nur linux-2.6.18-rc5/include/net/sctp/structs.h linux-2.6.19/include/net/sctp/structs.h
44389--- linux-2.6.18-rc5/include/net/sctp/structs.h 2006-08-28 05:41:48.000000000 +0200
44390+++ linux-2.6.19/include/net/sctp/structs.h 2006-09-22 10:04:57.000000000 +0200
44391@@ -127,9 +127,9 @@
44392 * RTO.Alpha - 1/8 (3 when converted to right shifts.)
44393 * RTO.Beta - 1/4 (2 when converted to right shifts.)
44394 */
44395- unsigned long rto_initial;
44396- unsigned long rto_min;
44397- unsigned long rto_max;
44398+ unsigned int rto_initial;
44399+ unsigned int rto_min;
44400+ unsigned int rto_max;
44401
44402 /* Note: rto_alpha and rto_beta are really defined as inverse
44403 * powers of two to facilitate integer operations.
44404@@ -144,13 +144,13 @@
44405 int cookie_preserve_enable;
44406
44407 /* Valid.Cookie.Life - 60 seconds */
44408- unsigned long valid_cookie_life;
44409+ unsigned int valid_cookie_life;
44410
44411 /* Delayed SACK timeout 200ms default*/
44412- unsigned long sack_timeout;
44413+ unsigned int sack_timeout;
44414
44415 /* HB.interval - 30 seconds */
44416- unsigned long hb_interval;
44417+ unsigned int hb_interval;
44418
44419 /* Association.Max.Retrans - 10 attempts
44420 * Path.Max.Retrans - 5 attempts (per destination address)
44421diff -Nur linux-2.6.18-rc5/include/net/snmp.h linux-2.6.19/include/net/snmp.h
44422--- linux-2.6.18-rc5/include/net/snmp.h 2006-08-28 05:41:48.000000000 +0200
44423+++ linux-2.6.19/include/net/snmp.h 2006-09-22 10:04:57.000000000 +0200
44424@@ -100,12 +100,6 @@
44425 unsigned long mibs[UDP_MIB_MAX];
44426 } __SNMP_MIB_ALIGN__;
44427
44428-/* SCTP */
44429-#define SCTP_MIB_MAX __SCTP_MIB_MAX
44430-struct sctp_mib {
44431- unsigned long mibs[SCTP_MIB_MAX];
44432-} __SNMP_MIB_ALIGN__;
44433-
44434 /* Linux */
44435 #define LINUX_MIB_MAX __LINUX_MIB_MAX
44436 struct linux_mib {
44437diff -Nur linux-2.6.18-rc5/include/net/sock.h linux-2.6.19/include/net/sock.h
44438--- linux-2.6.18-rc5/include/net/sock.h 2006-08-28 05:41:48.000000000 +0200
44439+++ linux-2.6.19/include/net/sock.h 2006-09-22 10:04:57.000000000 +0200
44440@@ -862,30 +862,24 @@
44441 *
44442 */
44443
44444-static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
44445+static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
44446 {
44447 int err;
44448+ struct sk_filter *filter;
44449
44450 err = security_sock_rcv_skb(sk, skb);
44451 if (err)
44452 return err;
44453
44454- if (sk->sk_filter) {
44455- struct sk_filter *filter;
44456-
44457- if (needlock)
44458- bh_lock_sock(sk);
44459-
44460- filter = sk->sk_filter;
44461- if (filter) {
44462- unsigned int pkt_len = sk_run_filter(skb, filter->insns,
44463- filter->len);
44464- err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
44465- }
44466-
44467- if (needlock)
44468- bh_unlock_sock(sk);
44469+ rcu_read_lock_bh();
44470+ filter = sk->sk_filter;
44471+ if (filter) {
44472+ unsigned int pkt_len = sk_run_filter(skb, filter->insns,
44473+ filter->len);
44474+ err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
44475 }
44476+ rcu_read_unlock_bh();
44477+
44478 return err;
44479 }
44480
44481@@ -897,6 +891,12 @@
44482 * Remove a filter from a socket and release its resources.
44483 */
44484
44485+static inline void sk_filter_rcu_free(struct rcu_head *rcu)
44486+{
44487+ struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
44488+ kfree(fp);
44489+}
44490+
44491 static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp)
44492 {
44493 unsigned int size = sk_filter_len(fp);
44494@@ -904,7 +904,7 @@
44495 atomic_sub(size, &sk->sk_omem_alloc);
44496
44497 if (atomic_dec_and_test(&fp->refcnt))
44498- kfree(fp);
44499+ call_rcu_bh(&fp->rcu, sk_filter_rcu_free);
44500 }
44501
44502 static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
44503@@ -969,9 +969,23 @@
44504 sk->sk_sleep = &parent->wait;
44505 parent->sk = sk;
44506 sk->sk_socket = parent;
44507+ security_sock_graft(sk, parent);
44508 write_unlock_bh(&sk->sk_callback_lock);
44509 }
44510
44511+static inline void sock_copy(struct sock *nsk, const struct sock *osk)
44512+{
44513+#ifdef CONFIG_SECURITY_NETWORK
44514+ void *sptr = nsk->sk_security;
44515+#endif
44516+
44517+ memcpy(nsk, osk, osk->sk_prot->obj_size);
44518+#ifdef CONFIG_SECURITY_NETWORK
44519+ nsk->sk_security = sptr;
44520+ security_sk_clone(osk, nsk);
44521+#endif
44522+}
44523+
44524 extern int sock_i_uid(struct sock *sk);
44525 extern unsigned long sock_i_ino(struct sock *sk);
44526
44527diff -Nur linux-2.6.18-rc5/include/net/tc_act/tc_defact.h linux-2.6.19/include/net/tc_act/tc_defact.h
44528--- linux-2.6.18-rc5/include/net/tc_act/tc_defact.h 2006-08-28 05:41:48.000000000 +0200
44529+++ linux-2.6.19/include/net/tc_act/tc_defact.h 2006-09-22 10:04:57.000000000 +0200
44530@@ -3,11 +3,12 @@
44531
44532 #include <net/act_api.h>
44533
44534-struct tcf_defact
44535-{
44536- tca_gen(defact);
44537- u32 datalen;
44538- void *defdata;
44539+struct tcf_defact {
44540+ struct tcf_common common;
44541+ u32 tcfd_datalen;
44542+ void *tcfd_defdata;
44543 };
44544+#define to_defact(pc) \
44545+ container_of(pc, struct tcf_defact, common)
44546
44547-#endif
44548+#endif /* __NET_TC_DEF_H */
44549diff -Nur linux-2.6.18-rc5/include/net/tc_act/tc_gact.h linux-2.6.19/include/net/tc_act/tc_gact.h
44550--- linux-2.6.18-rc5/include/net/tc_act/tc_gact.h 2006-08-28 05:41:48.000000000 +0200
44551+++ linux-2.6.19/include/net/tc_act/tc_gact.h 2006-09-22 10:04:57.000000000 +0200
44552@@ -3,15 +3,15 @@
44553
44554 #include <net/act_api.h>
44555
44556-struct tcf_gact
44557-{
44558- tca_gen(gact);
44559+struct tcf_gact {
44560+ struct tcf_common common;
44561 #ifdef CONFIG_GACT_PROB
44562- u16 ptype;
44563- u16 pval;
44564- int paction;
44565+ u16 tcfg_ptype;
44566+ u16 tcfg_pval;
44567+ int tcfg_paction;
44568 #endif
44569-
44570 };
44571-
44572-#endif
44573+#define to_gact(pc) \
44574+ container_of(pc, struct tcf_gact, common)
44575+
44576+#endif /* __NET_TC_GACT_H */
44577diff -Nur linux-2.6.18-rc5/include/net/tc_act/tc_ipt.h linux-2.6.19/include/net/tc_act/tc_ipt.h
44578--- linux-2.6.18-rc5/include/net/tc_act/tc_ipt.h 2006-08-28 05:41:48.000000000 +0200
44579+++ linux-2.6.19/include/net/tc_act/tc_ipt.h 2006-09-22 10:04:57.000000000 +0200
44580@@ -5,12 +5,13 @@
44581
44582 struct xt_entry_target;
44583
44584-struct tcf_ipt
44585-{
44586- tca_gen(ipt);
44587- u32 hook;
44588- char *tname;
44589- struct xt_entry_target *t;
44590+struct tcf_ipt {
44591+ struct tcf_common common;
44592+ u32 tcfi_hook;
44593+ char *tcfi_tname;
44594+ struct xt_entry_target *tcfi_t;
44595 };
44596+#define to_ipt(pc) \
44597+ container_of(pc, struct tcf_ipt, common)
44598
44599-#endif
44600+#endif /* __NET_TC_IPT_H */
44601diff -Nur linux-2.6.18-rc5/include/net/tc_act/tc_mirred.h linux-2.6.19/include/net/tc_act/tc_mirred.h
44602--- linux-2.6.18-rc5/include/net/tc_act/tc_mirred.h 2006-08-28 05:41:48.000000000 +0200
44603+++ linux-2.6.19/include/net/tc_act/tc_mirred.h 2006-09-22 10:04:57.000000000 +0200
44604@@ -3,13 +3,14 @@
44605
44606 #include <net/act_api.h>
44607
44608-struct tcf_mirred
44609-{
44610- tca_gen(mirred);
44611- int eaction;
44612- int ifindex;
44613- int ok_push;
44614- struct net_device *dev;
44615+struct tcf_mirred {
44616+ struct tcf_common common;
44617+ int tcfm_eaction;
44618+ int tcfm_ifindex;
44619+ int tcfm_ok_push;
44620+ struct net_device *tcfm_dev;
44621 };
44622+#define to_mirred(pc) \
44623+ container_of(pc, struct tcf_mirred, common)
44624
44625-#endif
44626+#endif /* __NET_TC_MIR_H */
44627diff -Nur linux-2.6.18-rc5/include/net/tc_act/tc_pedit.h linux-2.6.19/include/net/tc_act/tc_pedit.h
44628--- linux-2.6.18-rc5/include/net/tc_act/tc_pedit.h 2006-08-28 05:41:48.000000000 +0200
44629+++ linux-2.6.19/include/net/tc_act/tc_pedit.h 2006-09-22 10:04:57.000000000 +0200
44630@@ -3,12 +3,13 @@
44631
44632 #include <net/act_api.h>
44633
44634-struct tcf_pedit
44635-{
44636- tca_gen(pedit);
44637- unsigned char nkeys;
44638- unsigned char flags;
44639- struct tc_pedit_key *keys;
44640+struct tcf_pedit {
44641+ struct tcf_common common;
44642+ unsigned char tcfp_nkeys;
44643+ unsigned char tcfp_flags;
44644+ struct tc_pedit_key *tcfp_keys;
44645 };
44646+#define to_pedit(pc) \
44647+ container_of(pc, struct tcf_pedit, common)
44648
44649-#endif
44650+#endif /* __NET_TC_PED_H */
44651diff -Nur linux-2.6.18-rc5/include/net/udp.h linux-2.6.19/include/net/udp.h
44652--- linux-2.6.18-rc5/include/net/udp.h 2006-08-28 05:41:48.000000000 +0200
44653+++ linux-2.6.19/include/net/udp.h 2006-09-22 10:04:57.000000000 +0200
44654@@ -30,25 +30,9 @@
44655
44656 #define UDP_HTABLE_SIZE 128
44657
44658-/* udp.c: This needs to be shared by v4 and v6 because the lookup
44659- * and hashing code needs to work with different AF's yet
44660- * the port space is shared.
44661- */
44662 extern struct hlist_head udp_hash[UDP_HTABLE_SIZE];
44663 extern rwlock_t udp_hash_lock;
44664
44665-extern int udp_port_rover;
44666-
44667-static inline int udp_lport_inuse(u16 num)
44668-{
44669- struct sock *sk;
44670- struct hlist_node *node;
44671-
44672- sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)])
44673- if (inet_sk(sk)->num == num)
44674- return 1;
44675- return 0;
44676-}
44677
44678 /* Note: this must match 'valbool' in sock_setsockopt */
44679 #define UDP_CSUM_NOXMIT 1
44680@@ -63,6 +47,8 @@
44681
44682 struct sk_buff;
44683
44684+extern int udp_get_port(struct sock *sk, unsigned short snum,
44685+ int (*saddr_cmp)(const struct sock *, const struct sock *));
44686 extern void udp_err(struct sk_buff *, u32);
44687
44688 extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
44689diff -Nur linux-2.6.18-rc5/include/net/xfrm.h linux-2.6.19/include/net/xfrm.h
44690--- linux-2.6.18-rc5/include/net/xfrm.h 2006-08-28 05:41:48.000000000 +0200
44691+++ linux-2.6.19/include/net/xfrm.h 2006-09-22 10:04:57.000000000 +0200
44692@@ -10,6 +10,7 @@
44693 #include <linux/socket.h>
44694 #include <linux/crypto.h>
44695 #include <linux/pfkeyv2.h>
44696+#include <linux/ipsec.h>
44697 #include <linux/in6.h>
44698 #include <linux/mutex.h>
44699
44700@@ -94,8 +95,9 @@
44701 struct xfrm_state
44702 {
44703 /* Note: bydst is re-used during gc */
44704- struct list_head bydst;
44705- struct list_head byspi;
44706+ struct hlist_node bydst;
44707+ struct hlist_node bysrc;
44708+ struct hlist_node byspi;
44709
44710 atomic_t refcnt;
44711 spinlock_t lock;
44712@@ -103,6 +105,8 @@
44713 struct xfrm_id id;
44714 struct xfrm_selector sel;
44715
44716+ u32 genid;
44717+
44718 /* Key manger bits */
44719 struct {
44720 u8 state;
44721@@ -133,6 +137,9 @@
44722 /* Data for encapsulator */
44723 struct xfrm_encap_tmpl *encap;
44724
44725+ /* Data for care-of address */
44726+ xfrm_address_t *coaddr;
44727+
44728 /* IPComp needs an IPIP tunnel for handling uncompressed packets */
44729 struct xfrm_state *tunnel;
44730
44731@@ -163,6 +170,9 @@
44732 struct xfrm_lifetime_cur curlft;
44733 struct timer_list timer;
44734
44735+ /* Last used time */
44736+ u64 lastused;
44737+
44738 /* Reference to data common to all the instances of this
44739 * transformer. */
44740 struct xfrm_type *type;
44741@@ -196,6 +206,7 @@
44742 u32 proto;
44743 u32 byid;
44744 u32 aevent;
44745+ u32 type;
44746 } data;
44747
44748 u32 seq;
44749@@ -212,6 +223,7 @@
44750 struct dst_ops *dst_ops;
44751 void (*garbage_collect)(void);
44752 int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
44753+ int (*get_saddr)(xfrm_address_t *saddr, xfrm_address_t *daddr);
44754 struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy);
44755 int (*bundle_create)(struct xfrm_policy *policy,
44756 struct xfrm_state **xfrm,
44757@@ -235,16 +247,12 @@
44758
44759 struct xfrm_state_afinfo {
44760 unsigned short family;
44761- struct list_head *state_bydst;
44762- struct list_head *state_byspi;
44763 int (*init_flags)(struct xfrm_state *x);
44764 void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
44765 struct xfrm_tmpl *tmpl,
44766 xfrm_address_t *daddr, xfrm_address_t *saddr);
44767- struct xfrm_state *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto);
44768- struct xfrm_state *(*find_acq)(u8 mode, u32 reqid, u8 proto,
44769- xfrm_address_t *daddr, xfrm_address_t *saddr,
44770- int create);
44771+ int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
44772+ int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
44773 };
44774
44775 extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
44776@@ -257,11 +265,17 @@
44777 char *description;
44778 struct module *owner;
44779 __u8 proto;
44780+ __u8 flags;
44781+#define XFRM_TYPE_NON_FRAGMENT 1
44782
44783 int (*init_state)(struct xfrm_state *x);
44784 void (*destructor)(struct xfrm_state *);
44785 int (*input)(struct xfrm_state *, struct sk_buff *skb);
44786 int (*output)(struct xfrm_state *, struct sk_buff *pskb);
44787+ int (*reject)(struct xfrm_state *, struct sk_buff *, struct flowi *);
44788+ int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
44789+ xfrm_address_t *(*local_addr)(struct xfrm_state *, xfrm_address_t *);
44790+ xfrm_address_t *(*remote_addr)(struct xfrm_state *, xfrm_address_t *);
44791 /* Estimate maximal size of result of transformation of a dgram */
44792 u32 (*get_max_size)(struct xfrm_state *, int size);
44793 };
44794@@ -273,7 +287,7 @@
44795
44796 struct xfrm_mode {
44797 int (*input)(struct xfrm_state *x, struct sk_buff *skb);
44798- int (*output)(struct sk_buff *skb);
44799+ int (*output)(struct xfrm_state *x,struct sk_buff *skb);
44800
44801 struct module *owner;
44802 unsigned int encap;
44803@@ -299,7 +313,7 @@
44804
44805 __u32 reqid;
44806
44807-/* Mode: transport/tunnel */
44808+/* Mode: transport, tunnel etc. */
44809 __u8 mode;
44810
44811 /* Sharing mode: unique, this session only, this user only etc. */
44812@@ -314,18 +328,20 @@
44813 __u32 calgos;
44814 };
44815
44816-#define XFRM_MAX_DEPTH 4
44817+#define XFRM_MAX_DEPTH 6
44818
44819 struct xfrm_policy
44820 {
44821 struct xfrm_policy *next;
44822- struct list_head list;
44823+ struct hlist_node bydst;
44824+ struct hlist_node byidx;
44825
44826 /* This lock only affects elements except for entry. */
44827 rwlock_t lock;
44828 atomic_t refcnt;
44829 struct timer_list timer;
44830
44831+ u8 type;
44832 u32 priority;
44833 u32 index;
44834 struct xfrm_selector selector;
44835@@ -363,16 +379,16 @@
44836 char *id;
44837 int (*notify)(struct xfrm_state *x, struct km_event *c);
44838 int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
44839- struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir);
44840+ struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
44841 int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
44842 int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
44843+ int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
44844 };
44845
44846 extern int xfrm_register_km(struct xfrm_mgr *km);
44847 extern int xfrm_unregister_km(struct xfrm_mgr *km);
44848
44849-
44850-extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
44851+extern unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
44852
44853 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
44854 {
44855@@ -388,67 +404,19 @@
44856 __xfrm_policy_destroy(policy);
44857 }
44858
44859-#define XFRM_DST_HSIZE 1024
44860-
44861-static __inline__
44862-unsigned __xfrm4_dst_hash(xfrm_address_t *addr)
44863-{
44864- unsigned h;
44865- h = ntohl(addr->a4);
44866- h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
44867- return h;
44868-}
44869-
44870-static __inline__
44871-unsigned __xfrm6_dst_hash(xfrm_address_t *addr)
44872-{
44873- unsigned h;
44874- h = ntohl(addr->a6[2]^addr->a6[3]);
44875- h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
44876- return h;
44877-}
44878-
44879-static __inline__
44880-unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family)
44881-{
44882- switch (family) {
44883- case AF_INET:
44884- return __xfrm4_dst_hash(addr);
44885- case AF_INET6:
44886- return __xfrm6_dst_hash(addr);
44887- }
44888- return 0;
44889-}
44890-
44891-static __inline__
44892-unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto)
44893+#ifdef CONFIG_XFRM_SUB_POLICY
44894+static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
44895 {
44896- unsigned h;
44897- h = ntohl(addr->a4^spi^proto);
44898- h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
44899- return h;
44900+ int i;
44901+ for (i = npols - 1; i >= 0; --i)
44902+ xfrm_pol_put(pols[i]);
44903 }
44904-
44905-static __inline__
44906-unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto)
44907-{
44908- unsigned h;
44909- h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto);
44910- h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
44911- return h;
44912-}
44913-
44914-static __inline__
44915-unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family)
44916+#else
44917+static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
44918 {
44919- switch (family) {
44920- case AF_INET:
44921- return __xfrm4_spi_hash(addr, spi, proto);
44922- case AF_INET6:
44923- return __xfrm6_spi_hash(addr, spi, proto);
44924- }
44925- return 0; /*XXX*/
44926+ xfrm_pol_put(pols[0]);
44927 }
44928+#endif
44929
44930 extern void __xfrm_state_destroy(struct xfrm_state *);
44931
44932@@ -508,6 +476,11 @@
44933 case IPPROTO_ICMPV6:
44934 port = htons(fl->fl_icmp_type);
44935 break;
44936+#ifdef CONFIG_IPV6_MIP6
44937+ case IPPROTO_MH:
44938+ port = htons(fl->fl_mh_type);
44939+ break;
44940+#endif
44941 default:
44942 port = 0; /*XXX*/
44943 }
44944@@ -608,6 +581,7 @@
44945 struct rt6_info rt6;
44946 } u;
44947 struct dst_entry *route;
44948+ u32 genid;
44949 u32 route_mtu_cached;
44950 u32 child_mtu_cached;
44951 u32 route_cookie;
44952@@ -659,6 +633,18 @@
44953 }
44954
44955 static inline int
44956+xfrm_addr_any(xfrm_address_t *addr, unsigned short family)
44957+{
44958+ switch (family) {
44959+ case AF_INET:
44960+ return addr->a4 == 0;
44961+ case AF_INET6:
44962+ return ipv6_addr_any((struct in6_addr *)&addr->a6);
44963+ }
44964+ return 0;
44965+}
44966+
44967+static inline int
44968 __xfrm4_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
44969 {
44970 return (tmpl->saddr.a4 &&
44971@@ -692,8 +678,8 @@
44972 {
44973 if (sk && sk->sk_policy[XFRM_POLICY_IN])
44974 return __xfrm_policy_check(sk, dir, skb, family);
44975-
44976- return (!xfrm_policy_list[dir] && !skb->sp) ||
44977+
44978+ return (!xfrm_policy_count[dir] && !skb->sp) ||
44979 (skb->dst->flags & DST_NOPOLICY) ||
44980 __xfrm_policy_check(sk, dir, skb, family);
44981 }
44982@@ -713,7 +699,7 @@
44983
44984 static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
44985 {
44986- return !xfrm_policy_list[XFRM_POLICY_OUT] ||
44987+ return !xfrm_policy_count[XFRM_POLICY_OUT] ||
44988 (skb->dst->flags & DST_NOXFRM) ||
44989 __xfrm_route_forward(skb, family);
44990 }
44991@@ -831,11 +817,36 @@
44992 return 0;
44993 }
44994
44995+static __inline__ int
44996+xfrm_state_addr_flow_check(struct xfrm_state *x, struct flowi *fl,
44997+ unsigned short family)
44998+{
44999+ switch (family) {
45000+ case AF_INET:
45001+ return __xfrm4_state_addr_check(x,
45002+ (xfrm_address_t *)&fl->fl4_dst,
45003+ (xfrm_address_t *)&fl->fl4_src);
45004+ case AF_INET6:
45005+ return __xfrm6_state_addr_check(x,
45006+ (xfrm_address_t *)&fl->fl6_dst,
45007+ (xfrm_address_t *)&fl->fl6_src);
45008+ }
45009+ return 0;
45010+}
45011+
45012 static inline int xfrm_state_kern(struct xfrm_state *x)
45013 {
45014 return atomic_read(&x->tunnel_users);
45015 }
45016
45017+static inline int xfrm_id_proto_match(u8 proto, u8 userproto)
45018+{
45019+ return (!userproto || proto == userproto ||
45020+ (userproto == IPSEC_PROTO_ANY && (proto == IPPROTO_AH ||
45021+ proto == IPPROTO_ESP ||
45022+ proto == IPPROTO_COMP)));
45023+}
45024+
45025 /*
45026 * xfrm algorithm information
45027 */
45028@@ -902,6 +913,25 @@
45029 extern int xfrm_state_add(struct xfrm_state *x);
45030 extern int xfrm_state_update(struct xfrm_state *x);
45031 extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
45032+extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family);
45033+#ifdef CONFIG_XFRM_SUB_POLICY
45034+extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
45035+ int n, unsigned short family);
45036+extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
45037+ int n, unsigned short family);
45038+#else
45039+static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
45040+ int n, unsigned short family)
45041+{
45042+ return -ENOSYS;
45043+}
45044+
45045+static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
45046+ int n, unsigned short family)
45047+{
45048+ return -ENOSYS;
45049+}
45050+#endif
45051 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
45052 extern int xfrm_state_delete(struct xfrm_state *x);
45053 extern void xfrm_state_flush(u8 proto);
45054@@ -917,12 +947,16 @@
45055 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
45056 extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi);
45057 extern int xfrm6_rcv(struct sk_buff **pskb);
45058+extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
45059+ xfrm_address_t *saddr, u8 proto);
45060 extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
45061 extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
45062 extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
45063 extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
45064 extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
45065 extern int xfrm6_output(struct sk_buff *skb);
45066+extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
45067+ u8 **prevhdr);
45068
45069 #ifdef CONFIG_XFRM
45070 extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
45071@@ -947,27 +981,27 @@
45072 #endif
45073
45074 struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
45075-extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
45076+extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), void *);
45077 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
45078-struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel,
45079+struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
45080+ struct xfrm_selector *sel,
45081 struct xfrm_sec_ctx *ctx, int delete);
45082-struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
45083-void xfrm_policy_flush(void);
45084+struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete);
45085+void xfrm_policy_flush(u8 type);
45086 u32 xfrm_get_acqseq(void);
45087 void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
45088 struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
45089 xfrm_address_t *daddr, xfrm_address_t *saddr,
45090 int create, unsigned short family);
45091-extern void xfrm_policy_flush(void);
45092+extern void xfrm_policy_flush(u8 type);
45093 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
45094-extern int xfrm_flush_bundles(void);
45095-extern void xfrm_flush_all_bundles(void);
45096-extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family);
45097+extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family, int strict);
45098 extern void xfrm_init_pmtu(struct dst_entry *dst);
45099
45100 extern wait_queue_head_t km_waitq;
45101 extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
45102 extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
45103+extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
45104
45105 extern void xfrm_input_init(void);
45106 extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq);
This page took 5.540068 seconds and 4 git commands to generate.