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