libip6t_frag.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include <stdio.h>
  2. #include <xtables.h>
  3. #include <linux/netfilter_ipv6/ip6t_frag.h>
  4. enum {
  5. O_FRAGID = 0,
  6. O_FRAGLEN,
  7. O_FRAGRES,
  8. O_FRAGFIRST,
  9. O_FRAGMORE,
  10. O_FRAGLAST,
  11. F_FRAGMORE = 1 << O_FRAGMORE,
  12. F_FRAGLAST = 1 << O_FRAGLAST,
  13. };
  14. static void frag_help(void)
  15. {
  16. printf(
  17. "frag match options:\n"
  18. "[!] --fragid id[:id] match the id (range)\n"
  19. "[!] --fraglen length total length of this header\n"
  20. " --fragres check the reserved field too\n"
  21. " --fragfirst matches on the first fragment\n"
  22. " [--fragmore|--fraglast] there are more fragments or this\n"
  23. " is the last one\n");
  24. }
  25. #define s struct ip6t_frag
  26. static const struct xt_option_entry frag_opts[] = {
  27. {.name = "fragid", .id = O_FRAGID, .type = XTTYPE_UINT32RC,
  28. .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, ids)},
  29. {.name = "fraglen", .id = O_FRAGLEN, .type = XTTYPE_UINT32,
  30. .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)},
  31. {.name = "fragres", .id = O_FRAGRES, .type = XTTYPE_NONE},
  32. {.name = "fragfirst", .id = O_FRAGFIRST, .type = XTTYPE_NONE},
  33. {.name = "fragmore", .id = O_FRAGMORE, .type = XTTYPE_NONE,
  34. .excl = F_FRAGLAST},
  35. {.name = "fraglast", .id = O_FRAGLAST, .type = XTTYPE_NONE,
  36. .excl = F_FRAGMORE},
  37. XTOPT_TABLEEND,
  38. };
  39. #undef s
  40. static void frag_init(struct xt_entry_match *m)
  41. {
  42. struct ip6t_frag *fraginfo = (void *)m->data;
  43. fraginfo->ids[1] = ~0U;
  44. }
  45. static void frag_parse(struct xt_option_call *cb)
  46. {
  47. struct ip6t_frag *fraginfo = cb->data;
  48. xtables_option_parse(cb);
  49. switch (cb->entry->id) {
  50. case O_FRAGID:
  51. if (cb->nvals == 1)
  52. fraginfo->ids[1] = fraginfo->ids[0];
  53. if (cb->invert)
  54. fraginfo->invflags |= IP6T_FRAG_INV_IDS;
  55. /*
  56. * Note however that IP6T_FRAG_IDS is not tested by anything,
  57. * so it is merely here for completeness.
  58. */
  59. fraginfo->flags |= IP6T_FRAG_IDS;
  60. break;
  61. case O_FRAGLEN:
  62. /*
  63. * As of Linux 3.0, the kernel does not check for
  64. * fraglen at all.
  65. */
  66. if (cb->invert)
  67. fraginfo->invflags |= IP6T_FRAG_INV_LEN;
  68. fraginfo->flags |= IP6T_FRAG_LEN;
  69. break;
  70. case O_FRAGRES:
  71. fraginfo->flags |= IP6T_FRAG_RES;
  72. break;
  73. case O_FRAGFIRST:
  74. fraginfo->flags |= IP6T_FRAG_FST;
  75. break;
  76. case O_FRAGMORE:
  77. fraginfo->flags |= IP6T_FRAG_MF;
  78. break;
  79. case O_FRAGLAST:
  80. fraginfo->flags |= IP6T_FRAG_NMF;
  81. break;
  82. }
  83. }
  84. static void
  85. print_ids(const char *name, uint32_t min, uint32_t max,
  86. int invert)
  87. {
  88. const char *inv = invert ? "!" : "";
  89. if (min != 0 || max != 0xFFFFFFFF || invert) {
  90. printf("%s", name);
  91. if (min == max)
  92. printf(":%s%u", inv, min);
  93. else
  94. printf("s:%s%u:%u", inv, min, max);
  95. }
  96. }
  97. static void frag_print(const void *ip, const struct xt_entry_match *match,
  98. int numeric)
  99. {
  100. const struct ip6t_frag *frag = (struct ip6t_frag *)match->data;
  101. printf(" frag ");
  102. print_ids("id", frag->ids[0], frag->ids[1],
  103. frag->invflags & IP6T_FRAG_INV_IDS);
  104. if (frag->flags & IP6T_FRAG_LEN) {
  105. printf(" length:%s%u",
  106. frag->invflags & IP6T_FRAG_INV_LEN ? "!" : "",
  107. frag->hdrlen);
  108. }
  109. if (frag->flags & IP6T_FRAG_RES)
  110. printf(" reserved");
  111. if (frag->flags & IP6T_FRAG_FST)
  112. printf(" first");
  113. if (frag->flags & IP6T_FRAG_MF)
  114. printf(" more");
  115. if (frag->flags & IP6T_FRAG_NMF)
  116. printf(" last");
  117. if (frag->invflags & ~IP6T_FRAG_INV_MASK)
  118. printf(" Unknown invflags: 0x%X",
  119. frag->invflags & ~IP6T_FRAG_INV_MASK);
  120. }
  121. static void frag_save(const void *ip, const struct xt_entry_match *match)
  122. {
  123. const struct ip6t_frag *fraginfo = (struct ip6t_frag *)match->data;
  124. if (!(fraginfo->ids[0] == 0
  125. && fraginfo->ids[1] == 0xFFFFFFFF)) {
  126. printf("%s --fragid ",
  127. (fraginfo->invflags & IP6T_FRAG_INV_IDS) ? " !" : "");
  128. if (fraginfo->ids[0]
  129. != fraginfo->ids[1])
  130. printf("%u:%u",
  131. fraginfo->ids[0],
  132. fraginfo->ids[1]);
  133. else
  134. printf("%u",
  135. fraginfo->ids[0]);
  136. }
  137. if (fraginfo->flags & IP6T_FRAG_LEN) {
  138. printf("%s --fraglen %u",
  139. (fraginfo->invflags & IP6T_FRAG_INV_LEN) ? " !" : "",
  140. fraginfo->hdrlen);
  141. }
  142. if (fraginfo->flags & IP6T_FRAG_RES)
  143. printf(" --fragres");
  144. if (fraginfo->flags & IP6T_FRAG_FST)
  145. printf(" --fragfirst");
  146. if (fraginfo->flags & IP6T_FRAG_MF)
  147. printf(" --fragmore");
  148. if (fraginfo->flags & IP6T_FRAG_NMF)
  149. printf(" --fraglast");
  150. }
  151. static struct xtables_match frag_mt6_reg = {
  152. .name = "frag",
  153. .version = XTABLES_VERSION,
  154. .family = NFPROTO_IPV6,
  155. .size = XT_ALIGN(sizeof(struct ip6t_frag)),
  156. .userspacesize = XT_ALIGN(sizeof(struct ip6t_frag)),
  157. .help = frag_help,
  158. .init = frag_init,
  159. .print = frag_print,
  160. .save = frag_save,
  161. .x6_parse = frag_parse,
  162. .x6_options = frag_opts,
  163. };
  164. void
  165. _init(void)
  166. {
  167. xtables_register_match(&frag_mt6_reg);
  168. }