diff options
Diffstat (limited to 'net/netfilter/xt_conntrack.c')
-rw-r--r-- | net/netfilter/xt_conntrack.c | 80 |
1 files changed, 78 insertions, 2 deletions
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index e536710ad91..2c0086a4751 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -112,6 +112,54 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info, | |||
112 | return true; | 112 | return true; |
113 | } | 113 | } |
114 | 114 | ||
115 | static inline bool | ||
116 | port_match(u16 min, u16 max, u16 port, bool invert) | ||
117 | { | ||
118 | return (port >= min && port <= max) ^ invert; | ||
119 | } | ||
120 | |||
121 | static inline bool | ||
122 | ct_proto_port_check_v3(const struct xt_conntrack_mtinfo3 *info, | ||
123 | const struct nf_conn *ct) | ||
124 | { | ||
125 | const struct nf_conntrack_tuple *tuple; | ||
126 | |||
127 | tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; | ||
128 | if ((info->match_flags & XT_CONNTRACK_PROTO) && | ||
129 | (nf_ct_protonum(ct) == info->l4proto) ^ | ||
130 | !(info->invert_flags & XT_CONNTRACK_PROTO)) | ||
131 | return false; | ||
132 | |||
133 | /* Shortcut to match all recognized protocols by using ->src.all. */ | ||
134 | if ((info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) && | ||
135 | !port_match(info->origsrc_port, info->origsrc_port_high, | ||
136 | ntohs(tuple->src.u.all), | ||
137 | info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT)) | ||
138 | return false; | ||
139 | |||
140 | if ((info->match_flags & XT_CONNTRACK_ORIGDST_PORT) && | ||
141 | !port_match(info->origdst_port, info->origdst_port_high, | ||
142 | ntohs(tuple->dst.u.all), | ||
143 | info->invert_flags & XT_CONNTRACK_ORIGDST_PORT)) | ||
144 | return false; | ||
145 | |||
146 | tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; | ||
147 | |||
148 | if ((info->match_flags & XT_CONNTRACK_REPLSRC_PORT) && | ||
149 | !port_match(info->replsrc_port, info->replsrc_port_high, | ||
150 | ntohs(tuple->src.u.all), | ||
151 | info->invert_flags & XT_CONNTRACK_REPLSRC_PORT)) | ||
152 | return false; | ||
153 | |||
154 | if ((info->match_flags & XT_CONNTRACK_REPLDST_PORT) && | ||
155 | !port_match(info->repldst_port, info->repldst_port_high, | ||
156 | ntohs(tuple->dst.u.all), | ||
157 | info->invert_flags & XT_CONNTRACK_REPLDST_PORT)) | ||
158 | return false; | ||
159 | |||
160 | return true; | ||
161 | } | ||
162 | |||
115 | static bool | 163 | static bool |
116 | conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par, | 164 | conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par, |
117 | u16 state_mask, u16 status_mask) | 165 | u16 state_mask, u16 status_mask) |
@@ -170,8 +218,13 @@ conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par, | |||
170 | !(info->invert_flags & XT_CONNTRACK_REPLDST)) | 218 | !(info->invert_flags & XT_CONNTRACK_REPLDST)) |
171 | return false; | 219 | return false; |
172 | 220 | ||
173 | if (!ct_proto_port_check(info, ct)) | 221 | if (par->match->revision != 3) { |
174 | return false; | 222 | if (!ct_proto_port_check(info, ct)) |
223 | return false; | ||
224 | } else { | ||
225 | if (!ct_proto_port_check_v3(par->matchinfo, ct)) | ||
226 | return false; | ||
227 | } | ||
175 | 228 | ||
176 | if ((info->match_flags & XT_CONNTRACK_STATUS) && | 229 | if ((info->match_flags & XT_CONNTRACK_STATUS) && |
177 | (!!(status_mask & ct->status) ^ | 230 | (!!(status_mask & ct->status) ^ |
@@ -207,10 +260,23 @@ conntrack_mt_v2(const struct sk_buff *skb, struct xt_action_param *par) | |||
207 | return conntrack_mt(skb, par, info->state_mask, info->status_mask); | 260 | return conntrack_mt(skb, par, info->state_mask, info->status_mask); |
208 | } | 261 | } |
209 | 262 | ||
263 | static bool | ||
264 | conntrack_mt_v3(const struct sk_buff *skb, struct xt_action_param *par) | ||
265 | { | ||
266 | const struct xt_conntrack_mtinfo3 *info = par->matchinfo; | ||
267 | |||
268 | return conntrack_mt(skb, par, info->state_mask, info->status_mask); | ||
269 | } | ||
270 | |||
210 | static int conntrack_mt_check(const struct xt_mtchk_param *par) | 271 | static int conntrack_mt_check(const struct xt_mtchk_param *par) |
211 | { | 272 | { |
212 | int ret; | 273 | int ret; |
213 | 274 | ||
275 | if (strcmp(par->table, "raw") == 0) { | ||
276 | pr_info("state is undetermined at the time of raw table\n"); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
214 | ret = nf_ct_l3proto_try_module_get(par->family); | 280 | ret = nf_ct_l3proto_try_module_get(par->family); |
215 | if (ret < 0) | 281 | if (ret < 0) |
216 | pr_info("cannot load conntrack support for proto=%u\n", | 282 | pr_info("cannot load conntrack support for proto=%u\n", |
@@ -244,6 +310,16 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = { | |||
244 | .destroy = conntrack_mt_destroy, | 310 | .destroy = conntrack_mt_destroy, |
245 | .me = THIS_MODULE, | 311 | .me = THIS_MODULE, |
246 | }, | 312 | }, |
313 | { | ||
314 | .name = "conntrack", | ||
315 | .revision = 3, | ||
316 | .family = NFPROTO_UNSPEC, | ||
317 | .matchsize = sizeof(struct xt_conntrack_mtinfo3), | ||
318 | .match = conntrack_mt_v3, | ||
319 | .checkentry = conntrack_mt_check, | ||
320 | .destroy = conntrack_mt_destroy, | ||
321 | .me = THIS_MODULE, | ||
322 | }, | ||
247 | }; | 323 | }; |
248 | 324 | ||
249 | static int __init conntrack_mt_init(void) | 325 | static int __init conntrack_mt_init(void) |