History

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6

David S. Miller committed 17 years ago

Commit b5bb1432 parents bb4f92b 1d4520971 files · +1626 −784Browse files

Unified · Split

71 files
  1. drivers/leds/Kconfig +3 −0
  2. include/linux/netfilter/Kbuild +8 −0
  3. include/linux/netfilter/nfnetlink.h +1 −0
  4. include/linux/netfilter/x_tables.h +8 −7
  5. include/linux/netfilter/xt_LED.h +13 −0
  6. include/linux/netfilter/xt_cluster.h +15 −0
  7. include/linux/netfilter/xt_limit.h +5 −4
  8. include/linux/netfilter/xt_quota.h +3 −1
  9. include/linux/netfilter/xt_statistic.h +4 −3
  10. include/linux/netfilter_ipv6/Kbuild +1 −0
  11. include/net/netfilter/nf_conntrack.h +1 −1
  12. include/net/netfilter/nf_conntrack_l4proto.h +1 −9
  13. include/net/netfilter/nf_log.h +8 −3
  14. net/bridge/netfilter/ebtable_broute.c +0 −1
  15. net/bridge/netfilter/ebtable_filter.c +0 −1
  16. net/bridge/netfilter/ebtable_nat.c +0 −1
  17. net/ipv4/netfilter/Kconfig +12 −18
  18. net/ipv4/netfilter/Makefile +0 −2
  19. net/ipv4/netfilter/arp_tables.c +122 −37
  20. net/ipv4/netfilter/arptable_filter.c +0 −2
  21. net/ipv4/netfilter/ip_queue.c +2 −0
  22. net/ipv4/netfilter/ip_tables.c +108 −45
  23. net/ipv4/netfilter/ipt_LOG.c +1 −1
  24. net/ipv4/netfilter/ipt_TTL.c +0 −97
  25. net/ipv4/netfilter/ipt_ULOG.c +1 −1
  26. net/ipv4/netfilter/ipt_ttl.c +0 −63
  27. net/ipv4/netfilter/iptable_filter.c +0 −1
  28. net/ipv4/netfilter/iptable_mangle.c +0 −1
  29. net/ipv4/netfilter/iptable_raw.c +0 −1
  30. net/ipv4/netfilter/iptable_security.c +0 −1
  31. net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +3 −1
  32. net/ipv4/netfilter/nf_nat_rule.c +0 −1
  33. net/ipv6/netfilter/Kconfig +15 −23
  34. net/ipv6/netfilter/Makefile +0 −2
  35. net/ipv6/netfilter/ip6_queue.c +1 −0
  36. net/ipv6/netfilter/ip6_tables.c +105 −47
  37. net/ipv6/netfilter/ip6t_HL.c +0 −95
  38. net/ipv6/netfilter/ip6t_LOG.c +1 −1
  39. net/ipv6/netfilter/ip6t_hl.c +0 −68
  40. net/ipv6/netfilter/ip6table_filter.c +0 −1
  41. net/ipv6/netfilter/ip6table_mangle.c +0 −1
  42. net/ipv6/netfilter/ip6table_raw.c +0 −1
  43. net/ipv6/netfilter/ip6table_security.c +0 −1
  44. net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +1 −0
  45. net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +4 −0
  46. net/netfilter/Kconfig +63 −0
  47. net/netfilter/Makefile +4 −0
  48. net/netfilter/core.c +0 −2
  49. net/netfilter/nf_conntrack_core.c +9 −5
  50. net/netfilter/nf_conntrack_expect.c +2 −1
  51. net/netfilter/nf_conntrack_netlink.c +72 −89
  52. net/netfilter/nf_conntrack_proto.c +0 −21
  53. net/netfilter/nf_conntrack_proto_dccp.c +108 −37
  54. net/netfilter/nf_conntrack_proto_generic.c +1 −1
  55. net/netfilter/nf_conntrack_proto_tcp.c +2 −0
  56. net/netfilter/nf_conntrack_proto_udp.c +2 −0
  57. net/netfilter/nf_log.c +169 −32
  58. net/netfilter/nfnetlink.c +6 −0
  59. net/netfilter/nfnetlink_log.c +13 −5
  60. net/netfilter/x_tables.c +21 −5
  61. net/netfilter/xt_HL.c +171 −0
  62. net/netfilter/xt_LED.c +161 −0
  63. net/netfilter/xt_cluster.c +164 −0
  64. net/netfilter/xt_hashlimit.c +2 −5
  65. net/netfilter/xt_hl.c +108 −0
  66. net/netfilter/xt_limit.c +29 −11
  67. net/netfilter/xt_physdev.c +23 −14
  68. net/netfilter/xt_quota.c +24 −7
  69. net/netfilter/xt_statistic.c +23 −5
  70. net/netlink/af_netlink.c +1 −0
  71. net/sysctl_net.c +1 −1
