linux/net/ipv6/netfilter/ip6t_LOG.c
<<
>>
Prefs
   1/*
   2 * This is a module which is used for logging packets.
   3 */
   4
   5/* (C) 2001 Jan Rekorajski <baggins@pld.org.pl>
   6 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/moduleparam.h>
  15#include <linux/skbuff.h>
  16#include <linux/if_arp.h>
  17#include <linux/ip.h>
  18#include <linux/spinlock.h>
  19#include <linux/icmpv6.h>
  20#include <net/udp.h>
  21#include <net/tcp.h>
  22#include <net/ipv6.h>
  23#include <linux/netfilter.h>
  24#include <linux/netfilter/x_tables.h>
  25#include <linux/netfilter_ipv6/ip6_tables.h>
  26#include <net/netfilter/nf_log.h>
  27
  28MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
  29MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog");
  30MODULE_LICENSE("GPL");
  31
  32struct in_device;
  33#include <net/route.h>
  34#include <linux/netfilter_ipv6/ip6t_LOG.h>
  35
  36/* Use lock to serialize, so printks don't overlap */
  37static DEFINE_SPINLOCK(log_lock);
  38
  39/* One level of recursion won't kill us */
  40static void dump_packet(const struct nf_loginfo *info,
  41                        const struct sk_buff *skb, unsigned int ip6hoff,
  42                        int recurse)
  43{
  44        u_int8_t currenthdr;
  45        int fragment;
  46        struct ipv6hdr _ip6h;
  47        const struct ipv6hdr *ih;
  48        unsigned int ptr;
  49        unsigned int hdrlen = 0;
  50        unsigned int logflags;
  51
  52        if (info->type == NF_LOG_TYPE_LOG)
  53                logflags = info->u.log.logflags;
  54        else
  55                logflags = NF_LOG_MASK;
  56
  57        ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
  58        if (ih == NULL) {
  59                printk("TRUNCATED");
  60                return;
  61        }
  62
  63        /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
  64        printk("SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
  65
  66        /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
  67        printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
  68               ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
  69               (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
  70               ih->hop_limit,
  71               (ntohl(*(__be32 *)ih) & 0x000fffff));
  72
  73        fragment = 0;
  74        ptr = ip6hoff + sizeof(struct ipv6hdr);
  75        currenthdr = ih->nexthdr;
  76        while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
  77                struct ipv6_opt_hdr _hdr;
  78                const struct ipv6_opt_hdr *hp;
  79
  80                hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
  81                if (hp == NULL) {
  82                        printk("TRUNCATED");
  83                        return;
  84                }
  85
  86                /* Max length: 48 "OPT (...) " */
  87                if (logflags & IP6T_LOG_IPOPT)
  88                        printk("OPT ( ");
  89
  90                switch (currenthdr) {
  91                case IPPROTO_FRAGMENT: {
  92                        struct frag_hdr _fhdr;
  93                        const struct frag_hdr *fh;
  94
  95                        printk("FRAG:");
  96                        fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
  97                                                &_fhdr);
  98                        if (fh == NULL) {
  99                                printk("TRUNCATED ");
 100                                return;
 101                        }
 102
 103                        /* Max length: 6 "65535 " */
 104                        printk("%u ", ntohs(fh->frag_off) & 0xFFF8);
 105
 106                        /* Max length: 11 "INCOMPLETE " */
 107                        if (fh->frag_off & htons(0x0001))
 108                                printk("INCOMPLETE ");
 109
 110                        printk("ID:%08x ", ntohl(fh->identification));
 111
 112                        if (ntohs(fh->frag_off) & 0xFFF8)
 113                                fragment = 1;
 114
 115                        hdrlen = 8;
 116
 117                        break;
 118                }
 119                case IPPROTO_DSTOPTS:
 120                case IPPROTO_ROUTING:
 121                case IPPROTO_HOPOPTS:
 122                        if (fragment) {
 123                                if (logflags & IP6T_LOG_IPOPT)
 124                                        printk(")");
 125                                return;
 126                        }
 127                        hdrlen = ipv6_optlen(hp);
 128                        break;
 129                /* Max Length */
 130                case IPPROTO_AH:
 131                        if (logflags & IP6T_LOG_IPOPT) {
 132                                struct ip_auth_hdr _ahdr;
 133                                const struct ip_auth_hdr *ah;
 134
 135                                /* Max length: 3 "AH " */
 136                                printk("AH ");
 137
 138                                if (fragment) {
 139                                        printk(")");
 140                                        return;
 141                                }
 142
 143                                ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
 144                                                        &_ahdr);
 145                                if (ah == NULL) {
 146                                        /*
 147                                         * Max length: 26 "INCOMPLETE [65535
 148                                         *  bytes] )"
 149                                         */
 150                                        printk("INCOMPLETE [%u bytes] )",
 151                                               skb->len - ptr);
 152                                        return;
 153                                }
 154
 155                                /* Length: 15 "SPI=0xF1234567 */
 156                                printk("SPI=0x%x ", ntohl(ah->spi));
 157
 158                        }
 159
 160                        hdrlen = (hp->hdrlen+2)<<2;
 161                        break;
 162                case IPPROTO_ESP:
 163                        if (logflags & IP6T_LOG_IPOPT) {
 164                                struct ip_esp_hdr _esph;
 165                                const struct ip_esp_hdr *eh;
 166
 167                                /* Max length: 4 "ESP " */
 168                                printk("ESP ");
 169
 170                                if (fragment) {
 171                                        printk(")");
 172                                        return;
 173                                }
 174
 175                                /*
 176                                 * Max length: 26 "INCOMPLETE [65535 bytes] )"
 177                                 */
 178                                eh = skb_header_pointer(skb, ptr, sizeof(_esph),
 179                                                        &_esph);
 180                                if (eh == NULL) {
 181                                        printk("INCOMPLETE [%u bytes] )",
 182                                               skb->len - ptr);
 183                                        return;
 184                                }
 185
 186                                /* Length: 16 "SPI=0xF1234567 )" */
 187                                printk("SPI=0x%x )", ntohl(eh->spi) );
 188
 189                        }
 190                        return;
 191                default:
 192                        /* Max length: 20 "Unknown Ext Hdr 255" */
 193                        printk("Unknown Ext Hdr %u", currenthdr);
 194                        return;
 195                }
 196                if (logflags & IP6T_LOG_IPOPT)
 197                        printk(") ");
 198
 199                currenthdr = hp->nexthdr;
 200                ptr += hdrlen;
 201        }
 202
 203        switch (currenthdr) {
 204        case IPPROTO_TCP: {
 205                struct tcphdr _tcph;
 206                const struct tcphdr *th;
 207
 208                /* Max length: 10 "PROTO=TCP " */
 209                printk("PROTO=TCP ");
 210
 211                if (fragment)
 212                        break;
 213
 214                /* Max length: 25 "INCOMPLETE [65535 bytes] " */
 215                th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph);
 216                if (th == NULL) {
 217                        printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
 218                        return;
 219                }
 220
 221                /* Max length: 20 "SPT=65535 DPT=65535 " */
 222                printk("SPT=%u DPT=%u ",
 223                       ntohs(th->source), ntohs(th->dest));
 224                /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
 225                if (logflags & IP6T_LOG_TCPSEQ)
 226                        printk("SEQ=%u ACK=%u ",
 227                               ntohl(th->seq), ntohl(th->ack_seq));
 228                /* Max length: 13 "WINDOW=65535 " */
 229                printk("WINDOW=%u ", ntohs(th->window));
 230                /* Max length: 9 "RES=0x3C " */
 231                printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
 232                /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
 233                if (th->cwr)
 234                        printk("CWR ");
 235                if (th->ece)
 236                        printk("ECE ");
 237                if (th->urg)
 238                        printk("URG ");
 239                if (th->ack)
 240                        printk("ACK ");
 241                if (th->psh)
 242                        printk("PSH ");
 243                if (th->rst)
 244                        printk("RST ");
 245                if (th->syn)
 246                        printk("SYN ");
 247                if (th->fin)
 248                        printk("FIN ");
 249                /* Max length: 11 "URGP=65535 " */
 250                printk("URGP=%u ", ntohs(th->urg_ptr));
 251
 252                if ((logflags & IP6T_LOG_TCPOPT)
 253                    && th->doff * 4 > sizeof(struct tcphdr)) {
 254                        u_int8_t _opt[60 - sizeof(struct tcphdr)];
 255                        const u_int8_t *op;
 256                        unsigned int i;
 257                        unsigned int optsize = th->doff * 4
 258                                               - sizeof(struct tcphdr);
 259
 260                        op = skb_header_pointer(skb,
 261                                                ptr + sizeof(struct tcphdr),
 262                                                optsize, _opt);
 263                        if (op == NULL) {
 264                                printk("OPT (TRUNCATED)");
 265                                return;
 266                        }
 267
 268                        /* Max length: 127 "OPT (" 15*4*2chars ") " */
 269                        printk("OPT (");
 270                        for (i =0; i < optsize; i++)
 271                                printk("%02X", op[i]);
 272                        printk(") ");
 273                }
 274                break;
 275        }
 276        case IPPROTO_UDP:
 277        case IPPROTO_UDPLITE: {
 278                struct udphdr _udph;
 279                const struct udphdr *uh;
 280
 281                if (currenthdr == IPPROTO_UDP)
 282                        /* Max length: 10 "PROTO=UDP "     */
 283                        printk("PROTO=UDP " );
 284                else    /* Max length: 14 "PROTO=UDPLITE " */
 285                        printk("PROTO=UDPLITE ");
 286
 287                if (fragment)
 288                        break;
 289
 290                /* Max length: 25 "INCOMPLETE [65535 bytes] " */
 291                uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph);
 292                if (uh == NULL) {
 293                        printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
 294                        return;
 295                }
 296
 297                /* Max length: 20 "SPT=65535 DPT=65535 " */
 298                printk("SPT=%u DPT=%u LEN=%u ",
 299                       ntohs(uh->source), ntohs(uh->dest),
 300                       ntohs(uh->len));
 301                break;
 302        }
 303        case IPPROTO_ICMPV6: {
 304                struct icmp6hdr _icmp6h;
 305                const struct icmp6hdr *ic;
 306
 307                /* Max length: 13 "PROTO=ICMPv6 " */
 308                printk("PROTO=ICMPv6 ");
 309
 310                if (fragment)
 311                        break;
 312
 313                /* Max length: 25 "INCOMPLETE [65535 bytes] " */
 314                ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
 315                if (ic == NULL) {
 316                        printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
 317                        return;
 318                }
 319
 320                /* Max length: 18 "TYPE=255 CODE=255 " */
 321                printk("TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code);
 322
 323                switch (ic->icmp6_type) {
 324                case ICMPV6_ECHO_REQUEST:
 325                case ICMPV6_ECHO_REPLY:
 326                        /* Max length: 19 "ID=65535 SEQ=65535 " */
 327                        printk("ID=%u SEQ=%u ",
 328                                ntohs(ic->icmp6_identifier),
 329                                ntohs(ic->icmp6_sequence));
 330                        break;
 331                case ICMPV6_MGM_QUERY:
 332                case ICMPV6_MGM_REPORT:
 333                case ICMPV6_MGM_REDUCTION:
 334                        break;
 335
 336                case ICMPV6_PARAMPROB:
 337                        /* Max length: 17 "POINTER=ffffffff " */
 338                        printk("POINTER=%08x ", ntohl(ic->icmp6_pointer));
 339                        /* Fall through */
 340                case ICMPV6_DEST_UNREACH:
 341                case ICMPV6_PKT_TOOBIG:
 342                case ICMPV6_TIME_EXCEED:
 343                        /* Max length: 3+maxlen */
 344                        if (recurse) {
 345                                printk("[");
 346                                dump_packet(info, skb, ptr + sizeof(_icmp6h),
 347                                            0);
 348                                printk("] ");
 349                        }
 350
 351                        /* Max length: 10 "MTU=65535 " */
 352                        if (ic->icmp6_type == ICMPV6_PKT_TOOBIG)
 353                                printk("MTU=%u ", ntohl(ic->icmp6_mtu));
 354                }
 355                break;
 356        }
 357        /* Max length: 10 "PROTO=255 " */
 358        default:
 359                printk("PROTO=%u ", currenthdr);
 360        }
 361
 362        /* Max length: 15 "UID=4294967295 " */
 363        if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) {
 364                read_lock_bh(&skb->sk->sk_callback_lock);
 365                if (skb->sk->sk_socket && skb->sk->sk_socket->file)
 366                        printk("UID=%u GID=%u ",
 367                                skb->sk->sk_socket->file->f_cred->fsuid,
 368                                skb->sk->sk_socket->file->f_cred->fsgid);
 369                read_unlock_bh(&skb->sk->sk_callback_lock);
 370        }
 371
 372        /* Max length: 16 "MARK=0xFFFFFFFF " */
 373        if (!recurse && skb->mark)
 374                printk("MARK=0x%x ", skb->mark);
 375}
 376
 377static struct nf_loginfo default_loginfo = {
 378        .type   = NF_LOG_TYPE_LOG,
 379        .u = {
 380                .log = {
 381                        .level    = 0,
 382                        .logflags = NF_LOG_MASK,
 383                },
 384        },
 385};
 386
 387static void
 388ip6t_log_packet(u_int8_t pf,
 389                unsigned int hooknum,
 390                const struct sk_buff *skb,
 391                const struct net_device *in,
 392                const struct net_device *out,
 393                const struct nf_loginfo *loginfo,
 394                const char *prefix)
 395{
 396        if (!loginfo)
 397                loginfo = &default_loginfo;
 398
 399        spin_lock_bh(&log_lock);
 400        printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
 401                prefix,
 402                in ? in->name : "",
 403                out ? out->name : "");
 404        if (in && !out) {
 405                unsigned int len;
 406                /* MAC logging for input chain only. */
 407                printk("MAC=");
 408                if (skb->dev && (len = skb->dev->hard_header_len) &&
 409                    skb->mac_header != skb->network_header) {
 410                        const unsigned char *p = skb_mac_header(skb);
 411                        int i;
 412
 413                        if (skb->dev->type == ARPHRD_SIT &&
 414                            (p -= ETH_HLEN) < skb->head)
 415                                p = NULL;
 416
 417                        if (p != NULL) {
 418                                for (i = 0; i < len; i++)
 419                                        printk("%02x%s", p[i],
 420                                               i == len - 1 ? "" : ":");
 421                        }
 422                        printk(" ");
 423
 424                        if (skb->dev->type == ARPHRD_SIT) {
 425                                const struct iphdr *iph =
 426                                        (struct iphdr *)skb_mac_header(skb);
 427                                printk("TUNNEL=%pI4->%pI4 ",
 428                                       &iph->saddr, &iph->daddr);
 429                        }
 430                } else
 431                        printk(" ");
 432        }
 433
 434        dump_packet(loginfo, skb, skb_network_offset(skb), 1);
 435        printk("\n");
 436        spin_unlock_bh(&log_lock);
 437}
 438
 439static unsigned int
 440log_tg6(struct sk_buff *skb, const struct xt_target_param *par)
 441{
 442        const struct ip6t_log_info *loginfo = par->targinfo;
 443        struct nf_loginfo li;
 444
 445        li.type = NF_LOG_TYPE_LOG;
 446        li.u.log.level = loginfo->level;
 447        li.u.log.logflags = loginfo->logflags;
 448
 449        ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, par->out,
 450                        &li, loginfo->prefix);
 451        return XT_CONTINUE;
 452}
 453
 454
 455static bool log_tg6_check(const struct xt_tgchk_param *par)
 456{
 457        const struct ip6t_log_info *loginfo = par->targinfo;
 458
 459        if (loginfo->level >= 8) {
 460                pr_debug("LOG: level %u >= 8\n", loginfo->level);
 461                return false;
 462        }
 463        if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
 464                pr_debug("LOG: prefix term %i\n",
 465                         loginfo->prefix[sizeof(loginfo->prefix)-1]);
 466                return false;
 467        }
 468        return true;
 469}
 470
 471static struct xt_target log_tg6_reg __read_mostly = {
 472        .name           = "LOG",
 473        .family         = NFPROTO_IPV6,
 474        .target         = log_tg6,
 475        .targetsize     = sizeof(struct ip6t_log_info),
 476        .checkentry     = log_tg6_check,
 477        .me             = THIS_MODULE,
 478};
 479
 480static struct nf_logger ip6t_logger __read_mostly = {
 481        .name           = "ip6t_LOG",
 482        .logfn          = &ip6t_log_packet,
 483        .me             = THIS_MODULE,
 484};
 485
 486static int __init log_tg6_init(void)
 487{
 488        int ret;
 489
 490        ret = xt_register_target(&log_tg6_reg);
 491        if (ret < 0)
 492                return ret;
 493        nf_log_register(NFPROTO_IPV6, &ip6t_logger);
 494        return 0;
 495}
 496
 497static void __exit log_tg6_exit(void)
 498{
 499        nf_log_unregister(&ip6t_logger);
 500        xt_unregister_target(&log_tg6_reg);
 501}
 502
 503module_init(log_tg6_init);
 504module_exit(log_tg6_exit);
 505