Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
980e2c9b
Commit
980e2c9b
authored
Jan 12, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/davem/net-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
4cf14800
44032573
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
149 additions
and
144 deletions
+149
-144
net/bridge/netfilter/ebtables.c
net/bridge/netfilter/ebtables.c
+145
-143
net/ipv4/route.c
net/ipv4/route.c
+2
-0
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_ipv4.c
+2
-1
No files found.
net/bridge/netfilter/ebtables.c
View file @
980e2c9b
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* ebtables
* ebtables
*
*
* Author:
* Author:
* Bart De Schuymer <b
art.de.schuymer
@pandora.be>
* Bart De Schuymer <b
dschuym
@pandora.be>
*
*
* ebtables.c,v 2.0, July, 2002
* ebtables.c,v 2.0, July, 2002
*
*
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
* 2 of the License, or (at your option) any later version.
* 2 of the License, or (at your option) any later version.
*/
*/
/
/ used for print_string
/
* used for print_string */
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/tty.h>
...
@@ -27,18 +27,20 @@
...
@@ -27,18 +27,20 @@
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <linux/smp.h>
#include <linux/smp.h>
#include <net/sock.h>
#include <net/sock.h>
/
/ needed for logical [in,out]-dev filtering
/
* needed for logical [in,out]-dev filtering */
#include "../br_private.h"
#include "../br_private.h"
/
/ list_named_find
/
* list_named_find */
#define ASSERT_READ_LOCK(x)
#define ASSERT_READ_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/listhelp.h>
#include <linux/netfilter_ipv4/listhelp.h>
#if 0 // use this for remote debugging
#if 0
// Copyright (C) 1998 by Ori Pomerantz
/* use this for remote debugging
// Print the string to the appropriate tty, the one
* Copyright (C) 1998 by Ori Pomerantz
// the current task uses
* Print the string to the appropriate tty, the one
* the current task uses
*/
static void print_string(char *str)
static void print_string(char *str)
{
{
struct tty_struct *my_tty;
struct tty_struct *my_tty;
...
@@ -55,20 +57,22 @@ static void print_string(char *str)
...
@@ -55,20 +57,22 @@ static void print_string(char *str)
#else
#else
#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
"report to author: "format, ## args)
"report to author: "format, ## args)
/
/ #define BUGPRINT(format, args...)
/
* #define BUGPRINT(format, args...) */
#endif
#endif
#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
": out of memory: "format, ## args)
": out of memory: "format, ## args)
/
/ #define MEMPRINT(format, args...)
/
* #define MEMPRINT(format, args...) */
// Each cpu has its own set of counters, so there is no need for write_lock in
/*
// the softirq
* Each cpu has its own set of counters, so there is no need for write_lock in
// For reading or updating the counters, the user context needs to
* the softirq
// get a write_lock
* For reading or updating the counters, the user context needs to
* get a write_lock
*/
/
/ The size of each set of counters is altered to get cache alignment
/
* The size of each set of counters is altered to get cache alignment */
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
...
@@ -91,7 +95,7 @@ static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
...
@@ -91,7 +95,7 @@ static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
{
{
w
->
u
.
watcher
->
watcher
(
skb
,
in
,
out
,
w
->
data
,
w
->
u
.
watcher
->
watcher
(
skb
,
in
,
out
,
w
->
data
,
w
->
watcher_size
);
w
->
watcher_size
);
/
/ watchers don't give a verdict
/
* watchers don't give a verdict */
return
0
;
return
0
;
}
}
...
@@ -113,7 +117,7 @@ static inline int ebt_dev_check(char *entry, const struct net_device *device)
...
@@ -113,7 +117,7 @@ static inline int ebt_dev_check(char *entry, const struct net_device *device)
}
}
#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
/
/ process standard matches
/
* process standard matches */
static
inline
int
ebt_basic_match
(
struct
ebt_entry
*
e
,
struct
ethhdr
*
h
,
static
inline
int
ebt_basic_match
(
struct
ebt_entry
*
e
,
struct
ethhdr
*
h
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
)
const
struct
net_device
*
in
,
const
struct
net_device
*
out
)
{
{
...
@@ -156,7 +160,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
...
@@ -156,7 +160,7 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
return
0
;
return
0
;
}
}
/
/ Do some firewalling
/
* Do some firewalling */
unsigned
int
ebt_do_table
(
unsigned
int
hook
,
struct
sk_buff
**
pskb
,
unsigned
int
ebt_do_table
(
unsigned
int
hook
,
struct
sk_buff
**
pskb
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
struct
ebt_table
*
table
)
struct
ebt_table
*
table
)
...
@@ -182,7 +186,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -182,7 +186,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
nentries
=
private
->
hook_entry
[
hook
]
->
nentries
;
nentries
=
private
->
hook_entry
[
hook
]
->
nentries
;
point
=
(
struct
ebt_entry
*
)(
private
->
hook_entry
[
hook
]
->
data
);
point
=
(
struct
ebt_entry
*
)(
private
->
hook_entry
[
hook
]
->
data
);
counter_base
=
cb_base
+
private
->
hook_entry
[
hook
]
->
counter_offset
;
counter_base
=
cb_base
+
private
->
hook_entry
[
hook
]
->
counter_offset
;
/
/ base for chain jumps
/
* base for chain jumps */
base
=
private
->
entries
;
base
=
private
->
entries
;
i
=
0
;
i
=
0
;
while
(
i
<
nentries
)
{
while
(
i
<
nentries
)
{
...
@@ -192,18 +196,18 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -192,18 +196,18 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
if
(
EBT_MATCH_ITERATE
(
point
,
ebt_do_match
,
*
pskb
,
in
,
out
)
!=
0
)
if
(
EBT_MATCH_ITERATE
(
point
,
ebt_do_match
,
*
pskb
,
in
,
out
)
!=
0
)
goto
letscontinue
;
goto
letscontinue
;
/
/ increase counter
/
* increase counter */
(
*
(
counter_base
+
i
)).
pcnt
++
;
(
*
(
counter_base
+
i
)).
pcnt
++
;
(
*
(
counter_base
+
i
)).
bcnt
+=
(
**
pskb
).
len
;
(
*
(
counter_base
+
i
)).
bcnt
+=
(
**
pskb
).
len
;
/
/
these should only watch: not modify, nor tell us
/
*
these should only watch: not modify, nor tell us
// what to do with the packet
what to do with the packet */
EBT_WATCHER_ITERATE
(
point
,
ebt_do_watcher
,
*
pskb
,
in
,
EBT_WATCHER_ITERATE
(
point
,
ebt_do_watcher
,
*
pskb
,
in
,
out
);
out
);
t
=
(
struct
ebt_entry_target
*
)
t
=
(
struct
ebt_entry_target
*
)
(((
char
*
)
point
)
+
point
->
target_offset
);
(((
char
*
)
point
)
+
point
->
target_offset
);
/
/ standard target
/
* standard target */
if
(
!
t
->
u
.
target
->
target
)
if
(
!
t
->
u
.
target
->
target
)
verdict
=
((
struct
ebt_standard_target
*
)
t
)
->
verdict
;
verdict
=
((
struct
ebt_standard_target
*
)
t
)
->
verdict
;
else
else
...
@@ -222,12 +226,12 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -222,12 +226,12 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
#ifdef CONFIG_NETFILTER_DEBUG
#ifdef CONFIG_NETFILTER_DEBUG
if
(
sp
==
0
)
{
if
(
sp
==
0
)
{
BUGPRINT
(
"RETURN on base chain"
);
BUGPRINT
(
"RETURN on base chain"
);
/
/ act like this is EBT_CONTINUE
/
* act like this is EBT_CONTINUE */
goto
letscontinue
;
goto
letscontinue
;
}
}
#endif
#endif
sp
--
;
sp
--
;
/
/ put all the local variables right
/
* put all the local variables right */
i
=
cs
[
sp
].
n
;
i
=
cs
[
sp
].
n
;
chaininfo
=
cs
[
sp
].
chaininfo
;
chaininfo
=
cs
[
sp
].
chaininfo
;
nentries
=
chaininfo
->
nentries
;
nentries
=
chaininfo
->
nentries
;
...
@@ -245,7 +249,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -245,7 +249,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
return
NF_DROP
;
return
NF_DROP
;
}
}
#endif
#endif
/
/ jump to a udc
/
* jump to a udc */
cs
[
sp
].
n
=
i
+
1
;
cs
[
sp
].
n
=
i
+
1
;
cs
[
sp
].
chaininfo
=
chaininfo
;
cs
[
sp
].
chaininfo
=
chaininfo
;
cs
[
sp
].
e
=
(
struct
ebt_entry
*
)
cs
[
sp
].
e
=
(
struct
ebt_entry
*
)
...
@@ -270,7 +274,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -270,7 +274,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
i
++
;
i
++
;
}
}
/
/ I actually like this :)
/
* I actually like this :) */
if
(
chaininfo
->
policy
==
EBT_RETURN
)
if
(
chaininfo
->
policy
==
EBT_RETURN
)
goto
letsreturn
;
goto
letsreturn
;
if
(
chaininfo
->
policy
==
EBT_ACCEPT
)
{
if
(
chaininfo
->
policy
==
EBT_ACCEPT
)
{
...
@@ -281,7 +285,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
...
@@ -281,7 +285,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
return
NF_DROP
;
return
NF_DROP
;
}
}
/
/ If it succeeds, returns element and locks mutex
/
* If it succeeds, returns element and locks mutex */
static
inline
void
*
static
inline
void
*
find_inlist_lock_noload
(
struct
list_head
*
head
,
const
char
*
name
,
int
*
error
,
find_inlist_lock_noload
(
struct
list_head
*
head
,
const
char
*
name
,
int
*
error
,
struct
semaphore
*
mutex
)
struct
semaphore
*
mutex
)
...
@@ -359,14 +363,15 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
...
@@ -359,14 +363,15 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
if
(
!
match
)
if
(
!
match
)
return
ret
;
return
ret
;
m
->
u
.
match
=
match
;
m
->
u
.
match
=
match
;
if
(
match
->
me
)
if
(
!
try_module_get
(
match
->
me
))
{
__MOD_INC_USE_COUNT
(
match
->
me
);
up
(
&
ebt_mutex
);
return
-
EINVAL
;
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
if
(
match
->
check
&&
if
(
match
->
check
&&
match
->
check
(
name
,
hookmask
,
e
,
m
->
data
,
m
->
match_size
)
!=
0
)
{
match
->
check
(
name
,
hookmask
,
e
,
m
->
data
,
m
->
match_size
)
!=
0
)
{
BUGPRINT
(
"match->check failed
\n
"
);
BUGPRINT
(
"match->check failed
\n
"
);
if
(
match
->
me
)
module_put
(
match
->
me
);
__MOD_DEC_USE_COUNT
(
match
->
me
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
(
*
cnt
)
++
;
(
*
cnt
)
++
;
...
@@ -387,22 +392,25 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
...
@@ -387,22 +392,25 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
if
(
!
watcher
)
if
(
!
watcher
)
return
ret
;
return
ret
;
w
->
u
.
watcher
=
watcher
;
w
->
u
.
watcher
=
watcher
;
if
(
watcher
->
me
)
if
(
!
try_module_get
(
watcher
->
me
))
{
__MOD_INC_USE_COUNT
(
watcher
->
me
);
up
(
&
ebt_mutex
);
return
-
EINVAL
;
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
if
(
watcher
->
check
&&
if
(
watcher
->
check
&&
watcher
->
check
(
name
,
hookmask
,
e
,
w
->
data
,
w
->
watcher_size
)
!=
0
)
{
watcher
->
check
(
name
,
hookmask
,
e
,
w
->
data
,
w
->
watcher_size
)
!=
0
)
{
BUGPRINT
(
"watcher->check failed
\n
"
);
BUGPRINT
(
"watcher->check failed
\n
"
);
if
(
watcher
->
me
)
module_put
(
watcher
->
me
);
__MOD_DEC_USE_COUNT
(
watcher
->
me
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
(
*
cnt
)
++
;
(
*
cnt
)
++
;
return
0
;
return
0
;
}
}
// this one is very careful, as it is the first function
/*
// to parse the userspace data
* this one is very careful, as it is the first function
* to parse the userspace data
*/
static
inline
int
static
inline
int
ebt_check_entry_size_and_hooks
(
struct
ebt_entry
*
e
,
ebt_check_entry_size_and_hooks
(
struct
ebt_entry
*
e
,
struct
ebt_table_info
*
newinfo
,
char
*
base
,
char
*
limit
,
struct
ebt_table_info
*
newinfo
,
char
*
base
,
char
*
limit
,
...
@@ -418,24 +426,24 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
...
@@ -418,24 +426,24 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
(
char
*
)
e
-
newinfo
->
entries
)
(
char
*
)
e
-
newinfo
->
entries
)
break
;
break
;
}
}
/
/
beginning of a new chain
/
*
beginning of a new chain
// if i == NF_BR_NUMHOOKS it must be a user defined chain
if i == NF_BR_NUMHOOKS it must be a user defined chain */
if
(
i
!=
NF_BR_NUMHOOKS
||
!
(
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
))
{
if
(
i
!=
NF_BR_NUMHOOKS
||
!
(
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
))
{
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
!=
0
)
{
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
!=
0
)
{
/
/
we make userspace set this right,
/
*
we make userspace set this right,
// so there is no misunderstanding
so there is no misunderstanding */
BUGPRINT
(
"EBT_ENTRY_OR_ENTRIES shouldn't be set "
BUGPRINT
(
"EBT_ENTRY_OR_ENTRIES shouldn't be set "
"in distinguisher
\n
"
);
"in distinguisher
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/
this checks if the previous chain has as many entries
/
*
this checks if the previous chain has as many entries
// as it said it has
as it said it has */
if
(
*
n
!=
*
cnt
)
{
if
(
*
n
!=
*
cnt
)
{
BUGPRINT
(
"nentries does not equal the nr of entries "
BUGPRINT
(
"nentries does not equal the nr of entries "
"in the chain
\n
"
);
"in the chain
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ before we look at the struct, be sure it is not too big
/
* before we look at the struct, be sure it is not too big */
if
((
char
*
)
hook_entries
[
i
]
+
sizeof
(
struct
ebt_entries
)
if
((
char
*
)
hook_entries
[
i
]
+
sizeof
(
struct
ebt_entries
)
>
limit
)
{
>
limit
)
{
BUGPRINT
(
"entries_size too small
\n
"
);
BUGPRINT
(
"entries_size too small
\n
"
);
...
@@ -443,14 +451,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
...
@@ -443,14 +451,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
}
}
if
(((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_DROP
&&
if
(((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_DROP
&&
((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_ACCEPT
)
{
((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_ACCEPT
)
{
/
/ only RETURN from udc
/
* only RETURN from udc */
if
(
i
!=
NF_BR_NUMHOOKS
||
if
(
i
!=
NF_BR_NUMHOOKS
||
((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_RETURN
)
{
((
struct
ebt_entries
*
)
e
)
->
policy
!=
EBT_RETURN
)
{
BUGPRINT
(
"bad policy
\n
"
);
BUGPRINT
(
"bad policy
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
}
}
if
(
i
==
NF_BR_NUMHOOKS
)
/
/ it's a user defined chain
if
(
i
==
NF_BR_NUMHOOKS
)
/
* it's a user defined chain */
(
*
udc_cnt
)
++
;
(
*
udc_cnt
)
++
;
else
else
newinfo
->
hook_entry
[
i
]
=
(
struct
ebt_entries
*
)
e
;
newinfo
->
hook_entry
[
i
]
=
(
struct
ebt_entries
*
)
e
;
...
@@ -462,14 +470,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
...
@@ -462,14 +470,14 @@ ebt_check_entry_size_and_hooks(struct ebt_entry *e,
*
cnt
=
0
;
*
cnt
=
0
;
return
0
;
return
0
;
}
}
/
/ a plain old entry, heh
/
* a plain old entry, heh */
if
(
sizeof
(
struct
ebt_entry
)
>
e
->
watchers_offset
||
if
(
sizeof
(
struct
ebt_entry
)
>
e
->
watchers_offset
||
e
->
watchers_offset
>
e
->
target_offset
||
e
->
watchers_offset
>
e
->
target_offset
||
e
->
target_offset
>=
e
->
next_offset
)
{
e
->
target_offset
>=
e
->
next_offset
)
{
BUGPRINT
(
"entry offsets not in right order
\n
"
);
BUGPRINT
(
"entry offsets not in right order
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ this is not checked anywhere else
/
* this is not checked anywhere else */
if
(
e
->
next_offset
-
e
->
target_offset
<
sizeof
(
struct
ebt_entry_target
))
{
if
(
e
->
next_offset
-
e
->
target_offset
<
sizeof
(
struct
ebt_entry_target
))
{
BUGPRINT
(
"target size too small
\n
"
);
BUGPRINT
(
"target size too small
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -487,8 +495,10 @@ struct ebt_cl_stack
...
@@ -487,8 +495,10 @@ struct ebt_cl_stack
unsigned
int
hookmask
;
unsigned
int
hookmask
;
};
};
// we need these positions to check that the jumps to a different part of the
/*
// entries is a jump to the beginning of a new chain.
* we need these positions to check that the jumps to a different part of the
* entries is a jump to the beginning of a new chain.
*/
static
inline
int
static
inline
int
ebt_get_udc_positions
(
struct
ebt_entry
*
e
,
struct
ebt_table_info
*
newinfo
,
ebt_get_udc_positions
(
struct
ebt_entry
*
e
,
struct
ebt_table_info
*
newinfo
,
struct
ebt_entries
**
hook_entries
,
unsigned
int
*
n
,
unsigned
int
valid_hooks
,
struct
ebt_entries
**
hook_entries
,
unsigned
int
*
n
,
unsigned
int
valid_hooks
,
...
@@ -496,7 +506,7 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -496,7 +506,7 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
{
{
int
i
;
int
i
;
/
/ we're only interested in chain starts
/
* we're only interested in chain starts */
if
(
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
if
(
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
return
0
;
return
0
;
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
...
@@ -505,12 +515,12 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -505,12 +515,12 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
if
(
newinfo
->
hook_entry
[
i
]
==
(
struct
ebt_entries
*
)
e
)
if
(
newinfo
->
hook_entry
[
i
]
==
(
struct
ebt_entries
*
)
e
)
break
;
break
;
}
}
/
/ only care about udc
/
* only care about udc */
if
(
i
!=
NF_BR_NUMHOOKS
)
if
(
i
!=
NF_BR_NUMHOOKS
)
return
0
;
return
0
;
udc
[
*
n
].
cs
.
chaininfo
=
(
struct
ebt_entries
*
)
e
;
udc
[
*
n
].
cs
.
chaininfo
=
(
struct
ebt_entries
*
)
e
;
/
/ these initialisations are depended on later in check_chainloops()
/
* these initialisations are depended on later in check_chainloops() */
udc
[
*
n
].
cs
.
n
=
0
;
udc
[
*
n
].
cs
.
n
=
0
;
udc
[
*
n
].
hookmask
=
0
;
udc
[
*
n
].
hookmask
=
0
;
...
@@ -525,8 +535,7 @@ ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
...
@@ -525,8 +535,7 @@ ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
return
1
;
return
1
;
if
(
m
->
u
.
match
->
destroy
)
if
(
m
->
u
.
match
->
destroy
)
m
->
u
.
match
->
destroy
(
m
->
data
,
m
->
match_size
);
m
->
u
.
match
->
destroy
(
m
->
data
,
m
->
match_size
);
if
(
m
->
u
.
match
->
me
)
module_put
(
m
->
u
.
match
->
me
);
__MOD_DEC_USE_COUNT
(
m
->
u
.
match
->
me
);
return
0
;
return
0
;
}
}
...
@@ -538,8 +547,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
...
@@ -538,8 +547,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
return
1
;
return
1
;
if
(
w
->
u
.
watcher
->
destroy
)
if
(
w
->
u
.
watcher
->
destroy
)
w
->
u
.
watcher
->
destroy
(
w
->
data
,
w
->
watcher_size
);
w
->
u
.
watcher
->
destroy
(
w
->
data
,
w
->
watcher_size
);
if
(
w
->
u
.
watcher
->
me
)
module_put
(
w
->
u
.
watcher
->
me
);
__MOD_DEC_USE_COUNT
(
w
->
u
.
watcher
->
me
);
return
0
;
return
0
;
}
}
...
@@ -551,7 +559,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
...
@@ -551,7 +559,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
==
0
)
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
==
0
)
return
0
;
return
0
;
/
/ we're done
/
* we're done */
if
(
cnt
&&
(
*
cnt
)
--
==
0
)
if
(
cnt
&&
(
*
cnt
)
--
==
0
)
return
1
;
return
1
;
EBT_WATCHER_ITERATE
(
e
,
ebt_cleanup_watcher
,
NULL
);
EBT_WATCHER_ITERATE
(
e
,
ebt_cleanup_watcher
,
NULL
);
...
@@ -559,8 +567,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
...
@@ -559,8 +567,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
t
=
(
struct
ebt_entry_target
*
)(((
char
*
)
e
)
+
e
->
target_offset
);
t
=
(
struct
ebt_entry_target
*
)(((
char
*
)
e
)
+
e
->
target_offset
);
if
(
t
->
u
.
target
->
destroy
)
if
(
t
->
u
.
target
->
destroy
)
t
->
u
.
target
->
destroy
(
t
->
data
,
t
->
target_size
);
t
->
u
.
target
->
destroy
(
t
->
data
,
t
->
target_size
);
if
(
t
->
u
.
target
->
me
)
module_put
(
t
->
u
.
target
->
me
);
__MOD_DEC_USE_COUNT
(
t
->
u
.
target
->
me
);
return
0
;
return
0
;
}
}
...
@@ -575,7 +582,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -575,7 +582,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
unsigned
int
i
,
j
,
hook
=
0
,
hookmask
=
0
;
unsigned
int
i
,
j
,
hook
=
0
,
hookmask
=
0
;
int
ret
;
int
ret
;
/
/ Don't mess with the struct ebt_entries
/
* don't mess with the struct ebt_entries */
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
==
0
)
if
((
e
->
bitmask
&
EBT_ENTRY_OR_ENTRIES
)
==
0
)
return
0
;
return
0
;
...
@@ -591,7 +598,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -591,7 +598,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
BUGPRINT
(
"NOPROTO & 802_3 not allowed
\n
"
);
BUGPRINT
(
"NOPROTO & 802_3 not allowed
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ what hook do we belong to?
/
* what hook do we belong to? */
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
if
((
valid_hooks
&
(
1
<<
i
))
==
0
)
if
((
valid_hooks
&
(
1
<<
i
))
==
0
)
continue
;
continue
;
...
@@ -600,8 +607,8 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -600,8 +607,8 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
else
else
break
;
break
;
}
}
/
/
(1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
/
*
(1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
// a base chain
a base chain */
if
(
i
<
NF_BR_NUMHOOKS
)
if
(
i
<
NF_BR_NUMHOOKS
)
hookmask
=
(
1
<<
hook
)
|
(
1
<<
NF_BR_NUMHOOKS
);
hookmask
=
(
1
<<
hook
)
|
(
1
<<
NF_BR_NUMHOOKS
);
else
{
else
{
...
@@ -625,8 +632,10 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -625,8 +632,10 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
target
=
find_target_lock
(
t
->
u
.
name
,
&
ret
,
&
ebt_mutex
);
target
=
find_target_lock
(
t
->
u
.
name
,
&
ret
,
&
ebt_mutex
);
if
(
!
target
)
if
(
!
target
)
goto
cleanup_watchers
;
goto
cleanup_watchers
;
if
(
target
->
me
)
if
(
!
try_module_get
(
target
->
me
))
{
__MOD_INC_USE_COUNT
(
target
->
me
);
up
(
&
ebt_mutex
);
goto
cleanup_watchers
;
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
t
->
u
.
target
=
target
;
t
->
u
.
target
=
target
;
...
@@ -647,8 +656,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -647,8 +656,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
sizeof
(
struct
ebt_entry_target
)
>
e
->
next_offset
)
||
sizeof
(
struct
ebt_entry_target
)
>
e
->
next_offset
)
||
(
t
->
u
.
target
->
check
&&
(
t
->
u
.
target
->
check
&&
t
->
u
.
target
->
check
(
name
,
hookmask
,
e
,
t
->
data
,
t
->
target_size
)
!=
0
)){
t
->
u
.
target
->
check
(
name
,
hookmask
,
e
,
t
->
data
,
t
->
target_size
)
!=
0
)){
if
(
t
->
u
.
target
->
me
)
module_put
(
t
->
u
.
target
->
me
);
__MOD_DEC_USE_COUNT
(
t
->
u
.
target
->
me
);
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
goto
cleanup_watchers
;
goto
cleanup_watchers
;
}
}
...
@@ -661,10 +669,12 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
...
@@ -661,10 +669,12 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
return
ret
;
return
ret
;
}
}
// checks for loops and sets the hook mask for udc
/*
// the hook mask for udc tells us from which base chains the udc can be
* checks for loops and sets the hook mask for udc
// accessed. This mask is a parameter to the check() functions of the extensions
* the hook mask for udc tells us from which base chains the udc can be
int
check_chainloops
(
struct
ebt_entries
*
chain
,
struct
ebt_cl_stack
*
cl_s
,
* accessed. This mask is a parameter to the check() functions of the extensions
*/
static
int
check_chainloops
(
struct
ebt_entries
*
chain
,
struct
ebt_cl_stack
*
cl_s
,
unsigned
int
udc_cnt
,
unsigned
int
hooknr
,
char
*
base
)
unsigned
int
udc_cnt
,
unsigned
int
hooknr
,
char
*
base
)
{
{
int
i
,
chain_nr
=
-
1
,
pos
=
0
,
nentries
=
chain
->
nentries
,
verdict
;
int
i
,
chain_nr
=
-
1
,
pos
=
0
,
nentries
=
chain
->
nentries
,
verdict
;
...
@@ -672,9 +682,9 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -672,9 +682,9 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
struct
ebt_entry_target
*
t
;
struct
ebt_entry_target
*
t
;
while
(
pos
<
nentries
||
chain_nr
!=
-
1
)
{
while
(
pos
<
nentries
||
chain_nr
!=
-
1
)
{
/
/ end of udc, go back one 'recursion' step
/
* end of udc, go back one 'recursion' step */
if
(
pos
==
nentries
)
{
if
(
pos
==
nentries
)
{
/
/ put back values of the time when this chain was called
/
* put back values of the time when this chain was called */
e
=
cl_s
[
chain_nr
].
cs
.
e
;
e
=
cl_s
[
chain_nr
].
cs
.
e
;
if
(
cl_s
[
chain_nr
].
from
!=
-
1
)
if
(
cl_s
[
chain_nr
].
from
!=
-
1
)
nentries
=
nentries
=
...
@@ -682,7 +692,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -682,7 +692,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
else
else
nentries
=
chain
->
nentries
;
nentries
=
chain
->
nentries
;
pos
=
cl_s
[
chain_nr
].
cs
.
n
;
pos
=
cl_s
[
chain_nr
].
cs
.
n
;
/
/ make sure we won't see a loop that isn't one
/
* make sure we won't see a loop that isn't one */
cl_s
[
chain_nr
].
cs
.
n
=
0
;
cl_s
[
chain_nr
].
cs
.
n
=
0
;
chain_nr
=
cl_s
[
chain_nr
].
from
;
chain_nr
=
cl_s
[
chain_nr
].
from
;
if
(
pos
==
nentries
)
if
(
pos
==
nentries
)
...
@@ -698,13 +708,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -698,13 +708,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
return
-
1
;
return
-
1
;
}
}
verdict
=
((
struct
ebt_standard_target
*
)
t
)
->
verdict
;
verdict
=
((
struct
ebt_standard_target
*
)
t
)
->
verdict
;
if
(
verdict
>=
0
)
{
/
/ jump to another chain
if
(
verdict
>=
0
)
{
/
* jump to another chain */
struct
ebt_entries
*
hlp2
=
struct
ebt_entries
*
hlp2
=
(
struct
ebt_entries
*
)(
base
+
verdict
);
(
struct
ebt_entries
*
)(
base
+
verdict
);
for
(
i
=
0
;
i
<
udc_cnt
;
i
++
)
for
(
i
=
0
;
i
<
udc_cnt
;
i
++
)
if
(
hlp2
==
cl_s
[
i
].
cs
.
chaininfo
)
if
(
hlp2
==
cl_s
[
i
].
cs
.
chaininfo
)
break
;
break
;
/
/ bad destination or loop
/
* bad destination or loop */
if
(
i
==
udc_cnt
)
{
if
(
i
==
udc_cnt
)
{
BUGPRINT
(
"bad destination
\n
"
);
BUGPRINT
(
"bad destination
\n
"
);
return
-
1
;
return
-
1
;
...
@@ -713,7 +723,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -713,7 +723,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
BUGPRINT
(
"loop
\n
"
);
BUGPRINT
(
"loop
\n
"
);
return
-
1
;
return
-
1
;
}
}
/
/ this can't be 0, so the above test is correct
/
* this can't be 0, so the above test is correct */
cl_s
[
i
].
cs
.
n
=
pos
+
1
;
cl_s
[
i
].
cs
.
n
=
pos
+
1
;
pos
=
0
;
pos
=
0
;
cl_s
[
i
].
cs
.
e
=
((
void
*
)
e
+
e
->
next_offset
);
cl_s
[
i
].
cs
.
e
=
((
void
*
)
e
+
e
->
next_offset
);
...
@@ -721,7 +731,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -721,7 +731,7 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
nentries
=
hlp2
->
nentries
;
nentries
=
hlp2
->
nentries
;
cl_s
[
i
].
from
=
chain_nr
;
cl_s
[
i
].
from
=
chain_nr
;
chain_nr
=
i
;
chain_nr
=
i
;
/
/ this udc is accessible from the base chain for hooknr
/
* this udc is accessible from the base chain for hooknr */
cl_s
[
i
].
hookmask
|=
(
1
<<
hooknr
);
cl_s
[
i
].
hookmask
|=
(
1
<<
hooknr
);
continue
;
continue
;
}
}
...
@@ -732,13 +742,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
...
@@ -732,13 +742,13 @@ int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
return
0
;
return
0
;
}
}
/
/ do the parsing of the table/chains/entries/matches/watchers/targets, heh
/
* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
static
int
translate_table
(
struct
ebt_replace
*
repl
,
static
int
translate_table
(
struct
ebt_replace
*
repl
,
struct
ebt_table_info
*
newinfo
)
struct
ebt_table_info
*
newinfo
)
{
{
unsigned
int
i
,
j
,
k
,
udc_cnt
;
unsigned
int
i
,
j
,
k
,
udc_cnt
;
int
ret
;
int
ret
;
struct
ebt_cl_stack
*
cl_s
=
NULL
;
/
/ used in the checking for chain loops
struct
ebt_cl_stack
*
cl_s
=
NULL
;
/
* used in the checking for chain loops */
i
=
0
;
i
=
0
;
while
(
i
<
NF_BR_NUMHOOKS
&&
!
(
repl
->
valid_hooks
&
(
1
<<
i
)))
while
(
i
<
NF_BR_NUMHOOKS
&&
!
(
repl
->
valid_hooks
&
(
1
<<
i
)))
...
@@ -751,8 +761,8 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -751,8 +761,8 @@ static int translate_table(struct ebt_replace *repl,
BUGPRINT
(
"Chains don't start at beginning
\n
"
);
BUGPRINT
(
"Chains don't start at beginning
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/
make sure chains are ordered after each other in same order
/
*
make sure chains are ordered after each other in same order
// as their corresponding hooks
as their corresponding hooks */
for
(
j
=
i
+
1
;
j
<
NF_BR_NUMHOOKS
;
j
++
)
{
for
(
j
=
i
+
1
;
j
<
NF_BR_NUMHOOKS
;
j
++
)
{
if
(
!
(
repl
->
valid_hooks
&
(
1
<<
j
)))
if
(
!
(
repl
->
valid_hooks
&
(
1
<<
j
)))
continue
;
continue
;
...
@@ -769,12 +779,12 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -769,12 +779,12 @@ static int translate_table(struct ebt_replace *repl,
newinfo
->
entries_size
=
repl
->
entries_size
;
newinfo
->
entries_size
=
repl
->
entries_size
;
newinfo
->
nentries
=
repl
->
nentries
;
newinfo
->
nentries
=
repl
->
nentries
;
/
/ do some early checkings and initialize some things
/
* do some early checkings and initialize some things */
i
=
0
;
/
/ holds the expected nr. of entries for the chain
i
=
0
;
/
* holds the expected nr. of entries for the chain */
j
=
0
;
/
/ holds the up to now counted entries for the chain
j
=
0
;
/
* holds the up to now counted entries for the chain */
k
=
0
;
/
/
holds the total nr. of entries, should equal
k
=
0
;
/
*
holds the total nr. of entries, should equal
// newinfo->nentries afterwards
newinfo->nentries afterwards */
udc_cnt
=
0
;
/
/ will hold the nr. of user defined chains (udc)
udc_cnt
=
0
;
/
* will hold the nr. of user defined chains (udc) */
ret
=
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ret
=
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ebt_check_entry_size_and_hooks
,
newinfo
,
repl
->
entries
,
ebt_check_entry_size_and_hooks
,
newinfo
,
repl
->
entries
,
repl
->
entries
+
repl
->
entries_size
,
repl
->
hook_entry
,
&
i
,
&
j
,
&
k
,
repl
->
entries
+
repl
->
entries_size
,
repl
->
hook_entry
,
&
i
,
&
j
,
&
k
,
...
@@ -793,7 +803,7 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -793,7 +803,7 @@ static int translate_table(struct ebt_replace *repl,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ check if all valid hooks have a chain
/
* check if all valid hooks have a chain */
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
{
if
(
newinfo
->
hook_entry
[
i
]
==
NULL
&&
if
(
newinfo
->
hook_entry
[
i
]
==
NULL
&&
(
repl
->
valid_hooks
&
(
1
<<
i
)))
{
(
repl
->
valid_hooks
&
(
1
<<
i
)))
{
...
@@ -802,11 +812,11 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -802,11 +812,11 @@ static int translate_table(struct ebt_replace *repl,
}
}
}
}
/
/ G
et the location of the udc, put them in an array
/
* g
et the location of the udc, put them in an array
// While we're at it, allocate the chainstack
while we're at it, allocate the chainstack */
if
(
udc_cnt
)
{
if
(
udc_cnt
)
{
/
/
this will get free'd in do_replace()/ebt_register_table()
/
*
this will get free'd in do_replace()/ebt_register_table()
// if an error occurs
if an error occurs */
newinfo
->
chainstack
=
(
struct
ebt_chainstack
**
)
newinfo
->
chainstack
=
(
struct
ebt_chainstack
**
)
vmalloc
(
NR_CPUS
*
sizeof
(
struct
ebt_chainstack
));
vmalloc
(
NR_CPUS
*
sizeof
(
struct
ebt_chainstack
));
if
(
!
newinfo
->
chainstack
)
if
(
!
newinfo
->
chainstack
)
...
@@ -827,11 +837,11 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -827,11 +837,11 @@ static int translate_table(struct ebt_replace *repl,
vmalloc
(
udc_cnt
*
sizeof
(
struct
ebt_cl_stack
));
vmalloc
(
udc_cnt
*
sizeof
(
struct
ebt_cl_stack
));
if
(
!
cl_s
)
if
(
!
cl_s
)
return
-
ENOMEM
;
return
-
ENOMEM
;
i
=
0
;
/
/ the i'th udc
i
=
0
;
/
* the i'th udc */
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ebt_get_udc_positions
,
newinfo
,
repl
->
hook_entry
,
&
i
,
ebt_get_udc_positions
,
newinfo
,
repl
->
hook_entry
,
&
i
,
repl
->
valid_hooks
,
cl_s
);
repl
->
valid_hooks
,
cl_s
);
/
/ sanity check
/
* sanity check */
if
(
i
!=
udc_cnt
)
{
if
(
i
!=
udc_cnt
)
{
BUGPRINT
(
"i != udc_cnt
\n
"
);
BUGPRINT
(
"i != udc_cnt
\n
"
);
vfree
(
cl_s
);
vfree
(
cl_s
);
...
@@ -839,7 +849,7 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -839,7 +849,7 @@ static int translate_table(struct ebt_replace *repl,
}
}
}
}
/
/ Check for loops
/
* Check for loops */
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
for
(
i
=
0
;
i
<
NF_BR_NUMHOOKS
;
i
++
)
if
(
repl
->
valid_hooks
&
(
1
<<
i
))
if
(
repl
->
valid_hooks
&
(
1
<<
i
))
if
(
check_chainloops
(
newinfo
->
hook_entry
[
i
],
if
(
check_chainloops
(
newinfo
->
hook_entry
[
i
],
...
@@ -849,17 +859,17 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -849,17 +859,17 @@ static int translate_table(struct ebt_replace *repl,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/
we now know the following (along with E=mc):
/
*
we now know the following (along with E=mc):
//
- the nr of entries in each chain is right
- the nr of entries in each chain is right
//
- the size of the allocated space is right
- the size of the allocated space is right
//
- all valid hooks have a corresponding chain
- all valid hooks have a corresponding chain
//
- there are no loops
- there are no loops
//
- wrong data can still be on the level of a single entry
- wrong data can still be on the level of a single entry
//
- could be there are jumps to places that are not the
- could be there are jumps to places that are not the
//
beginning of a chain. This can only occur in chains that
beginning of a chain. This can only occur in chains that
// are not accessible from any base chains, so we don't care.
are not accessible from any base chains, so we don't care. */
/
/ used to know what we need to clean up if something goes wrong
/
* used to know what we need to clean up if something goes wrong */
i
=
0
;
i
=
0
;
ret
=
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ret
=
EBT_ENTRY_ITERATE
(
newinfo
->
entries
,
newinfo
->
entries_size
,
ebt_check_entry
,
newinfo
,
repl
->
name
,
&
i
,
repl
->
valid_hooks
,
ebt_check_entry
,
newinfo
,
repl
->
name
,
&
i
,
repl
->
valid_hooks
,
...
@@ -873,17 +883,17 @@ static int translate_table(struct ebt_replace *repl,
...
@@ -873,17 +883,17 @@ static int translate_table(struct ebt_replace *repl,
return
ret
;
return
ret
;
}
}
/
/ called under write_lock
/
* called under write_lock */
static
void
get_counters
(
struct
ebt_counter
*
oldcounters
,
static
void
get_counters
(
struct
ebt_counter
*
oldcounters
,
struct
ebt_counter
*
counters
,
unsigned
int
nentries
)
struct
ebt_counter
*
counters
,
unsigned
int
nentries
)
{
{
int
i
,
cpu
;
int
i
,
cpu
;
struct
ebt_counter
*
counter_base
;
struct
ebt_counter
*
counter_base
;
/
/ counters of cpu 0
/
* counters of cpu 0 */
memcpy
(
counters
,
oldcounters
,
memcpy
(
counters
,
oldcounters
,
sizeof
(
struct
ebt_counter
)
*
nentries
);
sizeof
(
struct
ebt_counter
)
*
nentries
);
/
/ add other counters to those of cpu 0
/
* add other counters to those of cpu 0 */
for
(
cpu
=
1
;
cpu
<
NR_CPUS
;
cpu
++
)
{
for
(
cpu
=
1
;
cpu
<
NR_CPUS
;
cpu
++
)
{
counter_base
=
COUNTER_BASE
(
oldcounters
,
nentries
,
cpu
);
counter_base
=
COUNTER_BASE
(
oldcounters
,
nentries
,
cpu
);
for
(
i
=
0
;
i
<
nentries
;
i
++
)
{
for
(
i
=
0
;
i
<
nentries
;
i
++
)
{
...
@@ -893,7 +903,7 @@ static void get_counters(struct ebt_counter *oldcounters,
...
@@ -893,7 +903,7 @@ static void get_counters(struct ebt_counter *oldcounters,
}
}
}
}
/
/ replace the table
/
* replace the table */
static
int
do_replace
(
void
*
user
,
unsigned
int
len
)
static
int
do_replace
(
void
*
user
,
unsigned
int
len
)
{
{
int
ret
,
i
,
countersize
;
int
ret
,
i
,
countersize
;
...
@@ -901,7 +911,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -901,7 +911,7 @@ static int do_replace(void *user, unsigned int len)
struct
ebt_replace
tmp
;
struct
ebt_replace
tmp
;
struct
ebt_table
*
t
;
struct
ebt_table
*
t
;
struct
ebt_counter
*
counterstmp
=
NULL
;
struct
ebt_counter
*
counterstmp
=
NULL
;
/
/ used to be able to unlock earlier
/
* used to be able to unlock earlier */
struct
ebt_table_info
*
table
;
struct
ebt_table_info
*
table
;
if
(
copy_from_user
(
&
tmp
,
user
,
sizeof
(
tmp
))
!=
0
)
if
(
copy_from_user
(
&
tmp
,
user
,
sizeof
(
tmp
))
!=
0
)
...
@@ -937,8 +947,8 @@ static int do_replace(void *user, unsigned int len)
...
@@ -937,8 +947,8 @@ static int do_replace(void *user, unsigned int len)
goto
free_entries
;
goto
free_entries
;
}
}
/
/
the user wants counters back
/
*
the user wants counters back
// the check on the size is done later, when we have the lock
the check on the size is done later, when we have the lock */
if
(
tmp
.
num_counters
)
{
if
(
tmp
.
num_counters
)
{
counterstmp
=
(
struct
ebt_counter
*
)
counterstmp
=
(
struct
ebt_counter
*
)
vmalloc
(
tmp
.
num_counters
*
sizeof
(
struct
ebt_counter
));
vmalloc
(
tmp
.
num_counters
*
sizeof
(
struct
ebt_counter
));
...
@@ -950,7 +960,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -950,7 +960,7 @@ static int do_replace(void *user, unsigned int len)
else
else
counterstmp
=
NULL
;
counterstmp
=
NULL
;
/
/ this can get initialized by translate_table()
/
* this can get initialized by translate_table() */
newinfo
->
chainstack
=
NULL
;
newinfo
->
chainstack
=
NULL
;
ret
=
translate_table
(
&
tmp
,
newinfo
);
ret
=
translate_table
(
&
tmp
,
newinfo
);
...
@@ -961,7 +971,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -961,7 +971,7 @@ static int do_replace(void *user, unsigned int len)
if
(
!
t
)
if
(
!
t
)
goto
free_iterate
;
goto
free_iterate
;
/
/ the table doesn't like it
/
* the table doesn't like it */
if
(
t
->
check
&&
(
ret
=
t
->
check
(
newinfo
,
tmp
.
valid_hooks
)))
if
(
t
->
check
&&
(
ret
=
t
->
check
(
newinfo
,
tmp
.
valid_hooks
)))
goto
free_unlock
;
goto
free_unlock
;
...
@@ -971,9 +981,9 @@ static int do_replace(void *user, unsigned int len)
...
@@ -971,9 +981,9 @@ static int do_replace(void *user, unsigned int len)
goto
free_unlock
;
goto
free_unlock
;
}
}
/
/ we have the mutex lock, so no danger in reading this pointer
/
* we have the mutex lock, so no danger in reading this pointer */
table
=
t
->
private
;
table
=
t
->
private
;
/
/ we need an atomic snapshot of the counters
/
* we need an atomic snapshot of the counters */
write_lock_bh
(
&
t
->
lock
);
write_lock_bh
(
&
t
->
lock
);
if
(
tmp
.
num_counters
)
if
(
tmp
.
num_counters
)
get_counters
(
t
->
private
->
counters
,
counterstmp
,
get_counters
(
t
->
private
->
counters
,
counterstmp
,
...
@@ -982,10 +992,10 @@ static int do_replace(void *user, unsigned int len)
...
@@ -982,10 +992,10 @@ static int do_replace(void *user, unsigned int len)
t
->
private
=
newinfo
;
t
->
private
=
newinfo
;
write_unlock_bh
(
&
t
->
lock
);
write_unlock_bh
(
&
t
->
lock
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
/
/ S
o, a user can change the chains while having messed up her counter
/
* s
o, a user can change the chains while having messed up her counter
//
allocation. Only reason why this is done is because this way the lock
allocation. Only reason why this is done is because this way the lock
//
is held only once, while this doesn't bring the kernel into a
is held only once, while this doesn't bring the kernel into a
// dangerous state.
dangerous state. */
if
(
tmp
.
num_counters
&&
if
(
tmp
.
num_counters
&&
copy_to_user
(
tmp
.
counters
,
counterstmp
,
copy_to_user
(
tmp
.
counters
,
counterstmp
,
tmp
.
num_counters
*
sizeof
(
struct
ebt_counter
)))
{
tmp
.
num_counters
*
sizeof
(
struct
ebt_counter
)))
{
...
@@ -995,7 +1005,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -995,7 +1005,7 @@ static int do_replace(void *user, unsigned int len)
else
else
ret
=
0
;
ret
=
0
;
/
/ decrease module count and free resources
/
* decrease module count and free resources */
EBT_ENTRY_ITERATE
(
table
->
entries
,
table
->
entries_size
,
EBT_ENTRY_ITERATE
(
table
->
entries
,
table
->
entries_size
,
ebt_cleanup_entry
,
NULL
);
ebt_cleanup_entry
,
NULL
);
...
@@ -1019,7 +1029,7 @@ static int do_replace(void *user, unsigned int len)
...
@@ -1019,7 +1029,7 @@ static int do_replace(void *user, unsigned int len)
free_counterstmp:
free_counterstmp:
if
(
counterstmp
)
if
(
counterstmp
)
vfree
(
counterstmp
);
vfree
(
counterstmp
);
/
/ can be initialized in translate_table()
/
* can be initialized in translate_table() */
if
(
newinfo
->
chainstack
)
{
if
(
newinfo
->
chainstack
)
{
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
vfree
(
newinfo
->
chainstack
[
i
]);
vfree
(
newinfo
->
chainstack
[
i
]);
...
@@ -1046,7 +1056,6 @@ int ebt_register_target(struct ebt_target *target)
...
@@ -1046,7 +1056,6 @@ int ebt_register_target(struct ebt_target *target)
return
-
EEXIST
;
return
-
EEXIST
;
}
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_INC_USE_COUNT
;
return
0
;
return
0
;
}
}
...
@@ -1056,7 +1065,6 @@ void ebt_unregister_target(struct ebt_target *target)
...
@@ -1056,7 +1065,6 @@ void ebt_unregister_target(struct ebt_target *target)
down
(
&
ebt_mutex
);
down
(
&
ebt_mutex
);
LIST_DELETE
(
&
ebt_targets
,
target
);
LIST_DELETE
(
&
ebt_targets
,
target
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_DEC_USE_COUNT
;
}
}
int
ebt_register_match
(
struct
ebt_match
*
match
)
int
ebt_register_match
(
struct
ebt_match
*
match
)
...
@@ -1071,7 +1079,6 @@ int ebt_register_match(struct ebt_match *match)
...
@@ -1071,7 +1079,6 @@ int ebt_register_match(struct ebt_match *match)
return
-
EEXIST
;
return
-
EEXIST
;
}
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_INC_USE_COUNT
;
return
0
;
return
0
;
}
}
...
@@ -1081,7 +1088,6 @@ void ebt_unregister_match(struct ebt_match *match)
...
@@ -1081,7 +1088,6 @@ void ebt_unregister_match(struct ebt_match *match)
down
(
&
ebt_mutex
);
down
(
&
ebt_mutex
);
LIST_DELETE
(
&
ebt_matches
,
match
);
LIST_DELETE
(
&
ebt_matches
,
match
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_DEC_USE_COUNT
;
}
}
int
ebt_register_watcher
(
struct
ebt_watcher
*
watcher
)
int
ebt_register_watcher
(
struct
ebt_watcher
*
watcher
)
...
@@ -1096,7 +1102,6 @@ int ebt_register_watcher(struct ebt_watcher *watcher)
...
@@ -1096,7 +1102,6 @@ int ebt_register_watcher(struct ebt_watcher *watcher)
return
-
EEXIST
;
return
-
EEXIST
;
}
}
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_INC_USE_COUNT
;
return
0
;
return
0
;
}
}
...
@@ -1106,7 +1111,6 @@ void ebt_unregister_watcher(struct ebt_watcher *watcher)
...
@@ -1106,7 +1111,6 @@ void ebt_unregister_watcher(struct ebt_watcher *watcher)
down
(
&
ebt_mutex
);
down
(
&
ebt_mutex
);
LIST_DELETE
(
&
ebt_watchers
,
watcher
);
LIST_DELETE
(
&
ebt_watchers
,
watcher
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_DEC_USE_COUNT
;
}
}
int
ebt_register_table
(
struct
ebt_table
*
table
)
int
ebt_register_table
(
struct
ebt_table
*
table
)
...
@@ -1138,7 +1142,7 @@ int ebt_register_table(struct ebt_table *table)
...
@@ -1138,7 +1142,7 @@ int ebt_register_table(struct ebt_table *table)
if
(
countersize
)
if
(
countersize
)
memset
(
newinfo
->
counters
,
0
,
countersize
);
memset
(
newinfo
->
counters
,
0
,
countersize
);
/
/ fill in newinfo and parse the entries
/
* fill in newinfo and parse the entries */
newinfo
->
chainstack
=
NULL
;
newinfo
->
chainstack
=
NULL
;
ret
=
translate_table
(
table
->
table
,
newinfo
);
ret
=
translate_table
(
table
->
table
,
newinfo
);
if
(
ret
!=
0
)
{
if
(
ret
!=
0
)
{
...
@@ -1165,7 +1169,6 @@ int ebt_register_table(struct ebt_table *table)
...
@@ -1165,7 +1169,6 @@ int ebt_register_table(struct ebt_table *table)
list_prepend
(
&
ebt_tables
,
table
);
list_prepend
(
&
ebt_tables
,
table
);
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
MOD_INC_USE_COUNT
;
return
0
;
return
0
;
free_unlock:
free_unlock:
up
(
&
ebt_mutex
);
up
(
&
ebt_mutex
);
...
@@ -1202,10 +1205,9 @@ void ebt_unregister_table(struct ebt_table *table)
...
@@ -1202,10 +1205,9 @@ void ebt_unregister_table(struct ebt_table *table)
vfree
(
table
->
private
->
chainstack
);
vfree
(
table
->
private
->
chainstack
);
}
}
vfree
(
table
->
private
);
vfree
(
table
->
private
);
MOD_DEC_USE_COUNT
;
}
}
/
/ userspace just supplied us with counters
/
* userspace just supplied us with counters */
static
int
update_counters
(
void
*
user
,
unsigned
int
len
)
static
int
update_counters
(
void
*
user
,
unsigned
int
len
)
{
{
int
i
,
ret
;
int
i
,
ret
;
...
@@ -1244,10 +1246,10 @@ static int update_counters(void *user, unsigned int len)
...
@@ -1244,10 +1246,10 @@ static int update_counters(void *user, unsigned int len)
goto
unlock_mutex
;
goto
unlock_mutex
;
}
}
/
/ we want an atomic add of the counters
/
* we want an atomic add of the counters */
write_lock_bh
(
&
t
->
lock
);
write_lock_bh
(
&
t
->
lock
);
/
/ we add to the counters of the first cpu
/
* we add to the counters of the first cpu */
for
(
i
=
0
;
i
<
hlp
.
num_counters
;
i
++
)
{
for
(
i
=
0
;
i
<
hlp
.
num_counters
;
i
++
)
{
t
->
private
->
counters
[
i
].
pcnt
+=
tmp
[
i
].
pcnt
;
t
->
private
->
counters
[
i
].
pcnt
+=
tmp
[
i
].
pcnt
;
t
->
private
->
counters
[
i
].
bcnt
+=
tmp
[
i
].
bcnt
;
t
->
private
->
counters
[
i
].
bcnt
+=
tmp
[
i
].
bcnt
;
...
@@ -1303,7 +1305,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
...
@@ -1303,7 +1305,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
return
0
;
return
0
;
}
}
/
/ called with ebt_mutex down
/
* called with ebt_mutex down */
static
int
copy_everything_to_user
(
struct
ebt_table
*
t
,
void
*
user
,
static
int
copy_everything_to_user
(
struct
ebt_table
*
t
,
void
*
user
,
int
*
len
,
int
cmd
)
int
*
len
,
int
cmd
)
{
{
...
@@ -1345,7 +1347,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
...
@@ -1345,7 +1347,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/
/ userspace might not need the counters
/
* userspace might not need the counters */
if
(
tmp
.
num_counters
)
{
if
(
tmp
.
num_counters
)
{
if
(
tmp
.
num_counters
!=
nentries
)
{
if
(
tmp
.
num_counters
!=
nentries
)
{
BUGPRINT
(
"Num_counters wrong
\n
"
);
BUGPRINT
(
"Num_counters wrong
\n
"
);
...
@@ -1374,7 +1376,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
...
@@ -1374,7 +1376,7 @@ static int copy_everything_to_user(struct ebt_table *t, void *user,
BUGPRINT
(
"Couldn't copy entries to userspace
\n
"
);
BUGPRINT
(
"Couldn't copy entries to userspace
\n
"
);
return
-
EFAULT
;
return
-
EFAULT
;
}
}
/
/ set the match/watcher/target names right
/
* set the match/watcher/target names right */
return
EBT_ENTRY_ITERATE
(
entries
,
entries_size
,
return
EBT_ENTRY_ITERATE
(
entries
,
entries_size
,
ebt_make_names
,
entries
,
tmp
.
entries
);
ebt_make_names
,
entries
,
tmp
.
entries
);
}
}
...
@@ -1465,14 +1467,14 @@ static int __init init(void)
...
@@ -1465,14 +1467,14 @@ static int __init init(void)
if
((
ret
=
nf_register_sockopt
(
&
ebt_sockopts
))
<
0
)
if
((
ret
=
nf_register_sockopt
(
&
ebt_sockopts
))
<
0
)
return
ret
;
return
ret
;
printk
(
"Ebtables v2.0 registered
"
);
printk
(
KERN_NOTICE
"Ebtables v2.0 registered
\n
"
);
return
0
;
return
0
;
}
}
static
void
__exit
fini
(
void
)
static
void
__exit
fini
(
void
)
{
{
nf_unregister_sockopt
(
&
ebt_sockopts
);
nf_unregister_sockopt
(
&
ebt_sockopts
);
printk
(
"Ebtables v2.0 unregistered
"
);
printk
(
KERN_NOTICE
"Ebtables v2.0 unregistered
\n
"
);
}
}
EXPORT_SYMBOL
(
ebt_register_table
);
EXPORT_SYMBOL
(
ebt_register_table
);
...
...
net/ipv4/route.c
View file @
980e2c9b
...
@@ -2672,11 +2672,13 @@ int __init ip_rt_init(void)
...
@@ -2672,11 +2672,13 @@ int __init ip_rt_init(void)
ip_rt_gc_interval
;
ip_rt_gc_interval
;
add_timer
(
&
rt_periodic_timer
);
add_timer
(
&
rt_periodic_timer
);
#ifdef CONFIG_PROC_FS
if
(
rt_cache_proc_init
())
if
(
rt_cache_proc_init
())
goto
out_enomem
;
goto
out_enomem
;
proc_net_create
(
"rt_cache_stat"
,
0
,
rt_cache_stat_get_info
);
proc_net_create
(
"rt_cache_stat"
,
0
,
rt_cache_stat_get_info
);
#ifdef CONFIG_NET_CLS_ROUTE
#ifdef CONFIG_NET_CLS_ROUTE
create_proc_read_entry
(
"net/rt_acct"
,
0
,
0
,
ip_rt_acct_read
,
NULL
);
create_proc_read_entry
(
"net/rt_acct"
,
0
,
0
,
ip_rt_acct_read
,
NULL
);
#endif
#endif
#endif
xfrm_init
();
xfrm_init
();
out:
out:
...
...
net/ipv4/tcp_ipv4.c
View file @
980e2c9b
...
@@ -2412,7 +2412,8 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
...
@@ -2412,7 +2412,8 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
read_unlock_bh
(
&
tp
->
syn_wait_lock
);
read_unlock_bh
(
&
tp
->
syn_wait_lock
);
}
}
case
TCP_SEQ_STATE_LISTENING
:
case
TCP_SEQ_STATE_LISTENING
:
tcp_listen_unlock
();
if
(
v
!=
(
void
*
)
1
)
tcp_listen_unlock
();
break
;
break
;
case
TCP_SEQ_STATE_TIME_WAIT
:
case
TCP_SEQ_STATE_TIME_WAIT
:
case
TCP_SEQ_STATE_ESTABLISHED
:
case
TCP_SEQ_STATE_ESTABLISHED
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment