Containerized syslog working properly
[safe/jmp/linux-2.6] / net / ipv4 / netfilter / ipt_LOG.c
index d9c37fd..74761de 100644 (file)
@@ -9,8 +9,9 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/module.h>
+#include <linux/syslog.h>
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ipt_LOG.h>
+#include <net/netfilter/nf_log.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("iptables syslog logging module");
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
+MODULE_DESCRIPTION("Xtables: IPv4 packet logging to syslog");
 
 /* Use lock to serialize, so printks don't overlap */
 static DEFINE_SPINLOCK(log_lock);
@@ -41,7 +37,8 @@ static void dump_packet(const struct nf_loginfo *info,
                        const struct sk_buff *skb,
                        unsigned int iphoff)
 {
-       struct iphdr _iph, *ih;
+       struct iphdr _iph;
+       const struct iphdr *ih;
        unsigned int logflags;
 
        if (info->type == NF_LOG_TYPE_LOG)
@@ -58,8 +55,8 @@ static void dump_packet(const struct nf_loginfo *info,
        /* 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(ih->saddr), NIPQUAD(ih->daddr));
+       printk("SRC=%pI4 DST=%pI4 ",
+              &ih->saddr, &ih->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 ",
@@ -78,9 +75,10 @@ static void dump_packet(const struct nf_loginfo *info,
        if (ntohs(ih->frag_off) & IP_OFFSET)
                printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
 
-       if ((logflags & IPT_LOG_IPOPT)
-           && ih->ihl * 4 > sizeof(struct iphdr)) {
-               unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op;
+       if ((logflags & IPT_LOG_IPOPT) &&
+           ih->ihl * 4 > sizeof(struct iphdr)) {
+               const unsigned char *op;
+               unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
                unsigned int i, optsize;
 
                optsize = ih->ihl * 4 - sizeof(struct iphdr);
@@ -100,7 +98,8 @@ static void dump_packet(const struct nf_loginfo *info,
 
        switch (ih->protocol) {
        case IPPROTO_TCP: {
-               struct tcphdr _tcph, *th;
+               struct tcphdr _tcph;
+               const struct tcphdr *th;
 
                /* Max length: 10 "PROTO=TCP " */
                printk("PROTO=TCP ");
@@ -148,10 +147,10 @@ static void dump_packet(const struct nf_loginfo *info,
                /* Max length: 11 "URGP=65535 " */
                printk("URGP=%u ", ntohs(th->urg_ptr));
 
-               if ((logflags & IPT_LOG_TCPOPT)
-                   && th->doff * 4 > sizeof(struct tcphdr)) {
+               if ((logflags & IPT_LOG_TCPOPT) &&
+                   th->doff * 4 > sizeof(struct tcphdr)) {
                        unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
-                       unsigned char *op;
+                       const unsigned char *op;
                        unsigned int i, optsize;
 
                        optsize = th->doff * 4 - sizeof(struct tcphdr);
@@ -173,7 +172,8 @@ static void dump_packet(const struct nf_loginfo *info,
        }
        case IPPROTO_UDP:
        case IPPROTO_UDPLITE: {
-               struct udphdr _udph, *uh;
+               struct udphdr _udph;
+               const struct udphdr *uh;
 
                if (ih->protocol == IPPROTO_UDP)
                        /* Max length: 10 "PROTO=UDP "     */
@@ -200,7 +200,8 @@ static void dump_packet(const struct nf_loginfo *info,
                break;
        }
        case IPPROTO_ICMP: {
-               struct icmphdr _icmph, *ich;
+               struct icmphdr _icmph;
+               const struct icmphdr *ich;
                static const size_t required_len[NR_ICMP_TYPES+1]
                        = { [ICMP_ECHOREPLY] = 4,
                            [ICMP_DEST_UNREACH]
@@ -238,9 +239,9 @@ static void dump_packet(const struct nf_loginfo *info,
                printk("TYPE=%u CODE=%u ", ich->type, ich->code);
 
                /* Max length: 25 "INCOMPLETE [65535 bytes] " */
-               if (ich->type <= NR_ICMP_TYPES
-                   && required_len[ich->type]
-                   && skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
+               if (ich->type <= NR_ICMP_TYPES &&
+                   required_len[ich->type] &&
+                   skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
                        printk("INCOMPLETE [%u bytes] ",
                               skb->len - iphoff - ih->ihl*4);
                        break;
@@ -262,8 +263,7 @@ static void dump_packet(const struct nf_loginfo *info,
                        break;
                case ICMP_REDIRECT:
                        /* Max length: 24 "GATEWAY=255.255.255.255 " */
-                       printk("GATEWAY=%u.%u.%u.%u ",
-                              NIPQUAD(ich->un.gateway));
+                       printk("GATEWAY=%pI4 ", &ich->un.gateway);
                        /* Fall through */
                case ICMP_DEST_UNREACH:
                case ICMP_SOURCE_QUENCH:
@@ -277,15 +277,16 @@ static void dump_packet(const struct nf_loginfo *info,
                        }
 
                        /* Max length: 10 "MTU=65535 " */
-                       if (ich->type == ICMP_DEST_UNREACH
-                           && ich->code == ICMP_FRAG_NEEDED)
+                       if (ich->type == ICMP_DEST_UNREACH &&
+                           ich->code == ICMP_FRAG_NEEDED)
                                printk("MTU=%u ", ntohs(ich->un.frag.mtu));
                }
                break;
        }
        /* Max Length */
        case IPPROTO_AH: {
-               struct ip_auth_hdr _ahdr, *ah;
+               struct ip_auth_hdr _ahdr;
+               const struct ip_auth_hdr *ah;
 
                if (ntohs(ih->frag_off) & IP_OFFSET)
                        break;
@@ -307,7 +308,8 @@ static void dump_packet(const struct nf_loginfo *info,
                break;
        }
        case IPPROTO_ESP: {
-               struct ip_esp_hdr _esph, *eh;
+               struct ip_esp_hdr _esph;
+               const struct ip_esp_hdr *eh;
 
                /* Max length: 10 "PROTO=ESP " */
                printk("PROTO=ESP ");
@@ -337,10 +339,16 @@ static void dump_packet(const struct nf_loginfo *info,
        if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
                read_lock_bh(&skb->sk->sk_callback_lock);
                if (skb->sk->sk_socket && skb->sk->sk_socket->file)
-                       printk("UID=%u ", skb->sk->sk_socket->file->f_uid);
+                       printk("UID=%u GID=%u ",
+                               skb->sk->sk_socket->file->f_cred->fsuid,
+                               skb->sk->sk_socket->file->f_cred->fsgid);
                read_unlock_bh(&skb->sk->sk_callback_lock);
        }
 
+       /* Max length: 16 "MARK=0xFFFFFFFF " */
+       if (!iphoff && skb->mark)
+               printk("MARK=0x%x ", skb->mark);
+
        /* Proto    Max log string length */
        /* IP:      40+46+6+11+127 = 230 */
        /* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
@@ -360,14 +368,14 @@ static struct nf_loginfo default_loginfo = {
        .type   = NF_LOG_TYPE_LOG,
        .u = {
                .log = {
-                       .level    = 0,
+                       .level    = 5,
                        .logflags = NF_LOG_MASK,
                },
        },
 };
 
 static void
-ipt_log_packet(unsigned int pf,
+ipt_log_packet(u_int8_t pf,
               unsigned int hooknum,
               const struct sk_buff *skb,
               const struct net_device *in,
@@ -375,6 +383,14 @@ ipt_log_packet(unsigned int pf,
               const struct nf_loginfo *loginfo,
               const char *prefix)
 {
+       register struct syslog_ns *syslog_ns;
+
+
+       syslog_ns = (struct syslog_ns *)0;
+       if (skb->dev)   /*another syslog_ns possible?   */
+               syslog_ns = skb->dev->syslog_ns;
+       syslog_ns = switch_syslog_ns(syslog_ns);
+
        if (!loginfo)
                loginfo = &default_loginfo;
 
@@ -385,11 +401,13 @@ ipt_log_packet(unsigned int pf,
               out ? out->name : "");
 #ifdef CONFIG_BRIDGE_NETFILTER
        if (skb->nf_bridge) {
-               struct net_device *physindev = skb->nf_bridge->physindev;
-               struct net_device *physoutdev = skb->nf_bridge->physoutdev;
+               const struct net_device *physindev;
+               const struct net_device *physoutdev;
 
+               physindev = skb->nf_bridge->physindev;
                if (physindev && in != physindev)
                        printk("PHYSIN=%s ", physindev->name);
+               physoutdev = skb->nf_bridge->physoutdev;
                if (physoutdev && out != physoutdev)
                        printk("PHYSOUT=%s ", physoutdev->name);
        }
@@ -398,10 +416,10 @@ ipt_log_packet(unsigned int pf,
        if (in && !out) {
                /* MAC logging for input chain only. */
                printk("MAC=");
-               if (skb->dev && skb->dev->hard_header_len
-                   && skb->mac.raw != (void*)skb->nh.iph) {
+               if (skb->dev && skb->dev->hard_header_len &&
+                   skb->mac_header != skb->network_header) {
                        int i;
-                       unsigned char *p = skb->mac.raw;
+                       const unsigned char *p = skb_mac_header(skb);
                        for (i = 0; i < skb->dev->hard_header_len; i++,p++)
                                printk("%02x%c", *p,
                                       i==skb->dev->hard_header_len - 1
@@ -413,85 +431,70 @@ ipt_log_packet(unsigned int pf,
        dump_packet(loginfo, skb, 0);
        printk("\n");
        spin_unlock_bh(&log_lock);
+       (void) switch_syslog_ns(syslog_ns);
 }
 
 static unsigned int
-ipt_log_target(struct sk_buff **pskb,
-              const struct net_device *in,
-              const struct net_device *out,
-              unsigned int hooknum,
-              const struct xt_target *target,
-              const void *targinfo)
+log_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
-       const struct ipt_log_info *loginfo = targinfo;
+       const struct ipt_log_info *loginfo = par->targinfo;
        struct nf_loginfo li;
 
        li.type = NF_LOG_TYPE_LOG;
        li.u.log.level = loginfo->level;
        li.u.log.logflags = loginfo->logflags;
 
-       ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
+       ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, par->out, &li,
                       loginfo->prefix);
        return XT_CONTINUE;
 }
 
-static int ipt_log_checkentry(const char *tablename,
-                             const void *e,
-                             const struct xt_target *target,
-                             void *targinfo,
-                             unsigned int hook_mask)
+static int log_tg_check(const struct xt_tgchk_param *par)
 {
-       const struct ipt_log_info *loginfo = targinfo;
+       const struct ipt_log_info *loginfo = par->targinfo;
 
        if (loginfo->level >= 8) {
-               DEBUGP("LOG: level %u >= 8\n", loginfo->level);
-               return 0;
+               pr_debug("level %u >= 8\n", loginfo->level);
+               return -EINVAL;
        }
        if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
-               DEBUGP("LOG: prefix term %i\n",
-                      loginfo->prefix[sizeof(loginfo->prefix)-1]);
-               return 0;
+               pr_debug("prefix is not null-terminated\n");
+               return -EINVAL;
        }
-       return 1;
+       return 0;
 }
 
-static struct xt_target ipt_log_reg = {
+static struct xt_target log_tg_reg __read_mostly = {
        .name           = "LOG",
-       .family         = AF_INET,
-       .target         = ipt_log_target,
+       .family         = NFPROTO_IPV4,
+       .target         = log_tg,
        .targetsize     = sizeof(struct ipt_log_info),
-       .checkentry     = ipt_log_checkentry,
+       .checkentry     = log_tg_check,
        .me             = THIS_MODULE,
 };
 
-static struct nf_logger ipt_log_logger ={
+static struct nf_logger ipt_log_logger __read_mostly = {
        .name           = "ipt_LOG",
        .logfn          = &ipt_log_packet,
        .me             = THIS_MODULE,
 };
 
-static int __init ipt_log_init(void)
+static int __init log_tg_init(void)
 {
        int ret;
 
-       ret = xt_register_target(&ipt_log_reg);
+       ret = xt_register_target(&log_tg_reg);
        if (ret < 0)
                return ret;
-       if (nf_log_register(PF_INET, &ipt_log_logger) < 0) {
-               printk(KERN_WARNING "ipt_LOG: not logging via system console "
-                      "since somebody else already registered for PF_INET\n");
-               /* we cannot make module load fail here, since otherwise
-                * iptables userspace would abort */
-       }
-
+       nf_log_register(NFPROTO_IPV4, &ipt_log_logger);
        return 0;
 }
 
-static void __exit ipt_log_fini(void)
+static void __exit log_tg_exit(void)
 {
        nf_log_unregister(&ipt_log_logger);
-       xt_unregister_target(&ipt_log_reg);
+       xt_unregister_target(&log_tg_reg);
 }
 
-module_init(ipt_log_init);
-module_exit(ipt_log_fini);
+module_init(log_tg_init);
+module_exit(log_tg_exit);