root/net/ipv4/netfilter/nf_log_ipv4.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dump_ipv4_packet
  2. dump_ipv4_mac_header
  3. nf_log_ip_packet
  4. nf_log_ipv4_net_init
  5. nf_log_ipv4_net_exit
  6. nf_log_ipv4_init
  7. nf_log_ipv4_exit

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

/* [<][>][^][v][top][bottom][index][help] */