nf_log_arp.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * (C) 2014 by Pablo Neira Ayuso <pablo@netfilter.org>
  4. *
  5. * Based on code from ebt_log from:
  6. *
  7. * Bart De Schuymer <bdschuym@pandora.be>
  8. * Harald Welte <laforge@netfilter.org>
  9. */
  10. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  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/route.h>
  18. #include <linux/netfilter.h>
  19. #include <linux/netfilter/xt_LOG.h>
  20. #include <net/netfilter/nf_log.h>
  21. static const struct nf_loginfo default_loginfo = {
  22. .type = NF_LOG_TYPE_LOG,
  23. .u = {
  24. .log = {
  25. .level = LOGLEVEL_NOTICE,
  26. .logflags = NF_LOG_DEFAULT_MASK,
  27. },
  28. },
  29. };
  30. struct arppayload {
  31. unsigned char mac_src[ETH_ALEN];
  32. unsigned char ip_src[4];
  33. unsigned char mac_dst[ETH_ALEN];
  34. unsigned char ip_dst[4];
  35. };
  36. static void dump_arp_packet(struct nf_log_buf *m,
  37. const struct nf_loginfo *info,
  38. const struct sk_buff *skb, unsigned int nhoff)
  39. {
  40. const struct arppayload *ap;
  41. struct arppayload _arpp;
  42. const struct arphdr *ah;
  43. unsigned int logflags;
  44. struct arphdr _arph;
  45. ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
  46. if (ah == NULL) {
  47. nf_log_buf_add(m, "TRUNCATED");
  48. return;
  49. }
  50. if (info->type == NF_LOG_TYPE_LOG)
  51. logflags = info->u.log.logflags;
  52. else
  53. logflags = NF_LOG_DEFAULT_MASK;
  54. if (logflags & NF_LOG_MACDECODE) {
  55. nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
  56. eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
  57. nf_log_dump_vlan(m, skb);
  58. nf_log_buf_add(m, "MACPROTO=%04x ",
  59. ntohs(eth_hdr(skb)->h_proto));
  60. }
  61. nf_log_buf_add(m, "ARP HTYPE=%d PTYPE=0x%04x OPCODE=%d",
  62. ntohs(ah->ar_hrd), ntohs(ah->ar_pro), ntohs(ah->ar_op));
  63. /* If it's for Ethernet and the lengths are OK, then log the ARP
  64. * payload.
  65. */
  66. if (ah->ar_hrd != htons(ARPHRD_ETHER) ||
  67. ah->ar_hln != ETH_ALEN ||
  68. ah->ar_pln != sizeof(__be32))
  69. return;
  70. ap = skb_header_pointer(skb, sizeof(_arph), sizeof(_arpp), &_arpp);
  71. if (ap == NULL) {
  72. nf_log_buf_add(m, " INCOMPLETE [%zu bytes]",
  73. skb->len - sizeof(_arph));
  74. return;
  75. }
  76. nf_log_buf_add(m, " MACSRC=%pM IPSRC=%pI4 MACDST=%pM IPDST=%pI4",
  77. ap->mac_src, ap->ip_src, ap->mac_dst, ap->ip_dst);
  78. }
  79. static void nf_log_arp_packet(struct net *net, u_int8_t pf,
  80. unsigned int hooknum, const struct sk_buff *skb,
  81. const struct net_device *in,
  82. const struct net_device *out,
  83. const struct nf_loginfo *loginfo,
  84. const char *prefix)
  85. {
  86. struct nf_log_buf *m;
  87. /* FIXME: Disabled from containers until syslog ns is supported */
  88. if (!net_eq(net, &init_net) && !sysctl_nf_log_all_netns)
  89. return;
  90. m = nf_log_buf_open();
  91. if (!loginfo)
  92. loginfo = &default_loginfo;
  93. nf_log_dump_packet_common(m, pf, hooknum, skb, in, out, loginfo,
  94. prefix);
  95. dump_arp_packet(m, loginfo, skb, 0);
  96. nf_log_buf_close(m);
  97. }
  98. static struct nf_logger nf_arp_logger __read_mostly = {
  99. .name = "nf_log_arp",
  100. .type = NF_LOG_TYPE_LOG,
  101. .logfn = nf_log_arp_packet,
  102. .me = THIS_MODULE,
  103. };
  104. static int __net_init nf_log_arp_net_init(struct net *net)
  105. {
  106. return nf_log_set(net, NFPROTO_ARP, &nf_arp_logger);
  107. }
  108. static void __net_exit nf_log_arp_net_exit(struct net *net)
  109. {
  110. nf_log_unset(net, &nf_arp_logger);
  111. }
  112. static struct pernet_operations nf_log_arp_net_ops = {
  113. .init = nf_log_arp_net_init,
  114. .exit = nf_log_arp_net_exit,
  115. };
  116. static int __init nf_log_arp_init(void)
  117. {
  118. int ret;
  119. ret = register_pernet_subsys(&nf_log_arp_net_ops);
  120. if (ret < 0)
  121. return ret;
  122. ret = nf_log_register(NFPROTO_ARP, &nf_arp_logger);
  123. if (ret < 0) {
  124. pr_err("failed to register logger\n");
  125. goto err1;
  126. }
  127. return 0;
  128. err1:
  129. unregister_pernet_subsys(&nf_log_arp_net_ops);
  130. return ret;
  131. }
  132. static void __exit nf_log_arp_exit(void)
  133. {
  134. unregister_pernet_subsys(&nf_log_arp_net_ops);
  135. nf_log_unregister(&nf_arp_logger);
  136. }
  137. module_init(nf_log_arp_init);
  138. module_exit(nf_log_arp_exit);
  139. MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
  140. MODULE_DESCRIPTION("Netfilter ARP packet logging");
  141. MODULE_LICENSE("GPL");
  142. MODULE_ALIAS_NF_LOGGER(3, 0);