diff options
author | Harald Welte <laforge@netfilter.org> | 2005-08-09 22:58:27 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:38:07 -0400 |
commit | 608c8e4f7b6e61cc783283e9dff8a465a5ad59bb (patch) | |
tree | 55ca8bed99789cd6af07f6cc6ee99b0cf718a611 /net/core | |
parent | 838ab6364956d9bdcefe84712de1621cf20a40b3 (diff) |
[NETFILTER]: Extend netfilter logging API
This patch is in preparation to nfnetlink_log:
- loggers now have to register struct nf_logger instead of nf_logfn
- nf_log_unregister() replaced by nf_log_unregister_pf() and
nf_log_unregister_logger()
- add comment to ip[6]t_LOG.h to assure nobody redefines flags
- add /proc/net/netfilter/nf_log to tell user which logger is currently
registered for which address family
- if user has configured logging, but no logging backend (logger) is
available, always spit a message to syslog, not just the first time.
- split ip[6]t_LOG.c into two parts:
Backend: Always try to register as logger for the respective address family
Frontend: Always log via nf_log_packet() API
- modify all users of nf_log_packet() to accomodate additional argument
Signed-off-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/netfilter.c | 127 |
1 files changed, 110 insertions, 17 deletions
diff --git a/net/core/netfilter.c b/net/core/netfilter.c index 3e38084ac2bd..98cc61e79fea 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/if.h> | 22 | #include <linux/if.h> |
23 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
24 | #include <linux/inetdevice.h> | 24 | #include <linux/inetdevice.h> |
25 | #include <linux/proc_fs.h> | ||
25 | #include <net/sock.h> | 26 | #include <net/sock.h> |
26 | 27 | ||
27 | /* In this code, we can be waiting indefinitely for userspace to | 28 | /* In this code, we can be waiting indefinitely for userspace to |
@@ -535,11 +536,10 @@ EXPORT_SYMBOL(skb_make_writable); | |||
535 | 536 | ||
536 | #define NF_LOG_PREFIXLEN 128 | 537 | #define NF_LOG_PREFIXLEN 128 |
537 | 538 | ||
538 | static nf_logfn *nf_logging[NPROTO]; /* = NULL */ | 539 | static struct nf_logger *nf_logging[NPROTO]; /* = NULL */ |
539 | static int reported = 0; | ||
540 | static DEFINE_SPINLOCK(nf_log_lock); | 540 | static DEFINE_SPINLOCK(nf_log_lock); |
541 | 541 | ||
542 | int nf_log_register(int pf, nf_logfn *logfn) | 542 | int nf_log_register(int pf, struct nf_logger *logger) |
543 | { | 543 | { |
544 | int ret = -EBUSY; | 544 | int ret = -EBUSY; |
545 | 545 | ||
@@ -547,54 +547,134 @@ int nf_log_register(int pf, nf_logfn *logfn) | |||
547 | * substituting pointer. */ | 547 | * substituting pointer. */ |
548 | spin_lock(&nf_log_lock); | 548 | spin_lock(&nf_log_lock); |
549 | if (!nf_logging[pf]) { | 549 | if (!nf_logging[pf]) { |
550 | rcu_assign_pointer(nf_logging[pf], logfn); | 550 | rcu_assign_pointer(nf_logging[pf], logger); |
551 | ret = 0; | 551 | ret = 0; |
552 | } | 552 | } |
553 | spin_unlock(&nf_log_lock); | 553 | spin_unlock(&nf_log_lock); |
554 | return ret; | 554 | return ret; |
555 | } | 555 | } |
556 | 556 | ||
557 | void nf_log_unregister(int pf, nf_logfn *logfn) | 557 | void nf_log_unregister_pf(int pf) |
558 | { | 558 | { |
559 | spin_lock(&nf_log_lock); | 559 | spin_lock(&nf_log_lock); |
560 | if (nf_logging[pf] == logfn) | 560 | nf_logging[pf] = NULL; |
561 | nf_logging[pf] = NULL; | ||
562 | spin_unlock(&nf_log_lock); | 561 | spin_unlock(&nf_log_lock); |
563 | 562 | ||
564 | /* Give time to concurrent readers. */ | 563 | /* Give time to concurrent readers. */ |
565 | synchronize_net(); | 564 | synchronize_net(); |
566 | } | 565 | } |
566 | |||
567 | void nf_log_unregister_logger(struct nf_logger *logger) | ||
568 | { | ||
569 | int i; | ||
570 | |||
571 | spin_lock(&nf_log_lock); | ||
572 | for (i = 0; i < NPROTO; i++) { | ||
573 | if (nf_logging[i] == logger) | ||
574 | nf_logging[i] = NULL; | ||
575 | } | ||
576 | spin_unlock(&nf_log_lock); | ||
577 | |||
578 | synchronize_net(); | ||
579 | } | ||
567 | 580 | ||
568 | void nf_log_packet(int pf, | 581 | void nf_log_packet(int pf, |
569 | unsigned int hooknum, | 582 | unsigned int hooknum, |
570 | const struct sk_buff *skb, | 583 | const struct sk_buff *skb, |
571 | const struct net_device *in, | 584 | const struct net_device *in, |
572 | const struct net_device *out, | 585 | const struct net_device *out, |
586 | struct nf_loginfo *loginfo, | ||
573 | const char *fmt, ...) | 587 | const char *fmt, ...) |
574 | { | 588 | { |
575 | va_list args; | 589 | va_list args; |
576 | char prefix[NF_LOG_PREFIXLEN]; | 590 | char prefix[NF_LOG_PREFIXLEN]; |
577 | nf_logfn *logfn; | 591 | struct nf_logger *logger; |
578 | 592 | ||
579 | rcu_read_lock(); | 593 | rcu_read_lock(); |
580 | logfn = rcu_dereference(nf_logging[pf]); | 594 | logger = rcu_dereference(nf_logging[pf]); |
581 | if (logfn) { | 595 | if (logger) { |
582 | va_start(args, fmt); | 596 | va_start(args, fmt); |
583 | vsnprintf(prefix, sizeof(prefix), fmt, args); | 597 | vsnprintf(prefix, sizeof(prefix), fmt, args); |
584 | va_end(args); | 598 | va_end(args); |
585 | /* We must read logging before nf_logfn[pf] */ | 599 | /* We must read logging before nf_logfn[pf] */ |
586 | logfn(hooknum, skb, in, out, prefix); | 600 | logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix); |
587 | } else if (!reported) { | 601 | } else if (net_ratelimit()) { |
588 | printk(KERN_WARNING "nf_log_packet: can\'t log yet, " | 602 | printk(KERN_WARNING "nf_log_packet: can\'t log since " |
589 | "no backend logging module loaded in!\n"); | 603 | "no backend logging module loaded in! Please either " |
590 | reported++; | 604 | "load one, or disable logging explicitly\n"); |
591 | } | 605 | } |
592 | rcu_read_unlock(); | 606 | rcu_read_unlock(); |
593 | } | 607 | } |
594 | EXPORT_SYMBOL(nf_log_register); | 608 | EXPORT_SYMBOL(nf_log_register); |
595 | EXPORT_SYMBOL(nf_log_unregister); | 609 | EXPORT_SYMBOL(nf_log_unregister_pf); |
610 | EXPORT_SYMBOL(nf_log_unregister_logger); | ||
596 | EXPORT_SYMBOL(nf_log_packet); | 611 | EXPORT_SYMBOL(nf_log_packet); |
597 | 612 | ||
613 | #ifdef CONFIG_PROC_FS | ||
614 | struct proc_dir_entry *proc_net_netfilter; | ||
615 | EXPORT_SYMBOL(proc_net_netfilter); | ||
616 | |||
617 | static void *seq_start(struct seq_file *seq, loff_t *pos) | ||
618 | { | ||
619 | rcu_read_lock(); | ||
620 | |||
621 | if (*pos >= NPROTO) | ||
622 | return NULL; | ||
623 | |||
624 | return pos; | ||
625 | } | ||
626 | |||
627 | static void *seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
628 | { | ||
629 | (*pos)++; | ||
630 | |||
631 | if (*pos >= NPROTO) | ||
632 | return NULL; | ||
633 | |||
634 | return pos; | ||
635 | } | ||
636 | |||
637 | static void seq_stop(struct seq_file *s, void *v) | ||
638 | { | ||
639 | rcu_read_unlock(); | ||
640 | } | ||
641 | |||
642 | static int seq_show(struct seq_file *s, void *v) | ||
643 | { | ||
644 | loff_t *pos = v; | ||
645 | const struct nf_logger *logger; | ||
646 | |||
647 | logger = rcu_dereference(nf_logging[*pos]); | ||
648 | |||
649 | if (!logger) | ||
650 | return seq_printf(s, "%2lld NONE\n", *pos); | ||
651 | |||
652 | return seq_printf(s, "%2lld %s\n", *pos, logger->name); | ||
653 | } | ||
654 | |||
655 | static struct seq_operations nflog_seq_ops = { | ||
656 | .start = seq_start, | ||
657 | .next = seq_next, | ||
658 | .stop = seq_stop, | ||
659 | .show = seq_show, | ||
660 | }; | ||
661 | |||
662 | static int nflog_open(struct inode *inode, struct file *file) | ||
663 | { | ||
664 | return seq_open(file, &nflog_seq_ops); | ||
665 | } | ||
666 | |||
667 | static struct file_operations nflog_file_ops = { | ||
668 | .owner = THIS_MODULE, | ||
669 | .open = nflog_open, | ||
670 | .read = seq_read, | ||
671 | .llseek = seq_lseek, | ||
672 | .release = seq_release, | ||
673 | }; | ||
674 | |||
675 | #endif /* PROC_FS */ | ||
676 | |||
677 | |||
598 | /* This does not belong here, but locally generated errors need it if connection | 678 | /* This does not belong here, but locally generated errors need it if connection |
599 | tracking in use: without this, connection may not be in hash table, and hence | 679 | tracking in use: without this, connection may not be in hash table, and hence |
600 | manufactured ICMP or RST packets will not be associated with it. */ | 680 | manufactured ICMP or RST packets will not be associated with it. */ |
@@ -613,6 +693,9 @@ void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) | |||
613 | void __init netfilter_init(void) | 693 | void __init netfilter_init(void) |
614 | { | 694 | { |
615 | int i, h; | 695 | int i, h; |
696 | #ifdef CONFIG_PROC_FS | ||
697 | struct proc_dir_entry *pde; | ||
698 | #endif | ||
616 | 699 | ||
617 | queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter), | 700 | queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter), |
618 | GFP_KERNEL); | 701 | GFP_KERNEL); |
@@ -624,6 +707,16 @@ void __init netfilter_init(void) | |||
624 | for (h = 0; h < NF_MAX_HOOKS; h++) | 707 | for (h = 0; h < NF_MAX_HOOKS; h++) |
625 | INIT_LIST_HEAD(&nf_hooks[i][h]); | 708 | INIT_LIST_HEAD(&nf_hooks[i][h]); |
626 | } | 709 | } |
710 | |||
711 | #ifdef CONFIG_PROC_FS | ||
712 | proc_net_netfilter = proc_mkdir("netfilter", proc_net); | ||
713 | if (!proc_net_netfilter) | ||
714 | panic("cannot create netfilter proc entry"); | ||
715 | pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter); | ||
716 | if (!pde) | ||
717 | panic("cannot create /proc/net/netfilter/nf_log"); | ||
718 | pde->proc_fops = &nflog_file_ops; | ||
719 | #endif | ||
627 | } | 720 | } |
628 | 721 | ||
629 | EXPORT_SYMBOL(ip_ct_attach); | 722 | EXPORT_SYMBOL(ip_ct_attach); |