xt_HL.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * TTL modification target for IP tables
  4. * (C) 2000,2005 by Harald Welte <laforge@netfilter.org>
  5. *
  6. * Hop Limit modification target for ip6tables
  7. * Maciej Soltysiak <solt@dns.toxicfilms.tv>
  8. */
  9. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10. #include <linux/module.h>
  11. #include <linux/skbuff.h>
  12. #include <linux/ip.h>
  13. #include <linux/ipv6.h>
  14. #include <net/checksum.h>
  15. #include <linux/netfilter/x_tables.h>
  16. #include <linux/netfilter_ipv4/ipt_TTL.h>
  17. #include <linux/netfilter_ipv6/ip6t_HL.h>
  18. MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
  19. MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
  20. MODULE_DESCRIPTION("Xtables: Hoplimit/TTL Limit field modification target");
  21. MODULE_LICENSE("GPL");
  22. static unsigned int
  23. ttl_tg(struct sk_buff *skb, const struct xt_action_param *par)
  24. {
  25. struct iphdr *iph;
  26. const struct ipt_TTL_info *info = par->targinfo;
  27. int new_ttl;
  28. if (skb_ensure_writable(skb, sizeof(*iph)))
  29. return NF_DROP;
  30. iph = ip_hdr(skb);
  31. switch (info->mode) {
  32. case IPT_TTL_SET:
  33. new_ttl = info->ttl;
  34. break;
  35. case IPT_TTL_INC:
  36. new_ttl = iph->ttl + info->ttl;
  37. if (new_ttl > 255)
  38. new_ttl = 255;
  39. break;
  40. case IPT_TTL_DEC:
  41. new_ttl = iph->ttl - info->ttl;
  42. if (new_ttl < 0)
  43. new_ttl = 0;
  44. break;
  45. default:
  46. new_ttl = iph->ttl;
  47. break;
  48. }
  49. if (new_ttl != iph->ttl) {
  50. csum_replace2(&iph->check, htons(iph->ttl << 8),
  51. htons(new_ttl << 8));
  52. iph->ttl = new_ttl;
  53. }
  54. return XT_CONTINUE;
  55. }
  56. static unsigned int
  57. hl_tg6(struct sk_buff *skb, const struct xt_action_param *par)
  58. {
  59. struct ipv6hdr *ip6h;
  60. const struct ip6t_HL_info *info = par->targinfo;
  61. int new_hl;
  62. if (skb_ensure_writable(skb, sizeof(*ip6h)))
  63. return NF_DROP;
  64. ip6h = ipv6_hdr(skb);
  65. switch (info->mode) {
  66. case IP6T_HL_SET:
  67. new_hl = info->hop_limit;
  68. break;
  69. case IP6T_HL_INC:
  70. new_hl = ip6h->hop_limit + info->hop_limit;
  71. if (new_hl > 255)
  72. new_hl = 255;
  73. break;
  74. case IP6T_HL_DEC:
  75. new_hl = ip6h->hop_limit - info->hop_limit;
  76. if (new_hl < 0)
  77. new_hl = 0;
  78. break;
  79. default:
  80. new_hl = ip6h->hop_limit;
  81. break;
  82. }
  83. ip6h->hop_limit = new_hl;
  84. return XT_CONTINUE;
  85. }
  86. static int ttl_tg_check(const struct xt_tgchk_param *par)
  87. {
  88. const struct ipt_TTL_info *info = par->targinfo;
  89. if (info->mode > IPT_TTL_MAXMODE)
  90. return -EINVAL;
  91. if (info->mode != IPT_TTL_SET && info->ttl == 0)
  92. return -EINVAL;
  93. return 0;
  94. }
  95. static int hl_tg6_check(const struct xt_tgchk_param *par)
  96. {
  97. const struct ip6t_HL_info *info = par->targinfo;
  98. if (info->mode > IP6T_HL_MAXMODE)
  99. return -EINVAL;
  100. if (info->mode != IP6T_HL_SET && info->hop_limit == 0)
  101. return -EINVAL;
  102. return 0;
  103. }
  104. static struct xt_target hl_tg_reg[] __read_mostly = {
  105. {
  106. .name = "TTL",
  107. .revision = 0,
  108. .family = NFPROTO_IPV4,
  109. .target = ttl_tg,
  110. .targetsize = sizeof(struct ipt_TTL_info),
  111. .table = "mangle",
  112. .checkentry = ttl_tg_check,
  113. .me = THIS_MODULE,
  114. },
  115. {
  116. .name = "HL",
  117. .revision = 0,
  118. .family = NFPROTO_IPV6,
  119. .target = hl_tg6,
  120. .targetsize = sizeof(struct ip6t_HL_info),
  121. .table = "mangle",
  122. .checkentry = hl_tg6_check,
  123. .me = THIS_MODULE,
  124. },
  125. };
  126. static int __init hl_tg_init(void)
  127. {
  128. return xt_register_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg));
  129. }
  130. static void __exit hl_tg_exit(void)
  131. {
  132. xt_unregister_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg));
  133. }
  134. module_init(hl_tg_init);
  135. module_exit(hl_tg_exit);
  136. MODULE_ALIAS("ipt_TTL");
  137. MODULE_ALIAS("ip6t_HL");