010-add-set-dscpmark-support.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. From 74267bacce0c43e5038b0377cb7c08f1ad9d50a3 Mon Sep 17 00:00:00 2001
  2. From: Kevin Darbyshire-Bryant <[email protected]>
  3. Date: Sat, 23 Mar 2019 10:21:03 +0000
  4. Subject: [PATCH] iptables: connmark - add set-dscpmark option for openwrt
  5. Naive user space front end to xt_connmark 'setdscp' option.
  6. iptables -A QOS_MARK_eth0 -t mangle -j CONNMARK --set-dscpmark 0xfc000000/0x01000000
  7. This version has a hack to support a backport to 4.14
  8. Signed-off-by: Kevin Darbyshire-Bryant <[email protected]>
  9. ---
  10. extensions/libxt_CONNMARK.c | 315 +++++++++++++++++++++++++-
  11. include/linux/netfilter/xt_connmark.h | 10 +
  12. 2 files changed, 324 insertions(+), 1 deletion(-)
  13. diff --git a/extensions/libxt_CONNMARK.c b/extensions/libxt_CONNMARK.c
  14. index 21e10913..c777b110 100644
  15. --- a/extensions/libxt_CONNMARK.c
  16. +++ b/extensions/libxt_CONNMARK.c
  17. @@ -22,6 +22,7 @@
  18. #include <stdbool.h>
  19. #include <stdint.h>
  20. #include <stdio.h>
  21. +#include <strings.h>
  22. #include <xtables.h>
  23. #include <linux/netfilter/xt_CONNMARK.h>
  24. @@ -49,6 +50,7 @@ enum {
  25. O_CTMASK,
  26. O_NFMASK,
  27. O_MASK,
  28. + O_DSCP_MARK,
  29. F_SET_MARK = 1 << O_SET_MARK,
  30. F_SAVE_MARK = 1 << O_SAVE_MARK,
  31. F_RESTORE_MARK = 1 << O_RESTORE_MARK,
  32. @@ -61,8 +63,10 @@ enum {
  33. F_CTMASK = 1 << O_CTMASK,
  34. F_NFMASK = 1 << O_NFMASK,
  35. F_MASK = 1 << O_MASK,
  36. + F_DSCP_MARK = 1 << O_DSCP_MARK,
  37. F_OP_ANY = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
  38. - F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
  39. + F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK |
  40. + F_DSCP_MARK,
  41. };
  42. static const char *const xt_connmark_shift_ops[] = {
  43. @@ -114,6 +118,8 @@ static const struct xt_option_entry connmark_tg_opts[] = {
  44. .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
  45. {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
  46. .excl = F_CTMASK | F_NFMASK},
  47. + {.name = "set-dscpmark", .id = O_DSCP_MARK, .type = XTTYPE_MARKMASK32,
  48. + .excl = F_OP_ANY},
  49. XTOPT_TABLEEND,
  50. };
  51. #undef s
  52. @@ -148,6 +154,38 @@ static const struct xt_option_entry connmark_tg_opts_v2[] = {
  53. };
  54. #undef s
  55. +#define s struct xt_connmark_tginfo3
  56. +static const struct xt_option_entry connmark_tg_opts_v3[] = {
  57. + {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
  58. + .excl = F_OP_ANY},
  59. + {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
  60. + .excl = F_OP_ANY},
  61. + {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
  62. + .excl = F_OP_ANY},
  63. + {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
  64. + .excl = F_OP_ANY},
  65. + {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
  66. + .excl = F_OP_ANY},
  67. + {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
  68. + .excl = F_OP_ANY},
  69. + {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
  70. + .excl = F_OP_ANY},
  71. + {.name = "left-shift-mark", .id = O_LEFT_SHIFT_MARK, .type = XTTYPE_UINT8,
  72. + .min = 0, .max = 32},
  73. + {.name = "right-shift-mark", .id = O_RIGHT_SHIFT_MARK, .type = XTTYPE_UINT8,
  74. + .min = 0, .max = 32},
  75. + {.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
  76. + .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
  77. + {.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
  78. + .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
  79. + {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
  80. + .excl = F_CTMASK | F_NFMASK},
  81. + {.name = "set-dscpmark", .id = O_DSCP_MARK, .type = XTTYPE_MARKMASK32,
  82. + .excl = F_OP_ANY},
  83. + XTOPT_TABLEEND,
  84. +};
  85. +#undef s
  86. +
  87. static void connmark_tg_help(void)
  88. {
  89. printf(
  90. @@ -175,6 +213,15 @@ static void connmark_tg_help_v2(void)
  91. );
  92. }
  93. +static void connmark_tg_help_v3(void)
  94. +{
  95. + connmark_tg_help_v2();
  96. + printf(
  97. +" --set-dscpmark value/mask Save DSCP to conntrack mark value\n"
  98. +);
  99. +}
  100. +
  101. +
  102. static void connmark_tg_init(struct xt_entry_target *target)
  103. {
  104. struct xt_connmark_tginfo1 *info = (void *)target->data;
  105. @@ -199,6 +246,16 @@ static void connmark_tg_init_v2(struct xt_entry_target *target)
  106. info->shift_bits = 0;
  107. }
  108. +static void connmark_tg_init_v3(struct xt_entry_target *target)
  109. +{
  110. + struct xt_connmark_tginfo3 *info;
  111. +
  112. + connmark_tg_init_v2(target);
  113. + info = (void *)target->data;
  114. +
  115. + info->func = 0;
  116. +}
  117. +
  118. static void CONNMARK_parse(struct xt_option_call *cb)
  119. {
  120. struct xt_connmark_target_info *markinfo = cb->data;
  121. @@ -253,6 +310,23 @@ static void connmark_tg_parse(struct xt_option_call *cb)
  122. info->ctmark = cb->val.u32;
  123. info->ctmask = 0;
  124. break;
  125. + case O_DSCP_MARK:
  126. +/* we sneaky sneaky this. nfmask isn't used by the set mark functionality
  127. + * and by default is set to uint32max. We can use the top bit as a flag
  128. + * that we're in DSCP_MARK submode of SET_MARK, if set then it's normal
  129. + * if unset then we're in DSCP_MARK
  130. + */
  131. + info->mode = XT_CONNMARK_SET;
  132. + info->ctmark = cb->val.mark;
  133. + info->ctmask = cb->val.mask;
  134. + info->nfmask = info->ctmark ? ffs(info->ctmark) - 1 : 0;
  135. + /* need 6 contiguous bits */
  136. + if ((~0 & (info->ctmark >> info->nfmask)) != 0x3f)
  137. + xtables_error(PARAMETER_PROBLEM,
  138. + "CONNMARK set-dscpmark: need 6 contiguous dscpmask bits");
  139. + if (info->ctmark & info->ctmask)
  140. + xtables_error(PARAMETER_PROBLEM,
  141. + "CONNMARK set-dscpmark: dscpmask/statemask bits overlap");
  142. case O_SAVE_MARK:
  143. info->mode = XT_CONNMARK_SAVE;
  144. break;
  145. @@ -320,6 +394,78 @@ static void connmark_tg_parse_v2(struct xt_option_call *cb)
  146. }
  147. }
  148. +static void connmark_tg_parse_v3(struct xt_option_call *cb)
  149. +{
  150. + struct xt_connmark_tginfo3 *info = cb->data;
  151. +
  152. + xtables_option_parse(cb);
  153. + switch (cb->entry->id) {
  154. + case O_SET_XMARK:
  155. + info->mode = XT_CONNMARK_SET;
  156. + info->func = XT_CONNMARK_VALUE;
  157. + info->ctmark = cb->val.mark;
  158. + info->ctmask = cb->val.mask;
  159. + break;
  160. + case O_SET_MARK:
  161. + info->mode = XT_CONNMARK_SET;
  162. + info->func = XT_CONNMARK_VALUE;
  163. + info->ctmark = cb->val.mark;
  164. + info->ctmask = cb->val.mark | cb->val.mask;
  165. + break;
  166. + case O_AND_MARK:
  167. + info->mode = XT_CONNMARK_SET;
  168. + info->func = XT_CONNMARK_VALUE;
  169. + info->ctmark = 0;
  170. + info->ctmask = ~cb->val.u32;
  171. + break;
  172. + case O_OR_MARK:
  173. + info->mode = XT_CONNMARK_SET;
  174. + info->func = XT_CONNMARK_VALUE;
  175. + info->ctmark = cb->val.u32;
  176. + info->ctmask = cb->val.u32;
  177. + break;
  178. + case O_XOR_MARK:
  179. + info->mode = XT_CONNMARK_SET;
  180. + info->func = XT_CONNMARK_VALUE;
  181. + info->ctmark = cb->val.u32;
  182. + info->ctmask = 0;
  183. + break;
  184. + case O_DSCP_MARK:
  185. + info->mode = XT_CONNMARK_SET;
  186. + info->func = XT_CONNMARK_DSCP;
  187. + info->ctmark = cb->val.mark;
  188. + info->ctmask = cb->val.mask;
  189. + info->shift_bits = info->ctmark ? ffs(info->ctmark) - 1 : 0;
  190. + /* need 6 contiguous bits */
  191. + if ((~0 & (info->ctmark >> info->shift_bits)) != 0x3f)
  192. + xtables_error(PARAMETER_PROBLEM,
  193. + "CONNMARK set-dscpmark: need 6 contiguous dscpmask bits");
  194. + if (info->ctmark & info->ctmask)
  195. + xtables_error(PARAMETER_PROBLEM,
  196. + "CONNMARK set-dscpmark: dscpmask/statemask bits overlap");
  197. + break;
  198. + case O_SAVE_MARK:
  199. + info->mode = XT_CONNMARK_SAVE;
  200. + break;
  201. + case O_RESTORE_MARK:
  202. + info->mode = XT_CONNMARK_RESTORE;
  203. + break;
  204. + case O_MASK:
  205. + info->nfmask = info->ctmask = cb->val.u32;
  206. + break;
  207. + case O_LEFT_SHIFT_MARK:
  208. + info->shift_dir = D_SHIFT_LEFT;
  209. + info->shift_bits = cb->val.u8;
  210. + break;
  211. + case O_RIGHT_SHIFT_MARK:
  212. + info->shift_dir = D_SHIFT_RIGHT;
  213. + info->shift_bits = cb->val.u8;
  214. + break;
  215. + default:
  216. + break;
  217. + }
  218. +}
  219. +
  220. static void connmark_tg_check(struct xt_fcheck_call *cb)
  221. {
  222. if (!(cb->xflags & F_OP_ANY))
  223. @@ -463,6 +609,65 @@ connmark_tg_print_v2(const void *ip, const struct xt_entry_target *target,
  224. }
  225. }
  226. +static void
  227. +connmark_tg_print_v3(const void *ip, const struct xt_entry_target *target,
  228. + int numeric)
  229. +{
  230. + const struct xt_connmark_tginfo3 *info = (const void *)target->data;
  231. + const char *shift_op = xt_connmark_shift_ops[info->shift_dir];
  232. +
  233. + switch (info->mode) {
  234. + case XT_CONNMARK_SET:
  235. + if (info->func & XT_CONNMARK_DSCP) {
  236. + printf(" CONNMARK DSCP 0x%x/0x%x",
  237. + info->ctmark, info->ctmask);
  238. + }
  239. + if (info->func & XT_CONNMARK_VALUE) {
  240. + if (info->ctmark == 0)
  241. + printf(" CONNMARK and 0x%x",
  242. + (unsigned int)(uint32_t)~info->ctmask);
  243. + else if (info->ctmark == info->ctmask)
  244. + printf(" CONNMARK or 0x%x", info->ctmark);
  245. + else if (info->ctmask == 0)
  246. + printf(" CONNMARK xor 0x%x", info->ctmark);
  247. + else if (info->ctmask == 0xFFFFFFFFU)
  248. + printf(" CONNMARK set 0x%x", info->ctmark);
  249. + else
  250. + printf(" CONNMARK xset 0x%x/0x%x",
  251. + info->ctmark, info->ctmask);
  252. + }
  253. + break;
  254. + case XT_CONNMARK_SAVE:
  255. + if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
  256. + printf(" CONNMARK save");
  257. + else if (info->nfmask == info->ctmask)
  258. + printf(" CONNMARK save mask 0x%x", info->nfmask);
  259. + else
  260. + printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
  261. + info->nfmask, info->ctmask);
  262. + break;
  263. + case XT_CONNMARK_RESTORE:
  264. + if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
  265. + printf(" CONNMARK restore");
  266. + else if (info->ctmask == info->nfmask)
  267. + printf(" CONNMARK restore mask 0x%x", info->ctmask);
  268. + else
  269. + printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
  270. + info->ctmask, info->nfmask);
  271. + break;
  272. +
  273. + default:
  274. + printf(" ERROR: UNKNOWN CONNMARK MODE");
  275. + break;
  276. + }
  277. +
  278. + if (info->mode <= XT_CONNMARK_RESTORE &&
  279. + !(info->mode == XT_CONNMARK_SET && info->func == XT_CONNMARK_DSCP) &&
  280. + info->shift_bits != 0) {
  281. + printf(" %s %u", shift_op, info->shift_bits);
  282. + }
  283. +}
  284. +
  285. static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
  286. {
  287. const struct xt_connmark_target_info *markinfo =
  288. @@ -548,6 +753,38 @@ connmark_tg_save_v2(const void *ip, const struct xt_entry_target *target)
  289. }
  290. }
  291. +static void
  292. +connmark_tg_save_v3(const void *ip, const struct xt_entry_target *target)
  293. +{
  294. + const struct xt_connmark_tginfo3 *info = (const void *)target->data;
  295. + const char *shift_op = xt_connmark_shift_ops[info->shift_dir];
  296. +
  297. + switch (info->mode) {
  298. + case XT_CONNMARK_SET:
  299. + if (info->func & XT_CONNMARK_VALUE)
  300. + printf(" --set-xmark 0x%x/0x%x", info->ctmark, info->ctmask);
  301. + if (info->func & XT_CONNMARK_DSCP)
  302. + printf(" --set-dscpmark 0x%x/0x%x", info->ctmark, info->ctmask);
  303. + break;
  304. + case XT_CONNMARK_SAVE:
  305. + printf(" --save-mark --nfmask 0x%x --ctmask 0x%x",
  306. + info->nfmask, info->ctmask);
  307. + break;
  308. + case XT_CONNMARK_RESTORE:
  309. + printf(" --restore-mark --nfmask 0x%x --ctmask 0x%x",
  310. + info->nfmask, info->ctmask);
  311. + break;
  312. + default:
  313. + printf(" ERROR: UNKNOWN CONNMARK MODE");
  314. + break;
  315. + }
  316. + if (info->mode <= XT_CONNMARK_RESTORE &&
  317. + !(info->mode == XT_CONNMARK_SET && info->func == XT_CONNMARK_DSCP) &&
  318. + info->shift_bits != 0) {
  319. + printf(" --%s %u", shift_op, info->shift_bits);
  320. + }
  321. +}
  322. +
  323. static int connmark_tg_xlate(struct xt_xlate *xl,
  324. const struct xt_xlate_tg_params *params)
  325. {
  326. @@ -639,6 +876,66 @@ static int connmark_tg_xlate_v2(struct xt_xlate *xl,
  327. return 1;
  328. }
  329. +
  330. +static int connmark_tg_xlate_v3(struct xt_xlate *xl,
  331. + const struct xt_xlate_tg_params *params)
  332. +{
  333. + const struct xt_connmark_tginfo3 *info =
  334. + (const void *)params->target->data;
  335. + const char *shift_op = xt_connmark_shift_ops[info->shift_dir];
  336. +
  337. + switch (info->mode) {
  338. + case XT_CONNMARK_SET:
  339. + xt_xlate_add(xl, "ct mark set ");
  340. + if (info->func & XT_CONNMARK_VALUE) {
  341. + if (info->ctmask == 0xFFFFFFFFU)
  342. + xt_xlate_add(xl, "0x%x ", info->ctmark);
  343. + else if (info->ctmark == 0)
  344. + xt_xlate_add(xl, "ct mark and 0x%x", ~info->ctmask);
  345. + else if (info->ctmark == info->ctmask)
  346. + xt_xlate_add(xl, "ct mark or 0x%x",
  347. + info->ctmark);
  348. + else if (info->ctmask == 0)
  349. + xt_xlate_add(xl, "ct mark xor 0x%x",
  350. + info->ctmark);
  351. + else
  352. + xt_xlate_add(xl, "ct mark xor 0x%x and 0x%x",
  353. + info->ctmark, ~info->ctmask);
  354. + }
  355. + if (info->func & XT_CONNMARK_DSCP) {
  356. +/* FIXME the nftables syntax would go here if only we knew what it was */
  357. + xt_xlate_add(xl, "ct mark set typeof(ct mark) ip dscp "
  358. + "<< %u or 0x%x", info->shift_bits,
  359. + info->ctmask);
  360. + }
  361. + break;
  362. + case XT_CONNMARK_SAVE:
  363. + xt_xlate_add(xl, "ct mark set mark");
  364. + if (!(info->nfmask == UINT32_MAX &&
  365. + info->ctmask == UINT32_MAX)) {
  366. + if (info->nfmask == info->ctmask)
  367. + xt_xlate_add(xl, " and 0x%x", info->nfmask);
  368. + }
  369. + break;
  370. + case XT_CONNMARK_RESTORE:
  371. + xt_xlate_add(xl, "meta mark set ct mark");
  372. + if (!(info->nfmask == UINT32_MAX &&
  373. + info->ctmask == UINT32_MAX)) {
  374. + if (info->nfmask == info->ctmask)
  375. + xt_xlate_add(xl, " and 0x%x", info->nfmask);
  376. + }
  377. + break;
  378. + }
  379. +
  380. + if (info->mode <= XT_CONNMARK_RESTORE &&
  381. + !(info->mode == XT_CONNMARK_SET && info->func == XT_CONNMARK_DSCP) &&
  382. + info->shift_bits != 0) {
  383. + xt_xlate_add(xl, " %s %u", shift_op, info->shift_bits);
  384. + }
  385. +
  386. + return 1;
  387. +}
  388. +
  389. static struct xtables_target connmark_tg_reg[] = {
  390. {
  391. .family = NFPROTO_UNSPEC,
  392. @@ -687,6 +984,22 @@ static struct xtables_target connmark_tg_reg[] = {
  393. .x6_options = connmark_tg_opts_v2,
  394. .xlate = connmark_tg_xlate_v2,
  395. },
  396. + {
  397. + .version = XTABLES_VERSION,
  398. + .name = "CONNMARK",
  399. + .revision = 3,
  400. + .family = NFPROTO_UNSPEC,
  401. + .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo3)),
  402. + .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo3)),
  403. + .help = connmark_tg_help_v3,
  404. + .init = connmark_tg_init_v3,
  405. + .print = connmark_tg_print_v3,
  406. + .save = connmark_tg_save_v3,
  407. + .x6_parse = connmark_tg_parse_v3,
  408. + .x6_fcheck = connmark_tg_check,
  409. + .x6_options = connmark_tg_opts_v3,
  410. + .xlate = connmark_tg_xlate_v3,
  411. + },
  412. };
  413. void _init(void)
  414. diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h
  415. index bbf2acc9..1d8e721c 100644
  416. --- a/include/linux/netfilter/xt_connmark.h
  417. +++ b/include/linux/netfilter/xt_connmark.h
  418. @@ -18,6 +18,11 @@ enum {
  419. XT_CONNMARK_RESTORE
  420. };
  421. +enum {
  422. + XT_CONNMARK_VALUE = (1 << 0),
  423. + XT_CONNMARK_DSCP = (1 << 1)
  424. +};
  425. +
  426. struct xt_connmark_tginfo1 {
  427. __u32 ctmark, ctmask, nfmask;
  428. __u8 mode;
  429. @@ -28,6 +33,11 @@ struct xt_connmark_tginfo2 {
  430. __u8 shift_dir, shift_bits, mode;
  431. };
  432. +struct xt_connmark_tginfo3 {
  433. + __u32 ctmark, ctmask, nfmask;
  434. + __u8 shift_dir, shift_bits, mode, func;
  435. +};
  436. +
  437. struct xt_connmark_mtinfo1 {
  438. __u32 mark, mask;
  439. __u8 invert;
  440. --
  441. 2.21.0 (Apple Git-122.2)