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