aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter_arp/arp_tables.h20
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h27
-rw-r--r--net/bridge/br_fdb.c12
-rw-r--r--net/bridge/br_input.c2
-rw-r--r--net/bridge/br_stp_if.c9
-rw-r--r--net/dccp/dccp.h1
-rw-r--r--net/dccp/output.c34
-rw-r--r--net/ipv4/netfilter/arp_tables.c201
-rw-r--r--net/ipv6/mcast.c19
-rw-r--r--net/ipv6/netfilter/ip6_tables.c298
-rw-r--r--net/ipv6/netfilter/ip6t_MARK.c8
-rw-r--r--net/ipv6/route.c2
-rw-r--r--net/rose/rose_timer.c1
13 files changed, 415 insertions, 219 deletions
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index d759a637bded..e98a870a20be 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -68,7 +68,8 @@ struct arpt_entry_target
68 u_int16_t target_size; 68 u_int16_t target_size;
69 69
70 /* Used by userspace */ 70 /* Used by userspace */
71 char name[ARPT_FUNCTION_MAXNAMELEN]; 71 char name[ARPT_FUNCTION_MAXNAMELEN-1];
72 u_int8_t revision;
72 } user; 73 } user;
73 struct { 74 struct {
74 u_int16_t target_size; 75 u_int16_t target_size;
@@ -148,7 +149,9 @@ struct arpt_entry
148 149
149#define ARPT_SO_GET_INFO (ARPT_BASE_CTL) 150#define ARPT_SO_GET_INFO (ARPT_BASE_CTL)
150#define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1) 151#define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1)
151#define ARPT_SO_GET_MAX ARPT_SO_GET_ENTRIES 152/* #define ARPT_SO_GET_REVISION_MATCH (ARPT_BASE_CTL + 2)*/
153#define ARPT_SO_GET_REVISION_TARGET (ARPT_BASE_CTL + 3)
154#define ARPT_SO_GET_MAX ARPT_SO_GET_REVISION_TARGET
152 155
153/* CONTINUE verdict for targets */ 156/* CONTINUE verdict for targets */
154#define ARPT_CONTINUE 0xFFFFFFFF 157#define ARPT_CONTINUE 0xFFFFFFFF
@@ -236,6 +239,15 @@ struct arpt_get_entries
236 struct arpt_entry entrytable[0]; 239 struct arpt_entry entrytable[0];
237}; 240};
238 241
242/* The argument to ARPT_SO_GET_REVISION_*. Returns highest revision
243 * kernel supports, if >= revision. */
244struct arpt_get_revision
245{
246 char name[ARPT_FUNCTION_MAXNAMELEN-1];
247
248 u_int8_t revision;
249};
250
239/* Standard return verdict, or do jump. */ 251/* Standard return verdict, or do jump. */
240#define ARPT_STANDARD_TARGET "" 252#define ARPT_STANDARD_TARGET ""
241/* Error verdict. */ 253/* Error verdict. */
@@ -274,7 +286,9 @@ struct arpt_target
274{ 286{
275 struct list_head list; 287 struct list_head list;
276 288
277 const char name[ARPT_FUNCTION_MAXNAMELEN]; 289 const char name[ARPT_FUNCTION_MAXNAMELEN-1];
290
291 u_int8_t revision;
278 292
279 /* Returns verdict. */ 293 /* Returns verdict. */
280 unsigned int (*target)(struct sk_buff **pskb, 294 unsigned int (*target)(struct sk_buff **pskb,
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 59f70b34e029..2efc046d9e94 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -57,7 +57,8 @@ struct ip6t_entry_match
57 u_int16_t match_size; 57 u_int16_t match_size;
58 58
59 /* Used by userspace */ 59 /* Used by userspace */
60 char name[IP6T_FUNCTION_MAXNAMELEN]; 60 char name[IP6T_FUNCTION_MAXNAMELEN-1];
61 u_int8_t revision;
61 } user; 62 } user;
62 struct { 63 struct {
63 u_int16_t match_size; 64 u_int16_t match_size;
@@ -80,7 +81,8 @@ struct ip6t_entry_target
80 u_int16_t target_size; 81 u_int16_t target_size;
81 82
82 /* Used by userspace */ 83 /* Used by userspace */
83 char name[IP6T_FUNCTION_MAXNAMELEN]; 84 char name[IP6T_FUNCTION_MAXNAMELEN-1];
85 u_int8_t revision;
84 } user; 86 } user;
85 struct { 87 struct {
86 u_int16_t target_size; 88 u_int16_t target_size;
@@ -161,7 +163,9 @@ struct ip6t_entry
161 163
162#define IP6T_SO_GET_INFO (IP6T_BASE_CTL) 164#define IP6T_SO_GET_INFO (IP6T_BASE_CTL)
163#define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1) 165#define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1)
164#define IP6T_SO_GET_MAX IP6T_SO_GET_ENTRIES 166#define IP6T_SO_GET_REVISION_MATCH (IP6T_BASE_CTL + 2)
167#define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 3)
168#define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET
165 169
166/* CONTINUE verdict for targets */ 170/* CONTINUE verdict for targets */
167#define IP6T_CONTINUE 0xFFFFFFFF 171#define IP6T_CONTINUE 0xFFFFFFFF
@@ -291,6 +295,15 @@ struct ip6t_get_entries
291 struct ip6t_entry entrytable[0]; 295 struct ip6t_entry entrytable[0];
292}; 296};
293 297
298/* The argument to IP6T_SO_GET_REVISION_*. Returns highest revision
299 * kernel supports, if >= revision. */
300struct ip6t_get_revision
301{
302 char name[IP6T_FUNCTION_MAXNAMELEN-1];
303
304 u_int8_t revision;
305};
306
294/* Standard return verdict, or do jump. */ 307/* Standard return verdict, or do jump. */
295#define IP6T_STANDARD_TARGET "" 308#define IP6T_STANDARD_TARGET ""
296/* Error verdict. */ 309/* Error verdict. */
@@ -352,7 +365,9 @@ struct ip6t_match
352{ 365{
353 struct list_head list; 366 struct list_head list;
354 367
355 const char name[IP6T_FUNCTION_MAXNAMELEN]; 368 const char name[IP6T_FUNCTION_MAXNAMELEN-1];
369
370 u_int8_t revision;
356 371
357 /* Return true or false: return FALSE and set *hotdrop = 1 to 372 /* Return true or false: return FALSE and set *hotdrop = 1 to
358 force immediate packet drop. */ 373 force immediate packet drop. */
@@ -387,7 +402,9 @@ struct ip6t_target
387{ 402{
388 struct list_head list; 403 struct list_head list;
389 404
390 const char name[IP6T_FUNCTION_MAXNAMELEN]; 405 const char name[IP6T_FUNCTION_MAXNAMELEN-1];
406
407 u_int8_t revision;
391 408
392 /* Returns verdict. Argument order changed since 2.6.9, as this 409 /* Returns verdict. Argument order changed since 2.6.9, as this
393 must now handle non-linear skbs, using skb_copy_bits and 410 must now handle non-linear skbs, using skb_copy_bits and
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 24396b914d11..1f08a59b51ea 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -86,8 +86,8 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
86 struct net_bridge_port *op; 86 struct net_bridge_port *op;
87 list_for_each_entry(op, &br->port_list, list) { 87 list_for_each_entry(op, &br->port_list, list) {
88 if (op != p && 88 if (op != p &&
89 !memcmp(op->dev->dev_addr, 89 !compare_ether_addr(op->dev->dev_addr,
90 f->addr.addr, ETH_ALEN)) { 90 f->addr.addr)) {
91 f->dst = op; 91 f->dst = op;
92 goto insert; 92 goto insert;
93 } 93 }
@@ -151,8 +151,8 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
151 struct net_bridge_port *op; 151 struct net_bridge_port *op;
152 list_for_each_entry(op, &br->port_list, list) { 152 list_for_each_entry(op, &br->port_list, list) {
153 if (op != p && 153 if (op != p &&
154 !memcmp(op->dev->dev_addr, 154 !compare_ether_addr(op->dev->dev_addr,
155 f->addr.addr, ETH_ALEN)) { 155 f->addr.addr)) {
156 f->dst = op; 156 f->dst = op;
157 goto skip_delete; 157 goto skip_delete;
158 } 158 }
@@ -174,7 +174,7 @@ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
174 struct net_bridge_fdb_entry *fdb; 174 struct net_bridge_fdb_entry *fdb;
175 175
176 hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) { 176 hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) {
177 if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) { 177 if (!compare_ether_addr(fdb->addr.addr, addr)) {
178 if (unlikely(has_expired(br, fdb))) 178 if (unlikely(has_expired(br, fdb)))
179 break; 179 break;
180 return fdb; 180 return fdb;
@@ -264,7 +264,7 @@ static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
264 struct net_bridge_fdb_entry *fdb; 264 struct net_bridge_fdb_entry *fdb;
265 265
266 hlist_for_each_entry_rcu(fdb, h, head, hlist) { 266 hlist_for_each_entry_rcu(fdb, h, head, hlist) {
267 if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) 267 if (!compare_ether_addr(fdb->addr.addr, addr))
268 return fdb; 268 return fdb;
269 } 269 }
270 return NULL; 270 return NULL;
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 9a45e6279c57..b88220a64cd8 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -128,7 +128,7 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
128 dest = eth_hdr(skb)->h_dest; 128 dest = eth_hdr(skb)->h_dest;
129 } 129 }
130 130
131 if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN)) 131 if (!compare_ether_addr(p->br->dev->dev_addr, dest))
132 skb->pkt_type = PACKET_HOST; 132 skb->pkt_type = PACKET_HOST;
133 133
134 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, 134 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 0da11ff05fa3..ac09b6a23523 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -15,6 +15,7 @@
15 15
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/smp_lock.h> 17#include <linux/smp_lock.h>
18#include <linux/etherdevice.h>
18 19
19#include "br_private.h" 20#include "br_private.h"
20#include "br_private_stp.h" 21#include "br_private_stp.h"
@@ -133,10 +134,10 @@ static void br_stp_change_bridge_id(struct net_bridge *br,
133 memcpy(br->dev->dev_addr, addr, ETH_ALEN); 134 memcpy(br->dev->dev_addr, addr, ETH_ALEN);
134 135
135 list_for_each_entry(p, &br->port_list, list) { 136 list_for_each_entry(p, &br->port_list, list) {
136 if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN)) 137 if (!compare_ether_addr(p->designated_bridge.addr, oldaddr))
137 memcpy(p->designated_bridge.addr, addr, ETH_ALEN); 138 memcpy(p->designated_bridge.addr, addr, ETH_ALEN);
138 139
139 if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN)) 140 if (!compare_ether_addr(p->designated_root.addr, oldaddr))
140 memcpy(p->designated_root.addr, addr, ETH_ALEN); 141 memcpy(p->designated_root.addr, addr, ETH_ALEN);
141 142
142 } 143 }
@@ -157,12 +158,12 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
157 158
158 list_for_each_entry(p, &br->port_list, list) { 159 list_for_each_entry(p, &br->port_list, list) {
159 if (addr == br_mac_zero || 160 if (addr == br_mac_zero ||
160 memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0) 161 compare_ether_addr(p->dev->dev_addr, addr) < 0)
161 addr = p->dev->dev_addr; 162 addr = p->dev->dev_addr;
162 163
163 } 164 }
164 165
165 if (memcmp(br->bridge_id.addr, addr, ETH_ALEN)) 166 if (compare_ether_addr(br->bridge_id.addr, addr))
166 br_stp_change_bridge_id(br, addr); 167 br_stp_change_bridge_id(br, addr);
167} 168}
168 169
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 5871c027f9dc..f97b85d55ad8 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -118,7 +118,6 @@ DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics);
118#define DCCP_ADD_STATS_USER(field, val) \ 118#define DCCP_ADD_STATS_USER(field, val) \
119 SNMP_ADD_STATS_USER(dccp_statistics, field, val) 119 SNMP_ADD_STATS_USER(dccp_statistics, field, val)
120 120
121extern int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb);
122extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb); 121extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);
123 122
124extern int dccp_send_response(struct sock *sk); 123extern int dccp_send_response(struct sock *sk);
diff --git a/net/dccp/output.c b/net/dccp/output.c
index d59f86f7ceab..74ff87025878 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -12,6 +12,7 @@
12 12
13#include <linux/config.h> 13#include <linux/config.h>
14#include <linux/dccp.h> 14#include <linux/dccp.h>
15#include <linux/kernel.h>
15#include <linux/skbuff.h> 16#include <linux/skbuff.h>
16 17
17#include <net/sock.h> 18#include <net/sock.h>
@@ -25,13 +26,20 @@ static inline void dccp_event_ack_sent(struct sock *sk)
25 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); 26 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
26} 27}
27 28
29static inline void dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
30{
31 skb_set_owner_w(skb, sk);
32 WARN_ON(sk->sk_send_head);
33 sk->sk_send_head = skb;
34}
35
28/* 36/*
29 * All SKB's seen here are completely headerless. It is our 37 * All SKB's seen here are completely headerless. It is our
30 * job to build the DCCP header, and pass the packet down to 38 * job to build the DCCP header, and pass the packet down to
31 * IP so it can do the same plus pass the packet off to the 39 * IP so it can do the same plus pass the packet off to the
32 * device. 40 * device.
33 */ 41 */
34int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) 42static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
35{ 43{
36 if (likely(skb != NULL)) { 44 if (likely(skb != NULL)) {
37 const struct inet_sock *inet = inet_sk(sk); 45 const struct inet_sock *inet = inet_sk(sk);
@@ -50,10 +58,21 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
50 switch (dcb->dccpd_type) { 58 switch (dcb->dccpd_type) {
51 case DCCP_PKT_DATA: 59 case DCCP_PKT_DATA:
52 set_ack = 0; 60 set_ack = 0;
61 /* fall through */
62 case DCCP_PKT_DATAACK:
53 break; 63 break;
64
54 case DCCP_PKT_SYNC: 65 case DCCP_PKT_SYNC:
55 case DCCP_PKT_SYNCACK: 66 case DCCP_PKT_SYNCACK:
56 ackno = dcb->dccpd_seq; 67 ackno = dcb->dccpd_seq;
68 /* fall through */
69 default:
70 /*
71 * Only data packets should come through with skb->sk
72 * set.
73 */
74 WARN_ON(skb->sk);
75 skb_set_owner_w(skb, sk);
57 break; 76 break;
58 } 77 }
59 78
@@ -63,9 +82,6 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
63 skb->h.raw = skb_push(skb, dccp_header_size); 82 skb->h.raw = skb_push(skb, dccp_header_size);
64 dh = dccp_hdr(skb); 83 dh = dccp_hdr(skb);
65 84
66 if (!skb->sk)
67 skb_set_owner_w(skb, sk);
68
69 /* Build DCCP header and checksum it. */ 85 /* Build DCCP header and checksum it. */
70 memset(dh, 0, dccp_header_size); 86 memset(dh, 0, dccp_header_size);
71 dh->dccph_type = dcb->dccpd_type; 87 dh->dccph_type = dcb->dccpd_type;
@@ -393,10 +409,8 @@ int dccp_connect(struct sock *sk)
393 409
394 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; 410 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
395 skb->csum = 0; 411 skb->csum = 0;
396 skb_set_owner_w(skb, sk);
397 412
398 BUG_TRAP(sk->sk_send_head == NULL); 413 dccp_skb_entail(sk, skb);
399 sk->sk_send_head = skb;
400 dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL)); 414 dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
401 DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); 415 DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
402 416
@@ -425,7 +439,6 @@ void dccp_send_ack(struct sock *sk)
425 skb_reserve(skb, MAX_DCCP_HEADER); 439 skb_reserve(skb, MAX_DCCP_HEADER);
426 skb->csum = 0; 440 skb->csum = 0;
427 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK; 441 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK;
428 skb_set_owner_w(skb, sk);
429 dccp_transmit_skb(sk, skb); 442 dccp_transmit_skb(sk, skb);
430 } 443 }
431} 444}
@@ -482,7 +495,6 @@ void dccp_send_sync(struct sock *sk, const u64 seq,
482 DCCP_SKB_CB(skb)->dccpd_type = pkt_type; 495 DCCP_SKB_CB(skb)->dccpd_type = pkt_type;
483 DCCP_SKB_CB(skb)->dccpd_seq = seq; 496 DCCP_SKB_CB(skb)->dccpd_seq = seq;
484 497
485 skb_set_owner_w(skb, sk);
486 dccp_transmit_skb(sk, skb); 498 dccp_transmit_skb(sk, skb);
487} 499}
488 500
@@ -507,10 +519,8 @@ void dccp_send_close(struct sock *sk, const int active)
507 DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ? 519 DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ?
508 DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; 520 DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ;
509 521
510 skb_set_owner_w(skb, sk);
511 if (active) { 522 if (active) {
512 BUG_TRAP(sk->sk_send_head == NULL); 523 dccp_skb_entail(sk, skb);
513 sk->sk_send_head = skb;
514 dccp_transmit_skb(sk, skb_clone(skb, prio)); 524 dccp_transmit_skb(sk, skb_clone(skb, prio));
515 } else 525 } else
516 dccp_transmit_skb(sk, skb); 526 dccp_transmit_skb(sk, skb);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index a7969286e6e7..3c2e9639bba6 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -347,58 +347,106 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
347 return verdict; 347 return verdict;
348} 348}
349 349
350static inline void *find_inlist_lock_noload(struct list_head *head, 350/*
351 const char *name, 351 * These are weird, but module loading must not be done with mutex
352 int *error, 352 * held (since they will register), and we have to have a single
353 struct semaphore *mutex) 353 * function to use try_then_request_module().
354 */
355
356/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
357static inline struct arpt_table *find_table_lock(const char *name)
354{ 358{
355 void *ret; 359 struct arpt_table *t;
356 360
357 *error = down_interruptible(mutex); 361 if (down_interruptible(&arpt_mutex) != 0)
358 if (*error != 0) 362 return ERR_PTR(-EINTR);
359 return NULL;
360 363
361 ret = list_named_find(head, name); 364 list_for_each_entry(t, &arpt_tables, list)
362 if (!ret) { 365 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
363 *error = -ENOENT; 366 return t;
364 up(mutex); 367 up(&arpt_mutex);
365 } 368 return NULL;
366 return ret;
367} 369}
368 370
369#ifndef CONFIG_KMOD 371
370#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m)) 372/* Find target, grabs ref. Returns ERR_PTR() on error. */
371#else 373static inline struct arpt_target *find_target(const char *name, u8 revision)
372static void *
373find_inlist_lock(struct list_head *head,
374 const char *name,
375 const char *prefix,
376 int *error,
377 struct semaphore *mutex)
378{ 374{
379 void *ret; 375 struct arpt_target *t;
376 int err = 0;
380 377
381 ret = find_inlist_lock_noload(head, name, error, mutex); 378 if (down_interruptible(&arpt_mutex) != 0)
382 if (!ret) { 379 return ERR_PTR(-EINTR);
383 duprintf("find_inlist: loading `%s%s'.\n", prefix, name); 380
384 request_module("%s%s", prefix, name); 381 list_for_each_entry(t, &arpt_target, list) {
385 ret = find_inlist_lock_noload(head, name, error, mutex); 382 if (strcmp(t->name, name) == 0) {
383 if (t->revision == revision) {
384 if (try_module_get(t->me)) {
385 up(&arpt_mutex);
386 return t;
387 }
388 } else
389 err = -EPROTOTYPE; /* Found something. */
390 }
386 } 391 }
392 up(&arpt_mutex);
393 return ERR_PTR(err);
394}
387 395
388 return ret; 396struct arpt_target *arpt_find_target(const char *name, u8 revision)
397{
398 struct arpt_target *target;
399
400 target = try_then_request_module(find_target(name, revision),
401 "arpt_%s", name);
402 if (IS_ERR(target) || !target)
403 return NULL;
404 return target;
389} 405}
390#endif
391 406
392static inline struct arpt_table *arpt_find_table_lock(const char *name, int *error, struct semaphore *mutex) 407static int target_revfn(const char *name, u8 revision, int *bestp)
393{ 408{
394 return find_inlist_lock(&arpt_tables, name, "arptable_", error, mutex); 409 struct arpt_target *t;
410 int have_rev = 0;
411
412 list_for_each_entry(t, &arpt_target, list) {
413 if (strcmp(t->name, name) == 0) {
414 if (t->revision > *bestp)
415 *bestp = t->revision;
416 if (t->revision == revision)
417 have_rev =1;
418 }
419 }
420 return have_rev;
395} 421}
396 422
397static struct arpt_target *arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex) 423/* Returns true or false (if no such extension at all) */
424static inline int find_revision(const char *name, u8 revision,
425 int (*revfn)(const char *, u8, int *),
426 int *err)
398{ 427{
399 return find_inlist_lock(&arpt_target, name, "arpt_", error, mutex); 428 int have_rev, best = -1;
429
430 if (down_interruptible(&arpt_mutex) != 0) {
431 *err = -EINTR;
432 return 1;
433 }
434 have_rev = revfn(name, revision, &best);
435 up(&arpt_mutex);
436
437 /* Nothing at all? Return 0 to try loading module. */
438 if (best == -1) {
439 *err = -ENOENT;
440 return 0;
441 }
442
443 *err = best;
444 if (!have_rev)
445 *err = -EPROTONOSUPPORT;
446 return 1;
400} 447}
401 448
449
402/* All zeroes == unconditional rule. */ 450/* All zeroes == unconditional rule. */
403static inline int unconditional(const struct arpt_arp *arp) 451static inline int unconditional(const struct arpt_arp *arp)
404{ 452{
@@ -544,17 +592,15 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i
544 } 592 }
545 593
546 t = arpt_get_target(e); 594 t = arpt_get_target(e);
547 target = arpt_find_target_lock(t->u.user.name, &ret, &arpt_mutex); 595 target = try_then_request_module(find_target(t->u.user.name,
548 if (!target) { 596 t->u.user.revision),
597 "arpt_%s", t->u.user.name);
598 if (IS_ERR(target) || !target) {
549 duprintf("check_entry: `%s' not found\n", t->u.user.name); 599 duprintf("check_entry: `%s' not found\n", t->u.user.name);
600 ret = target ? PTR_ERR(target) : -ENOENT;
550 goto out; 601 goto out;
551 } 602 }
552 if (!try_module_get((target->me))) {
553 ret = -ENOENT;
554 goto out_unlock;
555 }
556 t->u.kernel.target = target; 603 t->u.kernel.target = target;
557 up(&arpt_mutex);
558 604
559 if (t->u.kernel.target == &arpt_standard_target) { 605 if (t->u.kernel.target == &arpt_standard_target) {
560 if (!standard_check(t, size)) { 606 if (!standard_check(t, size)) {
@@ -576,8 +622,6 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i
576 (*i)++; 622 (*i)++;
577 return 0; 623 return 0;
578 624
579out_unlock:
580 up(&arpt_mutex);
581out: 625out:
582 return ret; 626 return ret;
583} 627}
@@ -846,8 +890,8 @@ static int get_entries(const struct arpt_get_entries *entries,
846 int ret; 890 int ret;
847 struct arpt_table *t; 891 struct arpt_table *t;
848 892
849 t = arpt_find_table_lock(entries->name, &ret, &arpt_mutex); 893 t = find_table_lock(entries->name);
850 if (t) { 894 if (t || !IS_ERR(t)) {
851 duprintf("t->private->number = %u\n", 895 duprintf("t->private->number = %u\n",
852 t->private->number); 896 t->private->number);
853 if (entries->size == t->private->size) 897 if (entries->size == t->private->size)
@@ -859,10 +903,10 @@ static int get_entries(const struct arpt_get_entries *entries,
859 entries->size); 903 entries->size);
860 ret = -EINVAL; 904 ret = -EINVAL;
861 } 905 }
906 module_put(t->me);
862 up(&arpt_mutex); 907 up(&arpt_mutex);
863 } else 908 } else
864 duprintf("get_entries: Can't find %s!\n", 909 ret = t ? PTR_ERR(t) : -ENOENT;
865 entries->name);
866 910
867 return ret; 911 return ret;
868} 912}
@@ -913,22 +957,19 @@ static int do_replace(void __user *user, unsigned int len)
913 957
914 duprintf("arp_tables: Translated table\n"); 958 duprintf("arp_tables: Translated table\n");
915 959
916 t = arpt_find_table_lock(tmp.name, &ret, &arpt_mutex); 960 t = try_then_request_module(find_table_lock(tmp.name),
917 if (!t) 961 "arptable_%s", tmp.name);
962 if (!t || IS_ERR(t)) {
963 ret = t ? PTR_ERR(t) : -ENOENT;
918 goto free_newinfo_counters_untrans; 964 goto free_newinfo_counters_untrans;
965 }
919 966
920 /* You lied! */ 967 /* You lied! */
921 if (tmp.valid_hooks != t->valid_hooks) { 968 if (tmp.valid_hooks != t->valid_hooks) {
922 duprintf("Valid hook crap: %08X vs %08X\n", 969 duprintf("Valid hook crap: %08X vs %08X\n",
923 tmp.valid_hooks, t->valid_hooks); 970 tmp.valid_hooks, t->valid_hooks);
924 ret = -EINVAL; 971 ret = -EINVAL;
925 goto free_newinfo_counters_untrans_unlock; 972 goto put_module;
926 }
927
928 /* Get a reference in advance, we're not allowed fail later */
929 if (!try_module_get(t->me)) {
930 ret = -EBUSY;
931 goto free_newinfo_counters_untrans_unlock;
932 } 973 }
933 974
934 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 975 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
@@ -959,7 +1000,6 @@ static int do_replace(void __user *user, unsigned int len)
959 1000
960 put_module: 1001 put_module:
961 module_put(t->me); 1002 module_put(t->me);
962 free_newinfo_counters_untrans_unlock:
963 up(&arpt_mutex); 1003 up(&arpt_mutex);
964 free_newinfo_counters_untrans: 1004 free_newinfo_counters_untrans:
965 ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry, NULL); 1005 ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry, NULL);
@@ -989,7 +1029,7 @@ static int do_add_counters(void __user *user, unsigned int len)
989 unsigned int i; 1029 unsigned int i;
990 struct arpt_counters_info tmp, *paddc; 1030 struct arpt_counters_info tmp, *paddc;
991 struct arpt_table *t; 1031 struct arpt_table *t;
992 int ret; 1032 int ret = 0;
993 1033
994 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1034 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
995 return -EFAULT; 1035 return -EFAULT;
@@ -1006,9 +1046,11 @@ static int do_add_counters(void __user *user, unsigned int len)
1006 goto free; 1046 goto free;
1007 } 1047 }
1008 1048
1009 t = arpt_find_table_lock(tmp.name, &ret, &arpt_mutex); 1049 t = find_table_lock(tmp.name);
1010 if (!t) 1050 if (!t || IS_ERR(t)) {
1051 ret = t ? PTR_ERR(t) : -ENOENT;
1011 goto free; 1052 goto free;
1053 }
1012 1054
1013 write_lock_bh(&t->lock); 1055 write_lock_bh(&t->lock);
1014 if (t->private->number != paddc->num_counters) { 1056 if (t->private->number != paddc->num_counters) {
@@ -1025,6 +1067,7 @@ static int do_add_counters(void __user *user, unsigned int len)
1025 unlock_up_free: 1067 unlock_up_free:
1026 write_unlock_bh(&t->lock); 1068 write_unlock_bh(&t->lock);
1027 up(&arpt_mutex); 1069 up(&arpt_mutex);
1070 module_put(t->me);
1028 free: 1071 free:
1029 vfree(paddc); 1072 vfree(paddc);
1030 1073
@@ -1079,8 +1122,10 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1079 break; 1122 break;
1080 } 1123 }
1081 name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; 1124 name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
1082 t = arpt_find_table_lock(name, &ret, &arpt_mutex); 1125
1083 if (t) { 1126 t = try_then_request_module(find_table_lock(name),
1127 "arptable_%s", name);
1128 if (t && !IS_ERR(t)) {
1084 struct arpt_getinfo info; 1129 struct arpt_getinfo info;
1085 1130
1086 info.valid_hooks = t->valid_hooks; 1131 info.valid_hooks = t->valid_hooks;
@@ -1096,9 +1141,10 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1096 ret = -EFAULT; 1141 ret = -EFAULT;
1097 else 1142 else
1098 ret = 0; 1143 ret = 0;
1099
1100 up(&arpt_mutex); 1144 up(&arpt_mutex);
1101 } 1145 module_put(t->me);
1146 } else
1147 ret = t ? PTR_ERR(t) : -ENOENT;
1102 } 1148 }
1103 break; 1149 break;
1104 1150
@@ -1119,6 +1165,24 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1119 break; 1165 break;
1120 } 1166 }
1121 1167
1168 case ARPT_SO_GET_REVISION_TARGET: {
1169 struct arpt_get_revision rev;
1170
1171 if (*len != sizeof(rev)) {
1172 ret = -EINVAL;
1173 break;
1174 }
1175 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
1176 ret = -EFAULT;
1177 break;
1178 }
1179
1180 try_then_request_module(find_revision(rev.name, rev.revision,
1181 target_revfn, &ret),
1182 "arpt_%s", rev.name);
1183 break;
1184 }
1185
1122 default: 1186 default:
1123 duprintf("do_arpt_get_ctl: unknown request %i\n", cmd); 1187 duprintf("do_arpt_get_ctl: unknown request %i\n", cmd);
1124 ret = -EINVAL; 1188 ret = -EINVAL;
@@ -1136,12 +1200,9 @@ int arpt_register_target(struct arpt_target *target)
1136 if (ret != 0) 1200 if (ret != 0)
1137 return ret; 1201 return ret;
1138 1202
1139 if (!list_named_insert(&arpt_target, target)) { 1203 list_add(&target->list, &arpt_target);
1140 duprintf("arpt_register_target: `%s' already in list!\n",
1141 target->name);
1142 ret = -EINVAL;
1143 }
1144 up(&arpt_mutex); 1204 up(&arpt_mutex);
1205
1145 return ret; 1206 return ret;
1146} 1207}
1147 1208
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index c4f2a0ef7489..966b2372aaab 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1087,7 +1087,7 @@ static void mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
1087 1087
1088int igmp6_event_query(struct sk_buff *skb) 1088int igmp6_event_query(struct sk_buff *skb)
1089{ 1089{
1090 struct mld2_query *mlh2 = (struct mld2_query *) skb->h.raw; 1090 struct mld2_query *mlh2 = NULL;
1091 struct ifmcaddr6 *ma; 1091 struct ifmcaddr6 *ma;
1092 struct in6_addr *group; 1092 struct in6_addr *group;
1093 unsigned long max_delay; 1093 unsigned long max_delay;
@@ -1140,6 +1140,13 @@ int igmp6_event_query(struct sk_buff *skb)
1140 /* clear deleted report items */ 1140 /* clear deleted report items */
1141 mld_clear_delrec(idev); 1141 mld_clear_delrec(idev);
1142 } else if (len >= 28) { 1142 } else if (len >= 28) {
1143 int srcs_offset = sizeof(struct mld2_query) -
1144 sizeof(struct icmp6hdr);
1145 if (!pskb_may_pull(skb, srcs_offset)) {
1146 in6_dev_put(idev);
1147 return -EINVAL;
1148 }
1149 mlh2 = (struct mld2_query *) skb->h.raw;
1143 max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; 1150 max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000;
1144 if (!max_delay) 1151 if (!max_delay)
1145 max_delay = 1; 1152 max_delay = 1;
@@ -1156,7 +1163,15 @@ int igmp6_event_query(struct sk_buff *skb)
1156 return 0; 1163 return 0;
1157 } 1164 }
1158 /* mark sources to include, if group & source-specific */ 1165 /* mark sources to include, if group & source-specific */
1159 mark = mlh2->nsrcs != 0; 1166 if (mlh2->nsrcs != 0) {
1167 if (!pskb_may_pull(skb, srcs_offset +
1168 mlh2->nsrcs * sizeof(struct in6_addr))) {
1169 in6_dev_put(idev);
1170 return -EINVAL;
1171 }
1172 mlh2 = (struct mld2_query *) skb->h.raw;
1173 mark = 1;
1174 }
1160 } else { 1175 } else {
1161 in6_dev_put(idev); 1176 in6_dev_put(idev);
1162 return -EINVAL; 1177 return -EINVAL;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 21deec25a12b..7d492226c16e 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -2,7 +2,7 @@
2 * Packet matching code. 2 * Packet matching code.
3 * 3 *
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2002 Netfilter core team <coreteam@netfilter.org> 5 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -23,7 +23,6 @@
23#include <linux/tcp.h> 23#include <linux/tcp.h>
24#include <linux/udp.h> 24#include <linux/udp.h>
25#include <linux/icmpv6.h> 25#include <linux/icmpv6.h>
26#include <net/ip.h>
27#include <net/ipv6.h> 26#include <net/ipv6.h>
28#include <asm/uaccess.h> 27#include <asm/uaccess.h>
29#include <asm/semaphore.h> 28#include <asm/semaphore.h>
@@ -80,13 +79,12 @@ static DECLARE_MUTEX(ip6t_mutex);
80#define inline 79#define inline
81#endif 80#endif
82 81
83/* Locking is simple: we assume at worst case there will be one packet 82/*
84 in user context and one from bottom halves (or soft irq if Alexey's
85 softnet patch was applied).
86
87 We keep a set of rules for each CPU, so we can avoid write-locking 83 We keep a set of rules for each CPU, so we can avoid write-locking
88 them; doing a readlock_bh() stops packets coming through if we're 84 them in the softirq when updating the counters and therefore
89 in user context. 85 only need to read-lock in the softirq; doing a write_lock_bh() in user
86 context stops packets coming through and allows user context to read
87 the counters or update the rules.
90 88
91 To be cache friendly on SMP, we arrange them like so: 89 To be cache friendly on SMP, we arrange them like so:
92 [ n-entries ] 90 [ n-entries ]
@@ -356,7 +354,7 @@ ip6t_do_table(struct sk_buff **pskb,
356 struct ip6t_table *table, 354 struct ip6t_table *table,
357 void *userdata) 355 void *userdata)
358{ 356{
359 static const char nulldevname[IFNAMSIZ]; 357 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
360 int offset = 0; 358 int offset = 0;
361 unsigned int protoff = 0; 359 unsigned int protoff = 0;
362 int hotdrop = 0; 360 int hotdrop = 0;
@@ -369,7 +367,6 @@ ip6t_do_table(struct sk_buff **pskb,
369 /* Initialization */ 367 /* Initialization */
370 indev = in ? in->name : nulldevname; 368 indev = in ? in->name : nulldevname;
371 outdev = out ? out->name : nulldevname; 369 outdev = out ? out->name : nulldevname;
372
373 /* We handle fragments by dealing with the first fragment as 370 /* We handle fragments by dealing with the first fragment as
374 * if it was a normal packet. All other fragments are treated 371 * if it was a normal packet. All other fragments are treated
375 * normally, except that they will NEVER match rules that ask 372 * normally, except that they will NEVER match rules that ask
@@ -497,75 +494,145 @@ ip6t_do_table(struct sk_buff **pskb,
497#endif 494#endif
498} 495}
499 496
500/* If it succeeds, returns element and locks mutex */ 497/*
501static inline void * 498 * These are weird, but module loading must not be done with mutex
502find_inlist_lock_noload(struct list_head *head, 499 * held (since they will register), and we have to have a single
503 const char *name, 500 * function to use try_then_request_module().
504 int *error, 501 */
505 struct semaphore *mutex) 502
503/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
504static inline struct ip6t_table *find_table_lock(const char *name)
506{ 505{
507 void *ret; 506 struct ip6t_table *t;
508 507
509#if 1 508 if (down_interruptible(&ip6t_mutex) != 0)
510 duprintf("find_inlist: searching for `%s' in %s.\n", 509 return ERR_PTR(-EINTR);
511 name, head == &ip6t_target ? "ip6t_target"
512 : head == &ip6t_match ? "ip6t_match"
513 : head == &ip6t_tables ? "ip6t_tables" : "UNKNOWN");
514#endif
515 510
516 *error = down_interruptible(mutex); 511 list_for_each_entry(t, &ip6t_tables, list)
517 if (*error != 0) 512 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
518 return NULL; 513 return t;
514 up(&ip6t_mutex);
515 return NULL;
516}
517
518/* Find match, grabs ref. Returns ERR_PTR() on error. */
519static inline struct ip6t_match *find_match(const char *name, u8 revision)
520{
521 struct ip6t_match *m;
522 int err = 0;
519 523
520 ret = list_named_find(head, name); 524 if (down_interruptible(&ip6t_mutex) != 0)
521 if (!ret) { 525 return ERR_PTR(-EINTR);
522 *error = -ENOENT; 526
523 up(mutex); 527 list_for_each_entry(m, &ip6t_match, list) {
528 if (strcmp(m->name, name) == 0) {
529 if (m->revision == revision) {
530 if (try_module_get(m->me)) {
531 up(&ip6t_mutex);
532 return m;
533 }
534 } else
535 err = -EPROTOTYPE; /* Found something. */
536 }
524 } 537 }
525 return ret; 538 up(&ip6t_mutex);
539 return ERR_PTR(err);
526} 540}
527 541
528#ifndef CONFIG_KMOD 542/* Find target, grabs ref. Returns ERR_PTR() on error. */
529#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m)) 543static inline struct ip6t_target *find_target(const char *name, u8 revision)
530#else
531static void *
532find_inlist_lock(struct list_head *head,
533 const char *name,
534 const char *prefix,
535 int *error,
536 struct semaphore *mutex)
537{ 544{
538 void *ret; 545 struct ip6t_target *t;
546 int err = 0;
539 547
540 ret = find_inlist_lock_noload(head, name, error, mutex); 548 if (down_interruptible(&ip6t_mutex) != 0)
541 if (!ret) { 549 return ERR_PTR(-EINTR);
542 duprintf("find_inlist: loading `%s%s'.\n", prefix, name); 550
543 request_module("%s%s", prefix, name); 551 list_for_each_entry(t, &ip6t_target, list) {
544 ret = find_inlist_lock_noload(head, name, error, mutex); 552 if (strcmp(t->name, name) == 0) {
553 if (t->revision == revision) {
554 if (try_module_get(t->me)) {
555 up(&ip6t_mutex);
556 return t;
557 }
558 } else
559 err = -EPROTOTYPE; /* Found something. */
560 }
545 } 561 }
562 up(&ip6t_mutex);
563 return ERR_PTR(err);
564}
546 565
547 return ret; 566struct ip6t_target *ip6t_find_target(const char *name, u8 revision)
567{
568 struct ip6t_target *target;
569
570 target = try_then_request_module(find_target(name, revision),
571 "ip6t_%s", name);
572 if (IS_ERR(target) || !target)
573 return NULL;
574 return target;
548} 575}
549#endif
550 576
551static inline struct ip6t_table * 577static int match_revfn(const char *name, u8 revision, int *bestp)
552ip6t_find_table_lock(const char *name, int *error, struct semaphore *mutex)
553{ 578{
554 return find_inlist_lock(&ip6t_tables, name, "ip6table_", error, mutex); 579 struct ip6t_match *m;
580 int have_rev = 0;
581
582 list_for_each_entry(m, &ip6t_match, list) {
583 if (strcmp(m->name, name) == 0) {
584 if (m->revision > *bestp)
585 *bestp = m->revision;
586 if (m->revision == revision)
587 have_rev = 1;
588 }
589 }
590 return have_rev;
555} 591}
556 592
557static inline struct ip6t_match * 593static int target_revfn(const char *name, u8 revision, int *bestp)
558find_match_lock(const char *name, int *error, struct semaphore *mutex)
559{ 594{
560 return find_inlist_lock(&ip6t_match, name, "ip6t_", error, mutex); 595 struct ip6t_target *t;
596 int have_rev = 0;
597
598 list_for_each_entry(t, &ip6t_target, list) {
599 if (strcmp(t->name, name) == 0) {
600 if (t->revision > *bestp)
601 *bestp = t->revision;
602 if (t->revision == revision)
603 have_rev = 1;
604 }
605 }
606 return have_rev;
561} 607}
562 608
563static struct ip6t_target * 609/* Returns true or fals (if no such extension at all) */
564ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex) 610static inline int find_revision(const char *name, u8 revision,
611 int (*revfn)(const char *, u8, int *),
612 int *err)
565{ 613{
566 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex); 614 int have_rev, best = -1;
615
616 if (down_interruptible(&ip6t_mutex) != 0) {
617 *err = -EINTR;
618 return 1;
619 }
620 have_rev = revfn(name, revision, &best);
621 up(&ip6t_mutex);
622
623 /* Nothing at all? Return 0 to try loading module. */
624 if (best == -1) {
625 *err = -ENOENT;
626 return 0;
627 }
628
629 *err = best;
630 if (!have_rev)
631 *err = -EPROTONOSUPPORT;
632 return 1;
567} 633}
568 634
635
569/* All zeroes == unconditional rule. */ 636/* All zeroes == unconditional rule. */
570static inline int 637static inline int
571unconditional(const struct ip6t_ip6 *ipv6) 638unconditional(const struct ip6t_ip6 *ipv6)
@@ -725,20 +792,16 @@ check_match(struct ip6t_entry_match *m,
725 unsigned int hookmask, 792 unsigned int hookmask,
726 unsigned int *i) 793 unsigned int *i)
727{ 794{
728 int ret;
729 struct ip6t_match *match; 795 struct ip6t_match *match;
730 796
731 match = find_match_lock(m->u.user.name, &ret, &ip6t_mutex); 797 match = try_then_request_module(find_match(m->u.user.name,
732 if (!match) { 798 m->u.user.revision),
733 // duprintf("check_match: `%s' not found\n", m->u.name); 799 "ip6t_%s", m->u.user.name);
734 return ret; 800 if (IS_ERR(match) || !match) {
735 } 801 duprintf("check_match: `%s' not found\n", m->u.user.name);
736 if (!try_module_get(match->me)) { 802 return match ? PTR_ERR(match) : -ENOENT;
737 up(&ip6t_mutex);
738 return -ENOENT;
739 } 803 }
740 m->u.kernel.match = match; 804 m->u.kernel.match = match;
741 up(&ip6t_mutex);
742 805
743 if (m->u.kernel.match->checkentry 806 if (m->u.kernel.match->checkentry
744 && !m->u.kernel.match->checkentry(name, ipv6, m->data, 807 && !m->u.kernel.match->checkentry(name, ipv6, m->data,
@@ -776,22 +839,16 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
776 goto cleanup_matches; 839 goto cleanup_matches;
777 840
778 t = ip6t_get_target(e); 841 t = ip6t_get_target(e);
779 target = ip6t_find_target_lock(t->u.user.name, &ret, &ip6t_mutex); 842 target = try_then_request_module(find_target(t->u.user.name,
780 if (!target) { 843 t->u.user.revision),
844 "ip6t_%s", t->u.user.name);
845 if (IS_ERR(target) || !target) {
781 duprintf("check_entry: `%s' not found\n", t->u.user.name); 846 duprintf("check_entry: `%s' not found\n", t->u.user.name);
782 goto cleanup_matches; 847 ret = target ? PTR_ERR(target) : -ENOENT;
783 }
784 if (!try_module_get(target->me)) {
785 up(&ip6t_mutex);
786 ret = -ENOENT;
787 goto cleanup_matches; 848 goto cleanup_matches;
788 } 849 }
789 t->u.kernel.target = target; 850 t->u.kernel.target = target;
790 up(&ip6t_mutex); 851
791 if (!t->u.kernel.target) {
792 ret = -EBUSY;
793 goto cleanup_matches;
794 }
795 if (t->u.kernel.target == &ip6t_standard_target) { 852 if (t->u.kernel.target == &ip6t_standard_target) {
796 if (!standard_check(t, size)) { 853 if (!standard_check(t, size)) {
797 ret = -EINVAL; 854 ret = -EINVAL;
@@ -1118,8 +1175,8 @@ get_entries(const struct ip6t_get_entries *entries,
1118 int ret; 1175 int ret;
1119 struct ip6t_table *t; 1176 struct ip6t_table *t;
1120 1177
1121 t = ip6t_find_table_lock(entries->name, &ret, &ip6t_mutex); 1178 t = find_table_lock(entries->name);
1122 if (t) { 1179 if (t && !IS_ERR(t)) {
1123 duprintf("t->private->number = %u\n", 1180 duprintf("t->private->number = %u\n",
1124 t->private->number); 1181 t->private->number);
1125 if (entries->size == t->private->size) 1182 if (entries->size == t->private->size)
@@ -1131,10 +1188,10 @@ get_entries(const struct ip6t_get_entries *entries,
1131 entries->size); 1188 entries->size);
1132 ret = -EINVAL; 1189 ret = -EINVAL;
1133 } 1190 }
1191 module_put(t->me);
1134 up(&ip6t_mutex); 1192 up(&ip6t_mutex);
1135 } else 1193 } else
1136 duprintf("get_entries: Can't find %s!\n", 1194 ret = t ? PTR_ERR(t) : -ENOENT;
1137 entries->name);
1138 1195
1139 return ret; 1196 return ret;
1140} 1197}
@@ -1182,22 +1239,19 @@ do_replace(void __user *user, unsigned int len)
1182 1239
1183 duprintf("ip_tables: Translated table\n"); 1240 duprintf("ip_tables: Translated table\n");
1184 1241
1185 t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex); 1242 t = try_then_request_module(find_table_lock(tmp.name),
1186 if (!t) 1243 "ip6table_%s", tmp.name);
1244 if (!t || IS_ERR(t)) {
1245 ret = t ? PTR_ERR(t) : -ENOENT;
1187 goto free_newinfo_counters_untrans; 1246 goto free_newinfo_counters_untrans;
1247 }
1188 1248
1189 /* You lied! */ 1249 /* You lied! */
1190 if (tmp.valid_hooks != t->valid_hooks) { 1250 if (tmp.valid_hooks != t->valid_hooks) {
1191 duprintf("Valid hook crap: %08X vs %08X\n", 1251 duprintf("Valid hook crap: %08X vs %08X\n",
1192 tmp.valid_hooks, t->valid_hooks); 1252 tmp.valid_hooks, t->valid_hooks);
1193 ret = -EINVAL; 1253 ret = -EINVAL;
1194 goto free_newinfo_counters_untrans_unlock; 1254 goto put_module;
1195 }
1196
1197 /* Get a reference in advance, we're not allowed fail later */
1198 if (!try_module_get(t->me)) {
1199 ret = -EBUSY;
1200 goto free_newinfo_counters_untrans_unlock;
1201 } 1255 }
1202 1256
1203 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 1257 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
@@ -1219,7 +1273,6 @@ do_replace(void __user *user, unsigned int len)
1219 /* Decrease module usage counts and free resource */ 1273 /* Decrease module usage counts and free resource */
1220 IP6T_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL); 1274 IP6T_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL);
1221 vfree(oldinfo); 1275 vfree(oldinfo);
1222 /* Silent error: too late now. */
1223 if (copy_to_user(tmp.counters, counters, 1276 if (copy_to_user(tmp.counters, counters,
1224 sizeof(struct ip6t_counters) * tmp.num_counters) != 0) 1277 sizeof(struct ip6t_counters) * tmp.num_counters) != 0)
1225 ret = -EFAULT; 1278 ret = -EFAULT;
@@ -1229,7 +1282,6 @@ do_replace(void __user *user, unsigned int len)
1229 1282
1230 put_module: 1283 put_module:
1231 module_put(t->me); 1284 module_put(t->me);
1232 free_newinfo_counters_untrans_unlock:
1233 up(&ip6t_mutex); 1285 up(&ip6t_mutex);
1234 free_newinfo_counters_untrans: 1286 free_newinfo_counters_untrans:
1235 IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL); 1287 IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL);
@@ -1268,7 +1320,7 @@ do_add_counters(void __user *user, unsigned int len)
1268 unsigned int i; 1320 unsigned int i;
1269 struct ip6t_counters_info tmp, *paddc; 1321 struct ip6t_counters_info tmp, *paddc;
1270 struct ip6t_table *t; 1322 struct ip6t_table *t;
1271 int ret; 1323 int ret = 0;
1272 1324
1273 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1325 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1274 return -EFAULT; 1326 return -EFAULT;
@@ -1285,9 +1337,11 @@ do_add_counters(void __user *user, unsigned int len)
1285 goto free; 1337 goto free;
1286 } 1338 }
1287 1339
1288 t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex); 1340 t = find_table_lock(tmp.name);
1289 if (!t) 1341 if (!t || IS_ERR(t)) {
1342 ret = t ? PTR_ERR(t) : -ENOENT;
1290 goto free; 1343 goto free;
1344 }
1291 1345
1292 write_lock_bh(&t->lock); 1346 write_lock_bh(&t->lock);
1293 if (t->private->number != paddc->num_counters) { 1347 if (t->private->number != paddc->num_counters) {
@@ -1304,6 +1358,7 @@ do_add_counters(void __user *user, unsigned int len)
1304 unlock_up_free: 1358 unlock_up_free:
1305 write_unlock_bh(&t->lock); 1359 write_unlock_bh(&t->lock);
1306 up(&ip6t_mutex); 1360 up(&ip6t_mutex);
1361 module_put(t->me);
1307 free: 1362 free:
1308 vfree(paddc); 1363 vfree(paddc);
1309 1364
@@ -1360,8 +1415,10 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1360 break; 1415 break;
1361 } 1416 }
1362 name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; 1417 name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
1363 t = ip6t_find_table_lock(name, &ret, &ip6t_mutex); 1418
1364 if (t) { 1419 t = try_then_request_module(find_table_lock(name),
1420 "ip6table_%s", name);
1421 if (t && !IS_ERR(t)) {
1365 struct ip6t_getinfo info; 1422 struct ip6t_getinfo info;
1366 1423
1367 info.valid_hooks = t->valid_hooks; 1424 info.valid_hooks = t->valid_hooks;
@@ -1377,9 +1434,10 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1377 ret = -EFAULT; 1434 ret = -EFAULT;
1378 else 1435 else
1379 ret = 0; 1436 ret = 0;
1380
1381 up(&ip6t_mutex); 1437 up(&ip6t_mutex);
1382 } 1438 module_put(t->me);
1439 } else
1440 ret = t ? PTR_ERR(t) : -ENOENT;
1383 } 1441 }
1384 break; 1442 break;
1385 1443
@@ -1400,6 +1458,31 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1400 break; 1458 break;
1401 } 1459 }
1402 1460
1461 case IP6T_SO_GET_REVISION_MATCH:
1462 case IP6T_SO_GET_REVISION_TARGET: {
1463 struct ip6t_get_revision rev;
1464 int (*revfn)(const char *, u8, int *);
1465
1466 if (*len != sizeof(rev)) {
1467 ret = -EINVAL;
1468 break;
1469 }
1470 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
1471 ret = -EFAULT;
1472 break;
1473 }
1474
1475 if (cmd == IP6T_SO_GET_REVISION_TARGET)
1476 revfn = target_revfn;
1477 else
1478 revfn = match_revfn;
1479
1480 try_then_request_module(find_revision(rev.name, rev.revision,
1481 revfn, &ret),
1482 "ip6t_%s", rev.name);
1483 break;
1484 }
1485
1403 default: 1486 default:
1404 duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd); 1487 duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd);
1405 ret = -EINVAL; 1488 ret = -EINVAL;
@@ -1417,12 +1500,7 @@ ip6t_register_target(struct ip6t_target *target)
1417 ret = down_interruptible(&ip6t_mutex); 1500 ret = down_interruptible(&ip6t_mutex);
1418 if (ret != 0) 1501 if (ret != 0)
1419 return ret; 1502 return ret;
1420 1503 list_add(&target->list, &ip6t_target);
1421 if (!list_named_insert(&ip6t_target, target)) {
1422 duprintf("ip6t_register_target: `%s' already in list!\n",
1423 target->name);
1424 ret = -EINVAL;
1425 }
1426 up(&ip6t_mutex); 1504 up(&ip6t_mutex);
1427 return ret; 1505 return ret;
1428} 1506}
@@ -1444,11 +1522,7 @@ ip6t_register_match(struct ip6t_match *match)
1444 if (ret != 0) 1522 if (ret != 0)
1445 return ret; 1523 return ret;
1446 1524
1447 if (!list_named_insert(&ip6t_match, match)) { 1525 list_add(&match->list, &ip6t_match);
1448 duprintf("ip6t_register_match: `%s' already in list!\n",
1449 match->name);
1450 ret = -EINVAL;
1451 }
1452 up(&ip6t_mutex); 1526 up(&ip6t_mutex);
1453 1527
1454 return ret; 1528 return ret;
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c
index 81924fcc5857..0c7584f92172 100644
--- a/net/ipv6/netfilter/ip6t_MARK.c
+++ b/net/ipv6/netfilter/ip6t_MARK.c
@@ -56,8 +56,12 @@ checkentry(const char *tablename,
56 return 1; 56 return 1;
57} 57}
58 58
59static struct ip6t_target ip6t_mark_reg 59static struct ip6t_target ip6t_mark_reg = {
60= { { NULL, NULL }, "MARK", target, checkentry, NULL, THIS_MODULE }; 60 .name = "MARK",
61 .target = target,
62 .checkentry = checkentry,
63 .me = THIS_MODULE
64};
61 65
62static int __init init(void) 66static int __init init(void)
63{ 67{
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5d5bbb49ec78..227e99ed510c 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -483,7 +483,7 @@ restart:
483 goto out; 483 goto out;
484 } 484 }
485 485
486 rt = rt6_device_match(rt, skb->dev->ifindex, 0); 486 rt = rt6_device_match(rt, skb->dev->ifindex, strict);
487 BACKTRACK(); 487 BACKTRACK();
488 488
489 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { 489 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index 50ae0371dab8..b6c8f38cc26c 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -138,6 +138,7 @@ static void rose_heartbeat_expiry(unsigned long param)
138 is accepted() it isn't 'dead' so doesn't get removed. */ 138 is accepted() it isn't 'dead' so doesn't get removed. */
139 if (sock_flag(sk, SOCK_DESTROY) || 139 if (sock_flag(sk, SOCK_DESTROY) ||
140 (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { 140 (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
141 bh_unlock_sock(sk);
141 rose_destroy_socket(sk); 142 rose_destroy_socket(sk);
142 return; 143 return;
143 } 144 }