linux/net/ipv4/netfilter/nf_log_ipv4.c
<<
>>
Prefs
   1/* (C) 1999-2001 Paul `Rusty' Russell
   2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9
  10#include <linux/module.h>
  11#include <linux/spinlock.h>
  12#include <linux/skbuff.h>
  13#include <linux/if_arp.h>
  14#include <linux/ip.h>
  15#include <net/ipv6.h>
  16#include <net/icmp.h>
  17#include <net/udp.h>
  18#include <net/tcp.h>
  19#include <net/route.h>
  20
  21#include <linux/netfilter.h>
  22#include <linux/netfilter/xt_LOG.h>
  23#include <net/netfilter/nf_log.h>
  24
  25static struct nf_loginfo default_loginfo = {
  26        .type   = NF_LOG_TYPE_LOG,
  27        .u = {
  28                .log = {
  29                        .level    = 5,
  30                        .logflags = NF_LOG_MASK,
  31                },
  32        },
  33};
  34
  35/* One level of recursion won't kill us */
  36static void dump_ipv4_packet(struct nf_log_buf *m,
  37                             const struct nf_loginfo *info,
  38                             const struct sk_buff *skb, unsigned int iphoff)
  39{
  40        struct iphdr _iph;
  41        const struct iphdr *ih;
  42        unsigned int logflags;
  43
  44        if (info->type == NF_LOG_TYPE_LOG)
  45                logflags = info->u.log.logflags;
  46        else
  47                logflags = NF_LOG_MASK;
  48
  49        ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
  50        if (ih == NULL) {
  51                nf_log_buf_add(m, "TRUNCATED");
  52                return;
  53        }
  54
  55        /* Important fields:
  56         * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
  57        /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
  58        nf_log_buf_add(m, "SRC=%pI4 DST=%pI4 ", &ih->saddr, &ih->daddr);
  59
  60        /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
  61        nf_log_buf_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
  62                       ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
  63                       ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
  64
  65        /* Max length: 6 "CE DF MF " */
  66        if (ntohs(ih->frag_off) & IP_CE)
  67                nf_log_buf_add(m, "CE ");
  68        if (ntohs(ih->frag_off) & IP_DF)
  69                nf_log_buf_add(m, "DF ");
  70        if (ntohs(ih->frag_off) & IP_MF)
  71                nf_log_buf_add(m, "MF ");
  72
  73        /* Max length: 11 "FRAG:65535 " */
  74        if (ntohs(ih->frag_off) & IP_OFFSET)
  75                nf_log_buf_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
  76
  77        if ((logflags & XT_LOG_IPOPT) &&
  78            ih->ihl * 4 > sizeof(struct iphdr)) {
  79                const unsigned char *op;
  80                unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
  81                unsigned int i, optsize;
  82
  83                optsize = ih->ihl * 4 - sizeof(struct iphdr);
  84                op = skb_header_pointer(skb, iphoff+sizeof(_iph),
  85                                        optsize, _opt);
  86                if (op == NULL) {
  87                        nf_log_buf_add(m, "TRUNCATED");
  88                        return;
  89                }
  90
  91                /* Max length: 127 "OPT (" 15*4*2chars ") " */
  92                nf_log_buf_add(m, "OPT (");
  93                for (i = 0; i < optsize; i++)
  94                        nf_log_buf_add(m, "%02X", op[i]);
  95                nf_log_buf_add(m, ") ");
  96        }
  97
  98        switch (ih->protocol) {
  99        case IPPROTO_TCP:
 100                if (nf_log_dump_tcp_header(m, skb, ih->protocol,
 101                                           ntohs(ih->frag_off) & IP_OFFSET,
 102                                           iphoff+ih->ihl*4, logflags))
 103                        return;
 104                break;
 105        case IPPROTO_UDP:
 106        case IPPROTO_UDPLITE:
 107                if (nf_log_dump_udp_header(m, skb, ih->protocol,
 108                                           ntohs(ih->frag_off) & IP_OFFSET,
 109                                           iphoff+ih->ihl*4))
 110                        return;
 111                break;
 112        case IPPROTO_ICMP: {
 113                struct icmphdr _icmph;
 114                const struct icmphdr *ich;
 115                static const size_t required_len[NR_ICMP_TYPES+1]
 116                        = { [ICMP_ECHOREPLY] = 4,
 117                            [ICMP_DEST_UNREACH]
 118                            = 8 + sizeof(struct iphdr),
 119                            [ICMP_SOURCE_QUENCH]
 120                            = 8 + sizeof(struct iphdr),
 121                            [ICMP_REDIRECT]
 122                            = 8 + sizeof(struct iphdr),
 123                            [ICMP_ECHO] = 4,
 124                            [ICMP_TIME_EXCEEDED]
 125                            = 8 + sizeof(struct iphdr),
 126                            [ICMP_PARAMETERPROB]
 127                            = 8 + sizeof(struct iphdr),
 128                            [ICMP_TIMESTAMP] = 20,
 129                            [ICMP_TIMESTAMPREPLY] = 20,
 130                            [ICMP_ADDRESS] = 12,
 131                            [ICMP_ADDRESSREPLY] = 12 };
 132
 133                /* Max length: 11 "PROTO=ICMP " */
 134                nf_log_buf_add(m, "PROTO=ICMP ");
 135
 136                if (ntohs(ih->frag_off) & IP_OFFSET)
 137                        break;
 138
 139                /* Max length: 25 "INCOMPLETE [65535 bytes] " */
 140                ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
 141                                         sizeof(_icmph), &_icmph);
 142                if (ich == NULL) {
 143                        nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
 144                                       skb->len - iphoff - ih->ihl*4);
 145                        break;
 146                }
 147
 148                /* Max length: 18 "TYPE=255 CODE=255 " */
 149                nf_log_buf_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code);
 150
 151                /* Max length: 25 "INCOMPLETE [65535 bytes] " */
 152                if (ich->type <= NR_ICMP_TYPES &&
 153                    required_len[ich->type] &&
 154                    skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
 155                        nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
 156                                       skb->len - iphoff - ih->ihl*4);
 157                        break;
 158                }
 159
 160                switch (ich->type) {
 161                case ICMP_ECHOREPLY:
 162                case ICMP_ECHO:
 163                        /* Max length: 19 "ID=65535 SEQ=65535 " */
 164                        nf_log_buf_add(m, "ID=%u SEQ=%u ",
 165                                       ntohs(ich->un.echo.id),
 166                                       ntohs(ich->un.echo.sequence));
 167                        break;
 168
 169                case ICMP_PARAMETERPROB:
 170                        /* Max length: 14 "PARAMETER=255 " */
 171                        nf_log_buf_add(m, "PARAMETER=%u ",
 172                                       ntohl(ich->un.gateway) >> 24);
 173                        break;
 174                case ICMP_REDIRECT:
 175                        /* Max length: 24 "GATEWAY=255.255.255.255 " */
 176                        nf_log_buf_add(m, "GATEWAY=%pI4 ", &ich->un.gateway);
 177                        /* Fall through */
 178                case ICMP_DEST_UNREACH:
 179                case ICMP_SOURCE_QUENCH:
 180                case ICMP_TIME_EXCEEDED:
 181                        /* Max length: 3+maxlen */
 182                        if (!iphoff) { /* Only recurse once. */
 183                                nf_log_buf_add(m, "[");
 184                                dump_ipv4_packet(m, info, skb,
 185                                            iphoff + ih->ihl*4+sizeof(_icmph));
 186                                nf_log_buf_add(m, "] ");
 187                        }
 188
 189                        /* Max length: 10 "MTU=65535 " */
 190                        if (ich->type == ICMP_DEST_UNREACH &&
 191                            ich->code == ICMP_FRAG_NEEDED) {
 192                                nf_log_buf_add(m, "MTU=%u ",
 193                                               ntohs(ich->un.frag.mtu));
 194                        }
 195                }
 196                break;
 197        }
 198        /* Max Length */
 199        case IPPROTO_AH: {
 200                struct ip_auth_hdr _ahdr;
 201                const struct ip_auth_hdr *ah;
 202
 203                if (ntohs(ih->frag_off) & IP_OFFSET)
 204                        break;
 205
 206                /* Max length: 9 "PROTO=AH " */
 207                nf_log_buf_add(m, "PROTO=AH ");
 208
 209                /* Max length: 25 "INCOMPLETE [65535 bytes] " */
 210                ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
 211                                        sizeof(_ahdr), &_ahdr);
 212                if (ah == NULL) {
 213                        nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
 214                                       skb->len - iphoff - ih->ihl*4);
 215                        break;
 216                }
 217
 218                /* Length: 15 "SPI=0xF1234567 " */
 219                nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi));
 220                break;
 221        }
 222        case IPPROTO_ESP: {
 223                struct ip_esp_hdr _esph;
 224                const struct ip_esp_hdr *eh;
 225
 226                /* Max length: 10 "PROTO=ESP " */
 227                nf_log_buf_add(m, "PROTO=ESP ");
 228
 229                if (ntohs(ih->frag_off) & IP_OFFSET)
 230                        break;
 231
 232                /* Max length: 25 "INCOMPLETE [65535 bytes] " */
 233                eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
 234                                        sizeof(_esph), &_esph);
 235                if (eh == NULL) {
 236                        nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
 237                                       skb->len - iphoff - ih->ihl*4);
 238                        break;
 239                }
 240
 241                /* Length: 15 "SPI=0xF1234567 " */
 242                nf_log_buf_add(m, "SPI=0x%x ", ntohl(eh->spi));
 243                break;
 244        }
 245        /* Max length: 10 "PROTO 255 " */
 246        default:
 247                nf_log_buf_add(m, "PROTO=%u ", ih->protocol);
 248        }
 249
 250        /* Max length: 15 "UID=4294967295 " */
 251        if ((logflags & XT_LOG_UID) && !iphoff)
 252                nf_log_dump_sk_uid_gid(m, skb->sk);
 253
 254        /* Max length: 16 "MARK=0xFFFFFFFF " */
 255        if (!iphoff && skb->mark)
 256                nf_log_buf_add(m, "MARK=0x%x ", skb->mark);
 257
 258        /* Proto    Max log string length */
 259        /* IP:      40+46+6+11+127 = 230 */
 260        /* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
 261        /* UDP:     10+max(25,20) = 35 */
 262        /* UDPLITE: 14+max(25,20) = 39 */
 263        /* ICMP:    11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
 264        /* ESP:     10+max(25)+15 = 50 */
 265        /* AH:      9+max(25)+15 = 49 */
 266        /* unknown: 10 */
 267
 268        /* (ICMP allows recursion one level deep) */
 269        /* maxlen =  IP + ICMP +  IP + max(TCP,UDP,ICMP,unknown) */
 270        /* maxlen = 230+   91  + 230 + 252 = 803 */
 271}
 272
 273static void dump_ipv4_mac_header(struct nf_log_buf *m,
 274                            const struct nf_loginfo *info,
 275                            const struct sk_buff *skb)
 276{
 277        struct net_device *dev = skb->dev;
 278        unsigned int logflags = 0;
 279
 280        if (info->type == NF_LOG_TYPE_LOG)
 281                logflags = info->u.log.logflags;
 282
 283        if (!(logflags & XT_LOG_MACDECODE))
 284                goto fallback;
 285
 286        switch (dev->type) {
 287        case ARPHRD_ETHER:
 288                nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
 289                               eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
 290                               ntohs(eth_hdr(skb)->h_proto));
 291                return;
 292        default:
 293                break;
 294        }
 295
 296fallback:
 297        nf_log_buf_add(m, "MAC=");
 298        if (dev->hard_header_len &&
 299            skb->mac_header != skb->network_header) {
 300                const unsigned char *p = skb_mac_header(skb);
 301                unsigned int i;
 302
 303                nf_log_buf_add(m, "%02x", *p++);
 304                for (i = 1; i < dev->hard_header_len; i++, p++)
 305                        nf_log_buf_add(m, ":%02x", *p);
 306        }
 307        nf_log_buf_add(m, " ");
 308}
 309
 310static void nf_log_ip_packet(struct net *net, u_int8_t pf,
 311                             unsigned int hooknum, const struct sk_buff *skb,
 312                             const struct net_device *in,
 313                             const struct net_device *out,
 314                             const struct nf_loginfo *loginfo,
 315                             const char *prefix)
 316{
 317        struct nf_log_buf *m;
 318
 319        /* FIXME: Disabled from containers until syslog ns is supported */
 320        if (!net_eq(net, &init_net) && !sysctl_nf_log_all_netns)
 321                return;
 322
 323        m = nf_log_buf_open();
 324
 325        if (!loginfo)
 326                loginfo = &default_loginfo;
 327
 328        nf_log_dump_packet_common(m, pf, hooknum, skb, in,
 329                                  out, loginfo, prefix);
 330
 331        if (in != NULL)
 332                dump_ipv4_mac_header(m, loginfo, skb);
 333
 334        dump_ipv4_packet(m, loginfo, skb, 0);
 335
 336        nf_log_buf_close(m);
 337}
 338
 339static struct nf_logger nf_ip_logger __read_mostly = {
 340        .name           = "nf_log_ipv4",
 341        .type           = NF_LOG_TYPE_LOG,
 342        .logfn          = nf_log_ip_packet,
 343        .me             = THIS_MODULE,
 344};
 345
 346static int __net_init nf_log_ipv4_net_init(struct net *net)
 347{
 348        nf_log_set(net, NFPROTO_IPV4, &nf_ip_logger);
 349        return 0;
 350}
 351
 352static void __net_exit nf_log_ipv4_net_exit(struct net *net)
 353{
 354        nf_log_unset(net, &nf_ip_logger);
 355}
 356
 357static struct pernet_operations nf_log_ipv4_net_ops = {
 358        .init = nf_log_ipv4_net_init,
 359        .exit = nf_log_ipv4_net_exit,
 360};
 361
 362static int __init nf_log_ipv4_init(void)
 363{
 364        int ret;
 365
 366        ret = register_pernet_subsys(&nf_log_ipv4_net_ops);
 367        if (ret < 0)
 368                return ret;
 369
 370        ret = nf_log_register(NFPROTO_IPV4, &nf_ip_logger);
 371        if (ret < 0) {
 372                pr_err("failed to register logger\n");
 373                goto err1;
 374        }
 375
 376        return 0;
 377
 378err1:
 379        unregister_pernet_subsys(&nf_log_ipv4_net_ops);
 380        return ret;
 381}
 382
 383static void __exit nf_log_ipv4_exit(void)
 384{
 385        unregister_pernet_subsys(&nf_log_ipv4_net_ops);
 386        nf_log_unregister(&nf_ip_logger);
 387}
 388
 389module_init(nf_log_ipv4_init);
 390module_exit(nf_log_ipv4_exit);
 391
 392MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 393MODULE_DESCRIPTION("Netfilter IPv4 packet logging");
 394MODULE_LICENSE("GPL");
 395MODULE_ALIAS_NF_LOGGER(AF_INET, 0);
 396