aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2009-06-02 07:44:56 -0400
committerPatrick McHardy <kaber@trash.net>2009-06-02 07:44:56 -0400
commit8cc848fa3445b3503465dfba5d8ad47559faa05a (patch)
tree6fe6128de6b6791493809b2ce440217579a0d6a8 /net/ipv4
parenta17c859849402315613a0015ac8fbf101acf0cc1 (diff)
parent451853645f3cb804b523227eca054701e4cbc589 (diff)
Merge branch 'master' of git://dev.medozas.de/linux
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/arp_tables.c109
-rw-r--r--net/ipv4/netfilter/ip_queue.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c170
3 files changed, 143 insertions, 138 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 831fe1879dc0..7505dff4ffdf 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -231,6 +231,12 @@ static inline struct arpt_entry *get_entry(void *base, unsigned int offset)
231 return (struct arpt_entry *)(base + offset); 231 return (struct arpt_entry *)(base + offset);
232} 232}
233 233
234static inline __pure
235struct arpt_entry *arpt_next_entry(const struct arpt_entry *entry)
236{
237 return (void *)entry + entry->next_offset;
238}
239
234unsigned int arpt_do_table(struct sk_buff *skb, 240unsigned int arpt_do_table(struct sk_buff *skb,
235 unsigned int hook, 241 unsigned int hook,
236 const struct net_device *in, 242 const struct net_device *in,
@@ -267,67 +273,64 @@ unsigned int arpt_do_table(struct sk_buff *skb,
267 273
268 arp = arp_hdr(skb); 274 arp = arp_hdr(skb);
269 do { 275 do {
270 if (arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { 276 struct arpt_entry_target *t;
271 struct arpt_entry_target *t; 277 int hdr_len;
272 int hdr_len;
273
274 hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) +
275 (2 * skb->dev->addr_len);
276 278
277 ADD_COUNTER(e->counters, hdr_len, 1); 279 if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
280 e = arpt_next_entry(e);
281 continue;
282 }
278 283
279 t = arpt_get_target(e); 284 hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) +
285 (2 * skb->dev->addr_len);
286 ADD_COUNTER(e->counters, hdr_len, 1);
280 287
281 /* Standard target? */ 288 t = arpt_get_target(e);
282 if (!t->u.kernel.target->target) {
283 int v;
284 289
285 v = ((struct arpt_standard_target *)t)->verdict; 290 /* Standard target? */
286 if (v < 0) { 291 if (!t->u.kernel.target->target) {
287 /* Pop from stack? */ 292 int v;
288 if (v != ARPT_RETURN) {
289 verdict = (unsigned)(-v) - 1;
290 break;
291 }
292 e = back;
293 back = get_entry(table_base,
294 back->comefrom);
295 continue;
296 }
297 if (table_base + v
298 != (void *)e + e->next_offset) {
299 /* Save old back ptr in next entry */
300 struct arpt_entry *next
301 = (void *)e + e->next_offset;
302 next->comefrom =
303 (void *)back - table_base;
304
305 /* set back pointer to next entry */
306 back = next;
307 }
308 293
309 e = get_entry(table_base, v); 294 v = ((struct arpt_standard_target *)t)->verdict;
310 } else { 295 if (v < 0) {
311 /* Targets which reenter must return 296 /* Pop from stack? */
312 * abs. verdicts 297 if (v != ARPT_RETURN) {
313 */ 298 verdict = (unsigned)(-v) - 1;
314 tgpar.target = t->u.kernel.target;
315 tgpar.targinfo = t->data;
316 verdict = t->u.kernel.target->target(skb,
317 &tgpar);
318
319 /* Target might have changed stuff. */
320 arp = arp_hdr(skb);
321
322 if (verdict == ARPT_CONTINUE)
323 e = (void *)e + e->next_offset;
324 else
325 /* Verdict */
326 break; 299 break;
300 }
301 e = back;
302 back = get_entry(table_base, back->comefrom);
303 continue;
327 } 304 }
328 } else { 305 if (table_base + v
329 e = (void *)e + e->next_offset; 306 != arpt_next_entry(e)) {
307 /* Save old back ptr in next entry */
308 struct arpt_entry *next = arpt_next_entry(e);
309 next->comefrom = (void *)back - table_base;
310
311 /* set back pointer to next entry */
312 back = next;
313 }
314
315 e = get_entry(table_base, v);
316 continue;
330 } 317 }
318
319 /* Targets which reenter must return
320 * abs. verdicts
321 */
322 tgpar.target = t->u.kernel.target;
323 tgpar.targinfo = t->data;
324 verdict = t->u.kernel.target->target(skb, &tgpar);
325
326 /* Target might have changed stuff. */
327 arp = arp_hdr(skb);
328
329 if (verdict == ARPT_CONTINUE)
330 e = arpt_next_entry(e);
331 else
332 /* Verdict */
333 break;
331 } while (!hotdrop); 334 } while (!hotdrop);
332 xt_info_rdunlock_bh(); 335 xt_info_rdunlock_bh();
333 336
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 5f22c91c6e15..c156db215987 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -596,7 +596,7 @@ static int __init ip_queue_init(void)
596#ifdef CONFIG_SYSCTL 596#ifdef CONFIG_SYSCTL
597 ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table); 597 ipq_sysctl_header = register_sysctl_paths(net_ipv4_ctl_path, ipq_table);
598#endif 598#endif
599 status = nf_register_queue_handler(PF_INET, &nfqh); 599 status = nf_register_queue_handler(NFPROTO_IPV4, &nfqh);
600 if (status < 0) { 600 if (status < 0) {
601 printk(KERN_ERR "ip_queue: failed to register queue handler\n"); 601 printk(KERN_ERR "ip_queue: failed to register queue handler\n");
602 goto cleanup_sysctl; 602 goto cleanup_sysctl;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 2ec8d7290c40..7b35c0b3841b 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -238,8 +238,8 @@ static struct nf_loginfo trace_loginfo = {
238/* Mildly perf critical (only if packet tracing is on) */ 238/* Mildly perf critical (only if packet tracing is on) */
239static inline int 239static inline int
240get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, 240get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
241 char *hookname, char **chainname, 241 const char *hookname, const char **chainname,
242 char **comment, unsigned int *rulenum) 242 const char **comment, unsigned int *rulenum)
243{ 243{
244 struct ipt_standard_target *t = (void *)ipt_get_target(s); 244 struct ipt_standard_target *t = (void *)ipt_get_target(s);
245 245
@@ -257,8 +257,8 @@ get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
257 && unconditional(&s->ip)) { 257 && unconditional(&s->ip)) {
258 /* Tail of chains: STANDARD target (return/policy) */ 258 /* Tail of chains: STANDARD target (return/policy) */
259 *comment = *chainname == hookname 259 *comment = *chainname == hookname
260 ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY] 260 ? comments[NF_IP_TRACE_COMMENT_POLICY]
261 : (char *)comments[NF_IP_TRACE_COMMENT_RETURN]; 261 : comments[NF_IP_TRACE_COMMENT_RETURN];
262 } 262 }
263 return 1; 263 return 1;
264 } else 264 } else
@@ -277,14 +277,14 @@ static void trace_packet(struct sk_buff *skb,
277{ 277{
278 void *table_base; 278 void *table_base;
279 const struct ipt_entry *root; 279 const struct ipt_entry *root;
280 char *hookname, *chainname, *comment; 280 const char *hookname, *chainname, *comment;
281 unsigned int rulenum = 0; 281 unsigned int rulenum = 0;
282 282
283 table_base = (void *)private->entries[smp_processor_id()]; 283 table_base = private->entries[smp_processor_id()];
284 root = get_entry(table_base, private->hook_entry[hook]); 284 root = get_entry(table_base, private->hook_entry[hook]);
285 285
286 hookname = chainname = (char *)hooknames[hook]; 286 hookname = chainname = hooknames[hook];
287 comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE]; 287 comment = comments[NF_IP_TRACE_COMMENT_RULE];
288 288
289 IPT_ENTRY_ITERATE(root, 289 IPT_ENTRY_ITERATE(root,
290 private->size - private->hook_entry[hook], 290 private->size - private->hook_entry[hook],
@@ -297,6 +297,12 @@ static void trace_packet(struct sk_buff *skb,
297} 297}
298#endif 298#endif
299 299
300static inline __pure
301struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
302{
303 return (void *)entry + entry->next_offset;
304}
305
300/* Returns one of the generic firewall policies, like NF_ACCEPT. */ 306/* Returns one of the generic firewall policies, like NF_ACCEPT. */
301unsigned int 307unsigned int
302ipt_do_table(struct sk_buff *skb, 308ipt_do_table(struct sk_buff *skb,
@@ -305,6 +311,8 @@ ipt_do_table(struct sk_buff *skb,
305 const struct net_device *out, 311 const struct net_device *out,
306 struct xt_table *table) 312 struct xt_table *table)
307{ 313{
314#define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
315
308 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 316 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
309 const struct iphdr *ip; 317 const struct iphdr *ip;
310 u_int16_t datalen; 318 u_int16_t datalen;
@@ -348,92 +356,84 @@ ipt_do_table(struct sk_buff *skb,
348 back = get_entry(table_base, private->underflow[hook]); 356 back = get_entry(table_base, private->underflow[hook]);
349 357
350 do { 358 do {
359 struct ipt_entry_target *t;
360
351 IP_NF_ASSERT(e); 361 IP_NF_ASSERT(e);
352 IP_NF_ASSERT(back); 362 IP_NF_ASSERT(back);
353 if (ip_packet_match(ip, indev, outdev, 363 if (!ip_packet_match(ip, indev, outdev,
354 &e->ip, mtpar.fragoff)) { 364 &e->ip, mtpar.fragoff) ||
355 struct ipt_entry_target *t; 365 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
356 366 e = ipt_next_entry(e);
357 if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) 367 continue;
358 goto no_match; 368 }
359 369
360 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); 370 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
361 371
362 t = ipt_get_target(e); 372 t = ipt_get_target(e);
363 IP_NF_ASSERT(t->u.kernel.target); 373 IP_NF_ASSERT(t->u.kernel.target);
364 374
365#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ 375#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
366 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) 376 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
367 /* The packet is traced: log it */ 377 /* The packet is traced: log it */
368 if (unlikely(skb->nf_trace)) 378 if (unlikely(skb->nf_trace))
369 trace_packet(skb, hook, in, out, 379 trace_packet(skb, hook, in, out,
370 table->name, private, e); 380 table->name, private, e);
371#endif 381#endif
372 /* Standard target? */ 382 /* Standard target? */
373 if (!t->u.kernel.target->target) { 383 if (!t->u.kernel.target->target) {
374 int v; 384 int v;
375 385
376 v = ((struct ipt_standard_target *)t)->verdict; 386 v = ((struct ipt_standard_target *)t)->verdict;
377 if (v < 0) { 387 if (v < 0) {
378 /* Pop from stack? */ 388 /* Pop from stack? */
379 if (v != IPT_RETURN) { 389 if (v != IPT_RETURN) {
380 verdict = (unsigned)(-v) - 1; 390 verdict = (unsigned)(-v) - 1;
381 break; 391 break;
382 }
383 e = back;
384 back = get_entry(table_base,
385 back->comefrom);
386 continue;
387 }
388 if (table_base + v != (void *)e + e->next_offset
389 && !(e->ip.flags & IPT_F_GOTO)) {
390 /* Save old back ptr in next entry */
391 struct ipt_entry *next
392 = (void *)e + e->next_offset;
393 next->comefrom
394 = (void *)back - table_base;
395 /* set back pointer to next entry */
396 back = next;
397 } 392 }
393 e = back;
394 back = get_entry(table_base, back->comefrom);
395 continue;
396 }
397 if (table_base + v != ipt_next_entry(e)
398 && !(e->ip.flags & IPT_F_GOTO)) {
399 /* Save old back ptr in next entry */
400 struct ipt_entry *next = ipt_next_entry(e);
401 next->comefrom = (void *)back - table_base;
402 /* set back pointer to next entry */
403 back = next;
404 }
405
406 e = get_entry(table_base, v);
407 continue;
408 }
409
410 /* Targets which reenter must return
411 abs. verdicts */
412 tgpar.target = t->u.kernel.target;
413 tgpar.targinfo = t->data;
414
398 415
399 e = get_entry(table_base, v);
400 } else {
401 /* Targets which reenter must return
402 abs. verdicts */
403 tgpar.target = t->u.kernel.target;
404 tgpar.targinfo = t->data;
405#ifdef CONFIG_NETFILTER_DEBUG 416#ifdef CONFIG_NETFILTER_DEBUG
406 ((struct ipt_entry *)table_base)->comefrom 417 tb_comefrom = 0xeeeeeeec;
407 = 0xeeeeeeec;
408#endif 418#endif
409 verdict = t->u.kernel.target->target(skb, 419 verdict = t->u.kernel.target->target(skb, &tgpar);
410 &tgpar);
411#ifdef CONFIG_NETFILTER_DEBUG 420#ifdef CONFIG_NETFILTER_DEBUG
412 if (((struct ipt_entry *)table_base)->comefrom 421 if (comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
413 != 0xeeeeeeec 422 printk("Target %s reentered!\n",
414 && verdict == IPT_CONTINUE) { 423 t->u.kernel.target->name);
415 printk("Target %s reentered!\n", 424 verdict = NF_DROP;
416 t->u.kernel.target->name); 425 }
417 verdict = NF_DROP; 426 tb_comefrom = 0x57acc001;
418 }
419 ((struct ipt_entry *)table_base)->comefrom
420 = 0x57acc001;
421#endif 427#endif
422 /* Target might have changed stuff. */ 428 /* Target might have changed stuff. */
423 ip = ip_hdr(skb); 429 ip = ip_hdr(skb);
424 datalen = skb->len - ip->ihl * 4; 430 datalen = skb->len - ip->ihl * 4;
425
426 if (verdict == IPT_CONTINUE)
427 e = (void *)e + e->next_offset;
428 else
429 /* Verdict */
430 break;
431 }
432 } else {
433 431
434 no_match: 432 if (verdict == IPT_CONTINUE)
435 e = (void *)e + e->next_offset; 433 e = ipt_next_entry(e);
436 } 434 else
435 /* Verdict */
436 break;
437 } while (!hotdrop); 437 } while (!hotdrop);
438 xt_info_rdunlock_bh(); 438 xt_info_rdunlock_bh();
439 439
@@ -444,6 +444,8 @@ ipt_do_table(struct sk_buff *skb,
444 return NF_DROP; 444 return NF_DROP;
445 else return verdict; 445 else return verdict;
446#endif 446#endif
447
448#undef tb_comefrom
447} 449}
448 450
449/* Figures out from what hook each rule can be called: returns 0 if 451/* Figures out from what hook each rule can be called: returns 0 if
@@ -2158,7 +2160,7 @@ static bool icmp_checkentry(const struct xt_mtchk_param *par)
2158static struct xt_target ipt_standard_target __read_mostly = { 2160static struct xt_target ipt_standard_target __read_mostly = {
2159 .name = IPT_STANDARD_TARGET, 2161 .name = IPT_STANDARD_TARGET,
2160 .targetsize = sizeof(int), 2162 .targetsize = sizeof(int),
2161 .family = AF_INET, 2163 .family = NFPROTO_IPV4,
2162#ifdef CONFIG_COMPAT 2164#ifdef CONFIG_COMPAT
2163 .compatsize = sizeof(compat_int_t), 2165 .compatsize = sizeof(compat_int_t),
2164 .compat_from_user = compat_standard_from_user, 2166 .compat_from_user = compat_standard_from_user,
@@ -2170,7 +2172,7 @@ static struct xt_target ipt_error_target __read_mostly = {
2170 .name = IPT_ERROR_TARGET, 2172 .name = IPT_ERROR_TARGET,
2171 .target = ipt_error, 2173 .target = ipt_error,
2172 .targetsize = IPT_FUNCTION_MAXNAMELEN, 2174 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2173 .family = AF_INET, 2175 .family = NFPROTO_IPV4,
2174}; 2176};
2175 2177
2176static struct nf_sockopt_ops ipt_sockopts = { 2178static struct nf_sockopt_ops ipt_sockopts = {
@@ -2196,17 +2198,17 @@ static struct xt_match icmp_matchstruct __read_mostly = {
2196 .matchsize = sizeof(struct ipt_icmp), 2198 .matchsize = sizeof(struct ipt_icmp),
2197 .checkentry = icmp_checkentry, 2199 .checkentry = icmp_checkentry,
2198 .proto = IPPROTO_ICMP, 2200 .proto = IPPROTO_ICMP,
2199 .family = AF_INET, 2201 .family = NFPROTO_IPV4,
2200}; 2202};
2201 2203
2202static int __net_init ip_tables_net_init(struct net *net) 2204static int __net_init ip_tables_net_init(struct net *net)
2203{ 2205{
2204 return xt_proto_init(net, AF_INET); 2206 return xt_proto_init(net, NFPROTO_IPV4);
2205} 2207}
2206 2208
2207static void __net_exit ip_tables_net_exit(struct net *net) 2209static void __net_exit ip_tables_net_exit(struct net *net)
2208{ 2210{
2209 xt_proto_fini(net, AF_INET); 2211 xt_proto_fini(net, NFPROTO_IPV4);
2210} 2212}
2211 2213
2212static struct pernet_operations ip_tables_net_ops = { 2214static struct pernet_operations ip_tables_net_ops = {