Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
net
netfilter
xt_ipvs.c
Go to the documentation of this file.
1
/*
2
* xt_ipvs - kernel module to match IPVS connection properties
3
*
4
* Author: Hannes Eder <
[email protected]
>
5
*/
6
7
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
9
#include <linux/module.h>
10
#include <
linux/moduleparam.h
>
11
#include <
linux/spinlock.h
>
12
#include <
linux/skbuff.h
>
13
#ifdef CONFIG_IP_VS_IPV6
14
#include <
net/ipv6.h
>
15
#endif
16
#include <
linux/ip_vs.h
>
17
#include <linux/types.h>
18
#include <linux/netfilter/x_tables.h>
19
#include <
linux/netfilter/xt_ipvs.h
>
20
#include <
net/netfilter/nf_conntrack.h
>
21
22
#include <
net/ip_vs.h
>
23
24
MODULE_AUTHOR
(
"Hannes Eder <
[email protected]
>"
);
25
MODULE_DESCRIPTION
(
"Xtables: match IPVS connection properties"
);
26
MODULE_LICENSE
(
"GPL"
);
27
MODULE_ALIAS
(
"ipt_ipvs"
);
28
MODULE_ALIAS
(
"ip6t_ipvs"
);
29
30
/* borrowed from xt_conntrack */
31
static
bool
ipvs_mt_addrcmp(
const
union
nf_inet_addr
*kaddr,
32
const
union
nf_inet_addr
*
uaddr
,
33
const
union
nf_inet_addr
*umask,
34
unsigned
int
l3proto)
35
{
36
if
(l3proto ==
NFPROTO_IPV4
)
37
return
((kaddr->
ip
^ uaddr->
ip
) & umask->
ip
) == 0;
38
#ifdef CONFIG_IP_VS_IPV6
39
else
if
(l3proto ==
NFPROTO_IPV6
)
40
return
ipv6_masked_addr_cmp(&kaddr->
in6
, &umask->
in6
,
41
&uaddr->
in6
) == 0;
42
#endif
43
else
44
return
false
;
45
}
46
47
static
bool
48
ipvs_mt(
const
struct
sk_buff
*
skb
,
struct
xt_action_param
*par)
49
{
50
const
struct
xt_ipvs_mtinfo
*
data
= par->
matchinfo
;
51
/* ipvs_mt_check ensures that family is only NFPROTO_IPV[46]. */
52
const
u_int8_t
family
= par->
family
;
53
struct
ip_vs_iphdr
iph;
54
struct
ip_vs_protocol
*
pp
;
55
struct
ip_vs_conn
*
cp
;
56
bool
match
=
true
;
57
58
if
(data->
bitmask
==
XT_IPVS_IPVS_PROPERTY
) {
59
match = skb->
ipvs_property
^
60
!!(data->
invert
&
XT_IPVS_IPVS_PROPERTY
);
61
goto
out
;
62
}
63
64
/* other flags than XT_IPVS_IPVS_PROPERTY are set */
65
if
(!skb->
ipvs_property
) {
66
match =
false
;
67
goto
out
;
68
}
69
70
ip_vs_fill_iphdr(family, skb_network_header(skb), &iph);
71
72
if
(data->
bitmask
&
XT_IPVS_PROTO
)
73
if
((iph.protocol == data->
l4proto
) ^
74
!(data->
invert
&
XT_IPVS_PROTO
)) {
75
match =
false
;
76
goto
out
;
77
}
78
79
pp =
ip_vs_proto_get
(iph.protocol);
80
if
(
unlikely
(!pp)) {
81
match =
false
;
82
goto
out
;
83
}
84
85
/*
86
* Check if the packet belongs to an existing entry
87
*/
88
cp = pp->
conn_out_get
(family, skb, &iph, iph.
len
, 1
/* inverse */
);
89
if
(
unlikely
(cp ==
NULL
)) {
90
match =
false
;
91
goto
out
;
92
}
93
94
/*
95
* We found a connection, i.e. ct != 0, make sure to call
96
* __ip_vs_conn_put before returning. In our case jump to out_put_con.
97
*/
98
99
if
(data->
bitmask
&
XT_IPVS_VPORT
)
100
if
((cp->
vport
== data->
vport
) ^
101
!(data->
invert
&
XT_IPVS_VPORT
)) {
102
match =
false
;
103
goto
out_put_cp;
104
}
105
106
if
(data->
bitmask
&
XT_IPVS_VPORTCTL
)
107
if
((cp->
control
!=
NULL
&&
108
cp->
control
->vport == data->
vportctl
) ^
109
!(data->
invert
&
XT_IPVS_VPORTCTL
)) {
110
match =
false
;
111
goto
out_put_cp;
112
}
113
114
if
(data->
bitmask
&
XT_IPVS_DIR
) {
115
enum
ip_conntrack_info
ctinfo;
116
struct
nf_conn
*
ct
= nf_ct_get(skb, &ctinfo);
117
118
if
(ct ==
NULL
|| nf_ct_is_untracked(ct)) {
119
match =
false
;
120
goto
out_put_cp;
121
}
122
123
if
((ctinfo >=
IP_CT_IS_REPLY
) ^
124
!!(data->
invert
&
XT_IPVS_DIR
)) {
125
match =
false
;
126
goto
out_put_cp;
127
}
128
}
129
130
if
(data->
bitmask
&
XT_IPVS_METHOD
)
131
if
(((cp->
flags
&
IP_VS_CONN_F_FWD_MASK
) == data->
fwd_method
) ^
132
!(data->
invert
&
XT_IPVS_METHOD
)) {
133
match =
false
;
134
goto
out_put_cp;
135
}
136
137
if
(data->
bitmask
&
XT_IPVS_VADDR
) {
138
if
(ipvs_mt_addrcmp(&cp->
vaddr
, &data->vaddr,
139
&data->
vmask
, family) ^
140
!(data->
invert
&
XT_IPVS_VADDR
)) {
141
match =
false
;
142
goto
out_put_cp;
143
}
144
}
145
146
out_put_cp:
147
__ip_vs_conn_put(cp);
148
out
:
149
pr_debug
(
"match=%d\n"
, match);
150
return
match
;
151
}
152
153
static
int
ipvs_mt_check(
const
struct
xt_mtchk_param
*par)
154
{
155
if
(par->
family
!=
NFPROTO_IPV4
156
#ifdef CONFIG_IP_VS_IPV6
157
&& par->
family
!=
NFPROTO_IPV6
158
#
endif
159
) {
160
pr_info
(
"protocol family %u not supported\n"
, par->
family
);
161
return
-
EINVAL
;
162
}
163
164
return
0;
165
}
166
167
static
struct
xt_match
xt_ipvs_mt_reg
__read_mostly
= {
168
.name =
"ipvs"
,
169
.revision = 0,
170
.family =
NFPROTO_UNSPEC
,
171
.match = ipvs_mt,
172
.checkentry = ipvs_mt_check,
173
.matchsize =
XT_ALIGN
(
sizeof
(
struct
xt_ipvs_mtinfo
)),
174
.me =
THIS_MODULE
,
175
};
176
177
static
int
__init
ipvs_mt_init(
void
)
178
{
179
return
xt_register_match
(&xt_ipvs_mt_reg);
180
}
181
182
static
void
__exit
ipvs_mt_exit(
void
)
183
{
184
xt_unregister_match
(&xt_ipvs_mt_reg);
185
}
186
187
module_init
(ipvs_mt_init);
188
module_exit
(ipvs_mt_exit);
Generated on Thu Jan 10 2013 15:00:55 for Linux Kernel by
1.8.2