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
Kirill Smelkov
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