libipt_SAME.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <xtables.h>
  5. #include <linux/netfilter/nf_nat.h>
  6. #include <linux/netfilter_ipv4/ipt_SAME.h>
  7. enum {
  8. O_TO_ADDR = 0,
  9. O_NODST,
  10. O_RANDOM,
  11. F_TO_ADDR = 1 << O_TO_ADDR,
  12. F_RANDOM = 1 << O_RANDOM,
  13. };
  14. static void SAME_help(void)
  15. {
  16. printf(
  17. "SAME target options:\n"
  18. " --to <ipaddr>-<ipaddr>\n"
  19. " Addresses to map source to.\n"
  20. " May be specified more than\n"
  21. " once for multiple ranges.\n"
  22. " --nodst\n"
  23. " Don't use destination-ip in\n"
  24. " source selection\n"
  25. " --random\n"
  26. " Randomize source port\n");
  27. }
  28. static const struct xt_option_entry SAME_opts[] = {
  29. {.name = "to", .id = O_TO_ADDR, .type = XTTYPE_STRING,
  30. .flags = XTOPT_MAND},
  31. {.name = "nodst", .id = O_NODST, .type = XTTYPE_NONE},
  32. {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
  33. XTOPT_TABLEEND,
  34. };
  35. /* Parses range of IPs */
  36. static void parse_to(const char *orig_arg, struct nf_nat_ipv4_range *range)
  37. {
  38. char *dash, *arg;
  39. const struct in_addr *ip;
  40. arg = strdup(orig_arg);
  41. if (arg == NULL)
  42. xtables_error(RESOURCE_PROBLEM, "strdup");
  43. range->flags |= NF_NAT_RANGE_MAP_IPS;
  44. dash = strchr(arg, '-');
  45. if (dash)
  46. *dash = '\0';
  47. ip = xtables_numeric_to_ipaddr(arg);
  48. if (!ip)
  49. xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
  50. arg);
  51. range->min_ip = ip->s_addr;
  52. if (dash) {
  53. ip = xtables_numeric_to_ipaddr(dash+1);
  54. if (!ip)
  55. xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
  56. dash+1);
  57. }
  58. range->max_ip = ip->s_addr;
  59. if (dash)
  60. if (range->min_ip > range->max_ip)
  61. xtables_error(PARAMETER_PROBLEM, "Bad IP range \"%s-%s\"\n",
  62. arg, dash+1);
  63. free(arg);
  64. }
  65. static void SAME_parse(struct xt_option_call *cb)
  66. {
  67. struct ipt_same_info *mr = cb->data;
  68. unsigned int count;
  69. xtables_option_parse(cb);
  70. switch (cb->entry->id) {
  71. case O_TO_ADDR:
  72. if (mr->rangesize == IPT_SAME_MAX_RANGE)
  73. xtables_error(PARAMETER_PROBLEM,
  74. "Too many ranges specified, maximum "
  75. "is %i ranges.\n",
  76. IPT_SAME_MAX_RANGE);
  77. parse_to(cb->arg, &mr->range[mr->rangesize]);
  78. mr->rangesize++;
  79. break;
  80. case O_NODST:
  81. mr->info |= IPT_SAME_NODST;
  82. break;
  83. case O_RANDOM:
  84. for (count=0; count < mr->rangesize; count++)
  85. mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
  86. break;
  87. }
  88. }
  89. static void SAME_fcheck(struct xt_fcheck_call *cb)
  90. {
  91. static const unsigned int f = F_TO_ADDR | F_RANDOM;
  92. struct ipt_same_info *mr = cb->data;
  93. unsigned int count;
  94. if ((cb->xflags & f) == f)
  95. for (count = 0; count < mr->rangesize; ++count)
  96. mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
  97. }
  98. static void SAME_print(const void *ip, const struct xt_entry_target *target,
  99. int numeric)
  100. {
  101. unsigned int count;
  102. const struct ipt_same_info *mr = (const void *)target->data;
  103. int random_selection = 0;
  104. printf(" same:");
  105. for (count = 0; count < mr->rangesize; count++) {
  106. const struct nf_nat_ipv4_range *r = &mr->range[count];
  107. struct in_addr a;
  108. a.s_addr = r->min_ip;
  109. printf("%s", xtables_ipaddr_to_numeric(&a));
  110. a.s_addr = r->max_ip;
  111. if (r->min_ip != r->max_ip)
  112. printf("-%s", xtables_ipaddr_to_numeric(&a));
  113. if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
  114. random_selection = 1;
  115. }
  116. if (mr->info & IPT_SAME_NODST)
  117. printf(" nodst");
  118. if (random_selection)
  119. printf(" random");
  120. }
  121. static void SAME_save(const void *ip, const struct xt_entry_target *target)
  122. {
  123. unsigned int count;
  124. const struct ipt_same_info *mr = (const void *)target->data;
  125. int random_selection = 0;
  126. for (count = 0; count < mr->rangesize; count++) {
  127. const struct nf_nat_ipv4_range *r = &mr->range[count];
  128. struct in_addr a;
  129. a.s_addr = r->min_ip;
  130. printf(" --to %s", xtables_ipaddr_to_numeric(&a));
  131. a.s_addr = r->max_ip;
  132. if (r->min_ip != r->max_ip)
  133. printf("-%s", xtables_ipaddr_to_numeric(&a));
  134. if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
  135. random_selection = 1;
  136. }
  137. if (mr->info & IPT_SAME_NODST)
  138. printf(" --nodst");
  139. if (random_selection)
  140. printf(" --random");
  141. }
  142. static struct xtables_target same_tg_reg = {
  143. .name = "SAME",
  144. .version = XTABLES_VERSION,
  145. .family = NFPROTO_IPV4,
  146. .size = XT_ALIGN(sizeof(struct ipt_same_info)),
  147. .userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)),
  148. .help = SAME_help,
  149. .x6_parse = SAME_parse,
  150. .x6_fcheck = SAME_fcheck,
  151. .print = SAME_print,
  152. .save = SAME_save,
  153. .x6_options = SAME_opts,
  154. };
  155. void _init(void)
  156. {
  157. xtables_register_target(&same_tg_reg);
  158. }