libxt_CT.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <xtables.h>
  4. #include <linux/netfilter/nf_conntrack_common.h>
  5. #include <linux/netfilter/xt_CT.h>
  6. static void ct_help(void)
  7. {
  8. printf(
  9. "CT target options:\n"
  10. " --notrack Don't track connection\n"
  11. " --helper name Use conntrack helper 'name' for connection\n"
  12. " --ctevents event[,event...] Generate specified conntrack events for connection\n"
  13. " --expevents event[,event...] Generate specified expectation events for connection\n"
  14. " --zone ID Assign/Lookup connection in zone ID\n"
  15. );
  16. }
  17. static void ct_help_v1(void)
  18. {
  19. printf(
  20. "CT target options:\n"
  21. " --notrack Don't track connection\n"
  22. " --helper name Use conntrack helper 'name' for connection\n"
  23. " --timeout name Use timeout policy 'name' for connection\n"
  24. " --ctevents event[,event...] Generate specified conntrack events for connection\n"
  25. " --expevents event[,event...] Generate specified expectation events for connection\n"
  26. " --zone ID Assign/Lookup connection in zone ID\n"
  27. );
  28. }
  29. enum {
  30. O_NOTRACK = 0,
  31. O_HELPER,
  32. O_TIMEOUT,
  33. O_CTEVENTS,
  34. O_EXPEVENTS,
  35. O_ZONE,
  36. };
  37. #define s struct xt_ct_target_info
  38. static const struct xt_option_entry ct_opts[] = {
  39. {.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE},
  40. {.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING,
  41. .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)},
  42. {.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
  43. {.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
  44. {.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16,
  45. .flags = XTOPT_PUT, XTOPT_POINTER(s, zone)},
  46. XTOPT_TABLEEND,
  47. };
  48. #undef s
  49. #define s struct xt_ct_target_info_v1
  50. static const struct xt_option_entry ct_opts_v1[] = {
  51. {.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE},
  52. {.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING,
  53. .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)},
  54. {.name = "timeout", .id = O_TIMEOUT, .type = XTTYPE_STRING,
  55. .flags = XTOPT_PUT, XTOPT_POINTER(s, timeout)},
  56. {.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
  57. {.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
  58. {.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16,
  59. .flags = XTOPT_PUT, XTOPT_POINTER(s, zone)},
  60. XTOPT_TABLEEND,
  61. };
  62. #undef s
  63. struct event_tbl {
  64. const char *name;
  65. unsigned int event;
  66. };
  67. static const struct event_tbl ct_event_tbl[] = {
  68. { "new", IPCT_NEW },
  69. { "related", IPCT_RELATED },
  70. { "destroy", IPCT_DESTROY },
  71. { "reply", IPCT_REPLY },
  72. { "assured", IPCT_ASSURED },
  73. { "protoinfo", IPCT_PROTOINFO },
  74. { "helper", IPCT_HELPER },
  75. { "mark", IPCT_MARK },
  76. { "natseqinfo", IPCT_NATSEQADJ },
  77. { "secmark", IPCT_SECMARK },
  78. };
  79. static const struct event_tbl exp_event_tbl[] = {
  80. { "new", IPEXP_NEW },
  81. };
  82. static uint32_t ct_parse_events(const struct event_tbl *tbl, unsigned int size,
  83. const char *events)
  84. {
  85. char str[strlen(events) + 1], *e = str, *t;
  86. unsigned int mask = 0, i;
  87. strcpy(str, events);
  88. while ((t = strsep(&e, ","))) {
  89. for (i = 0; i < size; i++) {
  90. if (strcmp(t, tbl[i].name))
  91. continue;
  92. mask |= 1 << tbl[i].event;
  93. break;
  94. }
  95. if (i == size)
  96. xtables_error(PARAMETER_PROBLEM, "Unknown event type \"%s\"", t);
  97. }
  98. return mask;
  99. }
  100. static void ct_print_events(const char *pfx, const struct event_tbl *tbl,
  101. unsigned int size, uint32_t mask)
  102. {
  103. const char *sep = "";
  104. unsigned int i;
  105. printf(" %s ", pfx);
  106. for (i = 0; i < size; i++) {
  107. if (mask & (1 << tbl[i].event)) {
  108. printf("%s%s", sep, tbl[i].name);
  109. sep = ",";
  110. }
  111. }
  112. }
  113. static void ct_parse(struct xt_option_call *cb)
  114. {
  115. struct xt_ct_target_info *info = cb->data;
  116. xtables_option_parse(cb);
  117. switch (cb->entry->id) {
  118. case O_NOTRACK:
  119. info->flags |= XT_CT_NOTRACK;
  120. break;
  121. case O_CTEVENTS:
  122. info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), cb->arg);
  123. break;
  124. case O_EXPEVENTS:
  125. info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), cb->arg);
  126. break;
  127. }
  128. }
  129. static void ct_parse_v1(struct xt_option_call *cb)
  130. {
  131. struct xt_ct_target_info_v1 *info = cb->data;
  132. xtables_option_parse(cb);
  133. switch (cb->entry->id) {
  134. case O_NOTRACK:
  135. info->flags |= XT_CT_NOTRACK;
  136. break;
  137. case O_CTEVENTS:
  138. info->ct_events = ct_parse_events(ct_event_tbl,
  139. ARRAY_SIZE(ct_event_tbl),
  140. cb->arg);
  141. break;
  142. case O_EXPEVENTS:
  143. info->exp_events = ct_parse_events(exp_event_tbl,
  144. ARRAY_SIZE(exp_event_tbl),
  145. cb->arg);
  146. break;
  147. }
  148. }
  149. static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric)
  150. {
  151. const struct xt_ct_target_info *info =
  152. (const struct xt_ct_target_info *)target->data;
  153. printf(" CT");
  154. if (info->flags & XT_CT_NOTRACK)
  155. printf(" notrack");
  156. if (info->helper[0])
  157. printf(" helper %s", info->helper);
  158. if (info->ct_events)
  159. ct_print_events("ctevents", ct_event_tbl,
  160. ARRAY_SIZE(ct_event_tbl), info->ct_events);
  161. if (info->exp_events)
  162. ct_print_events("expevents", exp_event_tbl,
  163. ARRAY_SIZE(exp_event_tbl), info->exp_events);
  164. if (info->zone)
  165. printf("zone %u ", info->zone);
  166. }
  167. static void
  168. ct_print_v1(const void *ip, const struct xt_entry_target *target, int numeric)
  169. {
  170. const struct xt_ct_target_info_v1 *info =
  171. (const struct xt_ct_target_info_v1 *)target->data;
  172. printf(" CT");
  173. if (info->flags & XT_CT_NOTRACK)
  174. printf(" notrack");
  175. if (info->helper[0])
  176. printf(" helper %s", info->helper);
  177. if (info->timeout[0])
  178. printf(" timeout %s", info->timeout);
  179. if (info->ct_events)
  180. ct_print_events("ctevents", ct_event_tbl,
  181. ARRAY_SIZE(ct_event_tbl), info->ct_events);
  182. if (info->exp_events)
  183. ct_print_events("expevents", exp_event_tbl,
  184. ARRAY_SIZE(exp_event_tbl), info->exp_events);
  185. if (info->zone)
  186. printf("zone %u ", info->zone);
  187. }
  188. static void ct_save(const void *ip, const struct xt_entry_target *target)
  189. {
  190. const struct xt_ct_target_info *info =
  191. (const struct xt_ct_target_info *)target->data;
  192. if (info->flags & XT_CT_NOTRACK)
  193. printf(" --notrack");
  194. if (info->helper[0])
  195. printf(" --helper %s", info->helper);
  196. if (info->ct_events)
  197. ct_print_events("--ctevents", ct_event_tbl,
  198. ARRAY_SIZE(ct_event_tbl), info->ct_events);
  199. if (info->exp_events)
  200. ct_print_events("--expevents", exp_event_tbl,
  201. ARRAY_SIZE(exp_event_tbl), info->exp_events);
  202. if (info->zone)
  203. printf(" --zone %u", info->zone);
  204. }
  205. static void ct_save_v1(const void *ip, const struct xt_entry_target *target)
  206. {
  207. const struct xt_ct_target_info_v1 *info =
  208. (const struct xt_ct_target_info_v1 *)target->data;
  209. if (info->flags & XT_CT_NOTRACK)
  210. printf(" --notrack");
  211. if (info->helper[0])
  212. printf(" --helper %s", info->helper);
  213. if (info->timeout[0])
  214. printf(" --timeout %s", info->timeout);
  215. if (info->ct_events)
  216. ct_print_events("--ctevents", ct_event_tbl,
  217. ARRAY_SIZE(ct_event_tbl), info->ct_events);
  218. if (info->exp_events)
  219. ct_print_events("--expevents", exp_event_tbl,
  220. ARRAY_SIZE(exp_event_tbl), info->exp_events);
  221. if (info->zone)
  222. printf(" --zone %u", info->zone);
  223. }
  224. static void notrack_ct0_tg_init(struct xt_entry_target *target)
  225. {
  226. struct xt_ct_target_info *info = (void *)target->data;
  227. info->flags = XT_CT_NOTRACK;
  228. }
  229. static void notrack_ct1_tg_init(struct xt_entry_target *target)
  230. {
  231. struct xt_ct_target_info_v1 *info = (void *)target->data;
  232. info->flags = XT_CT_NOTRACK;
  233. }
  234. static struct xtables_target ct_target_reg[] = {
  235. {
  236. .family = NFPROTO_UNSPEC,
  237. .name = "CT",
  238. .version = XTABLES_VERSION,
  239. .size = XT_ALIGN(sizeof(struct xt_ct_target_info)),
  240. .userspacesize = offsetof(struct xt_ct_target_info, ct),
  241. .help = ct_help,
  242. .print = ct_print,
  243. .save = ct_save,
  244. .x6_parse = ct_parse,
  245. .x6_options = ct_opts,
  246. },
  247. {
  248. .family = NFPROTO_UNSPEC,
  249. .name = "CT",
  250. .revision = 1,
  251. .version = XTABLES_VERSION,
  252. .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
  253. .userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
  254. .help = ct_help_v1,
  255. .print = ct_print_v1,
  256. .save = ct_save_v1,
  257. .x6_parse = ct_parse_v1,
  258. .x6_options = ct_opts_v1,
  259. },
  260. {
  261. .family = NFPROTO_UNSPEC,
  262. .name = "NOTRACK",
  263. .real_name = "CT",
  264. .revision = 0,
  265. .version = XTABLES_VERSION,
  266. .size = XT_ALIGN(sizeof(struct xt_ct_target_info)),
  267. .userspacesize = offsetof(struct xt_ct_target_info, ct),
  268. .init = notrack_ct0_tg_init,
  269. },
  270. {
  271. .family = NFPROTO_UNSPEC,
  272. .name = "NOTRACK",
  273. .real_name = "CT",
  274. .revision = 1,
  275. .version = XTABLES_VERSION,
  276. .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
  277. .userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
  278. .init = notrack_ct1_tg_init,
  279. },
  280. {
  281. .family = NFPROTO_UNSPEC,
  282. .name = "NOTRACK",
  283. .revision = 0,
  284. .version = XTABLES_VERSION,
  285. },
  286. };
  287. void _init(void)
  288. {
  289. xtables_register_targets(ct_target_reg, ARRAY_SIZE(ct_target_reg));
  290. }