nf_log_ipv6.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  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. #include <linux/kernel.h>
  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. #include <linux/netfilter.h>
  21. #include <linux/netfilter_ipv6/ip6_tables.h>
  22. #include <linux/netfilter/xt_LOG.h>
  23. #include <net/netfilter/nf_log.h>
  24. static struct nf_loginfo default_loginfo = {
  25. .type = NF_LOG_TYPE_LOG,
  26. .u = {
  27. .log = {
  28. .level = LOGLEVEL_NOTICE,
  29. .logflags = NF_LOG_MASK,
  30. },
  31. },
  32. };
  33. /* One level of recursion won't kill us */
  34. static void dump_ipv6_packet(struct nf_log_buf *m,
  35. const struct nf_loginfo *info,
  36. const struct sk_buff *skb, unsigned int ip6hoff,
  37. int recurse)
  38. {
  39. u_int8_t currenthdr;
  40. int fragment;
  41. struct ipv6hdr _ip6h;
  42. const struct ipv6hdr *ih;
  43. unsigned int ptr;
  44. unsigned int hdrlen = 0;
  45. unsigned int logflags;
  46. if (info->type == NF_LOG_TYPE_LOG)
  47. logflags = info->u.log.logflags;
  48. else
  49. logflags = NF_LOG_MASK;
  50. ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
  51. if (ih == NULL) {
  52. nf_log_buf_add(m, "TRUNCATED");
  53. return;
  54. }
  55. /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
  56. nf_log_buf_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
  57. /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
  58. nf_log_buf_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
  59. ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
  60. (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
  61. ih->hop_limit,
  62. (ntohl(*(__be32 *)ih) & 0x000fffff));
  63. fragment = 0;
  64. ptr = ip6hoff + sizeof(struct ipv6hdr);
  65. currenthdr = ih->nexthdr;
  66. while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
  67. struct ipv6_opt_hdr _hdr;
  68. const struct ipv6_opt_hdr *hp;
  69. hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
  70. if (hp == NULL) {
  71. nf_log_buf_add(m, "TRUNCATED");
  72. return;
  73. }
  74. /* Max length: 48 "OPT (...) " */
  75. if (logflags & XT_LOG_IPOPT)
  76. nf_log_buf_add(m, "OPT ( ");
  77. switch (currenthdr) {
  78. case IPPROTO_FRAGMENT: {
  79. struct frag_hdr _fhdr;
  80. const struct frag_hdr *fh;
  81. nf_log_buf_add(m, "FRAG:");
  82. fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
  83. &_fhdr);
  84. if (fh == NULL) {
  85. nf_log_buf_add(m, "TRUNCATED ");
  86. return;
  87. }
  88. /* Max length: 6 "65535 " */
  89. nf_log_buf_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8);
  90. /* Max length: 11 "INCOMPLETE " */
  91. if (fh->frag_off & htons(0x0001))
  92. nf_log_buf_add(m, "INCOMPLETE ");
  93. nf_log_buf_add(m, "ID:%08x ",
  94. ntohl(fh->identification));
  95. if (ntohs(fh->frag_off) & 0xFFF8)
  96. fragment = 1;
  97. hdrlen = 8;
  98. break;
  99. }
  100. case IPPROTO_DSTOPTS:
  101. case IPPROTO_ROUTING:
  102. case IPPROTO_HOPOPTS:
  103. if (fragment) {
  104. if (logflags & XT_LOG_IPOPT)
  105. nf_log_buf_add(m, ")");
  106. return;
  107. }
  108. hdrlen = ipv6_optlen(hp);
  109. break;
  110. /* Max Length */
  111. case IPPROTO_AH:
  112. if (logflags & XT_LOG_IPOPT) {
  113. struct ip_auth_hdr _ahdr;
  114. const struct ip_auth_hdr *ah;
  115. /* Max length: 3 "AH " */
  116. nf_log_buf_add(m, "AH ");
  117. if (fragment) {
  118. nf_log_buf_add(m, ")");
  119. return;
  120. }
  121. ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
  122. &_ahdr);
  123. if (ah == NULL) {
  124. /*
  125. * Max length: 26 "INCOMPLETE [65535
  126. * bytes] )"
  127. */
  128. nf_log_buf_add(m, "INCOMPLETE [%u bytes] )",
  129. skb->len - ptr);
  130. return;
  131. }
  132. /* Length: 15 "SPI=0xF1234567 */
  133. nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi));
  134. }
  135. hdrlen = (hp->hdrlen+2)<<2;
  136. break;
  137. case IPPROTO_ESP:
  138. if (logflags & XT_LOG_IPOPT) {
  139. struct ip_esp_hdr _esph;
  140. const struct ip_esp_hdr *eh;
  141. /* Max length: 4 "ESP " */
  142. nf_log_buf_add(m, "ESP ");
  143. if (fragment) {
  144. nf_log_buf_add(m, ")");
  145. return;
  146. }
  147. /*
  148. * Max length: 26 "INCOMPLETE [65535 bytes] )"
  149. */
  150. eh = skb_header_pointer(skb, ptr, sizeof(_esph),
  151. &_esph);
  152. if (eh == NULL) {
  153. nf_log_buf_add(m, "INCOMPLETE [%u bytes] )",
  154. skb->len - ptr);
  155. return;
  156. }
  157. /* Length: 16 "SPI=0xF1234567 )" */
  158. nf_log_buf_add(m, "SPI=0x%x )",
  159. ntohl(eh->spi));
  160. }
  161. return;
  162. default:
  163. /* Max length: 20 "Unknown Ext Hdr 255" */
  164. nf_log_buf_add(m, "Unknown Ext Hdr %u", currenthdr);
  165. return;
  166. }
  167. if (logflags & XT_LOG_IPOPT)
  168. nf_log_buf_add(m, ") ");
  169. currenthdr = hp->nexthdr;
  170. ptr += hdrlen;
  171. }
  172. switch (currenthdr) {
  173. case IPPROTO_TCP:
  174. if (nf_log_dump_tcp_header(m, skb, currenthdr, fragment,
  175. ptr, logflags))
  176. return;
  177. break;
  178. case IPPROTO_UDP:
  179. case IPPROTO_UDPLITE:
  180. if (nf_log_dump_udp_header(m, skb, currenthdr, fragment, ptr))
  181. return;
  182. break;
  183. case IPPROTO_ICMPV6: {
  184. struct icmp6hdr _icmp6h;
  185. const struct icmp6hdr *ic;
  186. /* Max length: 13 "PROTO=ICMPv6 " */
  187. nf_log_buf_add(m, "PROTO=ICMPv6 ");
  188. if (fragment)
  189. break;
  190. /* Max length: 25 "INCOMPLETE [65535 bytes] " */
  191. ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
  192. if (ic == NULL) {
  193. nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
  194. skb->len - ptr);
  195. return;
  196. }
  197. /* Max length: 18 "TYPE=255 CODE=255 " */
  198. nf_log_buf_add(m, "TYPE=%u CODE=%u ",
  199. ic->icmp6_type, ic->icmp6_code);
  200. switch (ic->icmp6_type) {
  201. case ICMPV6_ECHO_REQUEST:
  202. case ICMPV6_ECHO_REPLY:
  203. /* Max length: 19 "ID=65535 SEQ=65535 " */
  204. nf_log_buf_add(m, "ID=%u SEQ=%u ",
  205. ntohs(ic->icmp6_identifier),
  206. ntohs(ic->icmp6_sequence));
  207. break;
  208. case ICMPV6_MGM_QUERY:
  209. case ICMPV6_MGM_REPORT:
  210. case ICMPV6_MGM_REDUCTION:
  211. break;
  212. case ICMPV6_PARAMPROB:
  213. /* Max length: 17 "POINTER=ffffffff " */
  214. nf_log_buf_add(m, "POINTER=%08x ",
  215. ntohl(ic->icmp6_pointer));
  216. /* Fall through */
  217. case ICMPV6_DEST_UNREACH:
  218. case ICMPV6_PKT_TOOBIG:
  219. case ICMPV6_TIME_EXCEED:
  220. /* Max length: 3+maxlen */
  221. if (recurse) {
  222. nf_log_buf_add(m, "[");
  223. dump_ipv6_packet(m, info, skb,
  224. ptr + sizeof(_icmp6h), 0);
  225. nf_log_buf_add(m, "] ");
  226. }
  227. /* Max length: 10 "MTU=65535 " */
  228. if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) {
  229. nf_log_buf_add(m, "MTU=%u ",
  230. ntohl(ic->icmp6_mtu));
  231. }
  232. }
  233. break;
  234. }
  235. /* Max length: 10 "PROTO=255 " */
  236. default:
  237. nf_log_buf_add(m, "PROTO=%u ", currenthdr);
  238. }
  239. /* Max length: 15 "UID=4294967295 " */
  240. if ((logflags & XT_LOG_UID) && recurse)
  241. nf_log_dump_sk_uid_gid(m, skb->sk);
  242. /* Max length: 16 "MARK=0xFFFFFFFF " */
  243. if (recurse && skb->mark)
  244. nf_log_buf_add(m, "MARK=0x%x ", skb->mark);
  245. }
  246. static void dump_ipv6_mac_header(struct nf_log_buf *m,
  247. const struct nf_loginfo *info,
  248. const struct sk_buff *skb)
  249. {
  250. struct net_device *dev = skb->dev;
  251. unsigned int logflags = 0;
  252. if (info->type == NF_LOG_TYPE_LOG)
  253. logflags = info->u.log.logflags;
  254. if (!(logflags & XT_LOG_MACDECODE))
  255. goto fallback;
  256. switch (dev->type) {
  257. case ARPHRD_ETHER:
  258. nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
  259. eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
  260. ntohs(eth_hdr(skb)->h_proto));
  261. return;
  262. default:
  263. break;
  264. }
  265. fallback:
  266. nf_log_buf_add(m, "MAC=");
  267. if (dev->hard_header_len &&
  268. skb->mac_header != skb->network_header) {
  269. const unsigned char *p = skb_mac_header(skb);
  270. unsigned int len = dev->hard_header_len;
  271. unsigned int i;
  272. if (dev->type == ARPHRD_SIT) {
  273. p -= ETH_HLEN;
  274. if (p < skb->head)
  275. p = NULL;
  276. }
  277. if (p != NULL) {
  278. nf_log_buf_add(m, "%02x", *p++);
  279. for (i = 1; i < len; i++)
  280. nf_log_buf_add(m, ":%02x", *p++);
  281. }
  282. nf_log_buf_add(m, " ");
  283. if (dev->type == ARPHRD_SIT) {
  284. const struct iphdr *iph =
  285. (struct iphdr *)skb_mac_header(skb);
  286. nf_log_buf_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr,
  287. &iph->daddr);
  288. }
  289. } else {
  290. nf_log_buf_add(m, " ");
  291. }
  292. }
  293. static void nf_log_ip6_packet(struct net *net, u_int8_t pf,
  294. unsigned int hooknum, const struct sk_buff *skb,
  295. const struct net_device *in,
  296. const struct net_device *out,
  297. const struct nf_loginfo *loginfo,
  298. const char *prefix)
  299. {
  300. struct nf_log_buf *m;
  301. /* FIXME: Disabled from containers until syslog ns is supported */
  302. if (!net_eq(net, &init_net))
  303. return;
  304. m = nf_log_buf_open();
  305. if (!loginfo)
  306. loginfo = &default_loginfo;
  307. nf_log_dump_packet_common(m, pf, hooknum, skb, in, out,
  308. loginfo, prefix);
  309. if (in != NULL)
  310. dump_ipv6_mac_header(m, loginfo, skb);
  311. dump_ipv6_packet(m, loginfo, skb, skb_network_offset(skb), 1);
  312. nf_log_buf_close(m);
  313. }
  314. static struct nf_logger nf_ip6_logger __read_mostly = {
  315. .name = "nf_log_ipv6",
  316. .type = NF_LOG_TYPE_LOG,
  317. .logfn = nf_log_ip6_packet,
  318. .me = THIS_MODULE,
  319. };
  320. static int __net_init nf_log_ipv6_net_init(struct net *net)
  321. {
  322. nf_log_set(net, NFPROTO_IPV6, &nf_ip6_logger);
  323. return 0;
  324. }
  325. static void __net_exit nf_log_ipv6_net_exit(struct net *net)
  326. {
  327. nf_log_unset(net, &nf_ip6_logger);
  328. }
  329. static struct pernet_operations nf_log_ipv6_net_ops = {
  330. .init = nf_log_ipv6_net_init,
  331. .exit = nf_log_ipv6_net_exit,
  332. };
  333. static int __init nf_log_ipv6_init(void)
  334. {
  335. int ret;
  336. ret = register_pernet_subsys(&nf_log_ipv6_net_ops);
  337. if (ret < 0)
  338. return ret;
  339. ret = nf_log_register(NFPROTO_IPV6, &nf_ip6_logger);
  340. if (ret < 0) {
  341. pr_err("failed to register logger\n");
  342. goto err1;
  343. }
  344. return 0;
  345. err1:
  346. unregister_pernet_subsys(&nf_log_ipv6_net_ops);
  347. return ret;
  348. }
  349. static void __exit nf_log_ipv6_exit(void)
  350. {
  351. unregister_pernet_subsys(&nf_log_ipv6_net_ops);
  352. nf_log_unregister(&nf_ip6_logger);
  353. }
  354. module_init(nf_log_ipv6_init);
  355. module_exit(nf_log_ipv6_exit);
  356. MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
  357. MODULE_DESCRIPTION("Netfilter IPv6 packet logging");
  358. MODULE_LICENSE("GPL");
  359. MODULE_ALIAS_NF_LOGGER(AF_INET6, 0);