libxt_CONNMARK.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /* Shared library add-on to iptables to add CONNMARK target support.
  2. *
  3. * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
  4. * by Henrik Nordstrom <hno@marasystems.com>
  5. *
  6. * Version 1.1
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. #include <stdbool.h>
  23. #include <stdint.h>
  24. #include <stdio.h>
  25. #include <xtables.h>
  26. #include <linux/netfilter/xt_CONNMARK.h>
  27. struct xt_connmark_target_info {
  28. unsigned long mark;
  29. unsigned long mask;
  30. uint8_t mode;
  31. };
  32. enum {
  33. O_SET_MARK = 0,
  34. O_SAVE_MARK,
  35. O_RESTORE_MARK,
  36. O_AND_MARK,
  37. O_OR_MARK,
  38. O_XOR_MARK,
  39. O_SET_XMARK,
  40. O_CTMASK,
  41. O_NFMASK,
  42. O_MASK,
  43. F_SET_MARK = 1 << O_SET_MARK,
  44. F_SAVE_MARK = 1 << O_SAVE_MARK,
  45. F_RESTORE_MARK = 1 << O_RESTORE_MARK,
  46. F_AND_MARK = 1 << O_AND_MARK,
  47. F_OR_MARK = 1 << O_OR_MARK,
  48. F_XOR_MARK = 1 << O_XOR_MARK,
  49. F_SET_XMARK = 1 << O_SET_XMARK,
  50. F_CTMASK = 1 << O_CTMASK,
  51. F_NFMASK = 1 << O_NFMASK,
  52. F_MASK = 1 << O_MASK,
  53. F_OP_ANY = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
  54. F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
  55. };
  56. static void CONNMARK_help(void)
  57. {
  58. printf(
  59. "CONNMARK target options:\n"
  60. " --set-mark value[/mask] Set conntrack mark value\n"
  61. " --save-mark [--mask mask] Save the packet nfmark in the connection\n"
  62. " --restore-mark [--mask mask] Restore saved nfmark value\n");
  63. }
  64. #define s struct xt_connmark_target_info
  65. static const struct xt_option_entry CONNMARK_opts[] = {
  66. {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
  67. .excl = F_OP_ANY},
  68. {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
  69. .excl = F_OP_ANY},
  70. {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
  71. .excl = F_OP_ANY},
  72. {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32},
  73. XTOPT_TABLEEND,
  74. };
  75. #undef s
  76. #define s struct xt_connmark_tginfo1
  77. static const struct xt_option_entry connmark_tg_opts[] = {
  78. {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
  79. .excl = F_OP_ANY},
  80. {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
  81. .excl = F_OP_ANY},
  82. {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
  83. .excl = F_OP_ANY},
  84. {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
  85. .excl = F_OP_ANY},
  86. {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
  87. .excl = F_OP_ANY},
  88. {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
  89. .excl = F_OP_ANY},
  90. {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
  91. .excl = F_OP_ANY},
  92. {.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
  93. .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
  94. {.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
  95. .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
  96. {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
  97. .excl = F_CTMASK | F_NFMASK},
  98. XTOPT_TABLEEND,
  99. };
  100. #undef s
  101. static void connmark_tg_help(void)
  102. {
  103. printf(
  104. "CONNMARK target options:\n"
  105. " --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n"
  106. " --save-mark [--ctmask mask] [--nfmask mask]\n"
  107. " Copy ctmark to nfmark using masks\n"
  108. " --restore-mark [--ctmask mask] [--nfmask mask]\n"
  109. " Copy nfmark to ctmark using masks\n"
  110. " --set-mark value[/mask] Set conntrack mark value\n"
  111. " --save-mark [--mask mask] Save the packet nfmark in the connection\n"
  112. " --restore-mark [--mask mask] Restore saved nfmark value\n"
  113. " --and-mark value Binary AND the ctmark with bits\n"
  114. " --or-mark value Binary OR the ctmark with bits\n"
  115. " --xor-mark value Binary XOR the ctmark with bits\n"
  116. );
  117. }
  118. static void connmark_tg_init(struct xt_entry_target *target)
  119. {
  120. struct xt_connmark_tginfo1 *info = (void *)target->data;
  121. /*
  122. * Need these defaults for --save-mark/--restore-mark if no
  123. * --ctmark or --nfmask is given.
  124. */
  125. info->ctmask = UINT32_MAX;
  126. info->nfmask = UINT32_MAX;
  127. }
  128. static void CONNMARK_parse(struct xt_option_call *cb)
  129. {
  130. struct xt_connmark_target_info *markinfo = cb->data;
  131. xtables_option_parse(cb);
  132. switch (cb->entry->id) {
  133. case O_SET_MARK:
  134. markinfo->mode = XT_CONNMARK_SET;
  135. markinfo->mark = cb->val.mark;
  136. markinfo->mask = cb->val.mask;
  137. break;
  138. case O_SAVE_MARK:
  139. markinfo->mode = XT_CONNMARK_SAVE;
  140. break;
  141. case O_RESTORE_MARK:
  142. markinfo->mode = XT_CONNMARK_RESTORE;
  143. break;
  144. case O_MASK:
  145. markinfo->mask = cb->val.u32;
  146. break;
  147. }
  148. }
  149. static void connmark_tg_parse(struct xt_option_call *cb)
  150. {
  151. struct xt_connmark_tginfo1 *info = cb->data;
  152. xtables_option_parse(cb);
  153. switch (cb->entry->id) {
  154. case O_SET_XMARK:
  155. info->mode = XT_CONNMARK_SET;
  156. info->ctmark = cb->val.mark;
  157. info->ctmask = cb->val.mask;
  158. break;
  159. case O_SET_MARK:
  160. info->mode = XT_CONNMARK_SET;
  161. info->ctmark = cb->val.mark;
  162. info->ctmask = cb->val.mark | cb->val.mask;
  163. break;
  164. case O_AND_MARK:
  165. info->mode = XT_CONNMARK_SET;
  166. info->ctmark = 0;
  167. info->ctmask = ~cb->val.u32;
  168. break;
  169. case O_OR_MARK:
  170. info->mode = XT_CONNMARK_SET;
  171. info->ctmark = cb->val.u32;
  172. info->ctmask = cb->val.u32;
  173. break;
  174. case O_XOR_MARK:
  175. info->mode = XT_CONNMARK_SET;
  176. info->ctmark = cb->val.u32;
  177. info->ctmask = 0;
  178. break;
  179. case O_SAVE_MARK:
  180. info->mode = XT_CONNMARK_SAVE;
  181. break;
  182. case O_RESTORE_MARK:
  183. info->mode = XT_CONNMARK_RESTORE;
  184. break;
  185. case O_MASK:
  186. info->nfmask = info->ctmask = cb->val.u32;
  187. break;
  188. }
  189. }
  190. static void connmark_tg_check(struct xt_fcheck_call *cb)
  191. {
  192. if (!(cb->xflags & F_OP_ANY))
  193. xtables_error(PARAMETER_PROBLEM,
  194. "CONNMARK target: No operation specified");
  195. }
  196. static void
  197. print_mark(unsigned long mark)
  198. {
  199. printf("0x%lx", mark);
  200. }
  201. static void
  202. print_mask(const char *text, unsigned long mask)
  203. {
  204. if (mask != 0xffffffffUL)
  205. printf("%s0x%lx", text, mask);
  206. }
  207. static void CONNMARK_print(const void *ip,
  208. const struct xt_entry_target *target, int numeric)
  209. {
  210. const struct xt_connmark_target_info *markinfo =
  211. (const struct xt_connmark_target_info *)target->data;
  212. switch (markinfo->mode) {
  213. case XT_CONNMARK_SET:
  214. printf(" CONNMARK set ");
  215. print_mark(markinfo->mark);
  216. print_mask("/", markinfo->mask);
  217. break;
  218. case XT_CONNMARK_SAVE:
  219. printf(" CONNMARK save ");
  220. print_mask("mask ", markinfo->mask);
  221. break;
  222. case XT_CONNMARK_RESTORE:
  223. printf(" CONNMARK restore ");
  224. print_mask("mask ", markinfo->mask);
  225. break;
  226. default:
  227. printf(" ERROR: UNKNOWN CONNMARK MODE");
  228. break;
  229. }
  230. }
  231. static void
  232. connmark_tg_print(const void *ip, const struct xt_entry_target *target,
  233. int numeric)
  234. {
  235. const struct xt_connmark_tginfo1 *info = (const void *)target->data;
  236. switch (info->mode) {
  237. case XT_CONNMARK_SET:
  238. if (info->ctmark == 0)
  239. printf(" CONNMARK and 0x%x",
  240. (unsigned int)(uint32_t)~info->ctmask);
  241. else if (info->ctmark == info->ctmask)
  242. printf(" CONNMARK or 0x%x", info->ctmark);
  243. else if (info->ctmask == 0)
  244. printf(" CONNMARK xor 0x%x", info->ctmark);
  245. else if (info->ctmask == 0xFFFFFFFFU)
  246. printf(" CONNMARK set 0x%x", info->ctmark);
  247. else
  248. printf(" CONNMARK xset 0x%x/0x%x",
  249. info->ctmark, info->ctmask);
  250. break;
  251. case XT_CONNMARK_SAVE:
  252. if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
  253. printf(" CONNMARK save");
  254. else if (info->nfmask == info->ctmask)
  255. printf(" CONNMARK save mask 0x%x", info->nfmask);
  256. else
  257. printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
  258. info->nfmask, info->ctmask);
  259. break;
  260. case XT_CONNMARK_RESTORE:
  261. if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
  262. printf(" CONNMARK restore");
  263. else if (info->ctmask == info->nfmask)
  264. printf(" CONNMARK restore mask 0x%x", info->ctmask);
  265. else
  266. printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
  267. info->ctmask, info->nfmask);
  268. break;
  269. default:
  270. printf(" ERROR: UNKNOWN CONNMARK MODE");
  271. break;
  272. }
  273. }
  274. static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
  275. {
  276. const struct xt_connmark_target_info *markinfo =
  277. (const struct xt_connmark_target_info *)target->data;
  278. switch (markinfo->mode) {
  279. case XT_CONNMARK_SET:
  280. printf(" --set-mark ");
  281. print_mark(markinfo->mark);
  282. print_mask("/", markinfo->mask);
  283. break;
  284. case XT_CONNMARK_SAVE:
  285. printf(" --save-mark ");
  286. print_mask("--mask ", markinfo->mask);
  287. break;
  288. case XT_CONNMARK_RESTORE:
  289. printf(" --restore-mark ");
  290. print_mask("--mask ", markinfo->mask);
  291. break;
  292. default:
  293. printf(" ERROR: UNKNOWN CONNMARK MODE");
  294. break;
  295. }
  296. }
  297. static void CONNMARK_init(struct xt_entry_target *t)
  298. {
  299. struct xt_connmark_target_info *markinfo
  300. = (struct xt_connmark_target_info *)t->data;
  301. markinfo->mask = 0xffffffffUL;
  302. }
  303. static void
  304. connmark_tg_save(const void *ip, const struct xt_entry_target *target)
  305. {
  306. const struct xt_connmark_tginfo1 *info = (const void *)target->data;
  307. switch (info->mode) {
  308. case XT_CONNMARK_SET:
  309. printf(" --set-xmark 0x%x/0x%x", info->ctmark, info->ctmask);
  310. break;
  311. case XT_CONNMARK_SAVE:
  312. printf(" --save-mark --nfmask 0x%x --ctmask 0x%x",
  313. info->nfmask, info->ctmask);
  314. break;
  315. case XT_CONNMARK_RESTORE:
  316. printf(" --restore-mark --nfmask 0x%x --ctmask 0x%x",
  317. info->nfmask, info->ctmask);
  318. break;
  319. default:
  320. printf(" ERROR: UNKNOWN CONNMARK MODE");
  321. break;
  322. }
  323. }
  324. static struct xtables_target connmark_tg_reg[] = {
  325. {
  326. .family = NFPROTO_UNSPEC,
  327. .name = "CONNMARK",
  328. .revision = 0,
  329. .version = XTABLES_VERSION,
  330. .size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
  331. .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
  332. .help = CONNMARK_help,
  333. .init = CONNMARK_init,
  334. .print = CONNMARK_print,
  335. .save = CONNMARK_save,
  336. .x6_parse = CONNMARK_parse,
  337. .x6_fcheck = connmark_tg_check,
  338. .x6_options = CONNMARK_opts,
  339. },
  340. {
  341. .version = XTABLES_VERSION,
  342. .name = "CONNMARK",
  343. .revision = 1,
  344. .family = NFPROTO_UNSPEC,
  345. .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
  346. .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
  347. .help = connmark_tg_help,
  348. .init = connmark_tg_init,
  349. .print = connmark_tg_print,
  350. .save = connmark_tg_save,
  351. .x6_parse = connmark_tg_parse,
  352. .x6_fcheck = connmark_tg_check,
  353. .x6_options = connmark_tg_opts,
  354. },
  355. };
  356. void _init(void)
  357. {
  358. xtables_register_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
  359. }