drivers/leds/Kconfig+3−0
@@ -223,4 +223,7 @@ config LEDS_TRIGGER_DEFAULT_ON · 222 unmodified lines
223223 This allows LEDs to be initialised in the ON state.
224224 If unsure, say Y.
225225
226+comment "iptables trigger is under Netfilter config (LED target)"
227+ depends on LEDS_TRIGGERS
228+
226229 endif # NEW_LEDS
include/linux/netfilter/Kbuild+8−0
@@ -7,16 +7,21 @@ header-y += xt_CLASSIFY.h · 6 unmodified lines
77 header-y += xt_CONNMARK.h
88 header-y += xt_CONNSECMARK.h
99 header-y += xt_DSCP.h
10+header-y += xt_LED.h
1011 header-y += xt_MARK.h
1112 header-y += xt_NFLOG.h
1213 header-y += xt_NFQUEUE.h
1314 header-y += xt_RATEEST.h
1415 header-y += xt_SECMARK.h
1516 header-y += xt_TCPMSS.h
17+header-y += xt_TCPOPTSTRIP.h
18+header-y += xt_TPROXY.h
1619 header-y += xt_comment.h
1720 header-y += xt_connbytes.h
21+header-y += xt_connlimit.h
1822 header-y += xt_connmark.h
1923 header-y += xt_conntrack.h
24+header-y += xt_cluster.h
2025 header-y += xt_dccp.h
2126 header-y += xt_dscp.h
2227 header-y += xt_esp.h
@@ -30,6 +35,7 @@ header-y += xt_mark.h · 7 unmodified lines
3035 header-y += xt_multiport.h
3136 header-y += xt_owner.h
3237 header-y += xt_pkttype.h
38+header-y += xt_quota.h
3339 header-y += xt_rateest.h
3440 header-y += xt_realm.h
3541 header-y += xt_recent.h
@@ -39,6 +45,8 @@ header-y += xt_statistic.h · 3 unmodified lines
3945 header-y += xt_string.h
4046 header-y += xt_tcpmss.h
4147 header-y += xt_tcpudp.h
48+header-y += xt_time.h
49+header-y += xt_u32.h
4250
4351 unifdef-y += nf_conntrack_common.h
4452 unifdef-y += nf_conntrack_ftp.h
include/linux/netfilter/nfnetlink.h+1−0
@@ -76,6 +76,7 @@ extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); · 75 unmodified lines
7676 extern int nfnetlink_has_listeners(unsigned int group);
7777 extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group,
7878 int echo);
79+extern void nfnetlink_set_err(u32 pid, u32 group, int error);
7980 extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags);
8081
8182 extern void nfnl_lock(void);
include/linux/netfilter/x_tables.h+8−7
@@ -349,23 +349,22 @@ struct xt_table · 348 unmodified lines
349349 {
350350 struct list_head list;
351351
352− /* A unique name... */
353− const char name[XT_TABLE_MAXNAMELEN];
354−
355352 /* What hooks you will enter on */
356353 unsigned int valid_hooks;
357354
358355 /* Lock for the curtain */
359− rwlock_t lock;
356+ struct mutex lock;
360357
361358 /* Man behind the curtain... */
362− //struct ip6t_table_info *private;
363− void *private;
359+ struct xt_table_info *private;
364360
365361 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
366362 struct module *me;
367363
368364 u_int8_t af; /* address/protocol family */
365+
366+ /* A unique name... */
367+ const char name[XT_TABLE_MAXNAMELEN];
369368 };
370369
371370 #include <linux/netfilter_ipv4.h>
@@ -386,7 +385,7 @@ struct xt_table_info · 14 unmodified lines
386385
387386 /* ipt_entry tables: one per CPU */
388387 /* Note : this field MUST be the last one, see XT_TABLE_INFO_SZ */
389− char *entries[1];
388+ void *entries[1];
390389 };
391390
392391 #define XT_TABLE_INFO_SZ (offsetof(struct xt_table_info, entries) \
@@ -433,6 +432,8 @@ extern void xt_proto_fini(struct net *net, u_int8_t af); · 40 unmodified lines
433432
434433 extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
435434 extern void xt_free_table_info(struct xt_table_info *info);
435+extern void xt_table_entry_swap_rcu(struct xt_table_info *old,
436+ struct xt_table_info *new);
436437
437438 #ifdef CONFIG_COMPAT
438439 #include <net/compat.h>
include/linux/netfilter/xt_LED.h+13−0
@@ -0,0 +1,13 @@
1+#ifndef _XT_LED_H
2+#define _XT_LED_H
3+
4+struct xt_led_info {
5+ char id[27]; /* Unique ID for this trigger in the LED class */
6+ __u8 always_blink; /* Blink even if the LED is already on */
7+ __u32 delay; /* Delay until LED is switched off after trigger */
8+
9+ /* Kernel data used in the module */
10+ void *internal_data __attribute__((aligned(8)));
11+};
12+
13+#endif /* _XT_LED_H */
include/linux/netfilter/xt_cluster.h+15−0
@@ -0,0 +1,15 @@
1+#ifndef _XT_CLUSTER_MATCH_H
2+#define _XT_CLUSTER_MATCH_H
3+
4+enum xt_cluster_flags {
5+ XT_CLUSTER_F_INV = (1 << 0)
6+};
7+
8+struct xt_cluster_match_info {
9+ u_int32_t total_nodes;
10+ u_int32_t node_mask;
11+ u_int32_t hash_seed;
12+ u_int32_t flags;
13+};
14+
15+#endif /* _XT_CLUSTER_MATCH_H */
include/linux/netfilter/xt_limit.h+5−4
@@ -4,6 +4,8 @@ · 3 unmodified lines
44 /* timings are in milliseconds. */
55 #define XT_LIMIT_SCALE 10000
66
7+struct xt_limit_priv;
8+
79 /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
810 seconds, or one every 59 hours. */
911 struct xt_rateinfo {
@@ -11,11 +13,10 @@ struct xt_rateinfo { · 1 unmodified line
1113 u_int32_t burst; /* Period multiplier for upper limit. */
1214
1315 /* Used internally by the kernel */
14− unsigned long prev;
15− u_int32_t credit;
16+ unsigned long prev; /* moved to xt_limit_priv */
17+ u_int32_t credit; /* moved to xt_limit_priv */
1618 u_int32_t credit_cap, cost;
1719
18− /* Ugly, ugly fucker. */
19− struct xt_rateinfo *master;
20+ struct xt_limit_priv *master;
2021 };
2122 #endif /*_XT_RATE_H*/
include/linux/netfilter/xt_quota.h+3−1
@@ -6,13 +6,15 @@ enum xt_quota_flags { · 5 unmodified lines
66 };
77 #define XT_QUOTA_MASK 0x1
88
9+struct xt_quota_priv;
10+
911 struct xt_quota_info {
1012 u_int32_t flags;
1113 u_int32_t pad;
1214
1315 /* Used internally by the kernel */
1416 aligned_u64 quota;
15− struct xt_quota_info *master;
17+ struct xt_quota_priv *master;
1618 };
1719
1820 #endif /* _XT_QUOTA_H */
include/linux/netfilter/xt_statistic.h+4−3
@@ -13,6 +13,8 @@ enum xt_statistic_flags { · 12 unmodified lines
1313 };
1414 #define XT_STATISTIC_MASK 0x1
1515
16+struct xt_statistic_priv;
17+
1618 struct xt_statistic_info {
1719 u_int16_t mode;
1820 u_int16_t flags;
@@ -23,11 +25,10 @@ struct xt_statistic_info { · 4 unmodified lines
2325 struct {
2426 u_int32_t every;
2527 u_int32_t packet;
26− /* Used internally by the kernel */
27− u_int32_t count;
28+ u_int32_t count; /* unused */
2829 } nth;
2930 } u;
30− struct xt_statistic_info *master __attribute__((aligned(8)));
31+ struct xt_statistic_priv *master __attribute__((aligned(8)));
3132 };
3233
3334 #endif /* _XT_STATISTIC_H */
include/linux/netfilter_ipv6/Kbuild+1−0
@@ -11,6 +11,7 @@ header-y += ip6t_length.h · 10 unmodified lines
1111 header-y += ip6t_limit.h
1212 header-y += ip6t_mac.h
1313 header-y += ip6t_mark.h
14+header-y += ip6t_mh.h
1415 header-y += ip6t_multiport.h
1516 header-y += ip6t_opts.h
1617 header-y += ip6t_owner.h
include/net/netfilter/nf_conntrack.h+1−1
@@ -287,7 +287,7 @@ static inline int nf_ct_is_untracked(const struct sk_buff *skb) · 286 unmodified lines
287287
288288 extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
289289 extern unsigned int nf_conntrack_htable_size;
290−extern int nf_conntrack_max;
290+extern unsigned int nf_conntrack_max;
291291
292292 #define NF_CT_STAT_INC(net, count) \
293293 (per_cpu_ptr((net)->ct.stat, raw_smp_processor_id())->count++)
include/net/netfilter/nf_conntrack_l4proto.h+1−9
@@ -90,10 +90,7 @@ struct nf_conntrack_l4proto · 89 unmodified lines
9090 struct module *me;
9191 };
9292
93−/* Existing built-in protocols */
94−extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
95−extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
96−extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
93+/* Existing built-in generic protocol */
9794 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
9895
9996 #define MAX_NF_CT_PROTO 256
@@ -101,11 +98,6 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic; · 1 unmodified line
10198 extern struct nf_conntrack_l4proto *
10299 __nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto);
103100
104−extern struct nf_conntrack_l4proto *
105−nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t protocol);
106−
107−extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
108−
109101 /* Protocol registration. */
110102 extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
111103 extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
include/net/netfilter/nf_log.h+8−3
@@ -1,6 +1,8 @@
11 #ifndef _NF_LOG_H
22 #define _NF_LOG_H
33
4+#include <linux/netfilter.h>
5+
46 /* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will
57 * disappear once iptables is replaced with pkttables. Please DO NOT use them
68 * for any new code! */
@@ -40,12 +42,15 @@ struct nf_logger { · 33 unmodified lines
4042 struct module *me;
4143 nf_logfn *logfn;
4244 char *name;
45+ struct list_head list[NFPROTO_NUMPROTO];
4346 };
4447
4548 /* Function to register/unregister log function. */
46−int nf_log_register(u_int8_t pf, const struct nf_logger *logger);
47−void nf_log_unregister(const struct nf_logger *logger);
48−void nf_log_unregister_pf(u_int8_t pf);
49+int nf_log_register(u_int8_t pf, struct nf_logger *logger);
50+void nf_log_unregister(struct nf_logger *logger);
51+
52+int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger);
53+void nf_log_unbind_pf(u_int8_t pf);
4954
5055 /* Calls the registered backend logging function */
5156 void nf_log_packet(u_int8_t pf,
net/bridge/netfilter/ebtable_broute.c+0−1
@@ -46,7 +46,6 @@ static struct ebt_table broute_table = · 45 unmodified lines
4646 .name = "broute",
4747 .table = &initial_table,
4848 .valid_hooks = 1 << NF_BR_BROUTING,
49− .lock = __RW_LOCK_UNLOCKED(broute_table.lock),
5049 .check = check,
5150 .me = THIS_MODULE,
5251 };
net/bridge/netfilter/ebtable_filter.c+0−1
@@ -55,7 +55,6 @@ static struct ebt_table frame_filter = · 54 unmodified lines
5555 .name = "filter",
5656 .table = &initial_table,
5757 .valid_hooks = FILTER_VALID_HOOKS,
58− .lock = __RW_LOCK_UNLOCKED(frame_filter.lock),
5958 .check = check,
6059 .me = THIS_MODULE,
6160 };
net/bridge/netfilter/ebtable_nat.c+0−1
@@ -55,7 +55,6 @@ static struct ebt_table frame_nat = · 54 unmodified lines
5555 .name = "nat",
5656 .table = &initial_table,
5757 .valid_hooks = NAT_VALID_HOOKS,
58− .lock = __RW_LOCK_UNLOCKED(frame_nat.lock),
5958 .check = check,
6059 .me = THIS_MODULE,
6160 };
net/ipv4/netfilter/Kconfig+12−18
@@ -31,7 +31,7 @@ config NF_CONNTRACK_PROC_COMPAT · 30 unmodified lines
3131 default y
3232 help
3333 This option enables /proc and sysctl compatibility with the old
34− layer 3 dependant connection tracking. This is needed to keep
34+ layer 3 dependent connection tracking. This is needed to keep
3535 old programs that have not been adapted to the new names working.
3636
3737 If unsure, say Y.
@@ -95,11 +95,11 @@ config IP_NF_MATCH_ECN · 57 unmodified lines
9595 config IP_NF_MATCH_TTL
9696 tristate '"ttl" match support'
9797 depends on NETFILTER_ADVANCED
98− help
99− This adds CONFIG_IP_NF_MATCH_TTL option, which enabled the user
100− to match packets by their TTL value.
101−
102− To compile it as a module, choose M here. If unsure, say N.
98+ select NETFILTER_XT_MATCH_HL
99+ ---help---
100+ This is a backwards-compat option for the user's convenience
101+ (e.g. when running oldconfig). It selects
102+ CONFIG_NETFILTER_XT_MATCH_HL.
103103
104104 # `filter', generic and specific targets
105105 config IP_NF_FILTER
@@ -323,19 +323,13 @@ config IP_NF_TARGET_ECN · 217 unmodified lines
323323 To compile it as a module, choose M here. If unsure, say N.
324324
325325 config IP_NF_TARGET_TTL
326− tristate 'TTL target support'
327− depends on IP_NF_MANGLE
326+ tristate '"TTL" target support'
328327 depends on NETFILTER_ADVANCED
329− help
330− This option adds a `TTL' target, which enables the user to modify
331− the TTL value of the IP header.
332−
333− While it is safe to decrement/lower the TTL, this target also enables
334− functionality to increment and set the TTL value of the IP header to
335− arbitrary values. This is EXTREMELY DANGEROUS since you can easily
336− create immortal packets that loop forever on the network.
337−
338− To compile it as a module, choose M here. If unsure, say N.
328+ select NETFILTER_XT_TARGET_HL
329+ ---help---
330+ This is a backwards-compat option for the user's convenience
331+ (e.g. when running oldconfig). It selects
332+ CONFIG_NETFILTER_XT_TARGET_HL.
339333
340334 # raw + specific targets
341335 config IP_NF_RAW
net/ipv4/netfilter/Makefile+0−2
@@ -51,7 +51,6 @@ obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o · 50 unmodified lines
5151 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
5252 obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
5353 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
54−obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
5554
5655 # targets
5756 obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
@@ -61,7 +60,6 @@ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o · 3 unmodified lines
6160 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
6261 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
6362 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
64−obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
6563 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
6664
6765 # generic ARP tables
net/ipv4/netfilter/arp_tables.c+122−37
@@ -73,6 +73,36 @@ static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, · 72 unmodified lines
7373 return (ret != 0);
7474 }
7575
76+/*
77+ * Unfortunatly, _b and _mask are not aligned to an int (or long int)
78+ * Some arches dont care, unrolling the loop is a win on them.
79+ */
80+static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask)
81+{
82+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
83+ const unsigned long *a = (const unsigned long *)_a;
84+ const unsigned long *b = (const unsigned long *)_b;
85+ const unsigned long *mask = (const unsigned long *)_mask;
86+ unsigned long ret;
87+
88+ ret = (a[0] ^ b[0]) & mask[0];
89+ if (IFNAMSIZ > sizeof(unsigned long))
90+ ret |= (a[1] ^ b[1]) & mask[1];
91+ if (IFNAMSIZ > 2 * sizeof(unsigned long))
92+ ret |= (a[2] ^ b[2]) & mask[2];
93+ if (IFNAMSIZ > 3 * sizeof(unsigned long))
94+ ret |= (a[3] ^ b[3]) & mask[3];
95+ BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
96+#else
97+ unsigned long ret = 0;
98+ int i;
99+
100+ for (i = 0; i < IFNAMSIZ; i++)
101+ ret |= (_a[i] ^ _b[i]) & _mask[i];
102+#endif
103+ return ret;
104+}
105+
76106 /* Returns whether packet matches rule or not. */
77107 static inline int arp_packet_match(const struct arphdr *arphdr,
78108 struct net_device *dev,
@@ -83,7 +113,7 @@ static inline int arp_packet_match(const struct arphdr *arphdr, · 4 unmodified lines
83113 const char *arpptr = (char *)(arphdr + 1);
84114 const char *src_devaddr, *tgt_devaddr;
85115 __be32 src_ipaddr, tgt_ipaddr;
86− int i, ret;
116+ long ret;
87117
88118 #define FWINV(bool, invflg) ((bool) ^ !!(arpinfo->invflags & (invflg)))
89119
@@ -156,10 +186,7 @@ static inline int arp_packet_match(const struct arphdr *arphdr, · 66 unmodified lines
156186 }
157187
158188 /* Look for ifname matches. */
159− for (i = 0, ret = 0; i < IFNAMSIZ; i++) {
160− ret |= (indev[i] ^ arpinfo->iniface[i])
161− & arpinfo->iniface_mask[i];
162− }
189+ ret = ifname_compare(indev, arpinfo->iniface, arpinfo->iniface_mask);
163190
164191 if (FWINV(ret != 0, ARPT_INV_VIA_IN)) {
165192 dprintf("VIA in mismatch (%s vs %s).%s\n",
@@ -168,10 +195,7 @@ static inline int arp_packet_match(const struct arphdr *arphdr, · 2 unmodified lines
168195 return 0;
169196 }
170197
171− for (i = 0, ret = 0; i < IFNAMSIZ; i++) {
172− ret |= (outdev[i] ^ arpinfo->outiface[i])
173− & arpinfo->outiface_mask[i];
174− }
198+ ret = ifname_compare(outdev, arpinfo->outiface, arpinfo->outiface_mask);
175199
176200 if (FWINV(ret != 0, ARPT_INV_VIA_OUT)) {
177201 dprintf("VIA out mismatch (%s vs %s).%s\n",
@@ -221,7 +245,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, · 43 unmodified lines
221245 const struct net_device *out,
222246 struct xt_table *table)
223247 {
224− static const char nulldevname[IFNAMSIZ];
248+ static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
225249 unsigned int verdict = NF_DROP;
226250 const struct arphdr *arp;
227251 bool hotdrop = false;
@@ -237,9 +261,10 @@ unsigned int arpt_do_table(struct sk_buff *skb, · 9 unmodified lines
237261 indev = in ? in->name : nulldevname;
238262 outdev = out ? out->name : nulldevname;
239263
240− read_lock_bh(&table->lock);
241− private = table->private;
242− table_base = (void *)private->entries[smp_processor_id()];
264+ rcu_read_lock();
265+ private = rcu_dereference(table->private);
266+ table_base = rcu_dereference(private->entries[smp_processor_id()]);
267+
243268 e = get_entry(table_base, private->hook_entry[hook]);
244269 back = get_entry(table_base, private->underflow[hook]);
245270
@@ -311,7 +336,8 @@ unsigned int arpt_do_table(struct sk_buff *skb, · 65 unmodified lines
311336 e = (void *)e + e->next_offset;
312337 }
313338 } while (!hotdrop);
314− read_unlock_bh(&table->lock);
339+
340+ rcu_read_unlock();
315341
316342 if (hotdrop)
317343 return NF_DROP;
@@ -714,11 +740,65 @@ static void get_counters(const struct xt_table_info *t, · 396 unmodified lines
714740 }
715741 }
716742
717−static inline struct xt_counters *alloc_counters(struct xt_table *table)
743+
744+/* We're lazy, and add to the first CPU; overflow works its fey magic
745+ * and everything is OK. */
746+static int
747+add_counter_to_entry(struct arpt_entry *e,
748+ const struct xt_counters addme[],
749+ unsigned int *i)
750+{
751+ ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
752+
753+ (*i)++;
754+ return 0;
755+}
756+
757+/* Take values from counters and add them back onto the current cpu */
758+static void put_counters(struct xt_table_info *t,
759+ const struct xt_counters counters[])
760+{
761+ unsigned int i, cpu;
762+
763+ local_bh_disable();
764+ cpu = smp_processor_id();
765+ i = 0;
766+ ARPT_ENTRY_ITERATE(t->entries[cpu],
767+ t->size,
768+ add_counter_to_entry,
769+ counters,
770+ &i);
771+ local_bh_enable();
772+}
773+
774+static inline int
775+zero_entry_counter(struct arpt_entry *e, void *arg)
776+{
777+ e->counters.bcnt = 0;
778+ e->counters.pcnt = 0;
779+ return 0;
780+}
781+
782+static void
783+clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info)
784+{
785+ unsigned int cpu;
786+ const void *loc_cpu_entry = info->entries[raw_smp_processor_id()];
787+
788+ memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
789+ for_each_possible_cpu(cpu) {
790+ memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size);
791+ ARPT_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size,
792+ zero_entry_counter, NULL);
793+ }
794+}
795+
796+static struct xt_counters *alloc_counters(struct xt_table *table)
718797 {
719798 unsigned int countersize;
720799 struct xt_counters *counters;
721− const struct xt_table_info *private = table->private;
800+ struct xt_table_info *private = table->private;
801+ struct xt_table_info *info;
722802
723803 /* We need atomic snapshot of counters: rest doesn't change
724804 * (other than comefrom, which userspace doesn't care
@@ -728,14 +808,30 @@ static inline struct xt_counters *alloc_counters(struct xt_table *table) · 3 unmodified lines
728808 counters = vmalloc_node(countersize, numa_node_id());
729809
730810 if (counters == NULL)
731− return ERR_PTR(-ENOMEM);
811+ goto nomem;
812+
813+ info = xt_alloc_table_info(private->size);
814+ if (!info)
815+ goto free_counters;
816+
817+ clone_counters(info, private);
818+
819+ mutex_lock(&table->lock);
820+ xt_table_entry_swap_rcu(private, info);
821+ synchronize_net(); /* Wait until smoke has cleared */
822+
823+ get_counters(info, counters);
824+ put_counters(private, counters);
825+ mutex_unlock(&table->lock);
732826
733− /* First, sum counters... */
734− write_lock_bh(&table->lock);
735− get_counters(private, counters);
736− write_unlock_bh(&table->lock);
827+ xt_free_table_info(info);
737828
738829 return counters;
830+
831+ free_counters:
832+ vfree(counters);
833+ nomem:
834+ return ERR_PTR(-ENOMEM);
739835 }
740836
741837 static int copy_entries_to_user(unsigned int total_size,
@@ -1075,20 +1171,6 @@ static int do_replace(struct net *net, void __user *user, unsigned int len) · 333 unmodified lines
10751171 return ret;
10761172 }
10771173
1078−/* We're lazy, and add to the first CPU; overflow works its fey magic
1079− * and everything is OK.
1080− */
1081−static inline int add_counter_to_entry(struct arpt_entry *e,
1082− const struct xt_counters addme[],
1083− unsigned int *i)
1084−{
1085−
1086− ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1087−
1088− (*i)++;
1089− return 0;
1090−}
1091−
10921174 static int do_add_counters(struct net *net, void __user *user, unsigned int len,
10931175 int compat)
10941176 {
@@ -1148,13 +1230,14 @@ static int do_add_counters(struct net *net, void __user *user, unsigned int len, · 53 unmodified lines
11481230 goto free;
11491231 }
11501232
1151− write_lock_bh(&t->lock);
1233+ mutex_lock(&t->lock);
11521234 private = t->private;
11531235 if (private->number != num_counters) {
11541236 ret = -EINVAL;
11551237 goto unlock_up_free;
11561238 }
11571239
1240+ preempt_disable();
11581241 i = 0;
11591242 /* Choose the copy that is on our node */
11601243 loc_cpu_entry = private->entries[smp_processor_id()];
@@ -1163,8 +1246,10 @@ static int do_add_counters(struct net *net, void __user *user, unsigned int len, · 2 unmodified lines
11631246 add_counter_to_entry,
11641247 paddc,
11651248 &i);
1249+ preempt_enable();
11661250 unlock_up_free:
1167− write_unlock_bh(&t->lock);
1251+ mutex_unlock(&t->lock);
1252+
11681253 xt_table_unlock(t);
11691254 module_put(t->me);
11701255 free:
net/ipv4/netfilter/arptable_filter.c+0−2
@@ -48,8 +48,6 @@ static struct · 47 unmodified lines
4848 static struct xt_table packet_filter = {
4949 .name = "filter",
5050 .valid_hooks = FILTER_VALID_HOOKS,
51− .lock = __RW_LOCK_UNLOCKED(packet_filter.lock),
52− .private = NULL,
5351 .me = THIS_MODULE,
5452 .af = NFPROTO_ARP,
5553 };
net/ipv4/netfilter/ip_queue.c+2−0
@@ -24,6 +24,7 @@ · 23 unmodified lines
2424 #include <linux/proc_fs.h>
2525 #include <linux/seq_file.h>
2626 #include <linux/security.h>
27+#include <linux/net.h>
2728 #include <linux/mutex.h>
2829 #include <net/net_namespace.h>
2930 #include <net/sock.h>
@@ -640,6 +641,7 @@ static void __exit ip_queue_fini(void) · 610 unmodified lines
640641 MODULE_DESCRIPTION("IPv4 packet queue handler");
641642 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
642643 MODULE_LICENSE("GPL");
644+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_FIREWALL);
643645
644646 module_init(ip_queue_init);
645647 module_exit(ip_queue_fini);
net/ipv4/netfilter/ip_tables.c+108−45
@@ -74,6 +74,25 @@ do { \ · 73 unmodified lines
7474
7575 Hence the start of any table is given by get_table() below. */
7676
77+static unsigned long ifname_compare(const char *_a, const char *_b,
78+ const unsigned char *_mask)
79+{
80+ const unsigned long *a = (const unsigned long *)_a;
81+ const unsigned long *b = (const unsigned long *)_b;
82+ const unsigned long *mask = (const unsigned long *)_mask;
83+ unsigned long ret;
84+
85+ ret = (a[0] ^ b[0]) & mask[0];
86+ if (IFNAMSIZ > sizeof(unsigned long))
87+ ret |= (a[1] ^ b[1]) & mask[1];
88+ if (IFNAMSIZ > 2 * sizeof(unsigned long))
89+ ret |= (a[2] ^ b[2]) & mask[2];
90+ if (IFNAMSIZ > 3 * sizeof(unsigned long))
91+ ret |= (a[3] ^ b[3]) & mask[3];
92+ BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
93+ return ret;
94+}
95+
7796 /* Returns whether matches rule or not. */
7897 /* Performance critical - called for every packet */
7998 static inline bool
@@ -83,7 +102,6 @@ ip_packet_match(const struct iphdr *ip, · 3 unmodified lines
83102 const struct ipt_ip *ipinfo,
84103 int isfrag)
85104 {
86− size_t i;
87105 unsigned long ret;
88106
89107 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
@@ -103,12 +121,7 @@ ip_packet_match(const struct iphdr *ip, · 13 unmodified lines
103121 return false;
104122 }
105123
106− /* Look for ifname matches; this should unroll nicely. */
107− for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
108− ret |= (((const unsigned long *)indev)[i]
109− ^ ((const unsigned long *)ipinfo->iniface)[i])
110− & ((const unsigned long *)ipinfo->iniface_mask)[i];
111− }
124+ ret = ifname_compare(indev, ipinfo->iniface, ipinfo->iniface_mask);
112125
113126 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
114127 dprintf("VIA in mismatch (%s vs %s).%s\n",
@@ -117,11 +130,7 @@ ip_packet_match(const struct iphdr *ip, · 2 unmodified lines
117130 return false;
118131 }
119132
120− for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
121− ret |= (((const unsigned long *)outdev)[i]
122− ^ ((const unsigned long *)ipinfo->outiface)[i])
123− & ((const unsigned long *)ipinfo->outiface_mask)[i];
124− }
133+ ret = ifname_compare(outdev, ipinfo->outiface, ipinfo->outiface_mask);
125134
126135 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
127136 dprintf("VIA out mismatch (%s vs %s).%s\n",
@@ -347,10 +356,12 @@ ipt_do_table(struct sk_buff *skb, · 219 unmodified lines
347356 mtpar.family = tgpar.family = NFPROTO_IPV4;
348357 tgpar.hooknum = hook;
349358
350− read_lock_bh(&table->lock);
351359 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
352− private = table->private;
353− table_base = (void *)private->entries[smp_processor_id()];
360+
361+ rcu_read_lock();
362+ private = rcu_dereference(table->private);
363+ table_base = rcu_dereference(private->entries[smp_processor_id()]);
364+
354365 e = get_entry(table_base, private->hook_entry[hook]);
355366
356367 /* For return from builtin chain */
@@ -445,7 +456,7 @@ ipt_do_table(struct sk_buff *skb, · 88 unmodified lines
445456 }
446457 } while (!hotdrop);
447458
448− read_unlock_bh(&table->lock);
459+ rcu_read_unlock();
449460
450461 #ifdef DEBUG_ALLOW_ALL
451462 return NF_ACCEPT;
@@ -924,13 +935,68 @@ get_counters(const struct xt_table_info *t, · 472 unmodified lines
924935 counters,
925936 &i);
926937 }
938+
939+}
940+
941+/* We're lazy, and add to the first CPU; overflow works its fey magic
942+ * and everything is OK. */
943+static int
944+add_counter_to_entry(struct ipt_entry *e,
945+ const struct xt_counters addme[],
946+ unsigned int *i)
947+{
948+ ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
949+
950+ (*i)++;
951+ return 0;
952+}
953+
954+/* Take values from counters and add them back onto the current cpu */
955+static void put_counters(struct xt_table_info *t,
956+ const struct xt_counters counters[])
957+{
958+ unsigned int i, cpu;
959+
960+ local_bh_disable();
961+ cpu = smp_processor_id();
962+ i = 0;
963+ IPT_ENTRY_ITERATE(t->entries[cpu],
964+ t->size,
965+ add_counter_to_entry,
966+ counters,
967+ &i);
968+ local_bh_enable();
969+}
970+
971+
972+static inline int
973+zero_entry_counter(struct ipt_entry *e, void *arg)
974+{
975+ e->counters.bcnt = 0;
976+ e->counters.pcnt = 0;
977+ return 0;
978+}
979+
980+static void
981+clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info)
982+{
983+ unsigned int cpu;
984+ const void *loc_cpu_entry = info->entries[raw_smp_processor_id()];
985+
986+ memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
987+ for_each_possible_cpu(cpu) {
988+ memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size);
989+ IPT_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size,
990+ zero_entry_counter, NULL);
991+ }
927992 }
928993
929994 static struct xt_counters * alloc_counters(struct xt_table *table)
930995 {
931996 unsigned int countersize;
932997 struct xt_counters *counters;
933− const struct xt_table_info *private = table->private;
998+ struct xt_table_info *private = table->private;
999+ struct xt_table_info *info;
9341000
9351001 /* We need atomic snapshot of counters: rest doesn't change
9361002 (other than comefrom, which userspace doesn't care
@@ -939,14 +1005,30 @@ static struct xt_counters * alloc_counters(struct xt_table *table) · 2 unmodified lines
9391005 counters = vmalloc_node(countersize, numa_node_id());
9401006
9411007 if (counters == NULL)
942− return ERR_PTR(-ENOMEM);
1008+ goto nomem;
1009+
1010+ info = xt_alloc_table_info(private->size);
1011+ if (!info)
1012+ goto free_counters;
9431013
944− /* First, sum counters... */
945− write_lock_bh(&table->lock);
946− get_counters(private, counters);
947− write_unlock_bh(&table->lock);
1014+ clone_counters(info, private);
1015+
1016+ mutex_lock(&table->lock);
1017+ xt_table_entry_swap_rcu(private, info);
1018+ synchronize_net(); /* Wait until smoke has cleared */
1019+
1020+ get_counters(info, counters);
1021+ put_counters(private, counters);
1022+ mutex_unlock(&table->lock);
1023+
1024+ xt_free_table_info(info);
9481025
9491026 return counters;
1027+
1028+ free_counters:
1029+ vfree(counters);
1030+ nomem:
1031+ return ERR_PTR(-ENOMEM);
9501032 }
9511033
9521034 static int
@@ -1312,27 +1394,6 @@ do_replace(struct net *net, void __user *user, unsigned int len) · 359 unmodified lines
13121394 return ret;
13131395 }
13141396
1315−/* We're lazy, and add to the first CPU; overflow works its fey magic
1316− * and everything is OK. */
1317−static int
1318−add_counter_to_entry(struct ipt_entry *e,
1319− const struct xt_counters addme[],
1320− unsigned int *i)
1321−{
1322−#if 0
1323− duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1324− *i,
1325− (long unsigned int)e->counters.pcnt,
1326− (long unsigned int)e->counters.bcnt,
1327− (long unsigned int)addme[*i].pcnt,
1328− (long unsigned int)addme[*i].bcnt);
1329−#endif
1330−
1331− ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1332−
1333− (*i)++;
1334− return 0;
1335−}
13361397
13371398 static int
13381399 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
@@ -1393,13 +1454,14 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, int compat · 54 unmodified lines
13931454 goto free;
13941455 }
13951456
1396− write_lock_bh(&t->lock);
1457+ mutex_lock(&t->lock);
13971458 private = t->private;
13981459 if (private->number != num_counters) {
13991460 ret = -EINVAL;
14001461 goto unlock_up_free;
14011462 }
14021463
1464+ preempt_disable();
14031465 i = 0;
14041466 /* Choose the copy that is on our node */
14051467 loc_cpu_entry = private->entries[raw_smp_processor_id()];
@@ -1408,8 +1470,9 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, int compat · 2 unmodified lines
14081470 add_counter_to_entry,
14091471 paddc,
14101472 &i);
1473+ preempt_enable();
14111474 unlock_up_free:
1412− write_unlock_bh(&t->lock);
1475+ mutex_unlock(&t->lock);
14131476 xt_table_unlock(t);
14141477 module_put(t->me);
14151478 free:
net/ipv4/netfilter/ipt_LOG.c+1−1
@@ -464,7 +464,7 @@ static struct xt_target log_tg_reg __read_mostly = { · 463 unmodified lines
464464 .me = THIS_MODULE,
465465 };
466466
467−static const struct nf_logger ipt_log_logger ={
467+static struct nf_logger ipt_log_logger __read_mostly = {
468468 .name = "ipt_LOG",
469469 .logfn = &ipt_log_packet,
470470 .me = THIS_MODULE,
net/ipv4/netfilter/ipt_TTL.c+0−97
@@ -1,97 +0,0 @@
1−/* TTL modification target for IP tables
2− * (C) 2000,2005 by Harald Welte <laforge@netfilter.org>
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License version 2 as
6− * published by the Free Software Foundation.
7− *
8− */
9−
10−#include <linux/module.h>
11−#include <linux/skbuff.h>
12−#include <linux/ip.h>
13−#include <net/checksum.h>
14−
15−#include <linux/netfilter/x_tables.h>
16−#include <linux/netfilter_ipv4/ipt_TTL.h>
17−
18−MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19−MODULE_DESCRIPTION("Xtables: IPv4 TTL field modification target");
20−MODULE_LICENSE("GPL");
21−
22−static unsigned int
23−ttl_tg(struct sk_buff *skb, const struct xt_target_param *par)
24−{
25− struct iphdr *iph;
26− const struct ipt_TTL_info *info = par->targinfo;
27− int new_ttl;
28−
29− if (!skb_make_writable(skb, skb->len))
30− return NF_DROP;
31−
32− iph = ip_hdr(skb);
33−
34− switch (info->mode) {
35− case IPT_TTL_SET:
36− new_ttl = info->ttl;
37− break;
38− case IPT_TTL_INC:
39− new_ttl = iph->ttl + info->ttl;
40− if (new_ttl > 255)
41− new_ttl = 255;
42− break;
43− case IPT_TTL_DEC:
44− new_ttl = iph->ttl - info->ttl;
45− if (new_ttl < 0)
46− new_ttl = 0;
47− break;
48− default:
49− new_ttl = iph->ttl;
50− break;
51− }
52−
53− if (new_ttl != iph->ttl) {
54− csum_replace2(&iph->check, htons(iph->ttl << 8),
55− htons(new_ttl << 8));
56− iph->ttl = new_ttl;
57− }
58−
59− return XT_CONTINUE;
60−}
61−
62−static bool ttl_tg_check(const struct xt_tgchk_param *par)
63−{
64− const struct ipt_TTL_info *info = par->targinfo;
65−
66− if (info->mode > IPT_TTL_MAXMODE) {
67− printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
68− info->mode);
69− return false;
70− }
71− if (info->mode != IPT_TTL_SET && info->ttl == 0)
72− return false;
73− return true;
74−}
75−
76−static struct xt_target ttl_tg_reg __read_mostly = {
77− .name = "TTL",
78− .family = NFPROTO_IPV4,
79− .target = ttl_tg,
80− .targetsize = sizeof(struct ipt_TTL_info),
81− .table = "mangle",
82− .checkentry = ttl_tg_check,
83− .me = THIS_MODULE,
84−};
85−
86−static int __init ttl_tg_init(void)
87−{
88− return xt_register_target(&ttl_tg_reg);
89−}
90−
91−static void __exit ttl_tg_exit(void)
92−{
93− xt_unregister_target(&ttl_tg_reg);
94−}
95−
96−module_init(ttl_tg_init);
97−module_exit(ttl_tg_exit);
net/ipv4/netfilter/ipt_ULOG.c+1−1
@@ -379,7 +379,7 @@ static struct xt_target ulog_tg_reg __read_mostly = { · 378 unmodified lines
379379 .me = THIS_MODULE,
380380 };
381381
382−static struct nf_logger ipt_ulog_logger = {
382+static struct nf_logger ipt_ulog_logger __read_mostly = {
383383 .name = "ipt_ULOG",
384384 .logfn = ipt_logfn,
385385 .me = THIS_MODULE,
net/ipv4/netfilter/ipt_ttl.c+0−63
@@ -1,63 +0,0 @@
1−/* IP tables module for matching the value of the TTL
2− *
3− * (C) 2000,2001 by Harald Welte <laforge@netfilter.org>
4− *
5− * This program is free software; you can redistribute it and/or modify
6− * it under the terms of the GNU General Public License version 2 as
7− * published by the Free Software Foundation.
8− */
9−
10−#include <linux/ip.h>
11−#include <linux/module.h>
12−#include <linux/skbuff.h>
13−
14−#include <linux/netfilter_ipv4/ipt_ttl.h>
15−#include <linux/netfilter/x_tables.h>
16−
17−MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
18−MODULE_DESCRIPTION("Xtables: IPv4 TTL field match");
19−MODULE_LICENSE("GPL");
20−
21−static bool ttl_mt(const struct sk_buff *skb, const struct xt_match_param *par)
22−{
23− const struct ipt_ttl_info *info = par->matchinfo;
24− const u8 ttl = ip_hdr(skb)->ttl;
25−
26− switch (info->mode) {
27− case IPT_TTL_EQ:
28− return ttl == info->ttl;
29− case IPT_TTL_NE:
30− return ttl != info->ttl;
31− case IPT_TTL_LT:
32− return ttl < info->ttl;
33− case IPT_TTL_GT:
34− return ttl > info->ttl;
35− default:
36− printk(KERN_WARNING "ipt_ttl: unknown mode %d\n",
37− info->mode);
38− return false;
39− }
40−
41− return false;
42−}
43−
44−static struct xt_match ttl_mt_reg __read_mostly = {
45− .name = "ttl",
46− .family = NFPROTO_IPV4,
47− .match = ttl_mt,
48− .matchsize = sizeof(struct ipt_ttl_info),
49− .me = THIS_MODULE,
50−};
51−
52−static int __init ttl_mt_init(void)
53−{
54− return xt_register_match(&ttl_mt_reg);
55−}
56−
57−static void __exit ttl_mt_exit(void)
58−{
59− xt_unregister_match(&ttl_mt_reg);
60−}
61−
62−module_init(ttl_mt_init);
63−module_exit(ttl_mt_exit);
net/ipv4/netfilter/iptable_filter.c+0−1
@@ -56,7 +56,6 @@ static struct · 55 unmodified lines
5656 static struct xt_table packet_filter = {
5757 .name = "filter",
5858 .valid_hooks = FILTER_VALID_HOOKS,
59− .lock = __RW_LOCK_UNLOCKED(packet_filter.lock),
6059 .me = THIS_MODULE,
6160 .af = AF_INET,
6261 };
net/ipv4/netfilter/iptable_mangle.c+0−1
@@ -67,7 +67,6 @@ static struct · 66 unmodified lines
6767 static struct xt_table packet_mangler = {
6868 .name = "mangle",
6969 .valid_hooks = MANGLE_VALID_HOOKS,
70− .lock = __RW_LOCK_UNLOCKED(packet_mangler.lock),
7170 .me = THIS_MODULE,
7271 .af = AF_INET,
7372 };
net/ipv4/netfilter/iptable_raw.c+0−1
@@ -39,7 +39,6 @@ static struct · 38 unmodified lines
3939 static struct xt_table packet_raw = {
4040 .name = "raw",
4141 .valid_hooks = RAW_VALID_HOOKS,
42− .lock = __RW_LOCK_UNLOCKED(packet_raw.lock),
4342 .me = THIS_MODULE,
4443 .af = AF_INET,
4544 };
net/ipv4/netfilter/iptable_security.c+0−1
@@ -60,7 +60,6 @@ static struct · 59 unmodified lines
6060 static struct xt_table security_table = {
6161 .name = "security",
6262 .valid_hooks = SECURITY_VALID_HOOKS,
63− .lock = __RW_LOCK_UNLOCKED(security_table.lock),
6463 .me = THIS_MODULE,
6564 .af = AF_INET,
6665 };
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c+3−1
@@ -120,8 +120,10 @@ static unsigned int ipv4_confirm(unsigned int hooknum, · 119 unmodified lines
120120 typeof(nf_nat_seq_adjust_hook) seq_adjust;
121121
122122 seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
123− if (!seq_adjust || !seq_adjust(skb, ct, ctinfo))
123+ if (!seq_adjust || !seq_adjust(skb, ct, ctinfo)) {
124+ NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop);
124125 return NF_DROP;
126+ }
125127 }
126128 out:
127129 /* We've seen it coming out the other side: confirm it */
net/ipv4/netfilter/nf_nat_rule.c+0−1
@@ -61,7 +61,6 @@ static struct · 60 unmodified lines
6161 static struct xt_table nat_table = {
6262 .name = "nat",
6363 .valid_hooks = NAT_VALID_HOOKS,
64− .lock = __RW_LOCK_UNLOCKED(nat_table.lock),
6564 .me = THIS_MODULE,
6665 .af = AF_INET,
6766 };
net/ipv6/netfilter/Kconfig+15−23
@@ -95,13 +95,13 @@ config IP6_NF_MATCH_OPTS · 94 unmodified lines
9595 To compile it as a module, choose M here. If unsure, say N.
9696
9797 config IP6_NF_MATCH_HL
98− tristate '"hl" match support'
98+ tristate '"hl" hoplimit match support'
9999 depends on NETFILTER_ADVANCED
100− help
101− HL matching allows you to match packets based on the hop
102− limit of the packet.
103−
104− To compile it as a module, choose M here. If unsure, say N.
100+ select NETFILTER_XT_MATCH_HL
101+ ---help---
102+ This is a backwards-compat option for the user's convenience
103+ (e.g. when running oldconfig). It selects
104+ COFNIG_NETFILTER_XT_MATCH_HL.
105105
106106 config IP6_NF_MATCH_IPV6HEADER
107107 tristate '"ipv6header" IPv6 Extension Headers Match'
@@ -130,6 +130,15 @@ config IP6_NF_MATCH_RT · 22 unmodified lines
130130 To compile it as a module, choose M here. If unsure, say N.
131131
132132 # The targets
133+config IP6_NF_TARGET_HL
134+ tristate '"HL" hoplimit target support'
135+ depends on NETFILTER_ADVANCED
136+ select NETFILTER_XT_TARGET_HL
137+ ---help---
138+ This is a backwards-compat option for the user's convenience
139+ (e.g. when running oldconfig). It selects
140+ COFNIG_NETFILTER_XT_TARGET_HL.
141+
133142 config IP6_NF_TARGET_LOG
134143 tristate "LOG target support"
135144 default m if NETFILTER_ADVANCED=n
@@ -170,23 +179,6 @@ config IP6_NF_MANGLE · 34 unmodified lines
170179
171180 To compile it as a module, choose M here. If unsure, say N.
172181
173−config IP6_NF_TARGET_HL
174− tristate 'HL (hoplimit) target support'
175− depends on IP6_NF_MANGLE
176− depends on NETFILTER_ADVANCED
177− help
178− This option adds a `HL' target, which enables the user to decrement
179− the hoplimit value of the IPv6 header or set it to a given (lower)
180− value.
181−
182− While it is safe to decrement the hoplimit value, this option also
183− enables functionality to increment and set the hoplimit value of the
184− IPv6 header to arbitrary values. This is EXTREMELY DANGEROUS since
185− you can easily create immortal packets that loop forever on the
186− network.
187−
188− To compile it as a module, choose M here. If unsure, say N.
189−
190182 config IP6_NF_RAW
191183 tristate 'raw table support (required for TRACE)'
192184 depends on NETFILTER_ADVANCED
net/ipv6/netfilter/Makefile+0−2
@@ -20,13 +20,11 @@ obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o · 19 unmodified lines
2020 obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
2121 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
2222 obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
23−obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
2423 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
2524 obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
2625 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
2726 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
2827
2928 # targets
30−obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
3129 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
3230 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
net/ipv6/netfilter/ip6_queue.c+1−0
@@ -643,6 +643,7 @@ static void __exit ip6_queue_fini(void) · 642 unmodified lines
643643
644644 MODULE_DESCRIPTION("IPv6 packet queue handler");
645645 MODULE_LICENSE("GPL");
646+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_IP6_FW);
646647
647648 module_init(ip6_queue_init);
648649 module_exit(ip6_queue_fini);
net/ipv6/netfilter/ip6_tables.c+105−47
@@ -89,6 +89,25 @@ ip6t_ext_hdr(u8 nexthdr) · 88 unmodified lines
8989 (nexthdr == IPPROTO_DSTOPTS) );
9090 }
9191
92+static unsigned long ifname_compare(const char *_a, const char *_b,
93+ const unsigned char *_mask)
94+{
95+ const unsigned long *a = (const unsigned long *)_a;
96+ const unsigned long *b = (const unsigned long *)_b;
97+ const unsigned long *mask = (const unsigned long *)_mask;
98+ unsigned long ret;
99+
100+ ret = (a[0] ^ b[0]) & mask[0];
101+ if (IFNAMSIZ > sizeof(unsigned long))
102+ ret |= (a[1] ^ b[1]) & mask[1];
103+ if (IFNAMSIZ > 2 * sizeof(unsigned long))
104+ ret |= (a[2] ^ b[2]) & mask[2];
105+ if (IFNAMSIZ > 3 * sizeof(unsigned long))
106+ ret |= (a[3] ^ b[3]) & mask[3];
107+ BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
108+ return ret;
109+}
110+
92111 /* Returns whether matches rule or not. */
93112 /* Performance critical - called for every packet */
94113 static inline bool
@@ -99,7 +118,6 @@ ip6_packet_match(const struct sk_buff *skb, · 4 unmodified lines
99118 unsigned int *protoff,
100119 int *fragoff, bool *hotdrop)
101120 {
102− size_t i;
103121 unsigned long ret;
104122 const struct ipv6hdr *ipv6 = ipv6_hdr(skb);
105123
@@ -120,12 +138,7 @@ ip6_packet_match(const struct sk_buff *skb, · 14 unmodified lines
120138 return false;
121139 }
122140
123− /* Look for ifname matches; this should unroll nicely. */
124− for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
125− ret |= (((const unsigned long *)indev)[i]
126− ^ ((const unsigned long *)ip6info->iniface)[i])
127− & ((const unsigned long *)ip6info->iniface_mask)[i];
128− }
141+ ret = ifname_compare(indev, ip6info->iniface, ip6info->iniface_mask);
129142
130143 if (FWINV(ret != 0, IP6T_INV_VIA_IN)) {
131144 dprintf("VIA in mismatch (%s vs %s).%s\n",
@@ -134,11 +147,7 @@ ip6_packet_match(const struct sk_buff *skb, · 2 unmodified lines
134147 return false;
135148 }
136149
137− for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
138− ret |= (((const unsigned long *)outdev)[i]
139− ^ ((const unsigned long *)ip6info->outiface)[i])
140− & ((const unsigned long *)ip6info->outiface_mask)[i];
141− }
150+ ret = ifname_compare(outdev, ip6info->outiface, ip6info->outiface_mask);
142151
143152 if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) {
144153 dprintf("VIA out mismatch (%s vs %s).%s\n",
@@ -373,10 +382,12 @@ ip6t_do_table(struct sk_buff *skb, · 228 unmodified lines
373382 mtpar.family = tgpar.family = NFPROTO_IPV6;
374383 tgpar.hooknum = hook;
375384
376− read_lock_bh(&table->lock);
377385 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
378− private = table->private;
379− table_base = (void *)private->entries[smp_processor_id()];
386+
387+ rcu_read_lock();
388+ private = rcu_dereference(table->private);
389+ table_base = rcu_dereference(private->entries[smp_processor_id()]);
390+
380391 e = get_entry(table_base, private->hook_entry[hook]);
381392
382393 /* For return from builtin chain */
@@ -474,7 +485,7 @@ ip6t_do_table(struct sk_buff *skb, · 91 unmodified lines
474485 #ifdef CONFIG_NETFILTER_DEBUG
475486 ((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON;
476487 #endif
477− read_unlock_bh(&table->lock);
488+ rcu_read_unlock();
478489
479490 #ifdef DEBUG_ALLOW_ALL
480491 return NF_ACCEPT;
@@ -955,11 +966,64 @@ get_counters(const struct xt_table_info *t, · 474 unmodified lines
955966 }
956967 }
957968
969+/* We're lazy, and add to the first CPU; overflow works its fey magic
970+ * and everything is OK. */
971+static int
972+add_counter_to_entry(struct ip6t_entry *e,
973+ const struct xt_counters addme[],
974+ unsigned int *i)
975+{
976+ ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
977+
978+ (*i)++;
979+ return 0;
980+}
981+
982+/* Take values from counters and add them back onto the current cpu */
983+static void put_counters(struct xt_table_info *t,
984+ const struct xt_counters counters[])
985+{
986+ unsigned int i, cpu;
987+
988+ local_bh_disable();
989+ cpu = smp_processor_id();
990+ i = 0;
991+ IP6T_ENTRY_ITERATE(t->entries[cpu],
992+ t->size,
993+ add_counter_to_entry,
994+ counters,
995+ &i);
996+ local_bh_enable();
997+}
998+
999+static inline int
1000+zero_entry_counter(struct ip6t_entry *e, void *arg)
1001+{
1002+ e->counters.bcnt = 0;
1003+ e->counters.pcnt = 0;
1004+ return 0;
1005+}
1006+
1007+static void
1008+clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info)
1009+{
1010+ unsigned int cpu;
1011+ const void *loc_cpu_entry = info->entries[raw_smp_processor_id()];
1012+
1013+ memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1014+ for_each_possible_cpu(cpu) {
1015+ memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size);
1016+ IP6T_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size,
1017+ zero_entry_counter, NULL);
1018+ }
1019+}
1020+
9581021 static struct xt_counters *alloc_counters(struct xt_table *table)
9591022 {
9601023 unsigned int countersize;
9611024 struct xt_counters *counters;
962− const struct xt_table_info *private = table->private;
1025+ struct xt_table_info *private = table->private;
1026+ struct xt_table_info *info;
9631027
9641028 /* We need atomic snapshot of counters: rest doesn't change
9651029 (other than comefrom, which userspace doesn't care
@@ -968,14 +1032,28 @@ static struct xt_counters *alloc_counters(struct xt_table *table) · 2 unmodified lines
9681032 counters = vmalloc_node(countersize, numa_node_id());
9691033
9701034 if (counters == NULL)
971− return ERR_PTR(-ENOMEM);
1035+ goto nomem;
1036+
1037+ info = xt_alloc_table_info(private->size);
1038+ if (!info)
1039+ goto free_counters;
1040+
1041+ clone_counters(info, private);
9721042
973− /* First, sum counters... */
974− write_lock_bh(&table->lock);
975− get_counters(private, counters);
976− write_unlock_bh(&table->lock);
1043+ mutex_lock(&table->lock);
1044+ xt_table_entry_swap_rcu(private, info);
1045+ synchronize_net(); /* Wait until smoke has cleared */
9771046
978− return counters;
1047+ get_counters(info, counters);
1048+ put_counters(private, counters);
1049+ mutex_unlock(&table->lock);
1050+
1051+ xt_free_table_info(info);
1052+
1053+ free_counters:
1054+ vfree(counters);
1055+ nomem:
1056+ return ERR_PTR(-ENOMEM);
9791057 }
9801058
9811059 static int
@@ -1342,28 +1420,6 @@ do_replace(struct net *net, void __user *user, unsigned int len) · 360 unmodified lines
13421420 return ret;
13431421 }
13441422
1345−/* We're lazy, and add to the first CPU; overflow works its fey magic
1346− * and everything is OK. */
1347−static inline int
1348−add_counter_to_entry(struct ip6t_entry *e,
1349− const struct xt_counters addme[],
1350− unsigned int *i)
1351−{
1352−#if 0
1353− duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1354− *i,
1355− (long unsigned int)e->counters.pcnt,
1356− (long unsigned int)e->counters.bcnt,
1357− (long unsigned int)addme[*i].pcnt,
1358− (long unsigned int)addme[*i].bcnt);
1359−#endif
1360−
1361− ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1362−
1363− (*i)++;
1364− return 0;
1365−}
1366−
13671423 static int
13681424 do_add_counters(struct net *net, void __user *user, unsigned int len,
13691425 int compat)
@@ -1424,13 +1480,14 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, · 54 unmodified lines
14241480 goto free;
14251481 }
14261482
1427− write_lock_bh(&t->lock);
1483+ mutex_lock(&t->lock);
14281484 private = t->private;
14291485 if (private->number != num_counters) {
14301486 ret = -EINVAL;
14311487 goto unlock_up_free;
14321488 }
14331489
1490+ preempt_disable();
14341491 i = 0;
14351492 /* Choose the copy that is on our node */
14361493 loc_cpu_entry = private->entries[raw_smp_processor_id()];
@@ -1439,8 +1496,9 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, · 2 unmodified lines
14391496 add_counter_to_entry,
14401497 paddc,
14411498 &i);
1499+ preempt_enable();
14421500 unlock_up_free:
1443− write_unlock_bh(&t->lock);
1501+ mutex_unlock(&t->lock);
14441502 xt_table_unlock(t);
14451503 module_put(t->me);
14461504 free:
net/ipv6/netfilter/ip6t_HL.c+0−95
@@ -1,95 +0,0 @@
1−/*
2− * Hop Limit modification target for ip6tables
3− * Maciej Soltysiak <solt@dns.toxicfilms.tv>
4− * Based on HW's TTL module
5− *
6− * This software is distributed under the terms of GNU GPL
7− */
8−
9−#include <linux/module.h>
10−#include <linux/skbuff.h>
11−#include <linux/ip.h>
12−#include <linux/ipv6.h>
13−
14−#include <linux/netfilter/x_tables.h>
15−#include <linux/netfilter_ipv6/ip6t_HL.h>
16−
17−MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
18−MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field modification target");
19−MODULE_LICENSE("GPL");
20−
21−static unsigned int
22−hl_tg6(struct sk_buff *skb, const struct xt_target_param *par)
23−{
24− struct ipv6hdr *ip6h;
25− const struct ip6t_HL_info *info = par->targinfo;
26− int new_hl;
27−
28− if (!skb_make_writable(skb, skb->len))
29− return NF_DROP;
30−
31− ip6h = ipv6_hdr(skb);
32−
33− switch (info->mode) {
34− case IP6T_HL_SET:
35− new_hl = info->hop_limit;
36− break;
37− case IP6T_HL_INC:
38− new_hl = ip6h->hop_limit + info->hop_limit;
39− if (new_hl > 255)
40− new_hl = 255;
41− break;
42− case IP6T_HL_DEC:
43− new_hl = ip6h->hop_limit - info->hop_limit;
44− if (new_hl < 0)
45− new_hl = 0;
46− break;
47− default:
48− new_hl = ip6h->hop_limit;
49− break;
50− }
51−
52− ip6h->hop_limit = new_hl;
53−
54− return XT_CONTINUE;
55−}
56−
57−static bool hl_tg6_check(const struct xt_tgchk_param *par)
58−{
59− const struct ip6t_HL_info *info = par->targinfo;
60−
61− if (info->mode > IP6T_HL_MAXMODE) {
62− printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
63− info->mode);
64− return false;
65− }
66− if (info->mode != IP6T_HL_SET && info->hop_limit == 0) {
67− printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
68− "make sense with value 0\n");
69− return false;
70− }
71− return true;
72−}
73−
74−static struct xt_target hl_tg6_reg __read_mostly = {
75− .name = "HL",
76− .family = NFPROTO_IPV6,
77− .target = hl_tg6,
78− .targetsize = sizeof(struct ip6t_HL_info),
79− .table = "mangle",
80− .checkentry = hl_tg6_check,
81− .me = THIS_MODULE
82−};
83−
84−static int __init hl_tg6_init(void)
85−{
86− return xt_register_target(&hl_tg6_reg);
87−}
88−
89−static void __exit hl_tg6_exit(void)
90−{
91− xt_unregister_target(&hl_tg6_reg);
92−}
93−
94−module_init(hl_tg6_init);
95−module_exit(hl_tg6_exit);
net/ipv6/netfilter/ip6t_LOG.c+1−1
@@ -477,7 +477,7 @@ static struct xt_target log_tg6_reg __read_mostly = { · 476 unmodified lines
477477 .me = THIS_MODULE,
478478 };
479479
480−static const struct nf_logger ip6t_logger = {
480+static struct nf_logger ip6t_logger __read_mostly = {
481481 .name = "ip6t_LOG",
482482 .logfn = &ip6t_log_packet,
483483 .me = THIS_MODULE,
net/ipv6/netfilter/ip6t_hl.c+0−68
@@ -1,68 +0,0 @@
1−/* Hop Limit matching module */
2−
3−/* (C) 2001-2002 Maciej Soltysiak <solt@dns.toxicfilms.tv>
4− * Based on HW's ttl module
5− *
6− * This program is free software; you can redistribute it and/or modify
7− * it under the terms of the GNU General Public License version 2 as
8− * published by the Free Software Foundation.
9− */
10−
11−#include <linux/ipv6.h>
12−#include <linux/module.h>
13−#include <linux/skbuff.h>
14−
15−#include <linux/netfilter_ipv6/ip6t_hl.h>
16−#include <linux/netfilter/x_tables.h>
17−
18−MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
19−MODULE_DESCRIPTION("Xtables: IPv6 Hop Limit field match");
20−MODULE_LICENSE("GPL");
21−
22−static bool hl_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
23−{
24− const struct ip6t_hl_info *info = par->matchinfo;
25− const struct ipv6hdr *ip6h = ipv6_hdr(skb);
26−
27− switch (info->mode) {
28− case IP6T_HL_EQ:
29− return ip6h->hop_limit == info->hop_limit;
30− break;
31− case IP6T_HL_NE:
32− return ip6h->hop_limit != info->hop_limit;
33− break;
34− case IP6T_HL_LT:
35− return ip6h->hop_limit < info->hop_limit;
36− break;
37− case IP6T_HL_GT:
38− return ip6h->hop_limit > info->hop_limit;
39− break;
40− default:
41− printk(KERN_WARNING "ip6t_hl: unknown mode %d\n",
42− info->mode);
43− return false;
44− }
45−
46− return false;
47−}
48−
49−static struct xt_match hl_mt6_reg __read_mostly = {
50− .name = "hl",
51− .family = NFPROTO_IPV6,
52− .match = hl_mt6,
53− .matchsize = sizeof(struct ip6t_hl_info),
54− .me = THIS_MODULE,
55−};
56−
57−static int __init hl_mt6_init(void)
58−{
59− return xt_register_match(&hl_mt6_reg);
60−}
61−
62−static void __exit hl_mt6_exit(void)
63−{
64− xt_unregister_match(&hl_mt6_reg);
65−}
66−
67−module_init(hl_mt6_init);
68−module_exit(hl_mt6_exit);
net/ipv6/netfilter/ip6table_filter.c+0−1
@@ -54,7 +54,6 @@ static struct · 53 unmodified lines
5454 static struct xt_table packet_filter = {
5555 .name = "filter",
5656 .valid_hooks = FILTER_VALID_HOOKS,
57− .lock = __RW_LOCK_UNLOCKED(packet_filter.lock),
5857 .me = THIS_MODULE,
5958 .af = AF_INET6,
6059 };
net/ipv6/netfilter/ip6table_mangle.c+0−1
@@ -60,7 +60,6 @@ static struct · 59 unmodified lines
6060 static struct xt_table packet_mangler = {
6161 .name = "mangle",
6262 .valid_hooks = MANGLE_VALID_HOOKS,
63− .lock = __RW_LOCK_UNLOCKED(packet_mangler.lock),
6463 .me = THIS_MODULE,
6564 .af = AF_INET6,
6665 };
net/ipv6/netfilter/ip6table_raw.c+0−1
@@ -38,7 +38,6 @@ static struct · 37 unmodified lines
3838 static struct xt_table packet_raw = {
3939 .name = "raw",
4040 .valid_hooks = RAW_VALID_HOOKS,
41− .lock = __RW_LOCK_UNLOCKED(packet_raw.lock),
4241 .me = THIS_MODULE,
4342 .af = AF_INET6,
4443 };
net/ipv6/netfilter/ip6table_security.c+0−1
@@ -59,7 +59,6 @@ static struct · 58 unmodified lines
5959 static struct xt_table security_table = {
6060 .name = "security",
6161 .valid_hooks = SECURITY_VALID_HOOKS,
62− .lock = __RW_LOCK_UNLOCKED(security_table.lock),
6362 .me = THIS_MODULE,
6463 .af = AF_INET6,
6564 };
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c+1−0
@@ -26,6 +26,7 @@ · 25 unmodified lines
2626 #include <net/netfilter/nf_conntrack_l4proto.h>
2727 #include <net/netfilter/nf_conntrack_l3proto.h>
2828 #include <net/netfilter/nf_conntrack_core.h>
29+#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
2930
3031 static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
3132 struct nf_conntrack_tuple *tuple)
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c+4−0
@@ -126,6 +126,10 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, · 125 unmodified lines
126126 pr_debug("icmpv6: can't create new conn with type %u\n",
127127 type + 128);
128128 nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple);
129+ if (LOG_INVALID(nf_ct_net(ct), IPPROTO_ICMPV6))
130+ nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
131+ "nf_ct_icmpv6: invalid new with type %d ",
132+ type + 128);
129133 return false;
130134 }
131135 atomic_set(&ct->proto.icmp.count, 0);
net/netfilter/Kconfig+63−0
@@ -357,6 +357,45 @@ config NETFILTER_XT_TARGET_DSCP · 356 unmodified lines
357357
358358 To compile it as a module, choose M here. If unsure, say N.
359359
360+config NETFILTER_XT_TARGET_HL
361+ tristate '"HL" hoplimit target support'
362+ depends on IP_NF_MANGLE || IP6_NF_MANGLE
363+ depends on NETFILTER_ADVANCED
364+ ---help---
365+ This option adds the "HL" (for IPv6) and "TTL" (for IPv4)
366+ targets, which enable the user to change the
367+ hoplimit/time-to-live value of the IP header.
368+
369+ While it is safe to decrement the hoplimit/TTL value, the
370+ modules also allow to increment and set the hoplimit value of
371+ the header to arbitrary values. This is EXTREMELY DANGEROUS
372+ since you can easily create immortal packets that loop
373+ forever on the network.
374+
375+config NETFILTER_XT_TARGET_LED
376+ tristate '"LED" target support'
377+ depends on LEDS_CLASS
378+ depends on NETFILTER_ADVANCED
379+ help
380+ This option adds a `LED' target, which allows you to blink LEDs in
381+ response to particular packets passing through your machine.
382+
383+ This can be used to turn a spare LED into a network activity LED,
384+ which only flashes in response to FTP transfers, for example. Or
385+ you could have an LED which lights up for a minute or two every time
386+ somebody connects to your machine via SSH.
387+
388+ You will need support for the "led" class to make this work.
389+
390+ To create an LED trigger for incoming SSH traffic:
391+ iptables -A INPUT -p tcp --dport 22 -j LED --led-trigger-id ssh --led-delay 1000
392+
393+ Then attach the new trigger to an LED on your system:
394+ echo netfilter-ssh > /sys/class/leds/<ledname>/trigger
395+
396+ For more information on the LEDs available on your system, see
397+ Documentation/leds-class.txt
398+
360399 config NETFILTER_XT_TARGET_MARK
361400 tristate '"MARK" target support'
362401 default m if NETFILTER_ADVANCED=n
@@ -488,6 +527,22 @@ config NETFILTER_XT_TARGET_TCPOPTSTRIP · 125 unmodified lines
488527 This option adds a "TCPOPTSTRIP" target, which allows you to strip
489528 TCP options from TCP packets.
490529
530+config NETFILTER_XT_MATCH_CLUSTER
531+ tristate '"cluster" match support'
532+ depends on NF_CONNTRACK
533+ depends on NETFILTER_ADVANCED
534+ ---help---
535+ This option allows you to build work-load-sharing clusters of
536+ network servers/stateful firewalls without having a dedicated
537+ load-balancing router/server/switch. Basically, this match returns
538+ true when the packet must be handled by this cluster node. Thus,
539+ all nodes see all packets and this match decides which node handles
540+ what packets. The work-load sharing algorithm is based on source
541+ address hashing.
542+
543+ If you say Y or M here, try `iptables -m cluster --help` for
544+ more information.
545+
491546 config NETFILTER_XT_MATCH_COMMENT
492547 tristate '"comment" match support'
493548 depends on NETFILTER_ADVANCED
@@ -605,6 +660,14 @@ config NETFILTER_XT_MATCH_HELPER · 111 unmodified lines
605660
606661 To compile it as a module, choose M here. If unsure, say Y.
607662
663+config NETFILTER_XT_MATCH_HL
664+ tristate '"hl" hoplimit/TTL match support'
665+ depends on NETFILTER_ADVANCED
666+ ---help---
667+ HL matching allows you to match packets based on the hoplimit
668+ in the IPv6 header, or the time-to-live field in the IPv4
669+ header of the packet.
670+
608671 config NETFILTER_XT_MATCH_IPRANGE
609672 tristate '"iprange" address range match support'
610673 depends on NETFILTER_ADVANCED
net/netfilter/Makefile+4−0
@@ -45,6 +45,8 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o · 44 unmodified lines
4545 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
4646 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
4747 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
48+obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
49+obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
4850 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
4951 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
5052 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
@@ -57,6 +59,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o · 6 unmodified lines
5759 obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
5860
5961 # matches
62+obj-$(CONFIG_NETFILTER_XT_MATCH_CLUSTER) += xt_cluster.o
6063 obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
6164 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
6265 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o
@@ -67,6 +70,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o · 4 unmodified lines
6770 obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
6871 obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
6972 obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
73+obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.o
7074 obj-$(CONFIG_NETFILTER_XT_MATCH_IPRANGE) += xt_iprange.o
7175 obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
7276 obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
net/netfilter/core.c+0−2
@@ -174,7 +174,6 @@ next_hook: · 173 unmodified lines
174174 outdev, &elem, okfn, hook_thresh);
175175 if (verdict == NF_ACCEPT || verdict == NF_STOP) {
176176 ret = 1;
177− goto unlock;
178177 } else if (verdict == NF_DROP) {
179178 kfree_skb(skb);
180179 ret = -EPERM;
@@ -183,7 +182,6 @@ next_hook: · 2 unmodified lines
183182 verdict >> NF_VERDICT_BITS))
184183 goto next_hook;
185184 }
186−unlock:
187185 rcu_read_unlock();
188186 return ret;
189187 }
net/netfilter/nf_conntrack_core.c+9−5
@@ -54,7 +54,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_lock); · 53 unmodified lines
5454 unsigned int nf_conntrack_htable_size __read_mostly;
5555 EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
5656
57−int nf_conntrack_max __read_mostly;
57+unsigned int nf_conntrack_max __read_mostly;
5858 EXPORT_SYMBOL_GPL(nf_conntrack_max);
5959
6060 struct nf_conn nf_conntrack_untracked __read_mostly;
@@ -472,7 +472,8 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, · 411 unmodified lines
472472 struct nf_conn *ct;
473473
474474 if (unlikely(!nf_conntrack_hash_rnd_initted)) {
475− get_random_bytes(&nf_conntrack_hash_rnd, 4);
475+ get_random_bytes(&nf_conntrack_hash_rnd,
476+ sizeof(nf_conntrack_hash_rnd));
476477 nf_conntrack_hash_rnd_initted = 1;
477478 }
478479
@@ -516,16 +517,17 @@ EXPORT_SYMBOL_GPL(nf_conntrack_alloc); · 37 unmodified lines
516517 static void nf_conntrack_free_rcu(struct rcu_head *head)
517518 {
518519 struct nf_conn *ct = container_of(head, struct nf_conn, rcu);
519− struct net *net = nf_ct_net(ct);
520520
521521 nf_ct_ext_free(ct);
522522 kmem_cache_free(nf_conntrack_cachep, ct);
523− atomic_dec(&net->ct.count);
524523 }
525524
526525 void nf_conntrack_free(struct nf_conn *ct)
527526 {
527+ struct net *net = nf_ct_net(ct);
528+
528529 nf_ct_ext_destroy(ct);
530+ atomic_dec(&net->ct.count);
529531 call_rcu(&ct->rcu, nf_conntrack_free_rcu);
530532 }
531533 EXPORT_SYMBOL_GPL(nf_conntrack_free);
@@ -733,6 +735,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, · 201 unmodified lines
733735 nf_conntrack_put(skb->nfct);
734736 skb->nfct = NULL;
735737 NF_CT_STAT_INC_ATOMIC(net, invalid);
738+ if (ret == -NF_DROP)
739+ NF_CT_STAT_INC_ATOMIC(net, drop);
736740 return -ret;
737741 }
738742
@@ -1103,7 +1107,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) · 364 unmodified lines
11031107
11041108 /* We have to rehahs for the new table anyway, so we also can
11051109 * use a newrandom seed */
1106− get_random_bytes(&rnd, 4);
1110+ get_random_bytes(&rnd, sizeof(rnd));
11071111
11081112 /* Lookups in the old hash might happen in parallel, which means we
11091113 * might get false negatives during connection lookup. New connections
net/netfilter/nf_conntrack_expect.c+2−1
@@ -72,7 +72,8 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple · 71 unmodified lines
7272 unsigned int hash;
7373
7474 if (unlikely(!nf_ct_expect_hash_rnd_initted)) {
75− get_random_bytes(&nf_ct_expect_hash_rnd, 4);
75+ get_random_bytes(&nf_ct_expect_hash_rnd,
76+ sizeof(nf_ct_expect_hash_rnd));
7677 nf_ct_expect_hash_rnd_initted = 1;
7778 }
7879
net/netfilter/nf_conntrack_netlink.c+72−89
@@ -518,6 +518,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, · 517 unmodified lines
518518 nla_put_failure:
519519 rcu_read_unlock();
520520 nlmsg_failure:
521+ nfnetlink_set_err(0, group, -ENOBUFS);
521522 kfree_skb(skb);
522523 return NOTIFY_DONE;
523524 }
@@ -599,7 +600,8 @@ ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple) · 75 unmodified lines
599600
600601 nla_parse_nested(tb, CTA_IP_MAX, attr, NULL);
601602
602− l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
603+ rcu_read_lock();
604+ l3proto = __nf_ct_l3proto_find(tuple->src.l3num);
603605
604606 if (likely(l3proto->nlattr_to_tuple)) {
605607 ret = nla_validate_nested(attr, CTA_IP_MAX,
@@ -608,7 +610,7 @@ ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple) · 2 unmodified lines
608610 ret = l3proto->nlattr_to_tuple(tb, tuple);
609611 }
610612
611− nf_ct_l3proto_put(l3proto);
613+ rcu_read_unlock();
612614
613615 return ret;
614616 }
@@ -633,7 +635,8 @@ ctnetlink_parse_tuple_proto(struct nlattr *attr, · 18 unmodified lines
633635 return -EINVAL;
634636 tuple->dst.protonum = nla_get_u8(tb[CTA_PROTO_NUM]);
635637
636− l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
638+ rcu_read_lock();
639+ l4proto = __nf_ct_l4proto_find(tuple->src.l3num, tuple->dst.protonum);
637640
638641 if (likely(l4proto->nlattr_to_tuple)) {
639642 ret = nla_validate_nested(attr, CTA_PROTO_MAX,
@@ -642,7 +645,7 @@ ctnetlink_parse_tuple_proto(struct nlattr *attr, · 2 unmodified lines
642645 ret = l4proto->nlattr_to_tuple(tb, tuple);
643646 }
644647
645− nf_ct_l4proto_put(l4proto);
648+ rcu_read_unlock();
646649
647650 return ret;
648651 }
@@ -989,10 +992,11 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[]) · 340 unmodified lines
989992
990993 nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, NULL);
991994
992− l4proto = nf_ct_l4proto_find_get(nf_ct_l3num(ct), nf_ct_protonum(ct));
995+ rcu_read_lock();
996+ l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
993997 if (l4proto->from_nlattr)
994998 err = l4proto->from_nlattr(tb, ct);
995− nf_ct_l4proto_put(l4proto);
999+ rcu_read_unlock();
9961000
9971001 return err;
9981002 }
@@ -1062,6 +1066,10 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[]) · 63 unmodified lines
10621066 {
10631067 int err;
10641068
1069+ /* only allow NAT changes and master assignation for new conntracks */
1070+ if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST] || cda[CTA_TUPLE_MASTER])
1071+ return -EOPNOTSUPP;
1072+
10651073 if (cda[CTA_HELP]) {
10661074 err = ctnetlink_change_helper(ct, cda);
10671075 if (err < 0)
@@ -1124,13 +1132,11 @@ ctnetlink_event_report(struct nf_conn *ct, u32 pid, int report) · 56 unmodified lines
11241132 report);
11251133 }
11261134
1127−static int
1135+static struct nf_conn *
11281136 ctnetlink_create_conntrack(struct nlattr *cda[],
11291137 struct nf_conntrack_tuple *otuple,
11301138 struct nf_conntrack_tuple *rtuple,
1131− struct nf_conn *master_ct,
1132− u32 pid,
1133− int report)
1139+ u8 u3)
11341140 {
11351141 struct nf_conn *ct;
11361142 int err = -EINVAL;
@@ -1138,10 +1144,10 @@ ctnetlink_create_conntrack(struct nlattr *cda[], · 1 unmodified line
11381144
11391145 ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_ATOMIC);
11401146 if (IS_ERR(ct))
1141− return -ENOMEM;
1147+ return ERR_PTR(-ENOMEM);
11421148
11431149 if (!cda[CTA_TIMEOUT])
1144− goto err;
1150+ goto err1;
11451151 ct->timeout.expires = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
11461152
11471153 ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
@@ -1152,10 +1158,8 @@ ctnetlink_create_conntrack(struct nlattr *cda[], · 4 unmodified lines
11521158 char *helpname;
11531159
11541160 err = ctnetlink_parse_help(cda[CTA_HELP], &helpname);
1155− if (err < 0) {
1156− rcu_read_unlock();
1157− goto err;
1158− }
1161+ if (err < 0)
1162+ goto err2;
11591163
11601164 helper = __nf_conntrack_helper_find_byname(helpname);
11611165 if (helper == NULL) {
@@ -1163,28 +1167,26 @@ ctnetlink_create_conntrack(struct nlattr *cda[], · 1 unmodified line
11631167 #ifdef CONFIG_MODULES
11641168 if (request_module("nfct-helper-%s", helpname) < 0) {
11651169 err = -EOPNOTSUPP;
1166− goto err;
1170+ goto err1;
11671171 }
11681172
11691173 rcu_read_lock();
11701174 helper = __nf_conntrack_helper_find_byname(helpname);
11711175 if (helper) {
1172− rcu_read_unlock();
11731176 err = -EAGAIN;
1174− goto err;
1177+ goto err2;
11751178 }
11761179 rcu_read_unlock();
11771180 #endif
11781181 err = -EOPNOTSUPP;
1179− goto err;
1182+ goto err1;
11801183 } else {
11811184 struct nf_conn_help *help;
11821185
11831186 help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
11841187 if (help == NULL) {
1185− rcu_read_unlock();
11861188 err = -ENOMEM;
1187− goto err;
1189+ goto err2;
11881190 }
11891191
11901192 /* not in hash table yet so not strictly necessary */
@@ -1193,44 +1195,34 @@ ctnetlink_create_conntrack(struct nlattr *cda[], · 2 unmodified lines
11931195 } else {
11941196 /* try an implicit helper assignation */
11951197 err = __nf_ct_try_assign_helper(ct, GFP_ATOMIC);
1196− if (err < 0) {
1197− rcu_read_unlock();
1198− goto err;
1199− }
1198+ if (err < 0)
1199+ goto err2;
12001200 }
12011201
12021202 if (cda[CTA_STATUS]) {
12031203 err = ctnetlink_change_status(ct, cda);
1204− if (err < 0) {
1205− rcu_read_unlock();
1206− goto err;
1207− }
1204+ if (err < 0)
1205+ goto err2;
12081206 }
12091207
12101208 if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
12111209 err = ctnetlink_change_nat(ct, cda);
1212− if (err < 0) {
1213− rcu_read_unlock();
1214− goto err;
1215− }
1210+ if (err < 0)
1211+ goto err2;
12161212 }
12171213
12181214 #ifdef CONFIG_NF_NAT_NEEDED
12191215 if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) {
12201216 err = ctnetlink_change_nat_seq_adj(ct, cda);
1221− if (err < 0) {
1222− rcu_read_unlock();
1223− goto err;
1224− }
1217+ if (err < 0)
1218+ goto err2;
12251219 }
12261220 #endif
12271221
12281222 if (cda[CTA_PROTOINFO]) {
12291223 err = ctnetlink_change_protoinfo(ct, cda);
1230− if (err < 0) {
1231− rcu_read_unlock();
1232− goto err;
1233− }
1224+ if (err < 0)
1225+ goto err2;
12341226 }
12351227
12361228 nf_ct_acct_ext_add(ct, GFP_ATOMIC);
@@ -1241,23 +1233,37 @@ ctnetlink_create_conntrack(struct nlattr *cda[], · 4 unmodified lines
12411233 #endif
12421234
12431235 /* setup master conntrack: this is a confirmed expectation */
1244− if (master_ct) {
1236+ if (cda[CTA_TUPLE_MASTER]) {
1237+ struct nf_conntrack_tuple master;
1238+ struct nf_conntrack_tuple_hash *master_h;
1239+ struct nf_conn *master_ct;
1240+
1241+ err = ctnetlink_parse_tuple(cda, &master, CTA_TUPLE_MASTER, u3);
1242+ if (err < 0)
1243+ goto err2;
1244+
1245+ master_h = __nf_conntrack_find(&init_net, &master);
1246+ if (master_h == NULL) {
1247+ err = -ENOENT;
1248+ goto err2;
1249+ }
1250+ master_ct = nf_ct_tuplehash_to_ctrack(master_h);
1251+ nf_conntrack_get(&master_ct->ct_general);
12451252 __set_bit(IPS_EXPECTED_BIT, &ct->status);
12461253 ct->master = master_ct;
12471254 }
12481255
1249− nf_conntrack_get(&ct->ct_general);
12501256 add_timer(&ct->timeout);
12511257 nf_conntrack_hash_insert(ct);
12521258 rcu_read_unlock();
1253− ctnetlink_event_report(ct, pid, report);
1254− nf_ct_put(ct);
12551259
1256− return 0;
1260+ return ct;
12571261
1258−err:
1262+err2:
1263+ rcu_read_unlock();
1264+err1:
12591265 nf_conntrack_free(ct);
1260− return err;
1266+ return ERR_PTR(err);
12611267 }
12621268
12631269 static int
@@ -1289,38 +1295,25 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, · 25 unmodified lines
12891295 h = __nf_conntrack_find(&init_net, &rtuple);
12901296
12911297 if (h == NULL) {
1292− struct nf_conntrack_tuple master;
1293− struct nf_conntrack_tuple_hash *master_h = NULL;
1294− struct nf_conn *master_ct = NULL;
1295−
1296− if (cda[CTA_TUPLE_MASTER]) {
1297− err = ctnetlink_parse_tuple(cda,
1298− &master,
1299− CTA_TUPLE_MASTER,
1300− u3);
1301− if (err < 0)
1302− goto out_unlock;
1298+ err = -ENOENT;
1299+ if (nlh->nlmsg_flags & NLM_F_CREATE) {
1300+ struct nf_conn *ct;
13031301
1304− master_h = __nf_conntrack_find(&init_net, &master);
1305− if (master_h == NULL) {
1306− err = -ENOENT;
1302+ ct = ctnetlink_create_conntrack(cda, &otuple,
1303+ &rtuple, u3);
1304+ if (IS_ERR(ct)) {
1305+ err = PTR_ERR(ct);
13071306 goto out_unlock;
13081307 }
1309− master_ct = nf_ct_tuplehash_to_ctrack(master_h);
1310− nf_conntrack_get(&master_ct->ct_general);
1311− }
1312−
1313− err = -ENOENT;
1314− if (nlh->nlmsg_flags & NLM_F_CREATE)
1315− err = ctnetlink_create_conntrack(cda,
1316− &otuple,
1317− &rtuple,
1318− master_ct,
1319− NETLINK_CB(skb).pid,
1320− nlmsg_report(nlh));
1321− spin_unlock_bh(&nf_conntrack_lock);
1322− if (err < 0 && master_ct)
1323− nf_ct_put(master_ct);
1308+ err = 0;
1309+ nf_conntrack_get(&ct->ct_general);
1310+ spin_unlock_bh(&nf_conntrack_lock);
1311+ ctnetlink_event_report(ct,
1312+ NETLINK_CB(skb).pid,
1313+ nlmsg_report(nlh));
1314+ nf_ct_put(ct);
1315+ } else
1316+ spin_unlock_bh(&nf_conntrack_lock);
13241317
13251318 return err;
13261319 }
@@ -1332,17 +1325,6 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, · 5 unmodified lines
13321325 if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
13331326 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
13341327
1335− /* we only allow nat config for new conntracks */
1336− if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
1337− err = -EOPNOTSUPP;
1338− goto out_unlock;
1339− }
1340− /* can't link an existing conntrack to a master */
1341− if (cda[CTA_TUPLE_MASTER]) {
1342− err = -EOPNOTSUPP;
1343− goto out_unlock;
1344− }
1345−
13461328 err = ctnetlink_change_conntrack(ct, cda);
13471329 if (err == 0) {
13481330 nf_conntrack_get(&ct->ct_general);
@@ -1533,6 +1515,7 @@ static int ctnetlink_expect_event(struct notifier_block *this, · 184 unmodified lines
15331515 nla_put_failure:
15341516 rcu_read_unlock();
15351517 nlmsg_failure:
1518+ nfnetlink_set_err(0, 0, -ENOBUFS);
15361519 kfree_skb(skb);
15371520 return NOTIFY_DONE;
15381521 }
net/netfilter/nf_conntrack_proto.c+0−21
@@ -74,27 +74,6 @@ EXPORT_SYMBOL_GPL(__nf_ct_l4proto_find); · 73 unmodified lines
7474
7575 /* this is guaranteed to always return a valid protocol helper, since
7676 * it falls back to generic_protocol */
77−struct nf_conntrack_l4proto *
78−nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto)
79−{
80− struct nf_conntrack_l4proto *p;
81−
82− rcu_read_lock();
83− p = __nf_ct_l4proto_find(l3proto, l4proto);
84− if (!try_module_get(p->me))
85− p = &nf_conntrack_l4proto_generic;
86− rcu_read_unlock();
87−
88− return p;
89−}
90−EXPORT_SYMBOL_GPL(nf_ct_l4proto_find_get);
91−
92−void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p)
93−{
94− module_put(p->me);
95−}
96−EXPORT_SYMBOL_GPL(nf_ct_l4proto_put);
97−
9877 struct nf_conntrack_l3proto *
9978 nf_ct_l3proto_find_get(u_int16_t l3proto)
10079 {
net/netfilter/nf_conntrack_proto_dccp.c+108−37
@@ -16,6 +16,9 @@ · 15 unmodified lines
1616 #include <linux/skbuff.h>
1717 #include <linux/dccp.h>
1818
19+#include <net/net_namespace.h>
20+#include <net/netns/generic.h>
21+
1922 #include <linux/netfilter/nfnetlink_conntrack.h>
2023 #include <net/netfilter/nf_conntrack.h>
2124 #include <net/netfilter/nf_conntrack_l4proto.h>
@@ -23,8 +26,6 @@ · 1 unmodified line
2326
2427 static DEFINE_RWLOCK(dccp_lock);
2528
26−static int nf_ct_dccp_loose __read_mostly = 1;
27−
2829 /* Timeouts are based on values from RFC4340:
2930 *
3031 * - REQUEST:
@@ -72,16 +73,6 @@ static int nf_ct_dccp_loose __read_mostly = 1; · 41 unmodified lines
7273
7374 #define DCCP_MSL (2 * 60 * HZ)
7475
75−static unsigned int dccp_timeout[CT_DCCP_MAX + 1] __read_mostly = {
76− [CT_DCCP_REQUEST] = 2 * DCCP_MSL,
77− [CT_DCCP_RESPOND] = 4 * DCCP_MSL,
78− [CT_DCCP_PARTOPEN] = 4 * DCCP_MSL,
79− [CT_DCCP_OPEN] = 12 * 3600 * HZ,
80− [CT_DCCP_CLOSEREQ] = 64 * HZ,
81− [CT_DCCP_CLOSING] = 64 * HZ,
82− [CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL,
83−};
84−
8576 static const char * const dccp_state_names[] = {
8677 [CT_DCCP_NONE] = "NONE",
8778 [CT_DCCP_REQUEST] = "REQUEST",
@@ -393,6 +384,22 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = · 305 unmodified lines
393384 },
394385 };
395386
387+/* this module per-net specifics */
388+static int dccp_net_id;
389+struct dccp_net {
390+ int dccp_loose;
391+ unsigned int dccp_timeout[CT_DCCP_MAX + 1];
392+#ifdef CONFIG_SYSCTL
393+ struct ctl_table_header *sysctl_header;
394+ struct ctl_table *sysctl_table;
395+#endif
396+};
397+
398+static inline struct dccp_net *dccp_pernet(struct net *net)
399+{
400+ return net_generic(net, dccp_net_id);
401+}
402+
396403 static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
397404 struct nf_conntrack_tuple *tuple)
398405 {
@@ -419,6 +426,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, · 20 unmodified lines
419426 unsigned int dataoff)
420427 {
421428 struct net *net = nf_ct_net(ct);
429+ struct dccp_net *dn;
422430 struct dccp_hdr _dh, *dh;
423431 const char *msg;
424432 u_int8_t state;
@@ -429,7 +437,8 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, · 4 unmodified lines
429437 state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
430438 switch (state) {
431439 default:
432− if (nf_ct_dccp_loose == 0) {
440+ dn = dccp_pernet(net);
441+ if (dn->dccp_loose == 0) {
433442 msg = "nf_ct_dccp: not picking up existing connection ";
434443 goto out_invalid;
435444 }
@@ -465,6 +474,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, · 29 unmodified lines
465474 u_int8_t pf, unsigned int hooknum)
466475 {
467476 struct net *net = nf_ct_net(ct);
477+ struct dccp_net *dn;
468478 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
469479 struct dccp_hdr _dh, *dh;
470480 u_int8_t type, old_state, new_state;
@@ -542,7 +552,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, · 71 unmodified lines
542552 ct->proto.dccp.last_pkt = type;
543553 ct->proto.dccp.state = new_state;
544554 write_unlock_bh(&dccp_lock);
545− nf_ct_refresh_acct(ct, ctinfo, skb, dccp_timeout[new_state]);
555+
556+ dn = dccp_pernet(net);
557+ nf_ct_refresh_acct(ct, ctinfo, skb, dn->dccp_timeout[new_state]);
546558
547559 return NF_ACCEPT;
548560 }
@@ -660,13 +672,11 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) · 111 unmodified lines
660672 #endif
661673
662674 #ifdef CONFIG_SYSCTL
663−static unsigned int dccp_sysctl_table_users;
664−static struct ctl_table_header *dccp_sysctl_header;
665−static ctl_table dccp_sysctl_table[] = {
675+/* template, data assigned later */
676+static struct ctl_table dccp_sysctl_table[] = {
666677 {
667678 .ctl_name = CTL_UNNUMBERED,
668679 .procname = "nf_conntrack_dccp_timeout_request",
669− .data = &dccp_timeout[CT_DCCP_REQUEST],
670680 .maxlen = sizeof(unsigned int),
671681 .mode = 0644,
672682 .proc_handler = proc_dointvec_jiffies,
@@ -674,7 +684,6 @@ static ctl_table dccp_sysctl_table[] = { · 1 unmodified line
674684 {
675685 .ctl_name = CTL_UNNUMBERED,
676686 .procname = "nf_conntrack_dccp_timeout_respond",
677− .data = &dccp_timeout[CT_DCCP_RESPOND],
678687 .maxlen = sizeof(unsigned int),
679688 .mode = 0644,
680689 .proc_handler = proc_dointvec_jiffies,
@@ -682,7 +691,6 @@ static ctl_table dccp_sysctl_table[] = { · 1 unmodified line
682691 {
683692 .ctl_name = CTL_UNNUMBERED,
684693 .procname = "nf_conntrack_dccp_timeout_partopen",
685− .data = &dccp_timeout[CT_DCCP_PARTOPEN],
686694 .maxlen = sizeof(unsigned int),
687695 .mode = 0644,
688696 .proc_handler = proc_dointvec_jiffies,
@@ -690,7 +698,6 @@ static ctl_table dccp_sysctl_table[] = { · 1 unmodified line
690698 {
691699 .ctl_name = CTL_UNNUMBERED,
692700 .procname = "nf_conntrack_dccp_timeout_open",
693− .data = &dccp_timeout[CT_DCCP_OPEN],
694701 .maxlen = sizeof(unsigned int),
695702 .mode = 0644,
696703 .proc_handler = proc_dointvec_jiffies,
@@ -698,7 +705,6 @@ static ctl_table dccp_sysctl_table[] = { · 1 unmodified line
698705 {
699706 .ctl_name = CTL_UNNUMBERED,
700707 .procname = "nf_conntrack_dccp_timeout_closereq",
701− .data = &dccp_timeout[CT_DCCP_CLOSEREQ],
702708 .maxlen = sizeof(unsigned int),
703709 .mode = 0644,
704710 .proc_handler = proc_dointvec_jiffies,
@@ -706,7 +712,6 @@ static ctl_table dccp_sysctl_table[] = { · 1 unmodified line
706712 {
707713 .ctl_name = CTL_UNNUMBERED,
708714 .procname = "nf_conntrack_dccp_timeout_closing",
709− .data = &dccp_timeout[CT_DCCP_CLOSING],
710715 .maxlen = sizeof(unsigned int),
711716 .mode = 0644,
712717 .proc_handler = proc_dointvec_jiffies,
@@ -714,7 +719,6 @@ static ctl_table dccp_sysctl_table[] = { · 1 unmodified line
714719 {
715720 .ctl_name = CTL_UNNUMBERED,
716721 .procname = "nf_conntrack_dccp_timeout_timewait",
717− .data = &dccp_timeout[CT_DCCP_TIMEWAIT],
718722 .maxlen = sizeof(unsigned int),
719723 .mode = 0644,
720724 .proc_handler = proc_dointvec_jiffies,
@@ -722,8 +726,7 @@ static ctl_table dccp_sysctl_table[] = { · 1 unmodified line
722726 {
723727 .ctl_name = CTL_UNNUMBERED,
724728 .procname = "nf_conntrack_dccp_loose",
725− .data = &nf_ct_dccp_loose,
726− .maxlen = sizeof(nf_ct_dccp_loose),
729+ .maxlen = sizeof(int),
727730 .mode = 0644,
728731 .proc_handler = proc_dointvec,
729732 },
@@ -751,11 +754,6 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { · 21 unmodified lines
751754 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
752755 .nla_policy = nf_ct_port_nla_policy,
753756 #endif
754−#ifdef CONFIG_SYSCTL
755− .ctl_table_users = &dccp_sysctl_table_users,
756− .ctl_table_header = &dccp_sysctl_header,
757− .ctl_table = dccp_sysctl_table,
758−#endif
759757 };
760758
761759 static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
@@ -776,34 +774,107 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { · 14 unmodified lines
776774 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
777775 .nla_policy = nf_ct_port_nla_policy,
778776 #endif
777+};
778+
779+static __net_init int dccp_net_init(struct net *net)
780+{
781+ struct dccp_net *dn;
782+ int err;
783+
784+ dn = kmalloc(sizeof(*dn), GFP_KERNEL);
785+ if (!dn)
786+ return -ENOMEM;
787+
788+ /* default values */
789+ dn->dccp_loose = 1;
790+ dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL;
791+ dn->dccp_timeout[CT_DCCP_RESPOND] = 4 * DCCP_MSL;
792+ dn->dccp_timeout[CT_DCCP_PARTOPEN] = 4 * DCCP_MSL;
793+ dn->dccp_timeout[CT_DCCP_OPEN] = 12 * 3600 * HZ;
794+ dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ;
795+ dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ;
796+ dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL;
797+
798+ err = net_assign_generic(net, dccp_net_id, dn);
799+ if (err)
800+ goto out;
801+
779802 #ifdef CONFIG_SYSCTL
780− .ctl_table_users = &dccp_sysctl_table_users,
781− .ctl_table_header = &dccp_sysctl_header,
782− .ctl_table = dccp_sysctl_table,
803+ err = -ENOMEM;
804+ dn->sysctl_table = kmemdup(dccp_sysctl_table,
805+ sizeof(dccp_sysctl_table), GFP_KERNEL);
806+ if (!dn->sysctl_table)
807+ goto out;
808+
809+ dn->sysctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
810+ dn->sysctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
811+ dn->sysctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
812+ dn->sysctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
813+ dn->sysctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
814+ dn->sysctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
815+ dn->sysctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
816+ dn->sysctl_table[7].data = &dn->dccp_loose;
817+
818+ dn->sysctl_header = register_net_sysctl_table(net,
819+ nf_net_netfilter_sysctl_path, dn->sysctl_table);
820+ if (!dn->sysctl_header) {
821+ kfree(dn->sysctl_table);
822+ goto out;
823+ }
783824 #endif
825+
826+ return 0;
827+
828+out:
829+ kfree(dn);
830+ return err;
831+}
832+
833+static __net_exit void dccp_net_exit(struct net *net)
834+{
835+ struct dccp_net *dn = dccp_pernet(net);
836+#ifdef CONFIG_SYSCTL
837+ unregister_net_sysctl_table(dn->sysctl_header);
838+ kfree(dn->sysctl_table);
839+#endif
840+ kfree(dn);
841+
842+ net_assign_generic(net, dccp_net_id, NULL);
843+}
844+
845+static struct pernet_operations dccp_net_ops = {
846+ .init = dccp_net_init,
847+ .exit = dccp_net_exit,
784848 };
785849
786850 static int __init nf_conntrack_proto_dccp_init(void)
787851 {
788852 int err;
789853
790− err = nf_conntrack_l4proto_register(&dccp_proto4);
854+ err = register_pernet_gen_subsys(&dccp_net_id, &dccp_net_ops);
791855 if (err < 0)
792856 goto err1;
793857
794− err = nf_conntrack_l4proto_register(&dccp_proto6);
858+ err = nf_conntrack_l4proto_register(&dccp_proto4);
795859 if (err < 0)
796860 goto err2;
861+
862+ err = nf_conntrack_l4proto_register(&dccp_proto6);
863+ if (err < 0)
864+ goto err3;
797865 return 0;
798866
799−err2:
867+err3:
800868 nf_conntrack_l4proto_unregister(&dccp_proto4);
869+err2:
870+ unregister_pernet_gen_subsys(dccp_net_id, &dccp_net_ops);
801871 err1:
802872 return err;
803873 }
804874
805875 static void __exit nf_conntrack_proto_dccp_fini(void)
806876 {
877+ unregister_pernet_gen_subsys(dccp_net_id, &dccp_net_ops);
807878 nf_conntrack_l4proto_unregister(&dccp_proto6);
808879 nf_conntrack_l4proto_unregister(&dccp_proto4);
809880 }
net/netfilter/nf_conntrack_proto_generic.c+1−1
@@ -92,7 +92,7 @@ static struct ctl_table generic_compat_sysctl_table[] = { · 91 unmodified lines
9292 struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
9393 {
9494 .l3proto = PF_UNSPEC,
95− .l4proto = 0,
95+ .l4proto = 255,
9696 .name = "unknown",
9797 .pkt_to_tuple = generic_pkt_to_tuple,
9898 .invert_tuple = generic_invert_tuple,
net/netfilter/nf_conntrack_proto_tcp.c+2−0
@@ -25,6 +25,8 @@ · 24 unmodified lines
2525 #include <net/netfilter/nf_conntrack_l4proto.h>
2626 #include <net/netfilter/nf_conntrack_ecache.h>
2727 #include <net/netfilter/nf_log.h>
28+#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
29+#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
2830
2931 /* Protects ct->proto.tcp */
3032 static DEFINE_RWLOCK(tcp_lock);
net/netfilter/nf_conntrack_proto_udp.c+2−0
@@ -22,6 +22,8 @@ · 21 unmodified lines
2222 #include <net/netfilter/nf_conntrack_l4proto.h>
2323 #include <net/netfilter/nf_conntrack_ecache.h>
2424 #include <net/netfilter/nf_log.h>
25+#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
26+#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
2527
2628 static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
2729 static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
net/netfilter/nf_log.c+169−32
@@ -14,58 +14,63 @@ · 13 unmodified lines
1414 LOG target modules */
1515
1616 #define NF_LOG_PREFIXLEN 128
17+#define NFLOGGER_NAME_LEN 64
1718
1819 static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly;
20+static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly;
1921 static DEFINE_MUTEX(nf_log_mutex);
2022
21−/* return EBUSY if somebody else is registered, EEXIST if the same logger
22− * is registred, 0 on success. */
23−int nf_log_register(u_int8_t pf, const struct nf_logger *logger)
23+static struct nf_logger *__find_logger(int pf, const char *str_logger)
2424 {
25− int ret;
25+ struct nf_logger *t;
2626
27− if (pf >= ARRAY_SIZE(nf_loggers))
28− return -EINVAL;
29−
30− /* Any setup of logging members must be done before
31− * substituting pointer. */
32− ret = mutex_lock_interruptible(&nf_log_mutex);
33− if (ret < 0)
34− return ret;
35−
36− if (!nf_loggers[pf])
37− rcu_assign_pointer(nf_loggers[pf], logger);
38− else if (nf_loggers[pf] == logger)
39− ret = -EEXIST;
40− else
41− ret = -EBUSY;
27+ list_for_each_entry(t, &nf_loggers_l[pf], list[pf]) {
28+ if (!strnicmp(str_logger, t->name, strlen(t->name)))
29+ return t;
30+ }
4231
43− mutex_unlock(&nf_log_mutex);
44− return ret;
32+ return NULL;
4533 }
46−EXPORT_SYMBOL(nf_log_register);
4734
48−void nf_log_unregister_pf(u_int8_t pf)
35+/* return EEXIST if the same logger is registred, 0 on success. */
36+int nf_log_register(u_int8_t pf, struct nf_logger *logger)
4937 {
38+ const struct nf_logger *llog;
39+
5040 if (pf >= ARRAY_SIZE(nf_loggers))
51− return;
41+ return -EINVAL;
42+
5243 mutex_lock(&nf_log_mutex);
53− rcu_assign_pointer(nf_loggers[pf], NULL);
44+
45+ if (pf == NFPROTO_UNSPEC) {
46+ int i;
47+ for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
48+ list_add_tail(&(logger->list[i]), &(nf_loggers_l[i]));
49+ } else {
50+ /* register at end of list to honor first register win */
51+ list_add_tail(&logger->list[pf], &nf_loggers_l[pf]);
52+ llog = rcu_dereference(nf_loggers[pf]);
53+ if (llog == NULL)
54+ rcu_assign_pointer(nf_loggers[pf], logger);
55+ }
56+
5457 mutex_unlock(&nf_log_mutex);
5558
56− /* Give time to concurrent readers. */
57− synchronize_rcu();
59+ return 0;
5860 }
59−EXPORT_SYMBOL(nf_log_unregister_pf);
61+EXPORT_SYMBOL(nf_log_register);
6062
61−void nf_log_unregister(const struct nf_logger *logger)
63+void nf_log_unregister(struct nf_logger *logger)
6264 {
65+ const struct nf_logger *c_logger;
6366 int i;
6467
6568 mutex_lock(&nf_log_mutex);
6669 for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) {
67− if (nf_loggers[i] == logger)
70+ c_logger = rcu_dereference(nf_loggers[i]);
71+ if (c_logger == logger)
6872 rcu_assign_pointer(nf_loggers[i], NULL);
73+ list_del(&logger->list[i]);
6974 }
7075 mutex_unlock(&nf_log_mutex);
7176
@@ -73,6 +78,27 @@ void nf_log_unregister(const struct nf_logger *logger) · 1 unmodified line
7378 }
7479 EXPORT_SYMBOL(nf_log_unregister);
7580
81+int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger)
82+{
83+ mutex_lock(&nf_log_mutex);
84+ if (__find_logger(pf, logger->name) == NULL) {
85+ mutex_unlock(&nf_log_mutex);
86+ return -ENOENT;
87+ }
88+ rcu_assign_pointer(nf_loggers[pf], logger);
89+ mutex_unlock(&nf_log_mutex);
90+ return 0;
91+}
92+EXPORT_SYMBOL(nf_log_bind_pf);
93+
94+void nf_log_unbind_pf(u_int8_t pf)
95+{
96+ mutex_lock(&nf_log_mutex);
97+ rcu_assign_pointer(nf_loggers[pf], NULL);
98+ mutex_unlock(&nf_log_mutex);
99+}
100+EXPORT_SYMBOL(nf_log_unbind_pf);
101+
76102 void nf_log_packet(u_int8_t pf,
77103 unsigned int hooknum,
78104 const struct sk_buff *skb,
@@ -129,13 +155,37 @@ static int seq_show(struct seq_file *s, void *v) · 50 unmodified lines
129155 {
130156 loff_t *pos = v;
131157 const struct nf_logger *logger;
158+ struct nf_logger *t;
159+ int ret;
132160
133161 logger = rcu_dereference(nf_loggers[*pos]);
134162
135163 if (!logger)
136− return seq_printf(s, "%2lld NONE\n", *pos);
164+ ret = seq_printf(s, "%2lld NONE (", *pos);
165+ else
166+ ret = seq_printf(s, "%2lld %s (", *pos, logger->name);
167+
168+ if (ret < 0)
169+ return ret;
170+
171+ mutex_lock(&nf_log_mutex);
172+ list_for_each_entry(t, &nf_loggers_l[*pos], list[*pos]) {
173+ ret = seq_printf(s, "%s", t->name);
174+ if (ret < 0) {
175+ mutex_unlock(&nf_log_mutex);
176+ return ret;
177+ }
178+ if (&t->list[*pos] != nf_loggers_l[*pos].prev) {
179+ ret = seq_printf(s, ",");
180+ if (ret < 0) {
181+ mutex_unlock(&nf_log_mutex);
182+ return ret;
183+ }
184+ }
185+ }
186+ mutex_unlock(&nf_log_mutex);
137187
138− return seq_printf(s, "%2lld %s\n", *pos, logger->name);
188+ return seq_printf(s, ")\n");
139189 }
140190
141191 static const struct seq_operations nflog_seq_ops = {
@@ -158,15 +208,102 @@ static const struct file_operations nflog_file_ops = { · 16 unmodified lines
158208 .release = seq_release,
159209 };
160210
211+
161212 #endif /* PROC_FS */
162213
214+#ifdef CONFIG_SYSCTL
215+struct ctl_path nf_log_sysctl_path[] = {
216+ { .procname = "net", .ctl_name = CTL_NET, },
217+ { .procname = "netfilter", .ctl_name = NET_NETFILTER, },
218+ { .procname = "nf_log", .ctl_name = CTL_UNNUMBERED, },
219+ { }
220+};
221+
222+static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3];
223+static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1];
224+static struct ctl_table_header *nf_log_dir_header;
225+
226+static int nf_log_proc_dostring(ctl_table *table, int write, struct file *filp,
227+ void *buffer, size_t *lenp, loff_t *ppos)
228+{
229+ const struct nf_logger *logger;
230+ int r = 0;
231+ int tindex = (unsigned long)table->extra1;
232+
233+ if (write) {
234+ if (!strcmp(buffer, "NONE")) {
235+ nf_log_unbind_pf(tindex);
236+ return 0;
237+ }
238+ mutex_lock(&nf_log_mutex);
239+ logger = __find_logger(tindex, buffer);
240+ if (logger == NULL) {
241+ mutex_unlock(&nf_log_mutex);
242+ return -ENOENT;
243+ }
244+ rcu_assign_pointer(nf_loggers[tindex], logger);
245+ mutex_unlock(&nf_log_mutex);
246+ } else {
247+ rcu_read_lock();
248+ logger = rcu_dereference(nf_loggers[tindex]);
249+ if (!logger)
250+ table->data = "NONE";
251+ else
252+ table->data = logger->name;
253+ r = proc_dostring(table, write, filp, buffer, lenp, ppos);
254+ rcu_read_unlock();
255+ }
256+
257+ return r;
258+}
259+
260+static __init int netfilter_log_sysctl_init(void)
261+{
262+ int i;
263+
264+ for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
265+ snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], 3, "%d", i);
266+ nf_log_sysctl_table[i].ctl_name = CTL_UNNUMBERED;
267+ nf_log_sysctl_table[i].procname =
268+ nf_log_sysctl_fnames[i-NFPROTO_UNSPEC];
269+ nf_log_sysctl_table[i].data = NULL;
270+ nf_log_sysctl_table[i].maxlen =
271+ NFLOGGER_NAME_LEN * sizeof(char);
272+ nf_log_sysctl_table[i].mode = 0644;
273+ nf_log_sysctl_table[i].proc_handler = nf_log_proc_dostring;
274+ nf_log_sysctl_table[i].extra1 = (void *)(unsigned long) i;
275+ }
276+
277+ nf_log_dir_header = register_sysctl_paths(nf_log_sysctl_path,
278+ nf_log_sysctl_table);
279+ if (!nf_log_dir_header)
280+ return -ENOMEM;
281+
282+ return 0;
283+}
284+#else
285+static __init int netfilter_log_sysctl_init(void)
286+{
287+ return 0;
288+}
289+#endif /* CONFIG_SYSCTL */
163290
164291 int __init netfilter_log_init(void)
165292 {
293+ int i, r;
166294 #ifdef CONFIG_PROC_FS
167295 if (!proc_create("nf_log", S_IRUGO,
168296 proc_net_netfilter, &nflog_file_ops))
169297 return -1;
170298 #endif
299+
300+ /* Errors will trigger panic, unroll on error is unnecessary. */
301+ r = netfilter_log_sysctl_init();
302+ if (r < 0)
303+ return r;
304+
305+ for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
306+ INIT_LIST_HEAD(&(nf_loggers_l[i]));
307+
171308 return 0;
172309 }
net/netfilter/nfnetlink.c+6−0
@@ -113,6 +113,12 @@ int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) · 112 unmodified lines
113113 }
114114 EXPORT_SYMBOL_GPL(nfnetlink_send);
115115
116+void nfnetlink_set_err(u32 pid, u32 group, int error)
117+{
118+ netlink_set_err(nfnl, pid, group, error);
119+}
120+EXPORT_SYMBOL_GPL(nfnetlink_set_err);
121+
116122 int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags)
117123 {
118124 return netlink_unicast(nfnl, skb, pid, flags);
net/netfilter/nfnetlink_log.c+13−5
@@ -693,7 +693,7 @@ nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, · 692 unmodified lines
693693 return -ENOTSUPP;
694694 }
695695
696−static const struct nf_logger nfulnl_logger = {
696+static struct nf_logger nfulnl_logger __read_mostly = {
697697 .name = "nfnetlink_log",
698698 .logfn = &nfulnl_log_packet,
699699 .me = THIS_MODULE,
@@ -725,9 +725,9 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, · 25 unmodified lines
725725 /* Commands without queue context */
726726 switch (cmd->command) {
727727 case NFULNL_CFG_CMD_PF_BIND:
728− return nf_log_register(pf, &nfulnl_logger);
728+ return nf_log_bind_pf(pf, &nfulnl_logger);
729729 case NFULNL_CFG_CMD_PF_UNBIND:
730− nf_log_unregister_pf(pf);
730+ nf_log_unbind_pf(pf);
731731 return 0;
732732 }
733733 }
@@ -952,17 +952,25 @@ static int __init nfnetlink_log_init(void) · 218 unmodified lines
952952 goto cleanup_netlink_notifier;
953953 }
954954
955+ status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger);
956+ if (status < 0) {
957+ printk(KERN_ERR "log: failed to register logger\n");
958+ goto cleanup_subsys;
959+ }
960+
955961 #ifdef CONFIG_PROC_FS
956962 if (!proc_create("nfnetlink_log", 0440,
957963 proc_net_netfilter, &nful_file_ops))
958− goto cleanup_subsys;
964+ goto cleanup_logger;
959965 #endif
960966 return status;
961967
962968 #ifdef CONFIG_PROC_FS
969+cleanup_logger:
970+ nf_log_unregister(&nfulnl_logger);
971+#endif
963972 cleanup_subsys:
964973 nfnetlink_subsys_unregister(&nfulnl_subsys);
965−#endif
966974 cleanup_netlink_notifier:
967975 netlink_unregister_notifier(&nfulnl_rtnl_notifier);
968976 return status;
net/netfilter/x_tables.c+21−5
@@ -625,6 +625,20 @@ void xt_free_table_info(struct xt_table_info *info) · 624 unmodified lines
625625 }
626626 EXPORT_SYMBOL(xt_free_table_info);
627627
628+void xt_table_entry_swap_rcu(struct xt_table_info *oldinfo,
629+ struct xt_table_info *newinfo)
630+{
631+ unsigned int cpu;
632+
633+ for_each_possible_cpu(cpu) {
634+ void *p = oldinfo->entries[cpu];
635+ rcu_assign_pointer(oldinfo->entries[cpu], newinfo->entries[cpu]);
636+ newinfo->entries[cpu] = p;
637+ }
638+
639+}
640+EXPORT_SYMBOL_GPL(xt_table_entry_swap_rcu);
641+
628642 /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
629643 struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
630644 const char *name)
@@ -671,21 +685,22 @@ xt_replace_table(struct xt_table *table, · 40 unmodified lines
671685 struct xt_table_info *oldinfo, *private;
672686
673687 /* Do the substitution. */
674− write_lock_bh(&table->lock);
688+ mutex_lock(&table->lock);
675689 private = table->private;
676690 /* Check inside lock: is the old number correct? */
677691 if (num_counters != private->number) {
678692 duprintf("num_counters != table->private->number (%u/%u)\n",
679693 num_counters, private->number);
680− write_unlock_bh(&table->lock);
694+ mutex_unlock(&table->lock);
681695 *error = -EAGAIN;
682696 return NULL;
683697 }
684698 oldinfo = private;
685− table->private = newinfo;
699+ rcu_assign_pointer(table->private, newinfo);
686700 newinfo->initial_entries = oldinfo->initial_entries;
687− write_unlock_bh(&table->lock);
701+ mutex_unlock(&table->lock);
688702
703+ synchronize_net();
689704 return oldinfo;
690705 }
691706 EXPORT_SYMBOL_GPL(xt_replace_table);
@@ -719,7 +734,8 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table, · 27 unmodified lines
719734
720735 /* Simplifies replace_table code. */
721736 table->private = bootstrap;
722− rwlock_init(&table->lock);
737+ mutex_init(&table->lock);
738+
723739 if (!xt_replace_table(table, 0, newinfo, &ret))
724740 goto unlock;
725741
net/netfilter/xt_HL.c+171−0
@@ -0,0 +1,171 @@
1+/*
2+ * TTL modification target for IP tables
3+ * (C) 2000,2005 by Harald Welte <laforge@netfilter.org>
4+ *
5+ * Hop Limit modification target for ip6tables
6+ * Maciej Soltysiak <solt@dns.toxicfilms.tv>
7+ *
8+ * This program is free software; you can redistribute it and/or modify
9+ * it under the terms of the GNU General Public License version 2 as
10+ * published by the Free Software Foundation.
11+ */
12+
13+#include <linux/module.h>
14+#include <linux/skbuff.h>
15+#include <linux/ip.h>
16+#include <linux/ipv6.h>
17+#include <net/checksum.h>
18+
19+#include <linux/netfilter/x_tables.h>
20+#include <linux/netfilter_ipv4/ipt_TTL.h>
21+#include <linux/netfilter_ipv6/ip6t_HL.h>
22+
23+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
24+MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
25+MODULE_DESCRIPTION("Xtables: Hoplimit/TTL Limit field modification target");
26+MODULE_LICENSE("GPL");
27+
28+static unsigned int
29+ttl_tg(struct sk_buff *skb, const struct xt_target_param *par)
30+{
31+ struct iphdr *iph;
32+ const struct ipt_TTL_info *info = par->targinfo;
33+ int new_ttl;
34+
35+ if (!skb_make_writable(skb, skb->len))
36+ return NF_DROP;
37+
38+ iph = ip_hdr(skb);
39+
40+ switch (info->mode) {
41+ case IPT_TTL_SET:
42+ new_ttl = info->ttl;
43+ break;
44+ case IPT_TTL_INC:
45+ new_ttl = iph->ttl + info->ttl;
46+ if (new_ttl > 255)
47+ new_ttl = 255;
48+ break;
49+ case IPT_TTL_DEC:
50+ new_ttl = iph->ttl - info->ttl;
51+ if (new_ttl < 0)
52+ new_ttl = 0;
53+ break;
54+ default:
55+ new_ttl = iph->ttl;
56+ break;
57+ }
58+
59+ if (new_ttl != iph->ttl) {
60+ csum_replace2(&iph->check, htons(iph->ttl << 8),
61+ htons(new_ttl << 8));
62+ iph->ttl = new_ttl;
63+ }
64+
65+ return XT_CONTINUE;
66+}
67+
68+static unsigned int
69+hl_tg6(struct sk_buff *skb, const struct xt_target_param *par)
70+{
71+ struct ipv6hdr *ip6h;
72+ const struct ip6t_HL_info *info = par->targinfo;
73+ int new_hl;
74+
75+ if (!skb_make_writable(skb, skb->len))
76+ return NF_DROP;
77+
78+ ip6h = ipv6_hdr(skb);
79+
80+ switch (info->mode) {
81+ case IP6T_HL_SET:
82+ new_hl = info->hop_limit;
83+ break;
84+ case IP6T_HL_INC:
85+ new_hl = ip6h->hop_limit + info->hop_limit;
86+ if (new_hl > 255)
87+ new_hl = 255;
88+ break;
89+ case IP6T_HL_DEC:
90+ new_hl = ip6h->hop_limit - info->hop_limit;
91+ if (new_hl < 0)
92+ new_hl = 0;
93+ break;
94+ default:
95+ new_hl = ip6h->hop_limit;
96+ break;
97+ }
98+
99+ ip6h->hop_limit = new_hl;
100+
101+ return XT_CONTINUE;
102+}
103+
104+static bool ttl_tg_check(const struct xt_tgchk_param *par)
105+{
106+ const struct ipt_TTL_info *info = par->targinfo;
107+
108+ if (info->mode > IPT_TTL_MAXMODE) {
109+ printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
110+ info->mode);
111+ return false;
112+ }
113+ if (info->mode != IPT_TTL_SET && info->ttl == 0)
114+ return false;
115+ return true;
116+}
117+
118+static bool hl_tg6_check(const struct xt_tgchk_param *par)
119+{
120+ const struct ip6t_HL_info *info = par->targinfo;
121+
122+ if (info->mode > IP6T_HL_MAXMODE) {
123+ printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
124+ info->mode);
125+ return false;
126+ }
127+ if (info->mode != IP6T_HL_SET && info->hop_limit == 0) {
128+ printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
129+ "make sense with value 0\n");
130+ return false;
131+ }
132+ return true;
133+}
134+
135+static struct xt_target hl_tg_reg[] __read_mostly = {
136+ {
137+ .name = "TTL",
138+ .revision = 0,
139+ .family = NFPROTO_IPV4,
140+ .target = ttl_tg,
141+ .targetsize = sizeof(struct ipt_TTL_info),
142+ .table = "mangle",
143+ .checkentry = ttl_tg_check,
144+ .me = THIS_MODULE,
145+ },
146+ {
147+ .name = "HL",
148+ .revision = 0,
149+ .family = NFPROTO_IPV6,
150+ .target = hl_tg6,
151+ .targetsize = sizeof(struct ip6t_HL_info),
152+ .table = "mangle",
153+ .checkentry = hl_tg6_check,
154+ .me = THIS_MODULE,
155+ },
156+};
157+
158+static int __init hl_tg_init(void)
159+{
160+ return xt_register_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg));
161+}
162+
163+static void __exit hl_tg_exit(void)
164+{
165+ xt_unregister_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg));
166+}
167+
168+module_init(hl_tg_init);
169+module_exit(hl_tg_exit);
170+MODULE_ALIAS("ipt_TTL");
171+MODULE_ALIAS("ip6t_HL");
net/netfilter/xt_LED.c+161−0
@@ -0,0 +1,161 @@
1+/*
2+ * xt_LED.c - netfilter target to make LEDs blink upon packet matches
3+ *
4+ * Copyright (C) 2008 Adam Nielsen <a.nielsen@shikadi.net>
5+ *
6+ * This program is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; version 2 of the License.
9+ *
10+ * This program is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ * GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License
16+ * along with this program; if not, write to the Free Software
17+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18+ * 02110-1301 USA.
19+ *
20+ */
21+
22+#include <linux/module.h>
23+#include <linux/skbuff.h>
24+#include <linux/netfilter/x_tables.h>
25+#include <linux/leds.h>
26+#include <linux/mutex.h>
27+
28+#include <linux/netfilter/xt_LED.h>
29+
30+MODULE_LICENSE("GPL");
31+MODULE_AUTHOR("Adam Nielsen <a.nielsen@shikadi.net>");
32+MODULE_DESCRIPTION("Xtables: trigger LED devices on packet match");
33+
34+/*
35+ * This is declared in here (the kernel module) only, to avoid having these
36+ * dependencies in userspace code. This is what xt_led_info.internal_data
37+ * points to.
38+ */
39+struct xt_led_info_internal {
40+ struct led_trigger netfilter_led_trigger;
41+ struct timer_list timer;
42+};
43+
44+static unsigned int
45+led_tg(struct sk_buff *skb, const struct xt_target_param *par)
46+{
47+ const struct xt_led_info *ledinfo = par->targinfo;
48+ struct xt_led_info_internal *ledinternal = ledinfo->internal_data;
49+
50+ /*
51+ * If "always blink" is enabled, and there's still some time until the
52+ * LED will switch off, briefly switch it off now.
53+ */
54+ if ((ledinfo->delay > 0) && ledinfo->always_blink &&
55+ timer_pending(&ledinternal->timer))
56+ led_trigger_event(&ledinternal->netfilter_led_trigger,LED_OFF);
57+
58+ led_trigger_event(&ledinternal->netfilter_led_trigger, LED_FULL);
59+
60+ /* If there's a positive delay, start/update the timer */
61+ if (ledinfo->delay > 0) {
62+ mod_timer(&ledinternal->timer,
63+ jiffies + msecs_to_jiffies(ledinfo->delay));
64+
65+ /* Otherwise if there was no delay given, blink as fast as possible */
66+ } else if (ledinfo->delay == 0) {
67+ led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF);
68+ }
69+
70+ /* else the delay is negative, which means switch on and stay on */
71+
72+ return XT_CONTINUE;
73+}
74+
75+static void led_timeout_callback(unsigned long data)
76+{
77+ struct xt_led_info *ledinfo = (struct xt_led_info *)data;
78+ struct xt_led_info_internal *ledinternal = ledinfo->internal_data;
79+
80+ led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF);
81+}
82+
83+static bool led_tg_check(const struct xt_tgchk_param *par)
84+{
85+ struct xt_led_info *ledinfo = par->targinfo;
86+ struct xt_led_info_internal *ledinternal;
87+ int err;
88+
89+ if (ledinfo->id[0] == '\0') {
90+ printk(KERN_ERR KBUILD_MODNAME ": No 'id' parameter given.\n");
91+ return false;
92+ }
93+
94+ ledinternal = kzalloc(sizeof(struct xt_led_info_internal), GFP_KERNEL);
95+ if (!ledinternal) {
96+ printk(KERN_CRIT KBUILD_MODNAME ": out of memory\n");
97+ return false;
98+ }
99+
100+ ledinternal->netfilter_led_trigger.name = ledinfo->id;
101+
102+ err = led_trigger_register(&ledinternal->netfilter_led_trigger);
103+ if (err) {
104+ printk(KERN_CRIT KBUILD_MODNAME
105+ ": led_trigger_register() failed\n");
106+ if (err == -EEXIST)
107+ printk(KERN_ERR KBUILD_MODNAME
108+ ": Trigger name is already in use.\n");
109+ goto exit_alloc;
110+ }
111+
112+ /* See if we need to set up a timer */
113+ if (ledinfo->delay > 0)
114+ setup_timer(&ledinternal->timer, led_timeout_callback,
115+ (unsigned long)ledinfo);
116+
117+ ledinfo->internal_data = ledinternal;
118+
119+ return true;
120+
121+exit_alloc:
122+ kfree(ledinternal);
123+
124+ return false;
125+}
126+
127+static void led_tg_destroy(const struct xt_tgdtor_param *par)
128+{
129+ const struct xt_led_info *ledinfo = par->targinfo;
130+ struct xt_led_info_internal *ledinternal = ledinfo->internal_data;
131+
132+ if (ledinfo->delay > 0)
133+ del_timer_sync(&ledinternal->timer);
134+
135+ led_trigger_unregister(&ledinternal->netfilter_led_trigger);
136+ kfree(ledinternal);
137+}
138+
139+static struct xt_target led_tg_reg __read_mostly = {
140+ .name = "LED",
141+ .revision = 0,
142+ .family = NFPROTO_UNSPEC,
143+ .target = led_tg,
144+ .targetsize = XT_ALIGN(sizeof(struct xt_led_info)),
145+ .checkentry = led_tg_check,
146+ .destroy = led_tg_destroy,
147+ .me = THIS_MODULE,
148+};
149+
150+static int __init led_tg_init(void)
151+{
152+ return xt_register_target(&led_tg_reg);
153+}
154+
155+static void __exit led_tg_exit(void)
156+{
157+ xt_unregister_target(&led_tg_reg);
158+}
159+
160+module_init(led_tg_init);
161+module_exit(led_tg_exit);
net/netfilter/xt_cluster.c+164−0
@@ -0,0 +1,164 @@
1+/*
2+ * (C) 2008-2009 Pablo Neira Ayuso <pablo@netfilter.org>
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License version 2 as
6+ * published by the Free Software Foundation.
7+ */
8+#include <linux/module.h>
9+#include <linux/skbuff.h>
10+#include <linux/jhash.h>
11+#include <linux/ip.h>
12+#include <net/ipv6.h>
13+
14+#include <linux/netfilter/x_tables.h>
15+#include <net/netfilter/nf_conntrack.h>
16+#include <linux/netfilter/xt_cluster.h>
17+
18+static inline u_int32_t nf_ct_orig_ipv4_src(const struct nf_conn *ct)
19+{
20+ return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
21+}
22+
23+static inline const void *nf_ct_orig_ipv6_src(const struct nf_conn *ct)
24+{
25+ return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6;
26+}
27+
28+static inline u_int32_t
29+xt_cluster_hash_ipv4(u_int32_t ip, const struct xt_cluster_match_info *info)
30+{
31+ return jhash_1word(ip, info->hash_seed);
32+}
33+
34+static inline u_int32_t
35+xt_cluster_hash_ipv6(const void *ip, const struct xt_cluster_match_info *info)
36+{
37+ return jhash2(ip, NF_CT_TUPLE_L3SIZE / sizeof(__u32), info->hash_seed);
38+}
39+
40+static inline u_int32_t
41+xt_cluster_hash(const struct nf_conn *ct,
42+ const struct xt_cluster_match_info *info)
43+{
44+ u_int32_t hash = 0;
45+
46+ switch(nf_ct_l3num(ct)) {
47+ case AF_INET:
48+ hash = xt_cluster_hash_ipv4(nf_ct_orig_ipv4_src(ct), info);
49+ break;
50+ case AF_INET6:
51+ hash = xt_cluster_hash_ipv6(nf_ct_orig_ipv6_src(ct), info);
52+ break;
53+ default:
54+ WARN_ON(1);
55+ break;
56+ }
57+ return (((u64)hash * info->total_nodes) >> 32);
58+}
59+
60+static inline bool
61+xt_cluster_is_multicast_addr(const struct sk_buff *skb, u_int8_t family)
62+{
63+ bool is_multicast = false;
64+
65+ switch(family) {
66+ case NFPROTO_IPV4:
67+ is_multicast = ipv4_is_multicast(ip_hdr(skb)->daddr);
68+ break;
69+ case NFPROTO_IPV6:
70+ is_multicast = ipv6_addr_type(&ipv6_hdr(skb)->daddr) &
71+ IPV6_ADDR_MULTICAST;
72+ break;
73+ default:
74+ WARN_ON(1);
75+ break;
76+ }
77+ return is_multicast;
78+}
79+
80+static bool
81+xt_cluster_mt(const struct sk_buff *skb, const struct xt_match_param *par)
82+{
83+ struct sk_buff *pskb = (struct sk_buff *)skb;
84+ const struct xt_cluster_match_info *info = par->matchinfo;
85+ const struct nf_conn *ct;
86+ enum ip_conntrack_info ctinfo;
87+ unsigned long hash;
88+
89+ /* This match assumes that all nodes see the same packets. This can be
90+ * achieved if the switch that connects the cluster nodes support some
91+ * sort of 'port mirroring'. However, if your switch does not support
92+ * this, your cluster nodes can reply ARP request using a multicast MAC
93+ * address. Thus, your switch will flood the same packets to the
94+ * cluster nodes with the same multicast MAC address. Using a multicast
95+ * link address is a RFC 1812 (section 3.3.2) violation, but this works
96+ * fine in practise.
97+ *
98+ * Unfortunately, if you use the multicast MAC address, the link layer
99+ * sets skbuff's pkt_type to PACKET_MULTICAST, which is not accepted
100+ * by TCP and others for packets coming to this node. For that reason,
101+ * this match mangles skbuff's pkt_type if it detects a packet
102+ * addressed to a unicast address but using PACKET_MULTICAST. Yes, I
103+ * know, matches should not alter packets, but we are doing this here
104+ * because we would need to add a PKTTYPE target for this sole purpose.
105+ */
106+ if (!xt_cluster_is_multicast_addr(skb, par->family) &&
107+ skb->pkt_type == PACKET_MULTICAST) {
108+ pskb->pkt_type = PACKET_HOST;
109+ }
110+
111+ ct = nf_ct_get(skb, &ctinfo);
112+ if (ct == NULL)
113+ return false;
114+
115+ if (ct == &nf_conntrack_untracked)
116+ return false;
117+
118+ if (ct->master)
119+ hash = xt_cluster_hash(ct->master, info);
120+ else
121+ hash = xt_cluster_hash(ct, info);
122+
123+ return !!((1 << hash) & info->node_mask) ^
124+ !!(info->flags & XT_CLUSTER_F_INV);
125+}
126+
127+static bool xt_cluster_mt_checkentry(const struct xt_mtchk_param *par)
128+{
129+ struct xt_cluster_match_info *info = par->matchinfo;
130+
131+ if (info->node_mask >= (1 << info->total_nodes)) {
132+ printk(KERN_ERR "xt_cluster: this node mask cannot be "
133+ "higher than the total number of nodes\n");
134+ return false;
135+ }
136+ return true;
137+}
138+
139+static struct xt_match xt_cluster_match __read_mostly = {
140+ .name = "cluster",
141+ .family = NFPROTO_UNSPEC,
142+ .match = xt_cluster_mt,
143+ .checkentry = xt_cluster_mt_checkentry,
144+ .matchsize = sizeof(struct xt_cluster_match_info),
145+ .me = THIS_MODULE,
146+};
147+
148+static int __init xt_cluster_mt_init(void)
149+{
150+ return xt_register_match(&xt_cluster_match);
151+}
152+
153+static void __exit xt_cluster_mt_fini(void)
154+{
155+ xt_unregister_match(&xt_cluster_match);
156+}
157+
158+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
159+MODULE_LICENSE("GPL");
160+MODULE_DESCRIPTION("Xtables: hash-based cluster match");
161+MODULE_ALIAS("ipt_cluster");
162+MODULE_ALIAS("ip6t_cluster");
163+module_init(xt_cluster_mt_init);
164+module_exit(xt_cluster_mt_fini);
net/netfilter/xt_hashlimit.c+2−5
@@ -149,7 +149,7 @@ dsthash_alloc_init(struct xt_hashlimit_htable *ht, · 148 unmodified lines
149149 /* initialize hash with random val at the time we allocate
150150 * the first hashtable entry */
151151 if (!ht->rnd_initialized) {
152− get_random_bytes(&ht->rnd, 4);
152+ get_random_bytes(&ht->rnd, sizeof(ht->rnd));
153153 ht->rnd_initialized = 1;
154154 }
155155
@@ -565,8 +565,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, · 409 unmodified lines
565565 static bool
566566 hashlimit_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
567567 {
568− const struct xt_hashlimit_info *r =
569− ((const struct xt_hashlimit_info *)par->matchinfo)->u.master;
568+ const struct xt_hashlimit_info *r = par->matchinfo;
570569 struct xt_hashlimit_htable *hinfo = r->hinfo;
571570 unsigned long now = jiffies;
572571 struct dsthash_ent *dh;
@@ -702,8 +701,6 @@ static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par) · 129 unmodified lines
702701 }
703702 mutex_unlock(&hlimit_mutex);
704703
705− /* Ugly hack: For SMP, we only want to use one set */
706− r->u.master = r;
707704 return true;
708705 }
709706
net/netfilter/xt_hl.c+108−0
@@ -0,0 +1,108 @@
1+/*
2+ * IP tables module for matching the value of the TTL
3+ * (C) 2000,2001 by Harald Welte <laforge@netfilter.org>
4+ *
5+ * Hop Limit matching module
6+ * (C) 2001-2002 Maciej Soltysiak <solt@dns.toxicfilms.tv>
7+ *
8+ * This program is free software; you can redistribute it and/or modify
9+ * it under the terms of the GNU General Public License version 2 as
10+ * published by the Free Software Foundation.
11+ */
12+
13+#include <linux/ip.h>
14+#include <linux/ipv6.h>
15+#include <linux/module.h>
16+#include <linux/skbuff.h>
17+
18+#include <linux/netfilter/x_tables.h>
19+#include <linux/netfilter_ipv4/ipt_ttl.h>
20+#include <linux/netfilter_ipv6/ip6t_hl.h>
21+
22+MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
23+MODULE_DESCRIPTION("Xtables: Hoplimit/TTL field match");
24+MODULE_LICENSE("GPL");
25+MODULE_ALIAS("ipt_ttl");
26+MODULE_ALIAS("ip6t_hl");
27+
28+static bool ttl_mt(const struct sk_buff *skb, const struct xt_match_param *par)
29+{
30+ const struct ipt_ttl_info *info = par->matchinfo;
31+ const u8 ttl = ip_hdr(skb)->ttl;
32+
33+ switch (info->mode) {
34+ case IPT_TTL_EQ:
35+ return ttl == info->ttl;
36+ case IPT_TTL_NE:
37+ return ttl != info->ttl;
38+ case IPT_TTL_LT:
39+ return ttl < info->ttl;
40+ case IPT_TTL_GT:
41+ return ttl > info->ttl;
42+ default:
43+ printk(KERN_WARNING "ipt_ttl: unknown mode %d\n",
44+ info->mode);
45+ return false;
46+ }
47+
48+ return false;
49+}
50+
51+static bool hl_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
52+{
53+ const struct ip6t_hl_info *info = par->matchinfo;
54+ const struct ipv6hdr *ip6h = ipv6_hdr(skb);
55+
56+ switch (info->mode) {
57+ case IP6T_HL_EQ:
58+ return ip6h->hop_limit == info->hop_limit;
59+ break;
60+ case IP6T_HL_NE:
61+ return ip6h->hop_limit != info->hop_limit;
62+ break;
63+ case IP6T_HL_LT:
64+ return ip6h->hop_limit < info->hop_limit;
65+ break;
66+ case IP6T_HL_GT:
67+ return ip6h->hop_limit > info->hop_limit;
68+ break;
69+ default:
70+ printk(KERN_WARNING "ip6t_hl: unknown mode %d\n",
71+ info->mode);
72+ return false;
73+ }
74+
75+ return false;
76+}
77+
78+static struct xt_match hl_mt_reg[] __read_mostly = {
79+ {
80+ .name = "ttl",
81+ .revision = 0,
82+ .family = NFPROTO_IPV4,
83+ .match = ttl_mt,
84+ .matchsize = sizeof(struct ipt_ttl_info),
85+ .me = THIS_MODULE,
86+ },
87+ {
88+ .name = "hl",
89+ .revision = 0,
90+ .family = NFPROTO_IPV6,
91+ .match = hl_mt6,
92+ .matchsize = sizeof(struct ip6t_hl_info),
93+ .me = THIS_MODULE,
94+ },
95+};
96+
97+static int __init hl_mt_init(void)
98+{
99+ return xt_register_matches(hl_mt_reg, ARRAY_SIZE(hl_mt_reg));
100+}
101+
102+static void __exit hl_mt_exit(void)
103+{
104+ xt_unregister_matches(hl_mt_reg, ARRAY_SIZE(hl_mt_reg));
105+}
106+
107+module_init(hl_mt_init);
108+module_exit(hl_mt_exit);
net/netfilter/xt_limit.c+29−11
@@ -14,6 +14,11 @@ · 13 unmodified lines
1414 #include <linux/netfilter/x_tables.h>
1515 #include <linux/netfilter/xt_limit.h>
1616
17+struct xt_limit_priv {
18+ unsigned long prev;
19+ uint32_t credit;
20+};
21+
1722 MODULE_LICENSE("GPL");
1823 MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
1924 MODULE_DESCRIPTION("Xtables: rate-limit match");
@@ -60,18 +65,18 @@ static DEFINE_SPINLOCK(limit_lock); · 40 unmodified lines
6065 static bool
6166 limit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
6267 {
63− struct xt_rateinfo *r =
64− ((const struct xt_rateinfo *)par->matchinfo)->master;
68+ const struct xt_rateinfo *r = par->matchinfo;
69+ struct xt_limit_priv *priv = r->master;
6570 unsigned long now = jiffies;
6671
6772 spin_lock_bh(&limit_lock);
68− r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY;
69− if (r->credit > r->credit_cap)
70− r->credit = r->credit_cap;
73+ priv->credit += (now - xchg(&priv->prev, now)) * CREDITS_PER_JIFFY;
74+ if (priv->credit > r->credit_cap)
75+ priv->credit = r->credit_cap;
7176
72− if (r->credit >= r->cost) {
77+ if (priv->credit >= r->cost) {
7378 /* We're not limited. */
74− r->credit -= r->cost;
79+ priv->credit -= r->cost;
7580 spin_unlock_bh(&limit_lock);
7681 return true;
7782 }
@@ -95,6 +100,7 @@ user2credits(u_int32_t user) · 17 unmodified lines
95100 static bool limit_mt_check(const struct xt_mtchk_param *par)
96101 {
97102 struct xt_rateinfo *r = par->matchinfo;
103+ struct xt_limit_priv *priv;
98104
99105 /* Check for overflow. */
100106 if (r->burst == 0
@@ -104,19 +110,30 @@ static bool limit_mt_check(const struct xt_mtchk_param *par) · 3 unmodified lines
104110 return false;
105111 }
106112
107− /* For SMP, we only want to use one set of counters. */
108− r->master = r;
113+ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
114+ if (priv == NULL)
115+ return -ENOMEM;
116+
117+ /* For SMP, we only want to use one set of state. */
118+ r->master = priv;
109119 if (r->cost == 0) {
110120 /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
111121 128. */
112− r->prev = jiffies;
113− r->credit = user2credits(r->avg * r->burst); /* Credits full. */
122+ priv->prev = jiffies;
123+ priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
114124 r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
115125 r->cost = user2credits(r->avg);
116126 }
117127 return true;
118128 }
119129
130+static void limit_mt_destroy(const struct xt_mtdtor_param *par)
131+{
132+ const struct xt_rateinfo *info = par->matchinfo;
133+
134+ kfree(info->master);
135+}
136+
120137 #ifdef CONFIG_COMPAT
121138 struct compat_xt_rateinfo {
122139 u_int32_t avg;
@@ -167,6 +184,7 @@ static struct xt_match limit_mt_reg __read_mostly = { · 44 unmodified lines
167184 .family = NFPROTO_UNSPEC,
168185 .match = limit_mt,
169186 .checkentry = limit_mt_check,
187+ .destroy = limit_mt_destroy,
170188 .matchsize = sizeof(struct xt_rateinfo),
171189 #ifdef CONFIG_COMPAT
172190 .compatsize = sizeof(struct compat_xt_rateinfo),
net/netfilter/xt_physdev.c+23−14
@@ -20,13 +20,30 @@ MODULE_DESCRIPTION("Xtables: Bridge physical device match"); · 19 unmodified lines
2020 MODULE_ALIAS("ipt_physdev");
2121 MODULE_ALIAS("ip6t_physdev");
2222
23+static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask)
24+{
25+ const unsigned long *a = (const unsigned long *)_a;
26+ const unsigned long *b = (const unsigned long *)_b;
27+ const unsigned long *mask = (const unsigned long *)_mask;
28+ unsigned long ret;
29+
30+ ret = (a[0] ^ b[0]) & mask[0];
31+ if (IFNAMSIZ > sizeof(unsigned long))
32+ ret |= (a[1] ^ b[1]) & mask[1];
33+ if (IFNAMSIZ > 2 * sizeof(unsigned long))
34+ ret |= (a[2] ^ b[2]) & mask[2];
35+ if (IFNAMSIZ > 3 * sizeof(unsigned long))
36+ ret |= (a[3] ^ b[3]) & mask[3];
37+ BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
38+ return ret;
39+}
40+
2341 static bool
2442 physdev_mt(const struct sk_buff *skb, const struct xt_match_param *par)
2543 {
26− int i;
27− static const char nulldevname[IFNAMSIZ];
44+ static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
2845 const struct xt_physdev_info *info = par->matchinfo;
29− bool ret;
46+ unsigned long ret;
3047 const char *indev, *outdev;
3148 const struct nf_bridge_info *nf_bridge;
3249
@@ -68,11 +85,7 @@ physdev_mt(const struct sk_buff *skb, const struct xt_match_param *par) · 35 unmodified lines
6885 if (!(info->bitmask & XT_PHYSDEV_OP_IN))
6986 goto match_outdev;
7087 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
71− for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) {
72− ret |= (((const unsigned int *)indev)[i]
73− ^ ((const unsigned int *)info->physindev)[i])
74− & ((const unsigned int *)info->in_mask)[i];
75− }
88+ ret = ifname_compare(indev, info->physindev, info->in_mask);
7689
7790 if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN))
7891 return false;
@@ -82,13 +95,9 @@ match_outdev: · 3 unmodified lines
8295 return true;
8396 outdev = nf_bridge->physoutdev ?
8497 nf_bridge->physoutdev->name : nulldevname;
85− for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) {
86− ret |= (((const unsigned int *)outdev)[i]
87− ^ ((const unsigned int *)info->physoutdev)[i])
88− & ((const unsigned int *)info->out_mask)[i];
89− }
98+ ret = ifname_compare(outdev, info->physoutdev, info->out_mask);
9099
91− return ret ^ !(info->invert & XT_PHYSDEV_OP_OUT);
100+ return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT));
92101 }
93102
94103 static bool physdev_mt_check(const struct xt_mtchk_param *par)
net/netfilter/xt_quota.c+24−7
@@ -9,6 +9,10 @@ · 8 unmodified lines
99 #include <linux/netfilter/x_tables.h>
1010 #include <linux/netfilter/xt_quota.h>
1111
12+struct xt_quota_priv {
13+ uint64_t quota;
14+};
15+
1216 MODULE_LICENSE("GPL");
1317 MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
1418 MODULE_DESCRIPTION("Xtables: countdown quota match");
@@ -20,18 +24,20 @@ static DEFINE_SPINLOCK(quota_lock); · 5 unmodified lines
2024 static bool
2125 quota_mt(const struct sk_buff *skb, const struct xt_match_param *par)
2226 {
23− struct xt_quota_info *q =
24− ((const struct xt_quota_info *)par->matchinfo)->master;
27+ struct xt_quota_info *q = (void *)par->matchinfo;
28+ struct xt_quota_priv *priv = q->master;
2529 bool ret = q->flags & XT_QUOTA_INVERT;
2630
2731 spin_lock_bh(&quota_lock);
28− if (q->quota >= skb->len) {
29− q->quota -= skb->len;
32+ if (priv->quota >= skb->len) {
33+ priv->quota -= skb->len;
3034 ret = !ret;
3135 } else {
3236 /* we do not allow even small packets from now on */
33− q->quota = 0;
37+ priv->quota = 0;
3438 }
39+ /* Copy quota back to matchinfo so that iptables can display it */
40+ q->quota = priv->quota;
3541 spin_unlock_bh(&quota_lock);
3642
3743 return ret;
@@ -43,17 +49,28 @@ static bool quota_mt_check(const struct xt_mtchk_param *par) · 5 unmodified lines
4349
4450 if (q->flags & ~XT_QUOTA_MASK)
4551 return false;
46− /* For SMP, we only want to use one set of counters. */
47− q->master = q;
52+
53+ q->master = kmalloc(sizeof(*q->master), GFP_KERNEL);
54+ if (q->master == NULL)
55+ return -ENOMEM;
56+
4857 return true;
4958 }
5059
60+static void quota_mt_destroy(const struct xt_mtdtor_param *par)
61+{
62+ const struct xt_quota_info *q = par->matchinfo;
63+
64+ kfree(q->master);
65+}
66+
5167 static struct xt_match quota_mt_reg __read_mostly = {
5268 .name = "quota",
5369 .revision = 0,
5470 .family = NFPROTO_UNSPEC,
5571 .match = quota_mt,
5672 .checkentry = quota_mt_check,
73+ .destroy = quota_mt_destroy,
5774 .matchsize = sizeof(struct xt_quota_info),
5875 .me = THIS_MODULE,
5976 };
net/netfilter/xt_statistic.c+23−5
@@ -16,6 +16,10 @@ · 15 unmodified lines
1616 #include <linux/netfilter/xt_statistic.h>
1717 #include <linux/netfilter/x_tables.h>
1818
19+struct xt_statistic_priv {
20+ uint32_t count;
21+};
22+
1923 MODULE_LICENSE("GPL");
2024 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
2125 MODULE_DESCRIPTION("Xtables: statistics-based matching (\"Nth\", random)");
@@ -27,7 +31,7 @@ static DEFINE_SPINLOCK(nth_lock); · 5 unmodified lines
2731 static bool
2832 statistic_mt(const struct sk_buff *skb, const struct xt_match_param *par)
2933 {
30− struct xt_statistic_info *info = (void *)par->matchinfo;
34+ const struct xt_statistic_info *info = par->matchinfo;
3135 bool ret = info->flags & XT_STATISTIC_INVERT;
3236
3337 switch (info->mode) {
@@ -36,10 +40,9 @@ statistic_mt(const struct sk_buff *skb, const struct xt_match_param *par) · 2 unmodified lines
3640 ret = !ret;
3741 break;
3842 case XT_STATISTIC_MODE_NTH:
39− info = info->master;
4043 spin_lock_bh(&nth_lock);
41− if (info->u.nth.count++ == info->u.nth.every) {
42− info->u.nth.count = 0;
44+ if (info->master->count++ == info->u.nth.every) {
45+ info->master->count = 0;
4346 ret = !ret;
4447 }
4548 spin_unlock_bh(&nth_lock);
@@ -56,16 +59,31 @@ static bool statistic_mt_check(const struct xt_mtchk_param *par) · 10 unmodified lines
5659 if (info->mode > XT_STATISTIC_MODE_MAX ||
5760 info->flags & ~XT_STATISTIC_MASK)
5861 return false;
59− info->master = info;
62+
63+ info->master = kzalloc(sizeof(*info->master), GFP_KERNEL);
64+ if (info->master == NULL) {
65+ printk(KERN_ERR KBUILD_MODNAME ": Out of memory\n");
66+ return false;
67+ }
68+ info->master->count = info->u.nth.count;
69+
6070 return true;
6171 }
6272
73+static void statistic_mt_destroy(const struct xt_mtdtor_param *par)
74+{
75+ const struct xt_statistic_info *info = par->matchinfo;
76+
77+ kfree(info->master);
78+}
79+
6380 static struct xt_match xt_statistic_mt_reg __read_mostly = {
6481 .name = "statistic",
6582 .revision = 0,
6683 .family = NFPROTO_UNSPEC,
6784 .match = statistic_mt,
6885 .checkentry = statistic_mt_check,
86+ .destroy = statistic_mt_destroy,
6987 .matchsize = sizeof(struct xt_statistic_info),
7088 .me = THIS_MODULE,
7189 };
net/netlink/af_netlink.c+1−0
@@ -1117,6 +1117,7 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) · 1116 unmodified lines
11171117
11181118 read_unlock(&nl_table_lock);
11191119 }
1120+EXPORT_SYMBOL(netlink_set_err);
11201121
11211122 /* must be called with netlink table grabbed */
11221123 static void netlink_update_socket_mc(struct netlink_sock *nlk,
net/sysctl_net.c+1−1
@@ -61,7 +61,7 @@ static struct ctl_table_root net_sysctl_root = { · 60 unmodified lines
6161 static int net_ctl_ro_header_perms(struct ctl_table_root *root,
6262 struct nsproxy *namespaces, struct ctl_table *table)
6363 {
64− if (namespaces->net_ns == &init_net)
64+ if (net_eq(namespaces->net_ns, &init_net))
6565 return table->mode;
6666 else
6767 return table->mode & ~0222;