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
73baeace
Commit
73baeace
authored
May 21, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/acme/net-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents
6c17d503
f989c276
Changes
39
Hide whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
700 additions
and
738 deletions
+700
-738
include/linux/netfilter_ipv4/ip_tables.h
include/linux/netfilter_ipv4/ip_tables.h
+16
-13
include/net/transp_v6.h
include/net/transp_v6.h
+0
-1
net/core/dev.c
net/core/dev.c
+0
-7
net/core/dst.c
net/core/dst.c
+1
-0
net/core/dv.c
net/core/dv.c
+2
-1
net/ipv4/netfilter/ip_nat_rule.c
net/ipv4/netfilter/ip_nat_rule.c
+2
-2
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ip_tables.c
+68
-76
net/ipv4/netfilter/ipt_DSCP.c
net/ipv4/netfilter/ipt_DSCP.c
+14
-20
net/ipv4/netfilter/ipt_ECN.c
net/ipv4/netfilter/ipt_ECN.c
+45
-65
net/ipv4/netfilter/ipt_LOG.c
net/ipv4/netfilter/ipt_LOG.c
+104
-76
net/ipv4/netfilter/ipt_MARK.c
net/ipv4/netfilter/ipt_MARK.c
+1
-1
net/ipv4/netfilter/ipt_MASQUERADE.c
net/ipv4/netfilter/ipt_MASQUERADE.c
+1
-1
net/ipv4/netfilter/ipt_MIRROR.c
net/ipv4/netfilter/ipt_MIRROR.c
+19
-16
net/ipv4/netfilter/ipt_REDIRECT.c
net/ipv4/netfilter/ipt_REDIRECT.c
+1
-1
net/ipv4/netfilter/ipt_REJECT.c
net/ipv4/netfilter/ipt_REJECT.c
+123
-144
net/ipv4/netfilter/ipt_TCPMSS.c
net/ipv4/netfilter/ipt_TCPMSS.c
+3
-10
net/ipv4/netfilter/ipt_TOS.c
net/ipv4/netfilter/ipt_TOS.c
+14
-19
net/ipv4/netfilter/ipt_ULOG.c
net/ipv4/netfilter/ipt_ULOG.c
+4
-3
net/ipv4/netfilter/ipt_ah.c
net/ipv4/netfilter/ipt_ah.c
+9
-9
net/ipv4/netfilter/ipt_conntrack.c
net/ipv4/netfilter/ipt_conntrack.c
+0
-2
net/ipv4/netfilter/ipt_dscp.c
net/ipv4/netfilter/ipt_dscp.c
+1
-2
net/ipv4/netfilter/ipt_ecn.c
net/ipv4/netfilter/ipt_ecn.c
+19
-15
net/ipv4/netfilter/ipt_esp.c
net/ipv4/netfilter/ipt_esp.c
+9
-9
net/ipv4/netfilter/ipt_helper.c
net/ipv4/netfilter/ipt_helper.c
+0
-2
net/ipv4/netfilter/ipt_length.c
net/ipv4/netfilter/ipt_length.c
+0
-2
net/ipv4/netfilter/ipt_limit.c
net/ipv4/netfilter/ipt_limit.c
+0
-2
net/ipv4/netfilter/ipt_mac.c
net/ipv4/netfilter/ipt_mac.c
+0
-2
net/ipv4/netfilter/ipt_mark.c
net/ipv4/netfilter/ipt_mark.c
+0
-2
net/ipv4/netfilter/ipt_multiport.c
net/ipv4/netfilter/ipt_multiport.c
+11
-10
net/ipv4/netfilter/ipt_owner.c
net/ipv4/netfilter/ipt_owner.c
+4
-3
net/ipv4/netfilter/ipt_physdev.c
net/ipv4/netfilter/ipt_physdev.c
+0
-2
net/ipv4/netfilter/ipt_pkttype.c
net/ipv4/netfilter/ipt_pkttype.c
+0
-2
net/ipv4/netfilter/ipt_state.c
net/ipv4/netfilter/ipt_state.c
+0
-2
net/ipv4/netfilter/ipt_tcpmss.c
net/ipv4/netfilter/ipt_tcpmss.c
+26
-19
net/ipv4/netfilter/ipt_tos.c
net/ipv4/netfilter/ipt_tos.c
+1
-4
net/ipv4/netfilter/ipt_ttl.c
net/ipv4/netfilter/ipt_ttl.c
+5
-7
net/ipv4/netfilter/ipt_unclean.c
net/ipv4/netfilter/ipt_unclean.c
+171
-163
net/ipv6/anycast.c
net/ipv6/anycast.c
+21
-20
net/ipv6/ndisc.c
net/ipv6/ndisc.c
+5
-3
No files found.
include/linux/netfilter_ipv4/ip_tables.h
View file @
73baeace
...
...
@@ -347,13 +347,14 @@ struct ipt_match
/* Return true or false: return FALSE and set *hotdrop = 1 to
force immediate packet drop. */
/* Arguments changed since 2.4, as this must now handle
non-linear skbs, using skb_copy_bits and
skb_ip_make_writable. */
int
(
*
match
)(
const
struct
sk_buff
*
skb
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
);
/* Called when user tries to insert an entry of this type. */
...
...
@@ -367,7 +368,7 @@ struct ipt_match
/* Called when entry of this type deleted. */
void
(
*
destroy
)(
void
*
matchinfo
,
unsigned
int
matchinfosize
);
/* Set this to THIS_MODULE
if you are a module, otherwise NULL
*/
/* Set this to THIS_MODULE
.
*/
struct
module
*
me
;
};
...
...
@@ -378,14 +379,6 @@ struct ipt_target
const
char
name
[
IPT_FUNCTION_MAXNAMELEN
];
/* Returns verdict. */
unsigned
int
(
*
target
)(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
void
*
targinfo
,
void
*
userdata
);
/* Called when user tries to insert an entry of this type:
hook_mask is a bitmask of hooks from which it can be
called. */
...
...
@@ -399,7 +392,17 @@ struct ipt_target
/* Called when entry of this type deleted. */
void
(
*
destroy
)(
void
*
targinfo
,
unsigned
int
targinfosize
);
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
/* Returns verdict. Argument order changed since 2.4, as this
must now handle non-linear skbs, using skb_copy_bits and
skb_ip_make_writable. */
unsigned
int
(
*
target
)(
struct
sk_buff
**
pskb
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userdata
);
/* Set this to THIS_MODULE. */
struct
module
*
me
;
};
...
...
@@ -429,7 +432,7 @@ struct ipt_table
/* Man behind the curtain... */
struct
ipt_table_info
*
private
;
/* Set t
his to THIS_MODULE if you are a module, otherwise NULL
*/
/* Set t
o THIS_MODULE.
*/
struct
module
*
me
;
};
...
...
include/net/transp_v6.h
View file @
73baeace
...
...
@@ -16,7 +16,6 @@ extern struct proto tcpv6_prot;
struct
flowi
;
/* extention headers */
extern
void
ipv6_hopopts_init
(
void
);
extern
void
ipv6_rthdr_init
(
void
);
extern
void
ipv6_frag_init
(
void
);
extern
void
ipv6_nodata_init
(
void
);
...
...
net/core/dev.c
View file @
73baeace
...
...
@@ -2863,9 +2863,6 @@ int unregister_netdevice(struct net_device *dev)
extern
void
net_device_init
(
void
);
extern
void
ip_auto_config
(
void
);
#ifdef CONFIG_NET_DIVERT
extern
void
dv_init
(
void
);
#endif
/* CONFIG_NET_DIVERT */
/*
...
...
@@ -2889,10 +2886,6 @@ static int __init net_dev_init(void)
for
(
i
=
0
;
i
<
16
;
i
++
)
INIT_LIST_HEAD
(
&
ptype_base
[
i
]);
#ifdef CONFIG_NET_DIVERT
dv_init
();
#endif
/* CONFIG_NET_DIVERT */
/*
* Initialise the packet receive queues.
*/
...
...
net/core/dst.c
View file @
73baeace
...
...
@@ -123,6 +123,7 @@ void * dst_alloc(struct dst_ops * ops)
if
(
!
dst
)
return
NULL
;
memset
(
dst
,
0
,
ops
->
entry_size
);
atomic_set
(
&
dst
->
__refcnt
,
0
);
dst
->
ops
=
ops
;
dst
->
lastuse
=
jiffies
;
dst
->
path
=
dst
;
...
...
net/core/dv.c
View file @
73baeace
...
...
@@ -40,11 +40,12 @@
const
char
sysctl_divert_version
[
32
]
=
"0.46"
;
/* Current version */
int
__init
dv_init
(
void
)
static
int
__init
dv_init
(
void
)
{
printk
(
KERN_INFO
"NET4: Frame Diverter %s
\n
"
,
sysctl_divert_version
);
return
0
;
}
module_init
(
dv_init
);
/*
* Allocate a divert_blk for a device. This must be an ethernet nic.
...
...
net/ipv4/netfilter/ip_nat_rule.c
View file @
73baeace
...
...
@@ -111,9 +111,9 @@ static struct ipt_table nat_table = {
/* Source NAT */
static
unsigned
int
ipt_snat_target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
...
...
@@ -132,9 +132,9 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
}
static
unsigned
int
ipt_dnat_target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
...
...
net/ipv4/netfilter/ip_tables.c
View file @
73baeace
...
...
@@ -214,9 +214,9 @@ ip_checkentry(const struct ipt_ip *ip)
static
unsigned
int
ipt_error
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
...
...
@@ -232,13 +232,10 @@ int do_match(struct ipt_entry_match *m,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
/* Stop iteration if it doesn't match */
if
(
!
m
->
u
.
kernel
.
match
->
match
(
skb
,
in
,
out
,
m
->
data
,
offset
,
hdr
,
datalen
,
hotdrop
))
if
(
!
m
->
u
.
kernel
.
match
->
match
(
skb
,
in
,
out
,
m
->
data
,
offset
,
hotdrop
))
return
1
;
else
return
0
;
...
...
@@ -262,7 +259,6 @@ ipt_do_table(struct sk_buff **pskb,
static
const
char
nulldevname
[
IFNAMSIZ
]
=
{
0
};
u_int16_t
offset
;
struct
iphdr
*
ip
;
void
*
protohdr
;
u_int16_t
datalen
;
int
hotdrop
=
0
;
/* Initializing verdict to NF_DROP keeps gcc happy. */
...
...
@@ -271,13 +267,8 @@ ipt_do_table(struct sk_buff **pskb,
void
*
table_base
;
struct
ipt_entry
*
e
,
*
back
;
/* FIXME: Push down to extensions --RR */
if
(
skb_is_nonlinear
(
*
pskb
)
&&
skb_linearize
(
*
pskb
,
GFP_ATOMIC
)
!=
0
)
return
NF_DROP
;
/* Initialization */
ip
=
(
*
pskb
)
->
nh
.
iph
;
protohdr
=
(
u_int32_t
*
)
ip
+
ip
->
ihl
;
datalen
=
(
*
pskb
)
->
len
-
ip
->
ihl
*
4
;
indev
=
in
?
in
->
name
:
nulldevname
;
outdev
=
out
?
out
->
name
:
nulldevname
;
...
...
@@ -320,8 +311,7 @@ ipt_do_table(struct sk_buff **pskb,
if
(
IPT_MATCH_ITERATE
(
e
,
do_match
,
*
pskb
,
in
,
out
,
offset
,
protohdr
,
datalen
,
&
hotdrop
)
!=
0
)
offset
,
&
hotdrop
)
!=
0
)
goto
no_match
;
ADD_COUNTER
(
e
->
counters
,
ntohs
(
ip
->
tot_len
),
1
);
...
...
@@ -364,8 +354,8 @@ ipt_do_table(struct sk_buff **pskb,
=
0xeeeeeeec
;
#endif
verdict
=
t
->
u
.
kernel
.
target
->
target
(
pskb
,
hook
,
in
,
out
,
hook
,
t
->
data
,
userdata
);
...
...
@@ -382,7 +372,6 @@ ipt_do_table(struct sk_buff **pskb,
#endif
/* Target might have changed stuff. */
ip
=
(
*
pskb
)
->
nh
.
iph
;
protohdr
=
(
u_int32_t
*
)
ip
+
ip
->
ihl
;
datalen
=
(
*
pskb
)
->
len
-
ip
->
ihl
*
4
;
if
(
verdict
==
IPT_CONTINUE
)
...
...
@@ -1458,22 +1447,24 @@ port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
static
int
tcp_find_option
(
u_int8_t
option
,
const
struct
tcphdr
*
tcp
,
u
_int16_t
data
len
,
const
struct
sk_buff
*
skb
,
u
nsigned
int
opt
len
,
int
invert
,
int
*
hotdrop
)
{
unsigned
int
i
=
sizeof
(
struct
tcphdr
);
const
u_int8_t
*
opt
=
(
u_int8_t
*
)
tcp
;
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
char
opt
[
60
-
sizeof
(
struct
tcphdr
)];
unsigned
int
i
;
duprintf
(
"tcp_match: finding option
\n
"
);
/* If we don't have the whole header, drop packet. */
if
(
tcp
->
doff
*
4
>
datalen
)
{
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
+
sizeof
(
struct
tcphdr
),
opt
,
optlen
)
<
0
)
{
*
hotdrop
=
1
;
return
0
;
}
while
(
i
<
tcp
->
doff
*
4
)
{
for
(
i
=
0
;
i
<
optlen
;
)
{
if
(
opt
[
i
]
==
option
)
return
!
invert
;
if
(
opt
[
i
]
<
2
)
i
++
;
else
i
+=
opt
[
i
+
1
]
?:
1
;
...
...
@@ -1488,25 +1479,29 @@ tcp_match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
tcphdr
*
tcp
=
hdr
;
struct
tcphdr
tcph
;
const
struct
ipt_tcp
*
tcpinfo
=
matchinfo
;
/* To quote Alan:
Don't allow a fragment of TCP 8 bytes in. Nobody normal
causes this. Its a cracker trying to break in by doing a
flag overwrite to pass the direction checks.
*/
if
(
offset
)
{
/* To quote Alan:
if
(
offset
==
1
)
{
duprintf
(
"Dropping evil TCP offset=1 frag.
\n
"
);
*
hotdrop
=
1
;
Don't allow a fragment of TCP 8 bytes in. Nobody normal
causes this. Its a cracker trying to break in by doing a
flag overwrite to pass the direction checks.
*/
if
(
offset
==
1
)
{
duprintf
(
"Dropping evil TCP offset=1 frag.
\n
"
);
*
hotdrop
=
1
;
}
/* Must not be a fragment. */
return
0
;
}
else
if
(
offset
==
0
&&
datalen
<
sizeof
(
struct
tcphdr
))
{
}
#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
,
&
tcph
,
sizeof
(
tcph
))
<
0
)
{
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf
(
"Dropping evil TCP offset=0 tinygram.
\n
"
);
...
...
@@ -1514,27 +1509,24 @@ tcp_match(const struct sk_buff *skb,
return
0
;
}
/* FIXME: Try tcp doff >> packet len against various stacks --RR */
#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
/* Must not be a fragment. */
return
!
offset
&&
port_match
(
tcpinfo
->
spts
[
0
],
tcpinfo
->
spts
[
1
],
ntohs
(
tcp
->
source
),
!!
(
tcpinfo
->
invflags
&
IPT_TCP_INV_SRCPT
))
&&
port_match
(
tcpinfo
->
dpts
[
0
],
tcpinfo
->
dpts
[
1
],
ntohs
(
tcp
->
dest
),
!!
(
tcpinfo
->
invflags
&
IPT_TCP_INV_DSTPT
))
&&
FWINVTCP
((((
unsigned
char
*
)
tcp
)[
13
]
&
tcpinfo
->
flg_mask
)
==
tcpinfo
->
flg_cmp
,
IPT_TCP_INV_FLAGS
)
&&
(
!
tcpinfo
->
option
||
tcp_find_option
(
tcpinfo
->
option
,
tcp
,
datalen
,
tcpinfo
->
invflags
&
IPT_TCP_INV_OPTION
,
hotdrop
));
if
(
!
port_match
(
tcpinfo
->
spts
[
0
],
tcpinfo
->
spts
[
1
],
ntohs
(
tcph
.
source
),
!!
(
tcpinfo
->
invflags
&
IPT_TCP_INV_SRCPT
)))
return
0
;
if
(
!
port_match
(
tcpinfo
->
dpts
[
0
],
tcpinfo
->
dpts
[
1
],
ntohs
(
tcph
.
dest
),
!!
(
tcpinfo
->
invflags
&
IPT_TCP_INV_DSTPT
)))
return
0
;
if
(
!
FWINVTCP
((((
unsigned
char
*
)
&
tcph
)[
13
]
&
tcpinfo
->
flg_mask
)
==
tcpinfo
->
flg_cmp
,
IPT_TCP_INV_FLAGS
))
return
0
;
if
(
tcpinfo
->
option
&&
!
tcp_find_option
(
tcpinfo
->
option
,
skb
,
tcph
.
doff
*
4
-
sizeof
(
tcph
),
tcpinfo
->
invflags
&
IPT_TCP_INV_OPTION
,
hotdrop
))
return
0
;
return
1
;
}
/* Called when user tries to insert an entry of this type. */
...
...
@@ -1560,14 +1552,16 @@ udp_match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
udphdr
*
udp
=
hdr
;
struct
udphdr
udph
;
const
struct
ipt_udp
*
udpinfo
=
matchinfo
;
if
(
offset
==
0
&&
datalen
<
sizeof
(
struct
udphdr
))
{
/* Must not be a fragment. */
if
(
offset
)
return
0
;
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
,
&
udph
,
sizeof
(
udph
))
<
0
)
{
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf
(
"Dropping evil UDP tinygram.
\n
"
);
...
...
@@ -1575,13 +1569,11 @@ udp_match(const struct sk_buff *skb,
return
0
;
}
/* Must not be a fragment. */
return
!
offset
&&
port_match
(
udpinfo
->
spts
[
0
],
udpinfo
->
spts
[
1
],
ntohs
(
udp
->
source
),
!!
(
udpinfo
->
invflags
&
IPT_UDP_INV_SRCPT
))
return
port_match
(
udpinfo
->
spts
[
0
],
udpinfo
->
spts
[
1
],
ntohs
(
udph
.
source
),
!!
(
udpinfo
->
invflags
&
IPT_UDP_INV_SRCPT
))
&&
port_match
(
udpinfo
->
dpts
[
0
],
udpinfo
->
dpts
[
1
],
ntohs
(
udp
->
dest
),
ntohs
(
udp
h
.
dest
),
!!
(
udpinfo
->
invflags
&
IPT_UDP_INV_DSTPT
));
}
...
...
@@ -1631,14 +1623,16 @@ icmp_match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
icmphdr
*
icmp
=
hdr
;
struct
icmphdr
icmph
;
const
struct
ipt_icmp
*
icmpinfo
=
matchinfo
;
if
(
offset
==
0
&&
datalen
<
2
)
{
/* Must not be a fragment. */
if
(
offset
)
return
0
;
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
,
&
icmph
,
sizeof
(
icmph
))
<
0
){
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf
(
"Dropping evil ICMP tinygram.
\n
"
);
...
...
@@ -1646,13 +1640,11 @@ icmp_match(const struct sk_buff *skb,
return
0
;
}
/* Must not be a fragment. */
return
!
offset
&&
icmp_type_code_match
(
icmpinfo
->
type
,
icmpinfo
->
code
[
0
],
icmpinfo
->
code
[
1
],
icmp
->
type
,
icmp
->
code
,
!!
(
icmpinfo
->
invflags
&
IPT_ICMP_INV
));
return
icmp_type_code_match
(
icmpinfo
->
type
,
icmpinfo
->
code
[
0
],
icmpinfo
->
code
[
1
],
icmph
.
type
,
icmph
.
code
,
!!
(
icmpinfo
->
invflags
&
IPT_ICMP_INV
));
}
/* Called when user tries to insert an entry of this type. */
...
...
net/ipv4/netfilter/ipt_DSCP.c
View file @
73baeace
...
...
@@ -23,37 +23,31 @@ MODULE_LICENSE("GPL");
static
unsigned
int
target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
struct
iphdr
*
iph
=
(
*
pskb
)
->
nh
.
iph
;
const
struct
ipt_DSCP_info
*
dinfo
=
targinfo
;
u_int8_t
sh_dscp
=
((
dinfo
->
dscp
<<
IPT_DSCP_SHIFT
)
&
IPT_DSCP_MASK
);
if
((
iph
->
tos
&
IPT_DSCP_MASK
)
!=
sh_dscp
)
{
if
((
(
*
pskb
)
->
nh
.
iph
->
tos
&
IPT_DSCP_MASK
)
!=
sh_dscp
)
{
u_int16_t
diffs
[
2
];
/* raw socket (tcpdump) may have clone of incoming
* skb: don't disturb it --RR */
if
(
skb_cloned
(
*
pskb
)
&&
!
(
*
pskb
)
->
sk
)
{
struct
sk_buff
*
nskb
=
skb_copy
(
*
pskb
,
GFP_ATOMIC
);
if
(
!
nskb
)
return
NF_DROP
;
kfree_skb
(
*
pskb
);
*
pskb
=
nskb
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
}
diffs
[
0
]
=
htons
(
iph
->
tos
)
^
0xFFFF
;
iph
->
tos
=
(
iph
->
tos
&
~
IPT_DSCP_MASK
)
|
sh_dscp
;
diffs
[
1
]
=
htons
(
iph
->
tos
);
iph
->
check
=
csum_fold
(
csum_partial
((
char
*
)
diffs
,
sizeof
(
diffs
),
iph
->
check
^
0xFFFF
));
if
(
!
skb_ip_make_writable
(
pskb
,
sizeof
(
struct
iphdr
)))
return
NF_DROP
;
diffs
[
0
]
=
htons
((
*
pskb
)
->
nh
.
iph
->
tos
)
^
0xFFFF
;
(
*
pskb
)
->
nh
.
iph
->
tos
=
((
*
pskb
)
->
nh
.
iph
->
tos
&
~
IPT_DSCP_MASK
)
|
sh_dscp
;
diffs
[
1
]
=
htons
((
*
pskb
)
->
nh
.
iph
->
tos
);
(
*
pskb
)
->
nh
.
iph
->
check
=
csum_fold
(
csum_partial
((
char
*
)
diffs
,
sizeof
(
diffs
),
(
*
pskb
)
->
nh
.
iph
->
check
^
0xFFFF
));
(
*
pskb
)
->
nfcache
|=
NFC_ALTERED
;
}
return
IPT_CONTINUE
;
...
...
net/ipv4/netfilter/ipt_ECN.c
View file @
73baeace
...
...
@@ -19,105 +19,85 @@
MODULE_LICENSE
(
"GPL"
);
/* set ECT codepoint from IP header.
* return 0 in case there was no ECT codepoint
* return 1 in case ECT codepoint has been overwritten
* return < 0 in case there was error */
* return 0 if there was an error. */
static
inline
int
set_ect_ip
(
struct
sk_buff
**
pskb
,
struct
iphdr
*
iph
,
const
struct
ipt_ECN_info
*
einfo
)
set_ect_ip
(
struct
sk_buff
**
pskb
,
const
struct
ipt_ECN_info
*
einfo
)
{
if
((
iph
->
tos
&
IPT_ECN_IP_MASK
)
if
((
(
*
pskb
)
->
nh
.
iph
->
tos
&
IPT_ECN_IP_MASK
)
!=
(
einfo
->
ip_ect
&
IPT_ECN_IP_MASK
))
{
u_int16_t
diffs
[
2
];
/* raw socket (tcpdump) may have clone of incoming
* skb: don't disturb it --RR */
if
(
skb_cloned
(
*
pskb
)
&&
!
(
*
pskb
)
->
sk
)
{
struct
sk_buff
*
nskb
=
skb_copy
(
*
pskb
,
GFP_ATOMIC
);
if
(
!
nskb
)
return
NF_DROP
;
kfree_skb
(
*
pskb
);
*
pskb
=
nskb
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
}
diffs
[
0
]
=
htons
(
iph
->
tos
)
^
0xFFFF
;
iph
->
tos
=
iph
->
tos
&
~
IPT_ECN_IP_MASK
;
iph
->
tos
=
iph
->
tos
|
(
einfo
->
ip_ect
&
IPT_ECN_IP_MASK
);
diffs
[
1
]
=
htons
(
iph
->
tos
);
iph
->
check
=
csum_fold
(
csum_partial
((
char
*
)
diffs
,
sizeof
(
diffs
),
iph
->
check
^
0xFFFF
));
if
(
!
skb_ip_make_writable
(
pskb
,
sizeof
(
struct
iphdr
)))
return
0
;
diffs
[
0
]
=
htons
((
*
pskb
)
->
nh
.
iph
->
tos
)
^
0xFFFF
;
(
*
pskb
)
->
nh
.
iph
->
tos
&=
~
IPT_ECN_IP_MASK
;
(
*
pskb
)
->
nh
.
iph
->
tos
|=
(
einfo
->
ip_ect
&
IPT_ECN_IP_MASK
);
diffs
[
1
]
=
htons
((
*
pskb
)
->
nh
.
iph
->
tos
);
(
*
pskb
)
->
nh
.
iph
->
check
=
csum_fold
(
csum_partial
((
char
*
)
diffs
,
sizeof
(
diffs
),
(
*
pskb
)
->
nh
.
iph
->
check
^
0xFFFF
));
(
*
pskb
)
->
nfcache
|=
NFC_ALTERED
;
return
1
;
}
return
0
;
return
1
;
}
/* Return 0 if there was an error. */
static
inline
int
set_ect_tcp
(
struct
sk_buff
**
pskb
,
struct
iphdr
*
iph
,
const
struct
ipt_ECN_info
*
einfo
)
set_ect_tcp
(
struct
sk_buff
**
pskb
,
const
struct
ipt_ECN_info
*
einfo
)
{
struct
tcphdr
*
tcph
=
(
void
*
)
iph
+
iph
->
ihl
*
4
;
u_int16_t
*
tcpflags
=
(
u_int16_t
*
)
tcph
+
6
;
struct
tcphdr
tcph
;
u_int16_t
diffs
[
2
];
/* raw socket (tcpdump) may have clone of incoming
* skb: don't disturb it --RR */
if
(
skb_cloned
(
*
pskb
)
&&
!
(
*
pskb
)
->
sk
)
{
struct
sk_buff
*
nskb
=
skb_copy
(
*
pskb
,
GFP_ATOMIC
);
if
(
!
nskb
)
return
NF_DROP
;
kfree_skb
(
*
pskb
);
*
pskb
=
nskb
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
}
/* Not enought header? */
if
(
skb_copy_bits
(
*
pskb
,
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
,
&
tcph
,
sizeof
(
tcph
))
<
0
)
return
0
;
diffs
[
0
]
=
*
tcpflags
;
diffs
[
0
]
=
((
u_int16_t
*
)
&
tcph
)[
6
];
if
(
einfo
->
operation
&
IPT_ECN_OP_SET_ECE
)
tcph
.
ece
=
einfo
->
proto
.
tcp
.
ece
;
if
(
einfo
->
operation
&
IPT_ECN_OP_SET_ECE
&&
tcph
->
ece
!=
einfo
->
proto
.
tcp
.
ece
)
{
tcph
->
ece
=
einfo
->
proto
.
tcp
.
ece
;
}
if
(
einfo
->
operation
&
IPT_ECN_OP_SET_CWR
)
tcph
.
cwr
=
einfo
->
proto
.
tcp
.
cwr
;
diffs
[
1
]
=
((
u_int16_t
*
)
&
tcph
)[
6
];
if
(
einfo
->
operation
&
IPT_ECN_OP_SET_CWR
&&
tcph
->
cwr
!=
einfo
->
proto
.
tcp
.
cwr
)
{
tcph
->
cwr
=
einfo
->
proto
.
tcp
.
cwr
;
}
if
(
diffs
[
0
]
!=
*
tcpflags
)
{
/* Only mangle if it's changed. */
if
(
diffs
[
0
]
!=
diffs
[
1
])
{
diffs
[
0
]
=
diffs
[
0
]
^
0xFFFF
;
diffs
[
1
]
=
*
tcpflags
;
tcph
->
check
=
csum_fold
(
csum_partial
((
char
*
)
diffs
,
if
(
!
skb_ip_make_writable
(
pskb
,
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
+
sizeof
(
tcph
)))
return
0
;
tcph
.
check
=
csum_fold
(
csum_partial
((
char
*
)
diffs
,
sizeof
(
diffs
),
tcph
->
check
^
0xFFFF
));
tcph
.
check
^
0xFFFF
));
memcpy
((
*
pskb
)
->
data
+
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
,
&
tcph
,
sizeof
(
tcph
));
(
*
pskb
)
->
nfcache
|=
NFC_ALTERED
;
return
1
;
}
return
0
;
return
1
;
}
static
unsigned
int
target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
struct
iphdr
*
iph
=
(
*
pskb
)
->
nh
.
iph
;
const
struct
ipt_ECN_info
*
einfo
=
targinfo
;
if
(
einfo
->
operation
&
IPT_ECN_OP_SET_IP
)
set_ect_ip
(
pskb
,
iph
,
einfo
);
if
(
!
set_ect_ip
(
pskb
,
einfo
))
return
NF_DROP
;
if
(
einfo
->
operation
&
(
IPT_ECN_OP_SET_ECE
|
IPT_ECN_OP_SET_CWR
)
&&
iph
->
protocol
==
IPPROTO_TCP
)
set_ect_tcp
(
pskb
,
iph
,
einfo
);
&&
(
*
pskb
)
->
nh
.
iph
->
protocol
==
IPPROTO_TCP
)
if
(
!
set_ect_tcp
(
pskb
,
einfo
))
return
NF_DROP
;
return
IPT_CONTINUE
;
}
...
...
net/ipv4/netfilter/ipt_LOG.c
View file @
73baeace
...
...
@@ -29,127 +29,151 @@ static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
/* One level of recursion won't kill us */
static
void
dump_packet
(
const
struct
ipt_log_info
*
info
,
struct
iphdr
*
iph
,
unsigned
int
len
,
int
recurse
)
const
struct
sk_buff
*
skb
,
unsigned
int
iphoff
)
{
void
*
protoh
=
(
u_int32_t
*
)
iph
+
iph
->
ihl
;
unsigned
int
datalen
=
len
-
iph
->
ihl
*
4
;
struct
iphdr
iph
;
if
(
skb_copy_bits
(
skb
,
iphoff
,
&
iph
,
sizeof
(
iph
))
<
0
)
{
printk
(
"TRUNCATED"
);
return
;
}
/* Important fields:
* TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
printk
(
"SRC=%u.%u.%u.%u DST=%u.%u.%u.%u "
,
NIPQUAD
(
iph
->
saddr
),
NIPQUAD
(
iph
->
daddr
));
NIPQUAD
(
iph
.
saddr
),
NIPQUAD
(
iph
.
daddr
));
/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
printk
(
"LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u "
,
ntohs
(
iph
->
tot_len
),
iph
->
tos
&
IPTOS_TOS_MASK
,
iph
->
tos
&
IPTOS_PREC_MASK
,
iph
->
ttl
,
ntohs
(
iph
->
id
));
ntohs
(
iph
.
tot_len
),
iph
.
tos
&
IPTOS_TOS_MASK
,
iph
.
tos
&
IPTOS_PREC_MASK
,
iph
.
ttl
,
ntohs
(
iph
.
id
));
/* Max length: 6 "CE DF MF " */
if
(
ntohs
(
iph
->
frag_off
)
&
IP_CE
)
if
(
ntohs
(
iph
.
frag_off
)
&
IP_CE
)
printk
(
"CE "
);
if
(
ntohs
(
iph
->
frag_off
)
&
IP_DF
)
if
(
ntohs
(
iph
.
frag_off
)
&
IP_DF
)
printk
(
"DF "
);
if
(
ntohs
(
iph
->
frag_off
)
&
IP_MF
)
if
(
ntohs
(
iph
.
frag_off
)
&
IP_MF
)
printk
(
"MF "
);
/* Max length: 11 "FRAG:65535 " */
if
(
ntohs
(
iph
->
frag_off
)
&
IP_OFFSET
)
printk
(
"FRAG:%u "
,
ntohs
(
iph
->
frag_off
)
&
IP_OFFSET
);
if
(
ntohs
(
iph
.
frag_off
)
&
IP_OFFSET
)
printk
(
"FRAG:%u "
,
ntohs
(
iph
.
frag_off
)
&
IP_OFFSET
);
if
((
info
->
logflags
&
IPT_LOG_IPOPT
)
&&
iph
->
ihl
*
4
!=
sizeof
(
struct
iphdr
))
{
unsigned
int
i
;
&&
iph
.
ihl
*
4
!=
sizeof
(
struct
iphdr
))
{
unsigned
char
opt
[
4
*
15
-
sizeof
(
struct
iphdr
)];
unsigned
int
i
,
optsize
;
optsize
=
iph
.
ihl
*
4
-
sizeof
(
struct
iphdr
);
if
(
skb_copy_bits
(
skb
,
iphoff
+
sizeof
(
iph
),
opt
,
optsize
)
<
0
)
{
printk
(
"TRUNCATED"
);
return
;
}
/* Max length: 127 "OPT (" 15*4*2chars ") " */
printk
(
"OPT ("
);
for
(
i
=
sizeof
(
struct
iphdr
);
i
<
iph
->
ihl
*
4
;
i
++
)
printk
(
"%02X"
,
((
u_int8_t
*
)
iph
)
[
i
]);
for
(
i
=
0
;
i
<
optsize
;
i
++
)
printk
(
"%02X"
,
opt
[
i
]);
printk
(
") "
);
}
switch
(
iph
->
protocol
)
{
switch
(
iph
.
protocol
)
{
case
IPPROTO_TCP
:
{
struct
tcphdr
*
tcph
=
proto
h
;
struct
tcphdr
tcp
h
;
/* Max length: 10 "PROTO=TCP " */
printk
(
"PROTO=TCP "
);
if
(
ntohs
(
iph
->
frag_off
)
&
IP_OFFSET
)
if
(
ntohs
(
iph
.
frag_off
)
&
IP_OFFSET
)
break
;
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
if
(
datalen
<
sizeof
(
*
tcph
))
{
printk
(
"INCOMPLETE [%u bytes] "
,
datalen
);
if
(
skb_copy_bits
(
skb
,
iphoff
+
iph
.
ihl
*
4
,
&
tcph
,
sizeof
(
tcph
))
<
0
)
{
printk
(
"INCOMPLETE [%u bytes] "
,
skb
->
len
-
iphoff
-
iph
.
ihl
*
4
);
break
;
}
/* Max length: 20 "SPT=65535 DPT=65535 " */
printk
(
"SPT=%u DPT=%u "
,
ntohs
(
tcph
->
source
),
ntohs
(
tcph
->
dest
));
ntohs
(
tcph
.
source
),
ntohs
(
tcph
.
dest
));
/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
if
(
info
->
logflags
&
IPT_LOG_TCPSEQ
)
printk
(
"SEQ=%u ACK=%u "
,
ntohl
(
tcph
->
seq
),
ntohl
(
tcph
->
ack_seq
));
ntohl
(
tcph
.
seq
),
ntohl
(
tcph
.
ack_seq
));
/* Max length: 13 "WINDOW=65535 " */
printk
(
"WINDOW=%u "
,
ntohs
(
tcph
->
window
));
printk
(
"WINDOW=%u "
,
ntohs
(
tcph
.
window
));
/* Max length: 9 "RES=0x3F " */
printk
(
"RES=0x%02x "
,
(
u
_int8_t
)(
ntohl
(
tcp_flag_word
(
tcph
)
&
TCP_RESERVED_BITS
)
>>
22
));
printk
(
"RES=0x%02x "
,
(
u
8
)(
ntohl
(
tcp_flag_word
(
&
tcph
)
&
TCP_RESERVED_BITS
)
>>
22
));
/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
if
(
tcph
->
cwr
)
if
(
tcph
.
cwr
)
printk
(
"CWR "
);
if
(
tcph
->
ece
)
if
(
tcph
.
ece
)
printk
(
"ECE "
);
if
(
tcph
->
urg
)
if
(
tcph
.
urg
)
printk
(
"URG "
);
if
(
tcph
->
ack
)
if
(
tcph
.
ack
)
printk
(
"ACK "
);
if
(
tcph
->
psh
)
if
(
tcph
.
psh
)
printk
(
"PSH "
);
if
(
tcph
->
rst
)
if
(
tcph
.
rst
)
printk
(
"RST "
);
if
(
tcph
->
syn
)
if
(
tcph
.
syn
)
printk
(
"SYN "
);
if
(
tcph
->
fin
)
if
(
tcph
.
fin
)
printk
(
"FIN "
);
/* Max length: 11 "URGP=65535 " */
printk
(
"URGP=%u "
,
ntohs
(
tcph
->
urg_ptr
));
printk
(
"URGP=%u "
,
ntohs
(
tcph
.
urg_ptr
));
if
((
info
->
logflags
&
IPT_LOG_TCPOPT
)
&&
tcph
->
doff
*
4
!=
sizeof
(
struct
tcphdr
))
{
unsigned
int
i
;
&&
tcph
.
doff
*
4
!=
sizeof
(
struct
tcphdr
))
{
unsigned
char
opt
[
4
*
15
-
sizeof
(
struct
tcphdr
)];
unsigned
int
i
,
optsize
;
optsize
=
tcph
.
doff
*
4
-
sizeof
(
struct
tcphdr
);
if
(
skb_copy_bits
(
skb
,
iphoff
+
iph
.
ihl
*
4
+
sizeof
(
tcph
),
opt
,
optsize
)
<
0
)
{
printk
(
"TRUNCATED"
);
return
;
}
/* Max length: 127 "OPT (" 15*4*2chars ") " */
printk
(
"OPT ("
);
for
(
i
=
sizeof
(
struct
tcphdr
);
i
<
tcph
->
doff
*
4
;
i
++
)
printk
(
"%02X"
,
((
u_int8_t
*
)
tcph
)
[
i
]);
for
(
i
=
0
;
i
<
optsize
;
i
++
)
printk
(
"%02X"
,
opt
[
i
]);
printk
(
") "
);
}
break
;
}
case
IPPROTO_UDP
:
{
struct
udphdr
*
udph
=
proto
h
;
struct
udphdr
udp
h
;
/* Max length: 10 "PROTO=UDP " */
printk
(
"PROTO=UDP "
);
if
(
ntohs
(
iph
->
frag_off
)
&
IP_OFFSET
)
if
(
ntohs
(
iph
.
frag_off
)
&
IP_OFFSET
)
break
;
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
if
(
datalen
<
sizeof
(
*
udph
))
{
printk
(
"INCOMPLETE [%u bytes] "
,
datalen
);
if
(
skb_copy_bits
(
skb
,
iphoff
+
iph
.
ihl
*
4
,
&
udph
,
sizeof
(
udph
))
<
0
)
{
printk
(
"INCOMPLETE [%u bytes] "
,
skb
->
len
-
iphoff
-
iph
.
ihl
*
4
);
break
;
}
/* Max length: 20 "SPT=65535 DPT=65535 " */
printk
(
"SPT=%u DPT=%u LEN=%u "
,
ntohs
(
udph
->
source
),
ntohs
(
udph
->
dest
),
ntohs
(
udph
->
len
));
ntohs
(
udph
.
source
),
ntohs
(
udph
.
dest
),
ntohs
(
udph
.
len
));
break
;
}
case
IPPROTO_ICMP
:
{
struct
icmphdr
*
icmph
=
proto
h
;
struct
icmphdr
icmp
h
;
static
size_t
required_len
[
NR_ICMP_TYPES
+
1
]
=
{
[
ICMP_ECHOREPLY
]
=
4
,
[
ICMP_DEST_UNREACH
]
...
...
@@ -171,89 +195,93 @@ static void dump_packet(const struct ipt_log_info *info,
/* Max length: 11 "PROTO=ICMP " */
printk
(
"PROTO=ICMP "
);
if
(
ntohs
(
iph
->
frag_off
)
&
IP_OFFSET
)
if
(
ntohs
(
iph
.
frag_off
)
&
IP_OFFSET
)
break
;
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
if
(
datalen
<
4
)
{
printk
(
"INCOMPLETE [%u bytes] "
,
datalen
);
if
(
skb_copy_bits
(
skb
,
iphoff
+
iph
.
ihl
*
4
,
&
icmph
,
sizeof
(
icmph
))
<
0
)
{
printk
(
"INCOMPLETE [%u bytes] "
,
skb
->
len
-
iphoff
-
iph
.
ihl
*
4
);
break
;
}
/* Max length: 18 "TYPE=255 CODE=255 " */
printk
(
"TYPE=%u CODE=%u "
,
icmph
->
type
,
icmph
->
code
);
printk
(
"TYPE=%u CODE=%u "
,
icmph
.
type
,
icmph
.
code
);
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
if
(
icmph
->
type
<=
NR_ICMP_TYPES
&&
required_len
[
icmph
->
type
]
&&
datalen
<
required_len
[
icmph
->
type
])
{
printk
(
"INCOMPLETE [%u bytes] "
,
datalen
);
if
(
icmph
.
type
<=
NR_ICMP_TYPES
&&
required_len
[
icmph
.
type
]
&&
skb
->
len
-
iphoff
-
iph
.
ihl
*
4
<
required_len
[
icmph
.
type
])
{
printk
(
"INCOMPLETE [%u bytes] "
,
skb
->
len
-
iphoff
-
iph
.
ihl
*
4
);
break
;
}
switch
(
icmph
->
type
)
{
switch
(
icmph
.
type
)
{
case
ICMP_ECHOREPLY
:
case
ICMP_ECHO
:
/* Max length: 19 "ID=65535 SEQ=65535 " */
printk
(
"ID=%u SEQ=%u "
,
ntohs
(
icmph
->
un
.
echo
.
id
),
ntohs
(
icmph
->
un
.
echo
.
sequence
));
ntohs
(
icmph
.
un
.
echo
.
id
),
ntohs
(
icmph
.
un
.
echo
.
sequence
));
break
;
case
ICMP_PARAMETERPROB
:
/* Max length: 14 "PARAMETER=255 " */
printk
(
"PARAMETER=%u "
,
ntohl
(
icmph
->
un
.
gateway
)
>>
24
);
ntohl
(
icmph
.
un
.
gateway
)
>>
24
);
break
;
case
ICMP_REDIRECT
:
/* Max length: 24 "GATEWAY=255.255.255.255 " */
printk
(
"GATEWAY=%u.%u.%u.%u "
,
NIPQUAD
(
icmph
->
un
.
gateway
));
printk
(
"GATEWAY=%u.%u.%u.%u "
,
NIPQUAD
(
icmph
.
un
.
gateway
));
/* Fall through */
case
ICMP_DEST_UNREACH
:
case
ICMP_SOURCE_QUENCH
:
case
ICMP_TIME_EXCEEDED
:
/* Max length: 3+maxlen */
if
(
recurse
)
{
if
(
!
iphoff
)
{
/* Only recurse once. */
printk
(
"["
);
dump_packet
(
info
,
(
struct
iphdr
*
)(
icmph
+
1
),
datalen
-
sizeof
(
struct
icmphdr
),
0
);
dump_packet
(
info
,
skb
,
iphoff
+
iph
.
ihl
*
4
+
sizeof
(
icmph
));
printk
(
"] "
);
}
/* Max length: 10 "MTU=65535 " */
if
(
icmph
->
type
==
ICMP_DEST_UNREACH
&&
icmph
->
code
==
ICMP_FRAG_NEEDED
)
printk
(
"MTU=%u "
,
ntohs
(
icmph
->
un
.
frag
.
mtu
));
if
(
icmph
.
type
==
ICMP_DEST_UNREACH
&&
icmph
.
code
==
ICMP_FRAG_NEEDED
)
printk
(
"MTU=%u "
,
ntohs
(
icmph
.
un
.
frag
.
mtu
));
}
break
;
}
/* Max Length */
case
IPPROTO_AH
:
case
IPPROTO_ESP
:
{
struct
esphdr
*
esph
=
proto
h
;
int
esp
=
(
iph
->
protocol
==
IPPROTO_ESP
);
struct
esphdr
esp
h
;
int
esp
=
(
iph
.
protocol
==
IPPROTO_ESP
);
/* Max length: 10 "PROTO=ESP " */
printk
(
"PROTO=%s "
,
esp
?
"ESP"
:
"AH"
);
if
(
ntohs
(
iph
->
frag_off
)
&
IP_OFFSET
)
if
(
ntohs
(
iph
.
frag_off
)
&
IP_OFFSET
)
break
;
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
if
(
datalen
<
sizeof
(
*
esph
))
{
printk
(
"INCOMPLETE [%u bytes] "
,
datalen
);
if
(
skb_copy_bits
(
skb
,
iphoff
+
iph
.
ihl
*
4
,
&
esph
,
sizeof
(
esph
))
<
0
)
{
printk
(
"INCOMPLETE [%u bytes] "
,
skb
->
len
-
iphoff
-
iph
.
ihl
*
4
);
break
;
}
/* Length: 15 "SPI=0xF1234567 " */
printk
(
"SPI=0x%x "
,
ntohl
(
esph
->
spi
)
);
printk
(
"SPI=0x%x "
,
ntohl
(
esph
.
spi
)
);
break
;
}
/* Max length: 10 "PROTO 255 " */
default:
printk
(
"PROTO=%u "
,
iph
->
protocol
);
printk
(
"PROTO=%u "
,
iph
.
protocol
);
}
/* Proto Max log string length */
...
...
@@ -272,13 +300,12 @@ static void dump_packet(const struct ipt_log_info *info,
static
unsigned
int
ipt_log_target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
struct
iphdr
*
iph
=
(
*
pskb
)
->
nh
.
iph
;
const
struct
ipt_log_info
*
loginfo
=
targinfo
;
char
level_string
[
4
]
=
"< >"
;
...
...
@@ -304,7 +331,8 @@ ipt_log_target(struct sk_buff **pskb,
if
(
in
&&
!
out
)
{
/* MAC logging for input chain only. */
printk
(
"MAC="
);
if
((
*
pskb
)
->
dev
&&
(
*
pskb
)
->
dev
->
hard_header_len
&&
(
*
pskb
)
->
mac
.
raw
!=
(
void
*
)
iph
)
{
if
((
*
pskb
)
->
dev
&&
(
*
pskb
)
->
dev
->
hard_header_len
&&
(
*
pskb
)
->
mac
.
raw
!=
(
void
*
)(
*
pskb
)
->
nh
.
iph
)
{
int
i
;
unsigned
char
*
p
=
(
*
pskb
)
->
mac
.
raw
;
for
(
i
=
0
;
i
<
(
*
pskb
)
->
dev
->
hard_header_len
;
i
++
,
p
++
)
...
...
@@ -315,7 +343,7 @@ ipt_log_target(struct sk_buff **pskb,
printk
(
" "
);
}
dump_packet
(
loginfo
,
iph
,
(
*
pskb
)
->
len
,
1
);
dump_packet
(
loginfo
,
*
pskb
,
0
);
printk
(
"
\n
"
);
spin_unlock_bh
(
&
log_lock
);
...
...
net/ipv4/netfilter/ipt_MARK.c
View file @
73baeace
...
...
@@ -9,9 +9,9 @@
static
unsigned
int
target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
...
...
net/ipv4/netfilter/ipt_MASQUERADE.c
View file @
73baeace
...
...
@@ -57,9 +57,9 @@ masquerade_check(const char *tablename,
static
unsigned
int
masquerade_target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
...
...
net/ipv4/netfilter/ipt_MIRROR.c
View file @
73baeace
...
...
@@ -65,18 +65,22 @@ static int route_mirror(struct sk_buff *skb)
return
0
;
}
static
void
ip_rewrite
(
struct
sk_buff
*
skb
)
static
int
ip_rewrite
(
struct
sk_buff
**
pskb
)
{
struct
iphdr
*
iph
=
skb
->
nh
.
iph
;
u32
odaddr
=
iph
->
saddr
;
u32
osaddr
=
iph
->
daddr
;
u32
odaddr
,
osaddr
;
skb
->
nfcache
|=
NFC_ALTERED
;
if
(
!
skb_ip_make_writable
(
pskb
,
sizeof
(
struct
iphdr
)))
return
0
;
odaddr
=
(
*
pskb
)
->
nh
.
iph
->
saddr
;
osaddr
=
(
*
pskb
)
->
nh
.
iph
->
daddr
;
(
*
pskb
)
->
nfcache
|=
NFC_ALTERED
;
/* Rewrite IP header */
iph
->
daddr
=
odaddr
;
iph
->
saddr
=
osaddr
;
(
*
pskb
)
->
nh
.
iph
->
daddr
=
odaddr
;
(
*
pskb
)
->
nh
.
iph
->
saddr
=
osaddr
;
return
1
;
}
/* Stolen from ip_finish_output2 */
...
...
@@ -100,29 +104,28 @@ static void ip_direct_send(struct sk_buff *skb)
}
static
unsigned
int
ipt_mirror_target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
if
(((
*
pskb
)
->
dst
!=
NULL
)
&&
route_mirror
(
*
pskb
))
{
ip_rewrite
(
*
pskb
);
if
(((
*
pskb
)
->
dst
!=
NULL
)
&&
route_mirror
(
*
pskb
))
{
if
(
!
ip_rewrite
(
pskb
))
return
NF_DROP
;
/* If we are not at FORWARD hook (INPUT/PREROUTING),
* the TTL isn't decreased by the IP stack */
if
(
hooknum
!=
NF_IP_FORWARD
)
{
struct
iphdr
*
iph
=
(
*
pskb
)
->
nh
.
iph
;
if
(
iph
->
ttl
<=
1
)
{
if
((
*
pskb
)
->
nh
.
iph
->
ttl
<=
1
)
{
/* this will traverse normal stack, and
* thus call conntrack on the icmp packet */
icmp_send
(
*
pskb
,
ICMP_TIME_EXCEEDED
,
ICMP_EXC_TTL
,
0
);
return
NF_DROP
;
}
ip_decrease_ttl
(
iph
);
/* Made writable by ip_rewrite */
ip_decrease_ttl
((
*
pskb
)
->
nh
.
iph
);
}
/* Don't let conntrack code see this packet:
...
...
net/ipv4/netfilter/ipt_REDIRECT.c
View file @
73baeace
...
...
@@ -53,9 +53,9 @@ redirect_check(const char *tablename,
static
unsigned
int
redirect_target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
...
...
net/ipv4/netfilter/ipt_REJECT.c
View file @
73baeace
...
...
@@ -29,152 +29,140 @@ static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
void
(
*
attach
)(
struct
sk_buff
*
,
struct
nf_ct_info
*
);
/* Avoid module unload race with ip_ct_attach being NULLed out */
if
(
nfct
&&
(
attach
=
ip_ct_attach
)
!=
NULL
)
if
(
nfct
&&
(
attach
=
ip_ct_attach
)
!=
NULL
)
{
mb
();
/* Just to be sure: must be read before executing this */
attach
(
new_skb
,
nfct
);
}
}
/* Send RST reply */
static
void
send_reset
(
struct
sk_buff
*
old
skb
,
int
local
)
static
unsigned
int
send_reset
(
struct
sk_buff
**
p
skb
,
int
local
)
{
struct
sk_buff
*
nskb
;
struct
tcphdr
*
otcph
,
*
tcph
;
struct
tcphdr
tcph
;
struct
rtable
*
rt
;
unsigned
int
otcplen
;
u_int16_t
tmp_port
;
u_int32_t
tmp_addr
;
int
needs_ack
;
int
hh_len
;
int
needs_ack
,
hh_len
,
datalen
;
struct
nf_ct_info
*
oldnfct
;
/* IP header checks: fragment, too short. */
if
(
oldskb
->
nh
.
iph
->
frag_off
&
htons
(
IP_OFFSET
)
||
oldskb
->
len
<
(
oldskb
->
nh
.
iph
->
ihl
<<
2
)
+
sizeof
(
struct
tcphdr
))
return
;
/* No RSTs for fragments. */
if
((
*
pskb
)
->
nh
.
iph
->
frag_off
&
htons
(
IP_OFFSET
))
return
NF_DROP
;
otcph
=
(
struct
tcphdr
*
)((
u_int32_t
*
)
oldskb
->
nh
.
iph
+
oldskb
->
nh
.
iph
->
ihl
);
otcplen
=
oldskb
->
len
-
oldskb
->
nh
.
iph
->
ihl
*
4
;
if
(
skb_copy_bits
(
*
pskb
,
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
,
&
tcph
,
sizeof
(
tcph
))
<
0
)
return
NF_DROP
;
/* No RST for RST. */
if
(
otcph
->
rst
)
return
;
/* Check checksum. */
if
(
tcp_v4_check
(
otcph
,
otcplen
,
oldskb
->
nh
.
iph
->
saddr
,
oldskb
->
nh
.
iph
->
daddr
,
csum_partial
((
char
*
)
otcph
,
otcplen
,
0
))
!=
0
)
return
;
if
(
tcph
.
rst
)
return
NF_DROP
;
/* FIXME: Check checksum. */
{
struct
flowi
fl
=
{
.
nl_u
=
{
.
ip4_u
=
{
.
daddr
=
oldskb
->
nh
.
iph
->
saddr
,
{
.
daddr
=
(
*
pskb
)
->
nh
.
iph
->
saddr
,
.
saddr
=
(
local
?
oldskb
->
nh
.
iph
->
daddr
:
(
*
pskb
)
->
nh
.
iph
->
daddr
:
0
),
.
tos
=
RT_TOS
(
oldskb
->
nh
.
iph
->
tos
)
}
}
};
.
tos
=
RT_TOS
(
(
*
pskb
)
->
nh
.
iph
->
tos
)
}
}
};
/* Routing: if not headed for us, route won't like source */
if
(
ip_route_output_key
(
&
rt
,
&
fl
))
return
;
return
NF_DROP
;
hh_len
=
(
rt
->
u
.
dst
.
dev
->
hard_header_len
+
15
)
&~
15
;
}
/* Copy skb (even if skb is about to be dropped, we can't just
clone it because there may be other things, such as tcpdump,
interested in it). We also need to expand headroom in case
hh_len of incoming interface < hh_len of outgoing interface */
nskb
=
skb_copy_expand
(
oldskb
,
hh_len
,
skb_tailroom
(
oldskb
),
GFP_ATOMIC
);
if
(
!
nskb
)
{
dst_release
(
&
rt
->
u
.
dst
);
return
;
/* We're going to flip the header around, drop options and data. */
if
(
!
skb_ip_make_writable
(
pskb
,
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
+
sizeof
(
tcph
)))
{
ip_rt_put
(
rt
);
return
NF_DROP
;
}
dst_release
(
nskb
->
dst
);
nskb
->
dst
=
&
rt
->
u
.
dst
;
(
*
pskb
)
->
h
.
th
=
(
void
*
)(
*
pskb
)
->
nh
.
iph
+
sizeof
(
tcph
);
datalen
=
(
*
pskb
)
->
len
-
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
-
tcph
.
doff
*
4
;
/* Change over route. */
dst_release
((
*
pskb
)
->
dst
);
(
*
pskb
)
->
dst
=
&
rt
->
u
.
dst
;
/* This packet will not be the same as the other: clear nf fields */
nf_conntrack_put
(
nskb
->
nfct
);
nskb
->
nfct
=
NULL
;
nskb
->
nfcache
=
0
;
(
*
pskb
)
->
nfcache
=
0
;
#ifdef CONFIG_NETFILTER_DEBUG
nskb
->
nf_debug
=
0
;
(
*
pskb
)
->
nf_debug
=
0
;
#endif
nskb
->
nfmark
=
0
;
tcph
=
(
struct
tcphdr
*
)((
u_int32_t
*
)
nskb
->
nh
.
iph
+
nskb
->
nh
.
iph
->
ihl
);
(
*
pskb
)
->
nfmark
=
0
;
/* Swap source and dest */
tmp_addr
=
nskb
->
nh
.
iph
->
saddr
;
nskb
->
nh
.
iph
->
saddr
=
nskb
->
nh
.
iph
->
daddr
;
nskb
->
nh
.
iph
->
daddr
=
tmp_addr
;
tmp_port
=
tcp
h
->
source
;
tcph
->
source
=
tcp
h
->
dest
;
tcp
h
->
dest
=
tmp_port
;
tmp_addr
=
(
*
pskb
)
->
nh
.
iph
->
saddr
;
(
*
pskb
)
->
nh
.
iph
->
saddr
=
(
*
pskb
)
->
nh
.
iph
->
daddr
;
(
*
pskb
)
->
nh
.
iph
->
daddr
=
tmp_addr
;
tmp_port
=
(
*
pskb
)
->
h
.
t
h
->
source
;
(
*
pskb
)
->
h
.
th
->
source
=
(
*
pskb
)
->
h
.
t
h
->
dest
;
(
*
pskb
)
->
h
.
t
h
->
dest
=
tmp_port
;
/* Truncate to length (no data) */
tcp
h
->
doff
=
sizeof
(
struct
tcphdr
)
/
4
;
skb_trim
(
nskb
,
nskb
->
nh
.
iph
->
ihl
*
4
+
sizeof
(
struct
tcphdr
));
nskb
->
nh
.
iph
->
tot_len
=
htons
(
nskb
->
len
);
(
*
pskb
)
->
h
.
t
h
->
doff
=
sizeof
(
struct
tcphdr
)
/
4
;
skb_trim
(
*
pskb
,
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
+
sizeof
(
struct
tcphdr
));
(
*
pskb
)
->
nh
.
iph
->
tot_len
=
htons
((
*
pskb
)
->
len
);
if
(
tcp
h
->
ack
)
{
if
(
(
*
pskb
)
->
h
.
t
h
->
ack
)
{
needs_ack
=
0
;
tcph
->
seq
=
otcph
->
ack_seq
;
tcp
h
->
ack_seq
=
0
;
(
*
pskb
)
->
h
.
th
->
seq
=
tcph
.
ack_seq
;
(
*
pskb
)
->
h
.
t
h
->
ack_seq
=
0
;
}
else
{
needs_ack
=
1
;
tcph
->
ack_seq
=
htonl
(
ntohl
(
otcph
->
seq
)
+
otcph
->
syn
+
otcph
->
fin
+
otcplen
-
(
otcph
->
doff
<<
2
));
tcph
->
seq
=
0
;
(
*
pskb
)
->
h
.
th
->
ack_seq
=
htonl
(
ntohl
(
tcph
.
seq
)
+
tcph
.
syn
+
tcph
.
fin
+
datalen
);
(
*
pskb
)
->
h
.
th
->
seq
=
0
;
}
/* Reset flags */
((
u_int8_t
*
)
tcph
)[
13
]
=
0
;
tcp
h
->
rst
=
1
;
tcp
h
->
ack
=
needs_ack
;
memset
((
*
pskb
)
->
h
.
raw
+
13
,
0
,
1
)
;
(
*
pskb
)
->
h
.
t
h
->
rst
=
1
;
(
*
pskb
)
->
h
.
t
h
->
ack
=
needs_ack
;
tcp
h
->
window
=
0
;
tcp
h
->
urg_ptr
=
0
;
(
*
pskb
)
->
h
.
t
h
->
window
=
0
;
(
*
pskb
)
->
h
.
t
h
->
urg_ptr
=
0
;
/* Adjust TCP checksum */
tcph
->
check
=
0
;
tcph
->
check
=
tcp_v4_check
(
tcph
,
sizeof
(
struct
tcphdr
),
nskb
->
nh
.
iph
->
saddr
,
nskb
->
nh
.
iph
->
daddr
,
csum_partial
((
char
*
)
tcph
,
sizeof
(
struct
tcphdr
),
0
));
(
*
pskb
)
->
h
.
th
->
check
=
0
;
(
*
pskb
)
->
h
.
th
->
check
=
tcp_v4_check
((
*
pskb
)
->
h
.
th
,
sizeof
(
struct
tcphdr
),
(
*
pskb
)
->
nh
.
iph
->
saddr
,
(
*
pskb
)
->
nh
.
iph
->
daddr
,
csum_partial
((
*
pskb
)
->
h
.
raw
,
sizeof
(
struct
tcphdr
),
0
));
/* Adjust IP TTL, DF */
nskb
->
nh
.
iph
->
ttl
=
MAXTTL
;
(
*
pskb
)
->
nh
.
iph
->
ttl
=
MAXTTL
;
/* Set DF, id = 0 */
nskb
->
nh
.
iph
->
frag_off
=
htons
(
IP_DF
);
nskb
->
nh
.
iph
->
id
=
0
;
(
*
pskb
)
->
nh
.
iph
->
frag_off
=
htons
(
IP_DF
);
(
*
pskb
)
->
nh
.
iph
->
id
=
0
;
/* Adjust IP checksum */
nskb
->
nh
.
iph
->
check
=
0
;
nskb
->
nh
.
iph
->
check
=
ip_fast_csum
((
unsigned
char
*
)
nskb
->
nh
.
iph
,
nskb
->
nh
.
iph
->
ihl
);
(
*
pskb
)
->
nh
.
iph
->
check
=
0
;
(
*
pskb
)
->
nh
.
iph
->
check
=
ip_fast_csum
((
*
pskb
)
->
nh
.
raw
,
(
*
pskb
)
->
nh
.
iph
->
ihl
);
/* "Never happens" */
if
(
nskb
->
len
>
dst_pmtu
(
nskb
->
dst
))
goto
free_nskb
;
if
(
(
*
pskb
)
->
len
>
dst_pmtu
((
*
pskb
)
->
dst
))
return
NF_DROP
;
connection_attach
(
nskb
,
oldskb
->
nfct
);
/* Related to old connection. */
oldnfct
=
(
*
pskb
)
->
nfct
;
connection_attach
(
*
pskb
,
oldnfct
);
nf_conntrack_put
(
oldnfct
);
NF_HOOK
(
PF_INET
,
NF_IP_LOCAL_OUT
,
nskb
,
NULL
,
nskb
->
dst
->
dev
,
NF_HOOK
(
PF_INET
,
NF_IP_LOCAL_OUT
,
*
pskb
,
NULL
,
(
*
pskb
)
->
dst
->
dev
,
ip_finish_output
);
return
;
free_nskb:
kfree_skb
(
nskb
);
return
NF_STOLEN
;
}
static
void
send_unreach
(
struct
sk_buff
*
skb_in
,
int
code
)
static
void
send_unreach
(
const
struct
sk_buff
*
skb_in
,
int
code
)
{
struct
iphdr
*
iph
;
struct
udphdr
*
udph
;
struct
icmphdr
*
icmph
;
struct
sk_buff
*
nskb
;
u32
saddr
;
u8
tos
;
...
...
@@ -189,8 +177,6 @@ static void send_unreach(struct sk_buff *skb_in, int code)
if
(
!
xrlim_allow
(
&
rt
->
u
.
dst
,
1
*
HZ
))
return
;
iph
=
skb_in
->
nh
.
iph
;
/* No replies to physical multicast/broadcast */
if
(
skb_in
->
pkt_type
!=
PACKET_HOST
)
return
;
...
...
@@ -200,46 +186,41 @@ static void send_unreach(struct sk_buff *skb_in, int code)
return
;
/* Only reply to fragment 0. */
if
(
iph
->
frag_off
&
htons
(
IP_OFFSET
))
if
(
skb_in
->
nh
.
iph
->
frag_off
&
htons
(
IP_OFFSET
))
return
;
/* Ensure we have at least 8 bytes of proto header. */
if
(
skb_in
->
len
<
skb_in
->
nh
.
iph
->
ihl
*
4
+
8
)
return
;
/* if UDP checksum is set, verify it's correct */
if
(
iph
->
protocol
==
IPPROTO_UDP
&&
skb_in
->
tail
-
(
u8
*
)
iph
>=
sizeof
(
struct
udphdr
))
{
int
datalen
=
skb_in
->
len
-
(
iph
->
ihl
<<
2
);
udph
=
(
struct
udphdr
*
)((
char
*
)
iph
+
(
iph
->
ihl
<<
2
));
if
(
udph
->
check
&&
csum_tcpudp_magic
(
iph
->
saddr
,
iph
->
daddr
,
datalen
,
IPPROTO_UDP
,
csum_partial
((
char
*
)
udph
,
datalen
,
0
))
!=
0
)
return
;
}
/* If we send an ICMP error to an ICMP error a mess would result.. */
if
(
iph
->
protocol
==
IPPROTO_ICMP
&&
skb_in
->
tail
-
(
u8
*
)
iph
>=
sizeof
(
struct
icmphdr
))
{
icmph
=
(
struct
icmphdr
*
)((
char
*
)
iph
+
(
iph
->
ihl
<<
2
));
if
(
skb_in
->
nh
.
iph
->
protocol
==
IPPROTO_ICMP
)
{
struct
icmphdr
icmph
;
if
(
skb_copy_bits
(
skb_in
,
skb_in
->
nh
.
iph
->
ihl
*
4
,
&
icmph
,
sizeof
(
icmph
))
<
0
)
return
;
/* Between echo-reply (0) and timestamp (13),
everything except echo-request (8) is an error.
Also, anything greater than NR_ICMP_TYPES is
unknown, and hence should be treated as an error... */
if
((
icmph
->
type
<
ICMP_TIMESTAMP
&&
icmph
->
type
!=
ICMP_ECHOREPLY
&&
icmph
->
type
!=
ICMP_ECHO
)
||
icmph
->
type
>
NR_ICMP_TYPES
)
if
((
icmph
.
type
<
ICMP_TIMESTAMP
&&
icmph
.
type
!=
ICMP_ECHOREPLY
&&
icmph
.
type
!=
ICMP_ECHO
)
||
icmph
.
type
>
NR_ICMP_TYPES
)
return
;
}
saddr
=
iph
->
daddr
;
saddr
=
skb_in
->
nh
.
iph
->
daddr
;
if
(
!
(
rt
->
rt_flags
&
RTCF_LOCAL
))
saddr
=
0
;
tos
=
(
iph
->
tos
&
IPTOS_TOS_MASK
)
|
IPTOS_PREC_INTERNETCONTROL
;
tos
=
(
skb_in
->
nh
.
iph
->
tos
&
IPTOS_TOS_MASK
)
|
IPTOS_PREC_INTERNETCONTROL
;
{
struct
flowi
fl
=
{
.
nl_u
=
{
.
ip4_u
=
{
.
daddr
=
iph
->
saddr
,
{
.
daddr
=
skb_in
->
nh
.
iph
->
saddr
,
.
saddr
=
saddr
,
.
tos
=
RT_TOS
(
tos
)
}
}
};
if
(
ip_route_output_key
(
&
rt
,
&
fl
))
...
...
@@ -266,40 +247,38 @@ static void send_unreach(struct sk_buff *skb_in, int code)
skb_reserve
(
nskb
,
hh_len
);
/* Set up IP header */
iph
=
nskb
->
nh
.
iph
=
(
struct
iphdr
*
)
skb_put
(
nskb
,
sizeof
(
struct
iphdr
));
iph
->
version
=
4
;
iph
->
ihl
=
5
;
iph
->
tos
=
tos
;
iph
->
tot_len
=
htons
(
length
);
nskb
->
nh
.
iph
=
(
struct
iphdr
*
)
skb_put
(
nskb
,
sizeof
(
struct
iphdr
));
nskb
->
nh
.
iph
->
version
=
4
;
nskb
->
nh
.
iph
->
ihl
=
5
;
nskb
->
nh
.
iph
->
tos
=
tos
;
nskb
->
nh
.
iph
->
tot_len
=
htons
(
length
);
/* PMTU discovery never applies to ICMP packets. */
iph
->
frag_off
=
0
;
nskb
->
nh
.
iph
->
frag_off
=
0
;
iph
->
ttl
=
MAXTTL
;
ip_select_ident
(
iph
,
&
rt
->
u
.
dst
,
NULL
);
iph
->
protocol
=
IPPROTO_ICMP
;
iph
->
saddr
=
rt
->
rt_src
;
iph
->
daddr
=
rt
->
rt_dst
;
iph
->
check
=
0
;
iph
->
check
=
ip_fast_csum
((
unsigned
char
*
)
iph
,
iph
->
ihl
);
nskb
->
nh
.
iph
->
ttl
=
MAXTTL
;
ip_select_ident
(
nskb
->
nh
.
iph
,
&
rt
->
u
.
dst
,
NULL
);
nskb
->
nh
.
iph
->
protocol
=
IPPROTO_ICMP
;
nskb
->
nh
.
iph
->
saddr
=
rt
->
rt_src
;
nskb
->
nh
.
iph
->
daddr
=
rt
->
rt_dst
;
nskb
->
nh
.
iph
->
check
=
0
;
nskb
->
nh
.
iph
->
check
=
ip_fast_csum
(
nskb
->
nh
.
raw
,
nskb
->
nh
.
iph
->
ihl
);
/* Set up ICMP header. */
icmph
=
nskb
->
h
.
icmph
=
(
struct
icmphdr
*
)
skb_put
(
nskb
,
sizeof
(
struct
icmphdr
));
icmph
->
type
=
ICMP_DEST_UNREACH
;
icmph
->
code
=
code
;
icmph
->
un
.
gateway
=
0
;
icmph
->
checksum
=
0
;
nskb
->
h
.
icmph
=
(
struct
icmphdr
*
)
skb_put
(
nskb
,
sizeof
(
struct
icmphdr
));
nskb
->
h
.
icmph
->
type
=
ICMP_DEST_UNREACH
;
nskb
->
h
.
icmph
->
code
=
code
;
nskb
->
h
.
icmph
->
un
.
gateway
=
0
;
nskb
->
h
.
icmph
->
checksum
=
0
;
/* Copy as much of original packet as will fit */
data
=
skb_put
(
nskb
,
length
-
sizeof
(
struct
iphdr
)
-
sizeof
(
struct
icmphdr
));
/* FIXME: won't work with nonlinear skbs --RR */
memcpy
(
data
,
skb_in
->
nh
.
iph
,
length
-
sizeof
(
struct
iphdr
)
-
sizeof
(
struct
icmphdr
));
icmph
->
checksum
=
ip_compute_csum
((
unsigned
char
*
)
icmph
,
length
-
sizeof
(
struct
iphdr
));
skb_copy_bits
(
skb_in
,
0
,
data
,
length
-
sizeof
(
struct
iphdr
)
-
sizeof
(
struct
icmphdr
));
nskb
->
h
.
icmph
->
checksum
=
ip_compute_csum
(
nskb
->
h
.
raw
,
length
-
sizeof
(
struct
iphdr
));
connection_attach
(
nskb
,
skb_in
->
nfct
);
...
...
@@ -308,9 +287,9 @@ static void send_unreach(struct sk_buff *skb_in, int code)
}
static
unsigned
int
reject
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
...
...
@@ -344,7 +323,7 @@ static unsigned int reject(struct sk_buff **pskb,
send_unreach
(
*
pskb
,
ICMP_HOST_ANO
);
break
;
case
IPT_TCP_RESET
:
send_reset
(
*
pskb
,
hooknum
==
NF_IP_LOCAL_IN
);
return
send_reset
(
pskb
,
hooknum
==
NF_IP_LOCAL_IN
);
case
IPT_ICMP_ECHOREPLY
:
/* Doesn't happen. */
break
;
...
...
net/ipv4/netfilter/ipt_TCPMSS.c
View file @
73baeace
...
...
@@ -36,9 +36,9 @@ optlen(const u_int8_t *opt, unsigned int offset)
static
unsigned
int
ipt_tcpmss_target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
...
...
@@ -49,15 +49,8 @@ ipt_tcpmss_target(struct sk_buff **pskb,
unsigned
int
i
;
u_int8_t
*
opt
;
/* raw socket (tcpdump) may have clone of incoming skb: don't
disturb it --RR */
if
(
skb_cloned
(
*
pskb
)
&&
!
(
*
pskb
)
->
sk
)
{
struct
sk_buff
*
nskb
=
skb_copy
(
*
pskb
,
GFP_ATOMIC
);
if
(
!
nskb
)
return
NF_DROP
;
kfree_skb
(
*
pskb
);
*
pskb
=
nskb
;
}
if
(
!
skb_ip_make_writable
(
pskb
,
(
*
pskb
)
->
len
))
return
NF_DROP
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
tcplen
=
(
*
pskb
)
->
len
-
iph
->
ihl
*
4
;
...
...
net/ipv4/netfilter/ipt_TOS.c
View file @
73baeace
...
...
@@ -9,35 +9,30 @@
static
unsigned
int
target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
struct
iphdr
*
iph
=
(
*
pskb
)
->
nh
.
iph
;
const
struct
ipt_tos_target_info
*
tosinfo
=
targinfo
;
if
((
iph
->
tos
&
IPTOS_TOS_MASK
)
!=
tosinfo
->
tos
)
{
if
((
(
*
pskb
)
->
nh
.
iph
->
tos
&
IPTOS_TOS_MASK
)
!=
tosinfo
->
tos
)
{
u_int16_t
diffs
[
2
];
/* raw socket (tcpdump) may have clone of incoming
skb: don't disturb it --RR */
if
(
skb_cloned
(
*
pskb
)
&&
!
(
*
pskb
)
->
sk
)
{
struct
sk_buff
*
nskb
=
skb_copy
(
*
pskb
,
GFP_ATOMIC
);
if
(
!
nskb
)
return
NF_DROP
;
kfree_skb
(
*
pskb
);
*
pskb
=
nskb
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
}
if
(
!
skb_ip_make_writable
(
pskb
,
sizeof
(
struct
iphdr
)))
return
NF_DROP
;
diffs
[
0
]
=
htons
(
iph
->
tos
)
^
0xFFFF
;
iph
->
tos
=
(
iph
->
tos
&
IPTOS_PREC_MASK
)
|
tosinfo
->
tos
;
diffs
[
1
]
=
htons
(
iph
->
tos
);
iph
->
check
=
csum_fold
(
csum_partial
((
char
*
)
diffs
,
sizeof
(
diffs
),
iph
->
check
^
0xFFFF
));
diffs
[
0
]
=
htons
((
*
pskb
)
->
nh
.
iph
->
tos
)
^
0xFFFF
;
(
*
pskb
)
->
nh
.
iph
->
tos
=
((
*
pskb
)
->
nh
.
iph
->
tos
&
IPTOS_PREC_MASK
)
|
tosinfo
->
tos
;
diffs
[
1
]
=
htons
((
*
pskb
)
->
nh
.
iph
->
tos
);
(
*
pskb
)
->
nh
.
iph
->
check
=
csum_fold
(
csum_partial
((
char
*
)
diffs
,
sizeof
(
diffs
),
(
*
pskb
)
->
nh
.
iph
->
check
^
0xFFFF
));
(
*
pskb
)
->
nfcache
|=
NFC_ALTERED
;
}
return
IPT_CONTINUE
;
...
...
net/ipv4/netfilter/ipt_ULOG.c
View file @
73baeace
...
...
@@ -155,9 +155,9 @@ struct sk_buff *ulog_alloc_skb(unsigned int size)
}
static
unsigned
int
ipt_ulog_target
(
struct
sk_buff
**
pskb
,
unsigned
int
hooknum
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
unsigned
int
hooknum
,
const
void
*
targinfo
,
void
*
userinfo
)
{
ulog_buff_t
*
ub
;
...
...
@@ -238,8 +238,9 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
else
pm
->
outdev_name
[
0
]
=
'\0'
;
if
(
copy_len
)
memcpy
(
pm
->
payload
,
(
*
pskb
)
->
data
,
copy_len
);
/* copy_len <= (*pskb)->len, so can't fail. */
if
(
skb_copy_bits
(
*
pskb
,
0
,
pm
->
payload
,
copy_len
)
<
0
)
BUG
();
/* check if we are building multi-part messages */
if
(
ub
->
qlen
>
1
)
{
...
...
net/ipv4/netfilter/ipt_ah.c
View file @
73baeace
...
...
@@ -35,14 +35,16 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ahhdr
*
ah
=
hdr
;
struct
ahhdr
ah
;
const
struct
ipt_ah
*
ahinfo
=
matchinfo
;
if
(
offset
==
0
&&
datalen
<
sizeof
(
struct
ahhdr
))
{
/* Must not be a fragment. */
if
(
offset
)
return
0
;
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
,
&
ah
,
sizeof
(
ah
))
<
0
)
{
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf
(
"Dropping evil AH tinygram.
\n
"
);
...
...
@@ -50,11 +52,9 @@ match(const struct sk_buff *skb,
return
0
;
}
/* Must not be a fragment. */
return
!
offset
&&
spi_match
(
ahinfo
->
spis
[
0
],
ahinfo
->
spis
[
1
],
ntohl
(
ah
->
spi
),
!!
(
ahinfo
->
invflags
&
IPT_AH_INV_SPI
));
return
spi_match
(
ahinfo
->
spis
[
0
],
ahinfo
->
spis
[
1
],
ntohl
(
ah
.
spi
),
!!
(
ahinfo
->
invflags
&
IPT_AH_INV_SPI
));
}
/* Called when user tries to insert an entry of this type. */
...
...
net/ipv4/netfilter/ipt_conntrack.c
View file @
73baeace
...
...
@@ -14,8 +14,6 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_conntrack_info
*
sinfo
=
matchinfo
;
...
...
net/ipv4/netfilter/ipt_dscp.c
View file @
73baeace
...
...
@@ -19,8 +19,7 @@ MODULE_LICENSE("GPL");
static
int
match
(
const
struct
sk_buff
*
skb
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
int
offset
,
int
*
hotdrop
)
{
const
struct
ipt_dscp_info
*
info
=
matchinfo
;
const
struct
iphdr
*
iph
=
skb
->
nh
.
iph
;
...
...
net/ipv4/netfilter/ipt_ecn.c
View file @
73baeace
...
...
@@ -19,34 +19,40 @@ MODULE_DESCRIPTION("IP tables ECN matching module");
MODULE_LICENSE
(
"GPL"
);
static
inline
int
match_ip
(
const
struct
sk_buff
*
skb
,
const
struct
iphdr
*
iph
,
const
struct
ipt_ecn_info
*
einfo
)
{
return
((
iph
->
tos
&
IPT_ECN_IP_MASK
)
==
einfo
->
ip_ect
);
return
((
skb
->
nh
.
iph
->
tos
&
IPT_ECN_IP_MASK
)
==
einfo
->
ip_ect
);
}
static
inline
int
match_tcp
(
const
struct
sk_buff
*
skb
,
const
struct
ip
hdr
*
iph
,
const
struct
ipt_ecn_info
*
einfo
)
const
struct
ip
t_ecn_info
*
einfo
,
int
*
hotdrop
)
{
struct
tcphdr
*
tcph
=
(
void
*
)
iph
+
iph
->
ihl
*
4
;
struct
tcphdr
tcph
;
/* In practice, TCP match does this, so can't fail. But let's
be good citizens. */
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
,
&
tcph
,
sizeof
(
tcph
))
<
0
)
{
*
hotdrop
=
0
;
return
0
;
}
if
(
einfo
->
operation
&
IPT_ECN_OP_MATCH_ECE
)
{
if
(
einfo
->
invert
&
IPT_ECN_OP_MATCH_ECE
)
{
if
(
tcph
->
ece
==
1
)
if
(
tcph
.
ece
==
1
)
return
0
;
}
else
{
if
(
tcph
->
ece
==
0
)
if
(
tcph
.
ece
==
0
)
return
0
;
}
}
if
(
einfo
->
operation
&
IPT_ECN_OP_MATCH_CWR
)
{
if
(
einfo
->
invert
&
IPT_ECN_OP_MATCH_CWR
)
{
if
(
tcph
->
cwr
==
1
)
if
(
tcph
.
cwr
==
1
)
return
0
;
}
else
{
if
(
tcph
->
cwr
==
0
)
if
(
tcph
.
cwr
==
0
)
return
0
;
}
}
...
...
@@ -56,20 +62,18 @@ static inline int match_tcp(const struct sk_buff *skb,
static
int
match
(
const
struct
sk_buff
*
skb
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
int
offset
,
int
*
hotdrop
)
{
const
struct
ipt_ecn_info
*
info
=
matchinfo
;
const
struct
iphdr
*
iph
=
skb
->
nh
.
iph
;
if
(
info
->
operation
&
IPT_ECN_OP_MATCH_IP
)
if
(
!
match_ip
(
skb
,
i
ph
,
i
nfo
))
if
(
!
match_ip
(
skb
,
info
))
return
0
;
if
(
info
->
operation
&
(
IPT_ECN_OP_MATCH_ECE
|
IPT_ECN_OP_MATCH_CWR
))
{
if
(
iph
->
protocol
!=
IPPROTO_TCP
)
if
(
skb
->
nh
.
iph
->
protocol
!=
IPPROTO_TCP
)
return
0
;
if
(
!
match_tcp
(
skb
,
i
ph
,
info
))
if
(
!
match_tcp
(
skb
,
i
nfo
,
hotdrop
))
return
0
;
}
...
...
net/ipv4/netfilter/ipt_esp.c
View file @
73baeace
...
...
@@ -35,14 +35,16 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
esphdr
*
esp
=
hdr
;
struct
esphdr
esp
;
const
struct
ipt_esp
*
espinfo
=
matchinfo
;
if
(
offset
==
0
&&
datalen
<
sizeof
(
struct
esphdr
))
{
/* Must not be a fragment. */
if
(
offset
)
return
0
;
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
,
&
esp
,
sizeof
(
esp
))
<
0
)
{
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf
(
"Dropping evil ESP tinygram.
\n
"
);
...
...
@@ -50,11 +52,9 @@ match(const struct sk_buff *skb,
return
0
;
}
/* Must not be a fragment. */
return
!
offset
&&
spi_match
(
espinfo
->
spis
[
0
],
espinfo
->
spis
[
1
],
ntohl
(
esp
->
spi
),
!!
(
espinfo
->
invflags
&
IPT_ESP_INV_SPI
));
return
spi_match
(
espinfo
->
spis
[
0
],
espinfo
->
spis
[
1
],
ntohl
(
esp
.
spi
),
!!
(
espinfo
->
invflags
&
IPT_ESP_INV_SPI
));
}
/* Called when user tries to insert an entry of this type. */
...
...
net/ipv4/netfilter/ipt_helper.c
View file @
73baeace
...
...
@@ -28,8 +28,6 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_helper_info
*
info
=
matchinfo
;
...
...
net/ipv4/netfilter/ipt_length.c
View file @
73baeace
...
...
@@ -15,8 +15,6 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_length_info
*
info
=
matchinfo
;
...
...
net/ipv4/netfilter/ipt_limit.c
View file @
73baeace
...
...
@@ -47,8 +47,6 @@ ipt_limit_match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
struct
ipt_rateinfo
*
r
=
((
struct
ipt_rateinfo
*
)
matchinfo
)
->
master
;
...
...
net/ipv4/netfilter/ipt_mac.c
View file @
73baeace
...
...
@@ -12,8 +12,6 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_mac_info
*
info
=
matchinfo
;
...
...
net/ipv4/netfilter/ipt_mark.c
View file @
73baeace
...
...
@@ -11,8 +11,6 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_mark_info
*
info
=
matchinfo
;
...
...
net/ipv4/netfilter/ipt_multiport.c
View file @
73baeace
...
...
@@ -39,15 +39,18 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
udphdr
*
udp
=
hdr
;
u16
ports
[
2
]
;
const
struct
ipt_multiport
*
multiinfo
=
matchinfo
;
/* Must be big enough to read ports. */
if
(
offset
==
0
&&
datalen
<
sizeof
(
struct
udphdr
))
{
/* Must not be a fragment. */
if
(
offset
)
return
0
;
/* Must be big enough to read ports (both UDP and TCP have
them at the start). */
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
,
ports
,
sizeof
(
ports
))
<
0
)
{
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf
(
"ipt_multiport:"
...
...
@@ -56,11 +59,9 @@ match(const struct sk_buff *skb,
return
0
;
}
/* Must not be a fragment. */
return
!
offset
&&
ports_match
(
multiinfo
->
ports
,
multiinfo
->
flags
,
multiinfo
->
count
,
ntohs
(
udp
->
source
),
ntohs
(
udp
->
dest
));
return
ports_match
(
multiinfo
->
ports
,
multiinfo
->
flags
,
multiinfo
->
count
,
ntohs
(
ports
[
0
]),
ntohs
(
ports
[
1
]));
}
/* Called when user tries to insert an entry of this type. */
...
...
net/ipv4/netfilter/ipt_owner.c
View file @
73baeace
...
...
@@ -115,8 +115,6 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_owner_info
*
info
=
matchinfo
;
...
...
@@ -170,8 +168,11 @@ checkentry(const char *tablename,
return
0
;
}
if
(
matchsize
!=
IPT_ALIGN
(
sizeof
(
struct
ipt_owner_info
)))
if
(
matchsize
!=
IPT_ALIGN
(
sizeof
(
struct
ipt_owner_info
)))
{
printk
(
"Matchsize %u != %Zu
\n
"
,
matchsize
,
IPT_ALIGN
(
sizeof
(
struct
ipt_owner_info
)));
return
0
;
}
return
1
;
}
...
...
net/ipv4/netfilter/ipt_physdev.c
View file @
73baeace
...
...
@@ -14,8 +14,6 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
int
i
;
...
...
net/ipv4/netfilter/ipt_pkttype.c
View file @
73baeace
...
...
@@ -13,8 +13,6 @@ static int match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_pkttype_info
*
info
=
matchinfo
;
...
...
net/ipv4/netfilter/ipt_state.c
View file @
73baeace
...
...
@@ -13,8 +13,6 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_state_info
*
sinfo
=
matchinfo
;
...
...
net/ipv4/netfilter/ipt_tcpmss.c
View file @
73baeace
...
...
@@ -11,24 +11,32 @@
/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */
static
inline
int
mssoption_match
(
u_int16_t
min
,
u_int16_t
max
,
const
struct
tcphdr
*
tcp
,
u_int16_t
datalen
,
const
struct
sk_buff
*
skb
,
int
invert
,
int
*
hotdrop
)
{
unsigned
int
i
;
const
u_int8_t
*
opt
=
(
u_int8_t
*
)
tcp
;
struct
tcphdr
tcph
;
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
u8
opt
[
15
*
4
-
sizeof
(
tcph
)];
unsigned
int
i
,
optlen
;
/* If we don't have the whole header, drop packet. */
if
(
tcp
->
doff
*
4
>
datalen
)
{
*
hotdrop
=
1
;
return
0
;
}
for
(
i
=
sizeof
(
struct
tcphdr
);
i
<
tcp
->
doff
*
4
;
)
{
if
((
opt
[
i
]
==
TCPOPT_MSS
)
&&
((
tcp
->
doff
*
4
-
i
)
>=
TCPOLEN_MSS
)
&&
(
opt
[
i
+
1
]
==
TCPOLEN_MSS
))
{
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
,
&
tcph
,
sizeof
(
tcph
))
<
0
)
goto
dropit
;
/* Malformed. */
if
(
tcph
.
doff
*
4
<
sizeof
(
tcph
))
goto
dropit
;
optlen
=
tcph
.
doff
*
4
-
sizeof
(
tcph
);
/* Truncated options. */
if
(
skb_copy_bits
(
skb
,
skb
->
nh
.
iph
->
ihl
*
4
+
sizeof
(
tcph
),
opt
,
optlen
)
<
0
)
goto
dropit
;
for
(
i
=
0
;
i
<
optlen
;
)
{
if
(
opt
[
i
]
==
TCPOPT_MSS
&&
(
optlen
-
i
)
>=
TCPOLEN_MSS
&&
opt
[
i
+
1
]
==
TCPOLEN_MSS
)
{
u_int16_t
mssval
;
mssval
=
(
opt
[
i
+
2
]
<<
8
)
|
opt
[
i
+
3
];
...
...
@@ -38,8 +46,11 @@ mssoption_match(u_int16_t min, u_int16_t max,
if
(
opt
[
i
]
<
2
)
i
++
;
else
i
+=
opt
[
i
+
1
]
?:
1
;
}
return
invert
;
dropit:
*
hotdrop
=
1
;
return
0
;
}
static
int
...
...
@@ -48,15 +59,11 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_tcpmss_match_info
*
info
=
matchinfo
;
const
struct
tcphdr
*
tcph
=
(
void
*
)
skb
->
nh
.
iph
+
skb
->
nh
.
iph
->
ihl
*
4
;
return
mssoption_match
(
info
->
mss_min
,
info
->
mss_max
,
tcph
,
skb
->
len
-
skb
->
nh
.
iph
->
ihl
*
4
,
return
mssoption_match
(
info
->
mss_min
,
info
->
mss_max
,
skb
,
info
->
invert
,
hotdrop
);
}
...
...
net/ipv4/netfilter/ipt_tos.c
View file @
73baeace
...
...
@@ -11,14 +11,11 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
const
struct
ipt_tos_info
*
info
=
matchinfo
;
const
struct
iphdr
*
iph
=
skb
->
nh
.
iph
;
return
(
iph
->
tos
==
info
->
tos
)
^
info
->
invert
;
return
(
skb
->
nh
.
iph
->
tos
==
info
->
tos
)
^
info
->
invert
;
}
static
int
...
...
net/ipv4/netfilter/ipt_ttl.c
View file @
73baeace
...
...
@@ -19,24 +19,22 @@ MODULE_LICENSE("GPL");
static
int
match
(
const
struct
sk_buff
*
skb
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
int
offset
,
int
*
hotdrop
)
{
const
struct
ipt_ttl_info
*
info
=
matchinfo
;
const
struct
iphdr
*
iph
=
skb
->
nh
.
iph
;
switch
(
info
->
mode
)
{
case
IPT_TTL_EQ
:
return
(
iph
->
ttl
==
info
->
ttl
);
return
(
skb
->
nh
.
iph
->
ttl
==
info
->
ttl
);
break
;
case
IPT_TTL_NE
:
return
(
!
(
iph
->
ttl
==
info
->
ttl
));
return
(
!
(
skb
->
nh
.
iph
->
ttl
==
info
->
ttl
));
break
;
case
IPT_TTL_LT
:
return
(
iph
->
ttl
<
info
->
ttl
);
return
(
skb
->
nh
.
iph
->
ttl
<
info
->
ttl
);
break
;
case
IPT_TTL_GT
:
return
(
iph
->
ttl
>
info
->
ttl
);
return
(
skb
->
nh
.
iph
->
ttl
>
info
->
ttl
);
break
;
default:
printk
(
KERN_WARNING
"ipt_ttl: unknown mode %d
\n
"
,
...
...
net/ipv4/netfilter/ipt_unclean.c
View file @
73baeace
...
...
@@ -31,16 +31,17 @@ struct icmp_info
};
static
int
check_ip
(
struct
iphdr
*
iph
,
size_t
length
,
int
embedded
);
check_ip
(
const
struct
sk_buff
*
skb
,
unsigned
int
offset
);
/* ICMP-specific checks. */
static
int
check_icmp
(
const
struct
icmphdr
*
icmph
,
u_int16_t
datalen
,
check_icmp
(
const
struct
sk_buff
*
skb
,
unsigned
int
offset
,
unsigned
int
fragoff
,
int
more_frags
,
int
embedded
)
{
struct
icmphdr
icmph
;
static
struct
icmp_info
info
[]
=
{
[
ICMP_ECHOREPLY
]
=
{
8
,
65536
,
ICMP_NOT_ERROR
,
0
,
0
},
...
...
@@ -76,92 +77,95 @@ check_icmp(const struct icmphdr *icmph,
=
{
12
,
12
,
ICMP_NOT_ERROR
,
0
,
0
}
};
/* Can't do anything if it's a fragment. */
if
(
offset
)
if
(
fragoff
)
return
1
;
/*
Must cover type and code
. */
if
(
datalen
<
2
)
{
limpk
(
"ICMP len=%u too short
\n
"
,
datalen
);
/*
CHECK: Must have whole header.
. */
if
(
skb_copy_bits
(
skb
,
offset
,
&
icmph
,
sizeof
(
icmph
))
<
0
)
{
limpk
(
"ICMP len=%u too short
\n
"
,
skb
->
len
-
offset
);
return
0
;
}
/* If not embedded. */
/* If not embedded
in an ICMP error already
. */
if
(
!
embedded
)
{
/* Bad checksum? Don't print, just ignore. */
if
(
!
more_frags
&&
ip_compute_csum
((
unsigned
char
*
)
icmph
,
datalen
)
!=
0
)
return
0
;
/* CHECK: Truncated ICMP (even if first fragment). */
if
(
icmph
->
type
<
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
&&
info
[
icmph
->
type
].
min_len
!=
0
&&
datalen
<
info
[
icmph
->
type
].
min_len
)
{
if
(
icmph
.
type
<
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
&&
info
[
icmph
.
type
].
min_len
!=
0
&&
skb
->
len
-
offset
<
info
[
icmph
.
type
].
min_len
)
{
limpk
(
"ICMP type %u len %u too short
\n
"
,
icmph
->
type
,
datalen
);
icmph
.
type
,
skb
->
len
-
offset
);
return
0
;
}
/* CHECK: Check within known error ICMPs. */
if
(
icmph
->
type
<
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
&&
info
[
icmph
->
type
].
err
==
ICMP_IS_ERROR
)
{
if
(
icmph
.
type
<
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
&&
info
[
icmph
.
type
].
err
==
ICMP_IS_ERROR
)
{
/* Max IP header size = 60 */
char
inner
[
60
+
8
];
struct
iphdr
*
inner_ip
=
(
struct
iphdr
*
)
inner
;
/* CHECK: Embedded packet must be at least
length of iph + 8 bytes. */
struct
iphdr
*
inner
=
(
void
*
)
icmph
+
8
;
/* datalen > 8 since all ICMP_IS_ERROR types
have min length > 8 */
if
(
datalen
-
8
<
sizeof
(
struct
iphdr
))
{
if
(
skb_copy_bits
(
skb
,
offset
+
sizeof
(
icmph
),
inner
,
sizeof
(
struct
iphdr
)
+
8
)
<
0
)
{
limpk
(
"ICMP error internal way too short
\n
"
);
return
0
;
}
if
(
datalen
-
8
<
inner
->
ihl
*
4
+
8
)
{
/* iphhdr may actually be longer: still need 8
actual protocol bytes. */
if
(
offset
+
sizeof
(
icmph
)
+
inner_ip
->
ihl
*
4
+
8
>
skb
->
len
)
{
limpk
(
"ICMP error internal too short
\n
"
);
return
0
;
}
if
(
!
check_ip
(
inner
,
datalen
-
8
,
1
))
if
(
!
check_ip
(
skb
,
offset
+
sizeof
(
icmph
)
))
return
0
;
}
}
else
{
/* CHECK: Can't embed ICMP unless known non-error. */
if
(
icmph
->
type
>=
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
||
info
[
icmph
->
type
].
err
!=
ICMP_NOT_ERROR
)
{
if
(
icmph
.
type
>=
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
||
info
[
icmph
.
type
].
err
!=
ICMP_NOT_ERROR
)
{
limpk
(
"ICMP type %u not embeddable
\n
"
,
icmph
->
type
);
icmph
.
type
);
return
0
;
}
}
/* CHECK: Invalid ICMP codes. */
if
(
icmph
->
type
<
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
&&
(
icmph
->
code
<
info
[
icmph
->
type
].
min_code
||
icmph
->
code
>
info
[
icmph
->
type
].
max_code
))
{
if
(
icmph
.
type
<
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
&&
(
icmph
.
code
<
info
[
icmph
.
type
].
min_code
||
icmph
.
code
>
info
[
icmph
.
type
].
max_code
))
{
limpk
(
"ICMP type=%u code=%u
\n
"
,
icmph
->
type
,
icmph
->
code
);
icmph
.
type
,
icmph
.
code
);
return
0
;
}
/* CHECK: Above maximum length. */
if
(
icmph
->
type
<
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
&&
info
[
icmph
->
type
].
max_len
!=
0
&&
datalen
>
info
[
icmph
->
type
].
max_len
)
{
if
(
icmph
.
type
<
sizeof
(
info
)
/
sizeof
(
struct
icmp_info
)
&&
info
[
icmph
.
type
].
max_len
!=
0
&&
skb
->
len
-
offset
>
info
[
icmph
.
type
].
max_len
)
{
limpk
(
"ICMP type=%u too long: %u bytes
\n
"
,
icmph
->
type
,
datalen
);
icmph
.
type
,
skb
->
len
-
offset
);
return
0
;
}
switch
(
icmph
->
type
)
{
switch
(
icmph
.
type
)
{
case
ICMP_PARAMETERPROB
:
{
/* CHECK: Problem param must be within error packet's
* IP header. */
struct
iphdr
*
iph
=
(
void
*
)
icmph
+
8
;
u_int32_t
arg
=
ntohl
(
icmph
->
un
.
gateway
);
u_int32_t
arg
=
ntohl
(
icmph
.
un
.
gateway
);
if
(
icmph
->
code
==
0
)
{
if
(
icmph
.
code
==
0
)
{
/* We've already made sure it's long enough. */
struct
iphdr
iph
;
skb_copy_bits
(
skb
,
offset
+
sizeof
(
icmph
),
&
iph
,
sizeof
(
iph
));
/* Code 0 means that upper 8 bits is pointer
to problem. */
if
((
arg
>>
24
)
>=
iph
->
ihl
*
4
)
{
if
((
arg
>>
24
)
>=
iph
.
ihl
*
4
)
{
limpk
(
"ICMP PARAMETERPROB ptr = %u
\n
"
,
ntohl
(
icmph
->
un
.
gateway
)
>>
24
);
ntohl
(
icmph
.
un
.
gateway
)
>>
24
);
return
0
;
}
arg
&=
0x00FFFFFF
;
...
...
@@ -179,9 +183,9 @@ check_icmp(const struct icmphdr *icmph,
case
ICMP_TIME_EXCEEDED
:
case
ICMP_SOURCE_QUENCH
:
/* CHECK: Unused must be zero. */
if
(
icmph
->
un
.
gateway
!=
0
)
{
if
(
icmph
.
un
.
gateway
!=
0
)
{
limpk
(
"ICMP type=%u unused = %u
\n
"
,
icmph
->
type
,
ntohl
(
icmph
->
un
.
gateway
));
icmph
.
type
,
ntohl
(
icmph
.
un
.
gateway
));
return
0
;
}
break
;
...
...
@@ -192,32 +196,26 @@ check_icmp(const struct icmphdr *icmph,
/* UDP-specific checks. */
static
int
check_udp
(
const
struct
iphdr
*
iph
,
const
struct
udphdr
*
udph
,
u_int16_t
datalen
,
check_udp
(
const
struct
sk_buff
*
skb
,
unsigned
int
offset
,
unsigned
int
fragoff
,
int
more_frags
,
int
embedded
)
{
struct
udphdr
udph
;
/* Can't do anything if it's a fragment. */
if
(
offset
)
if
(
fragoff
)
return
1
;
/* CHECK: Must cover UDP header. */
if
(
datalen
<
sizeof
(
struct
udphdr
)
)
{
limpk
(
"UDP len=%u too short
\n
"
,
datalen
);
if
(
skb_copy_bits
(
skb
,
offset
,
&
udph
,
sizeof
(
udph
))
<
0
)
{
limpk
(
"UDP len=%u too short
\n
"
,
skb
->
len
-
offset
);
return
0
;
}
/* Bad checksum? Don't print, just say it's unclean. */
/* FIXME: SRC ROUTE packets won't match checksum --RR */
if
(
!
more_frags
&&
!
embedded
&&
udph
->
check
&&
csum_tcpudp_magic
(
iph
->
saddr
,
iph
->
daddr
,
datalen
,
IPPROTO_UDP
,
csum_partial
((
char
*
)
udph
,
datalen
,
0
))
!=
0
)
return
0
;
/* CHECK: Destination port can't be zero. */
if
(
!
udph
->
dest
)
{
if
(
!
udph
.
dest
)
{
limpk
(
"UDP zero destination port
\n
"
);
return
0
;
}
...
...
@@ -225,24 +223,24 @@ check_udp(const struct iphdr *iph,
if
(
!
more_frags
)
{
if
(
!
embedded
)
{
/* CHECK: UDP length must match. */
if
(
ntohs
(
udph
->
len
)
!=
datalen
)
{
if
(
ntohs
(
udph
.
len
)
!=
skb
->
len
-
offset
)
{
limpk
(
"UDP len too short %u vs %u
\n
"
,
ntohs
(
udph
->
len
),
datalen
);
ntohs
(
udph
.
len
),
skb
->
len
-
offset
);
return
0
;
}
}
else
{
/* CHECK: UDP length be >= this truncated pkt. */
if
(
ntohs
(
udph
->
len
)
<
datalen
)
{
if
(
ntohs
(
udph
.
len
)
<
skb
->
len
-
offset
)
{
limpk
(
"UDP len too long %u vs %u
\n
"
,
ntohs
(
udph
->
len
),
datalen
);
ntohs
(
udph
.
len
),
skb
->
len
-
offset
);
return
0
;
}
}
}
else
{
/* CHECK: UDP length must be > this frag's length. */
if
(
ntohs
(
udph
->
len
)
<=
datalen
)
{
if
(
ntohs
(
udph
.
len
)
<=
skb
->
len
-
offset
)
{
limpk
(
"UDP fragment len too short %u vs %u
\n
"
,
ntohs
(
udph
->
len
),
datalen
);
ntohs
(
udph
.
len
),
skb
->
len
-
offset
);
return
0
;
}
}
...
...
@@ -250,104 +248,104 @@ check_udp(const struct iphdr *iph,
return
1
;
}
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
/* TCP-specific checks. */
static
int
check_tcp
(
const
struct
iphdr
*
iph
,
const
struct
tcphdr
*
tcph
,
u_int16_t
datalen
,
check_tcp
(
const
struct
sk_buff
*
skb
,
unsigned
int
offset
,
unsigned
int
fragoff
,
int
more_frags
,
int
embedded
)
{
u_int8_t
*
opt
=
(
u_int8_t
*
)
tcph
;
u
_int8_t
*
endhdr
=
(
u_int8_t
*
)
tcph
+
tcph
->
doff
*
4
;
u
_int8_t
tcpflags
;
struct
tcphdr
tcph
;
u
nsigned
char
opt
[
15
*
4
-
sizeof
(
struct
tcphdr
)]
;
u
32
tcpflags
;
int
end_of_options
=
0
;
size_t
i
;
unsigned
int
i
,
optlen
;
/* CHECK: Can't have offset=1: used to override TCP syn-checks. */
/* In fact, this is caught below (offset < 516). */
/* Can't do anything if it's a fragment. */
if
(
offset
)
if
(
fragoff
)
return
1
;
/* CHECK: Smaller than minimal TCP hdr. */
if
(
datalen
<
sizeof
(
struct
tcphdr
))
{
if
(
skb_copy_bits
(
skb
,
offset
,
&
tcph
,
sizeof
(
tcph
))
<
0
)
{
u16
ports
[
2
];
if
(
!
embedded
)
{
limpk
(
"Packet length %u < TCP header.
\n
"
,
datalen
);
limpk
(
"Packet length %u < TCP header.
\n
"
,
skb
->
len
-
offset
);
return
0
;
}
/* Must have ports available (datalen >= 8), from
check_icmp which set embedded = 1 */
/* CHECK: TCP ports inside ICMP error */
if
(
!
tcph
->
source
||
!
tcph
->
dest
)
{
skb_copy_bits
(
skb
,
offset
,
ports
,
sizeof
(
ports
));
if
(
!
ports
[
0
]
||
!
ports
[
1
])
{
limpk
(
"Zero TCP ports %u/%u.
\n
"
,
htons
(
tcph
->
source
),
htons
(
tcph
->
dest
));
htons
(
ports
[
0
]),
htons
(
ports
[
1
]
));
return
0
;
}
return
1
;
}
/* CHECK: Smaller than actual TCP hdr. */
if
(
datalen
<
tcph
->
doff
*
4
)
{
/* CHECK: TCP header claims tiny size. */
if
(
tcph
.
doff
*
4
<
sizeof
(
tcph
))
{
limpk
(
"TCP header claims tiny size %u
\n
"
,
tcph
.
doff
*
4
);
return
0
;
}
/* CHECK: Packet smaller than actual TCP hdr. */
optlen
=
tcph
.
doff
*
4
-
sizeof
(
tcph
);
if
(
skb_copy_bits
(
skb
,
offset
+
sizeof
(
tcph
),
opt
,
optlen
)
<
0
)
{
if
(
!
embedded
)
{
limpk
(
"Packet length %u < actual TCP header.
\n
"
,
datalen
);
skb
->
len
-
offset
);
return
0
;
}
else
return
1
;
}
/* Bad checksum? Don't print, just say it's unclean. */
/* FIXME: SRC ROUTE packets won't match checksum --RR */
if
(
!
more_frags
&&
!
embedded
&&
csum_tcpudp_magic
(
iph
->
saddr
,
iph
->
daddr
,
datalen
,
IPPROTO_TCP
,
csum_partial
((
char
*
)
tcph
,
datalen
,
0
))
!=
0
)
return
0
;
/* CHECK: TCP ports non-zero */
if
(
!
tcph
->
source
||
!
tcph
->
dest
)
{
if
(
!
tcph
.
source
||
!
tcph
.
dest
)
{
limpk
(
"Zero TCP ports %u/%u.
\n
"
,
htons
(
tcph
->
source
),
htons
(
tcph
->
dest
));
htons
(
tcph
.
source
),
htons
(
tcph
.
dest
));
return
0
;
}
tcpflags
=
tcp_flag_word
(
&
tcph
);
/* CHECK: TCP reserved bits zero. */
if
(
tcp_flag_word
(
tcph
)
&
TCP_RESERVED_BITS
)
{
if
(
tcpflags
&
TCP_RESERVED_BITS
)
{
limpk
(
"TCP reserved bits not zero
\n
"
);
return
0
;
}
tcpflags
&=
~
(
TCP_DATA_OFFSET
|
TCP_FLAG_CWR
|
TCP_FLAG_ECE
|
__constant_htonl
(
0x0000FFFF
));
/* CHECK: TCP flags. */
tcpflags
=
(((
u_int8_t
*
)
tcph
)[
13
]
&
~
(
TH_ECE
|
TH_CWR
));
if
(
tcpflags
!=
TH_SYN
&&
tcpflags
!=
(
TH_SYN
|
TH_ACK
)
&&
tcpflags
!=
TH_RST
&&
tcpflags
!=
(
T
H_RST
|
TH_ACK
)
&&
tcpflags
!=
(
T
H_RST
|
TH_ACK
|
TH_PUSH
)
&&
tcpflags
!=
(
TH_FIN
|
TH_ACK
)
&&
tcpflags
!=
TH_ACK
&&
tcpflags
!=
(
T
H_ACK
|
TH_PUSH
)
&&
tcpflags
!=
(
T
H_ACK
|
TH_URG
)
&&
tcpflags
!=
(
T
H_ACK
|
TH_URG
|
TH_PU
SH
)
&&
tcpflags
!=
(
T
H_FIN
|
TH_ACK
|
TH_PUSH
)
&&
tcpflags
!=
(
T
H_FIN
|
TH_ACK
|
TH_URG
)
&&
tcpflags
!=
(
TH_FIN
|
TH_ACK
|
TH_URG
|
TH_PU
SH
))
{
limpk
(
"TCP flags bad:
%u
\n
"
,
tcpflags
);
if
(
tcpflags
!=
TCP_FLAG_SYN
&&
tcpflags
!=
(
TCP_FLAG_SYN
|
TCP_FLAG_ACK
)
&&
tcpflags
!=
TCP_FLAG_RST
&&
tcpflags
!=
(
TCP_FLAG_RST
|
TCP_FLAG_ACK
)
&&
tcpflags
!=
(
T
CP_FLAG_RST
|
TCP_FLAG_ACK
|
TCP_FLAG_PSH
)
&&
tcpflags
!=
(
T
CP_FLAG_FIN
|
TCP_FLAG_ACK
)
&&
tcpflags
!=
TCP_FLAG_ACK
&&
tcpflags
!=
(
TCP_FLAG_ACK
|
TCP_FLAG_PSH
)
&&
tcpflags
!=
(
T
CP_FLAG_ACK
|
TCP_FLAG_URG
)
&&
tcpflags
!=
(
T
CP_FLAG_ACK
|
TCP_FLAG_URG
|
TCP_FLAG_PSH
)
&&
tcpflags
!=
(
T
CP_FLAG_FIN
|
TCP_FLAG_ACK
|
TCP_FLAG_P
SH
)
&&
tcpflags
!=
(
T
CP_FLAG_FIN
|
TCP_FLAG_ACK
|
TCP_FLAG_URG
)
&&
tcpflags
!=
(
T
CP_FLAG_FIN
|
TCP_FLAG_ACK
|
TCP_FLAG_URG
|
TCP_FLAG_P
SH
))
{
limpk
(
"TCP flags bad:
0x%04X
\n
"
,
ntohl
(
tcpflags
)
>>
16
);
return
0
;
}
for
(
i
=
sizeof
(
struct
tcphdr
);
i
<
tcph
->
doff
*
4
;
)
{
for
(
i
=
0
;
i
<
optlen
;
)
{
switch
(
opt
[
i
])
{
case
0
:
end_of_options
=
1
;
...
...
@@ -364,7 +362,7 @@ check_tcp(const struct iphdr *iph,
return
0
;
}
/* CHECK: options at tail. */
else
if
(
i
+
1
>=
tcph
->
doff
*
4
)
{
else
if
(
i
+
1
>=
optlen
)
{
limpk
(
"TCP option %u at tail
\n
"
,
opt
[
i
]);
return
0
;
...
...
@@ -376,8 +374,8 @@ check_tcp(const struct iphdr *iph,
return
0
;
}
/* CHECK: oversize options. */
else
if
(
&
opt
[
i
]
+
opt
[
i
+
1
]
>
endhdr
)
{
limpk
(
"TCP option %u at %
Z
u too long
\n
"
,
else
if
(
i
+
opt
[
i
+
1
]
>
optlen
)
{
limpk
(
"TCP option %u at %u too long
\n
"
,
(
unsigned
int
)
opt
[
i
],
i
);
return
0
;
}
...
...
@@ -392,34 +390,44 @@ check_tcp(const struct iphdr *iph,
/* Returns 1 if ok */
/* Standard IP checks. */
static
int
check_ip
(
struct
iphdr
*
iph
,
size_t
length
,
int
embedded
)
check_ip
(
const
struct
sk_buff
*
skb
,
unsigned
int
offset
)
{
u_int8_t
*
opt
=
(
u_int8_t
*
)
iph
;
u_int8_t
*
endhdr
=
(
u_int8_t
*
)
iph
+
iph
->
ihl
*
4
;
int
end_of_options
=
0
;
void
*
protoh
;
size_t
datalen
;
unsigned
int
datalen
,
optlen
;
unsigned
int
i
;
unsigned
int
offset
;
unsigned
int
fragoff
;
struct
iphdr
iph
;
unsigned
char
opt
[
15
*
4
-
sizeof
(
struct
iphdr
)];
int
embedded
=
offset
;
/* Should only happen for local outgoing raw-socket packets. */
/* CHECK: length >= ip header. */
if
(
length
<
sizeof
(
struct
iphdr
)
||
length
<
iph
->
ihl
*
4
)
{
limpk
(
"Packet length %Zu < IP header.
\n
"
,
length
);
if
(
skb_copy_bits
(
skb
,
offset
,
&
iph
,
sizeof
(
iph
))
<
0
)
{
limpk
(
"Packet length %u < IP header.
\n
"
,
skb
->
len
-
offset
);
return
0
;
}
if
(
iph
.
ihl
*
4
<
sizeof
(
iph
))
{
limpk
(
"IP len %u < minimum IP header.
\n
"
,
iph
.
ihl
*
4
);
return
0
;
}
optlen
=
iph
.
ihl
*
4
-
sizeof
(
iph
);
if
(
skb_copy_bits
(
skb
,
offset
+
sizeof
(
struct
iphdr
),
opt
,
optlen
)
<
0
)
{
limpk
(
"Packet length %u < IP header %u.
\n
"
,
skb
->
len
-
offset
,
iph
.
ihl
*
4
);
return
0
;
}
offset
=
ntohs
(
iph
->
frag_off
)
&
IP_OFFSET
;
protoh
=
(
void
*
)
iph
+
iph
->
ihl
*
4
;
datalen
=
length
-
iph
->
ihl
*
4
;
fragoff
=
(
ntohs
(
iph
.
frag_off
)
&
IP_OFFSET
);
datalen
=
skb
->
len
-
(
offset
+
sizeof
(
struct
iphdr
)
+
optlen
);
/* CHECK: Embedded fragment. */
if
(
embedded
&&
offset
)
{
if
(
offset
&&
fragoff
)
{
limpk
(
"Embedded fragment.
\n
"
);
return
0
;
}
for
(
i
=
sizeof
(
struct
iphdr
);
i
<
iph
->
ihl
*
4
;
)
{
for
(
i
=
0
;
i
<
optlen
;
)
{
switch
(
opt
[
i
])
{
case
0
:
end_of_options
=
1
;
...
...
@@ -436,7 +444,7 @@ check_ip(struct iphdr *iph, size_t length, int embedded)
return
0
;
}
/* CHECK: options at tail. */
else
if
(
i
+
1
>=
iph
->
ihl
*
4
)
{
else
if
(
i
+
1
>=
optlen
)
{
limpk
(
"IP option %u at tail
\n
"
,
opt
[
i
]);
return
0
;
...
...
@@ -448,7 +456,7 @@ check_ip(struct iphdr *iph, size_t length, int embedded)
return
0
;
}
/* CHECK: oversize options. */
else
if
(
&
opt
[
i
]
+
opt
[
i
+
1
]
>
endhdr
)
{
else
if
(
i
+
opt
[
i
+
1
]
>
optlen
)
{
limpk
(
"IP option %u at %u too long
\n
"
,
opt
[
i
],
i
);
return
0
;
...
...
@@ -461,30 +469,30 @@ check_ip(struct iphdr *iph, size_t length, int embedded)
/* Fragment checks. */
/* CHECK: More fragments, but doesn't fill 8-byte boundary. */
if
((
ntohs
(
iph
->
frag_off
)
&
IP_MF
)
&&
(
ntohs
(
iph
->
tot_len
)
%
8
)
!=
0
)
{
limpk
(
"Truncated fragment %u long.
\n
"
,
ntohs
(
iph
->
tot_len
));
if
((
ntohs
(
iph
.
frag_off
)
&
IP_MF
)
&&
(
ntohs
(
iph
.
tot_len
)
%
8
)
!=
0
)
{
limpk
(
"Truncated fragment %u long.
\n
"
,
ntohs
(
iph
.
tot_len
));
return
0
;
}
/* CHECK: Oversize fragment a-la Ping of Death. */
if
(
offset
*
8
+
datalen
>
65535
)
{
limpk
(
"Oversize fragment to %u.
\n
"
,
offset
*
8
);
if
(
fragoff
*
8
+
datalen
>
65535
)
{
limpk
(
"Oversize fragment to %u.
\n
"
,
fragoff
*
8
);
return
0
;
}
/* CHECK: DF set and
offset
or MF set. */
if
((
ntohs
(
iph
->
frag_off
)
&
IP_DF
)
&&
(
offset
||
(
ntohs
(
iph
->
frag_off
)
&
IP_MF
)))
{
/* CHECK: DF set and
fragoff
or MF set. */
if
((
ntohs
(
iph
.
frag_off
)
&
IP_DF
)
&&
(
fragoff
||
(
ntohs
(
iph
.
frag_off
)
&
IP_MF
)))
{
limpk
(
"DF set and offset=%u, MF=%u.
\n
"
,
offset
,
ntohs
(
iph
->
frag_off
)
&
IP_MF
);
fragoff
,
ntohs
(
iph
.
frag_off
)
&
IP_MF
);
return
0
;
}
/* CHECK: Zero-sized fragments. */
if
((
offset
||
(
ntohs
(
iph
->
frag_off
)
&
IP_MF
))
if
((
fragoff
||
(
ntohs
(
iph
.
frag_off
)
&
IP_MF
))
&&
datalen
==
0
)
{
limpk
(
"Zero size fragment offset=%u
\n
"
,
offset
);
limpk
(
"Zero size fragment offset=%u
\n
"
,
fragoff
);
return
0
;
}
...
...
@@ -500,52 +508,54 @@ check_ip(struct iphdr *iph, size_t length, int embedded)
here. */
#define MIN_LIKELY_MTU 128
/* CHECK: Min size of first frag = 128. */
if
((
ntohs
(
iph
->
frag_off
)
&
IP_MF
)
&&
offset
==
0
&&
ntohs
(
iph
->
tot_len
)
<
MIN_LIKELY_MTU
)
{
limpk
(
"First fragment size %u < %u
\n
"
,
ntohs
(
iph
->
tot_len
),
if
((
ntohs
(
iph
.
frag_off
)
&
IP_MF
)
&&
fragoff
==
0
&&
ntohs
(
iph
.
tot_len
)
<
MIN_LIKELY_MTU
)
{
limpk
(
"First fragment size %u < %u
\n
"
,
ntohs
(
iph
.
tot_len
),
MIN_LIKELY_MTU
);
return
0
;
}
/* CHECK: Min offset of frag = 128 - IP hdr len. */
if
(
offset
&&
offset
*
8
<
MIN_LIKELY_MTU
-
iph
->
ihl
*
4
)
{
limpk
(
"Fragment starts at %u < %u
\n
"
,
offset
*
8
,
MIN_LIKELY_MTU
-
iph
->
ihl
*
4
);
if
(
fragoff
&&
fragoff
*
8
<
MIN_LIKELY_MTU
-
iph
.
ihl
*
4
)
{
limpk
(
"Fragment starts at %u < %u
\n
"
,
fragoff
*
8
,
MIN_LIKELY_MTU
-
iph
.
ihl
*
4
);
return
0
;
}
/* CHECK: Protocol specification non-zero. */
if
(
iph
->
protocol
==
0
)
{
if
(
iph
.
protocol
==
0
)
{
limpk
(
"Zero protocol
\n
"
);
return
0
;
}
/* FIXME: This is already checked for in "Oversize fragment"
above --RR */
/* CHECK: Do not use what is unused.
* First bit of fragmentation flags should be unused.
* May be used by OS fingerprinting tools.
* 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
*/
if
(
ntohs
(
iph
->
frag_off
)
>>
15
)
{
if
(
ntohs
(
iph
.
frag_off
)
>>
15
)
{
limpk
(
"IP unused bit set
\n
"
);
return
0
;
}
/* Per-protocol checks. */
switch
(
iph
->
protocol
)
{
switch
(
iph
.
protocol
)
{
case
IPPROTO_ICMP
:
return
check_icmp
(
protoh
,
datalen
,
offset
,
(
ntohs
(
iph
->
frag_off
)
&
IP_MF
),
return
check_icmp
(
skb
,
offset
+
iph
.
ihl
*
4
,
fragoff
,
(
ntohs
(
iph
.
frag_off
)
&
IP_MF
),
embedded
);
case
IPPROTO_UDP
:
return
check_udp
(
iph
,
protoh
,
datalen
,
offset
,
(
ntohs
(
iph
->
frag_off
)
&
IP_MF
),
return
check_udp
(
skb
,
offset
+
iph
.
ihl
*
4
,
fragoff
,
(
ntohs
(
iph
.
frag_off
)
&
IP_MF
),
embedded
);
case
IPPROTO_TCP
:
return
check_tcp
(
iph
,
protoh
,
datalen
,
offset
,
(
ntohs
(
iph
->
frag_off
)
&
IP_MF
),
return
check_tcp
(
skb
,
offset
+
iph
.
ihl
*
4
,
fragoff
,
(
ntohs
(
iph
.
frag_off
)
&
IP_MF
),
embedded
);
default:
/* Ignorance is bliss. */
...
...
@@ -559,11 +569,9 @@ match(const struct sk_buff *skb,
const
struct
net_device
*
out
,
const
void
*
matchinfo
,
int
offset
,
const
void
*
hdr
,
u_int16_t
datalen
,
int
*
hotdrop
)
{
return
!
check_ip
(
skb
->
nh
.
iph
,
skb
->
len
,
0
);
return
!
check_ip
(
skb
,
0
);
}
/* Called when user tries to insert an entry of this type. */
...
...
net/ipv6/anycast.c
View file @
73baeace
...
...
@@ -127,8 +127,8 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
dev_hold
(
dev
);
dst_release
(
&
rt
->
u
.
dst
);
}
else
if
(
ishost
)
{
sock_kfree_s
(
sk
,
pac
,
sizeof
(
*
pac
))
;
return
-
EADDRNOTAVAIL
;
err
=
-
EADDRNOTAVAIL
;
goto
out_free_pac
;
}
else
{
/* router, no matching interface: just pick one */
...
...
@@ -138,18 +138,17 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
dev
=
dev_get_by_index
(
ifindex
);
if
(
dev
==
NULL
)
{
sock_kfree_s
(
sk
,
pac
,
sizeof
(
*
pac
))
;
return
-
ENODEV
;
err
=
-
ENODEV
;
goto
out_free_pac
;
}
idev
=
in6_dev_get
(
dev
);
if
(
!
idev
)
{
sock_kfree_s
(
sk
,
pac
,
sizeof
(
*
pac
));
dev_put
(
dev
);
if
(
ifindex
)
return
-
ENODEV
;
err
=
-
ENODEV
;
else
return
-
EADDRNOTAVAIL
;
err
=
-
EADDRNOTAVAIL
;
goto
out_dev_put
;
}
/* reset ishost, now that we have a specific device */
ishost
=
!
idev
->
cnf
.
forwarding
;
...
...
@@ -170,21 +169,17 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
err
=
-
EADDRNOTAVAIL
;
else
if
(
!
capable
(
CAP_NET_ADMIN
))
err
=
-
EPERM
;
if
(
err
)
{
sock_kfree_s
(
sk
,
pac
,
sizeof
(
*
pac
));
dev_put
(
dev
);
return
err
;
}
if
(
err
)
goto
out_dev_put
;
}
else
if
(
!
(
ipv6_addr_type
(
addr
)
&
IPV6_ADDR_ANYCAST
)
&&
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
!
capable
(
CAP_NET_ADMIN
))
{
err
=
-
EPERM
;
goto
out_dev_put
;
}
err
=
ipv6_dev_ac_inc
(
dev
,
addr
);
if
(
err
)
{
sock_kfree_s
(
sk
,
pac
,
sizeof
(
*
pac
));
dev_put
(
dev
);
return
err
;
}
if
(
err
)
goto
out_dev_put
;
write_lock_bh
(
&
ipv6_sk_ac_lock
);
pac
->
acl_next
=
np
->
ipv6_ac_list
;
...
...
@@ -194,6 +189,12 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
dev_put
(
dev
);
return
0
;
out_dev_put:
dev_put
(
dev
);
out_free_pac:
sock_kfree_s
(
sk
,
pac
,
sizeof
(
*
pac
));
return
err
;
}
/*
...
...
net/ipv6/ndisc.c
View file @
73baeace
...
...
@@ -441,8 +441,10 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
src_addr
=
solicited_addr
;
in6_ifa_put
(
ifp
);
}
else
{
if
(
ipv6_dev_get_saddr
(
dev
,
daddr
,
&
tmpaddr
,
0
))
if
(
ipv6_dev_get_saddr
(
dev
,
daddr
,
&
tmpaddr
,
0
))
{
dst_free
(
dst
);
return
;
}
src_addr
=
&
tmpaddr
;
}
...
...
@@ -450,11 +452,10 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
ndisc_rt_init
(
rt
,
dev
,
neigh
);
dst
=
(
struct
dst_entry
*
)
rt
;
dst_clone
(
dst
);
err
=
xfrm_lookup
(
&
dst
,
&
fl
,
NULL
,
0
);
if
(
err
<
0
)
{
dst_
releas
e
(
dst
);
dst_
fre
e
(
dst
);
return
;
}
...
...
@@ -470,6 +471,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
if
(
skb
==
NULL
)
{
ND_PRINTK1
(
"send_na: alloc skb failed
\n
"
);
dst_free
(
dst
);
return
;
}
...
...
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