Home | History | Annotate | Download | only in extensions
      1 #include <stdbool.h>
      2 #include <stdio.h>
      3 #include <xtables.h>
      4 #include <linux/netfilter/xt_MARK.h>
      5 
      6 /* Version 0 */
      7 struct xt_mark_target_info {
      8 	unsigned long mark;
      9 };
     10 
     11 /* Version 1 */
     12 enum {
     13 	XT_MARK_SET=0,
     14 	XT_MARK_AND,
     15 	XT_MARK_OR,
     16 };
     17 
     18 struct xt_mark_target_info_v1 {
     19 	unsigned long mark;
     20 	uint8_t mode;
     21 };
     22 
     23 enum {
     24 	O_SET_MARK = 0,
     25 	O_AND_MARK,
     26 	O_OR_MARK,
     27 	O_XOR_MARK,
     28 	O_SET_XMARK,
     29 	F_SET_MARK  = 1 << O_SET_MARK,
     30 	F_AND_MARK  = 1 << O_AND_MARK,
     31 	F_OR_MARK   = 1 << O_OR_MARK,
     32 	F_XOR_MARK  = 1 << O_XOR_MARK,
     33 	F_SET_XMARK = 1 << O_SET_XMARK,
     34 	F_ANY       = F_SET_MARK | F_AND_MARK | F_OR_MARK |
     35 	              F_XOR_MARK | F_SET_XMARK,
     36 };
     37 
     38 static void MARK_help(void)
     39 {
     40 	printf(
     41 "MARK target options:\n"
     42 "  --set-mark value                   Set nfmark value\n"
     43 "  --and-mark value                   Binary AND the nfmark with value\n"
     44 "  --or-mark  value                   Binary OR  the nfmark with value\n");
     45 }
     46 
     47 static const struct xt_option_entry MARK_opts[] = {
     48 	{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
     49 	 .excl = F_ANY},
     50 	{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
     51 	 .excl = F_ANY},
     52 	{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
     53 	 .excl = F_ANY},
     54 	XTOPT_TABLEEND,
     55 };
     56 
     57 static const struct xt_option_entry mark_tg_opts[] = {
     58 	{.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
     59 	 .excl = F_ANY},
     60 	{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
     61 	 .excl = F_ANY},
     62 	{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
     63 	 .excl = F_ANY},
     64 	{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
     65 	 .excl = F_ANY},
     66 	{.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
     67 	 .excl = F_ANY},
     68 	XTOPT_TABLEEND,
     69 };
     70 
     71 static void mark_tg_help(void)
     72 {
     73 	printf(
     74 "MARK target options:\n"
     75 "  --set-xmark value[/mask]  Clear bits in mask and XOR value into nfmark\n"
     76 "  --set-mark value[/mask]   Clear bits in mask and OR value into nfmark\n"
     77 "  --and-mark bits           Binary AND the nfmark with bits\n"
     78 "  --or-mark bits            Binary OR the nfmark with bits\n"
     79 "  --xor-mask bits           Binary XOR the nfmark with bits\n"
     80 "\n");
     81 }
     82 
     83 static void MARK_parse_v0(struct xt_option_call *cb)
     84 {
     85 	struct xt_mark_target_info *markinfo = cb->data;
     86 
     87 	xtables_option_parse(cb);
     88 	switch (cb->entry->id) {
     89 	case O_SET_MARK:
     90 		markinfo->mark = cb->val.mark;
     91 		break;
     92 	default:
     93 		xtables_error(PARAMETER_PROBLEM,
     94 			   "MARK target: kernel too old for --%s",
     95 			   cb->entry->name);
     96 	}
     97 }
     98 
     99 static void MARK_check(struct xt_fcheck_call *cb)
    100 {
    101 	if (cb->xflags == 0)
    102 		xtables_error(PARAMETER_PROBLEM,
    103 		           "MARK target: Parameter --set/and/or-mark"
    104 			   " is required");
    105 }
    106 
    107 static void MARK_parse_v1(struct xt_option_call *cb)
    108 {
    109 	struct xt_mark_target_info_v1 *markinfo = cb->data;
    110 
    111 	xtables_option_parse(cb);
    112 	switch (cb->entry->id) {
    113 	case O_SET_MARK:
    114 	        markinfo->mode = XT_MARK_SET;
    115 		break;
    116 	case O_AND_MARK:
    117 	        markinfo->mode = XT_MARK_AND;
    118 		break;
    119 	case O_OR_MARK:
    120 	        markinfo->mode = XT_MARK_OR;
    121 		break;
    122 	}
    123 	markinfo->mark = cb->val.u32;
    124 }
    125 
    126 static void mark_tg_parse(struct xt_option_call *cb)
    127 {
    128 	struct xt_mark_tginfo2 *info = cb->data;
    129 
    130 	xtables_option_parse(cb);
    131 	switch (cb->entry->id) {
    132 	case O_SET_XMARK:
    133 		info->mark = cb->val.mark;
    134 		info->mask = cb->val.mask;
    135 		break;
    136 	case O_SET_MARK:
    137 		info->mark = cb->val.mark;
    138 		info->mask = cb->val.mark | cb->val.mask;
    139 		break;
    140 	case O_AND_MARK:
    141 		info->mark = 0;
    142 		info->mask = ~cb->val.u32;
    143 		break;
    144 	case O_OR_MARK:
    145 		info->mark = info->mask = cb->val.u32;
    146 		break;
    147 	case O_XOR_MARK:
    148 		info->mark = cb->val.u32;
    149 		info->mask = 0;
    150 		break;
    151 	}
    152 }
    153 
    154 static void mark_tg_check(struct xt_fcheck_call *cb)
    155 {
    156 	if (cb->xflags == 0)
    157 		xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
    158 		           "--{and,or,xor,set}-mark options is required");
    159 }
    160 
    161 static void
    162 print_mark(unsigned long mark)
    163 {
    164 	printf(" 0x%lx", mark);
    165 }
    166 
    167 static void MARK_print_v0(const void *ip,
    168                           const struct xt_entry_target *target, int numeric)
    169 {
    170 	const struct xt_mark_target_info *markinfo =
    171 		(const struct xt_mark_target_info *)target->data;
    172 	printf(" MARK set");
    173 	print_mark(markinfo->mark);
    174 }
    175 
    176 static void MARK_save_v0(const void *ip, const struct xt_entry_target *target)
    177 {
    178 	const struct xt_mark_target_info *markinfo =
    179 		(const struct xt_mark_target_info *)target->data;
    180 
    181 	printf(" --set-mark");
    182 	print_mark(markinfo->mark);
    183 }
    184 
    185 static void MARK_print_v1(const void *ip, const struct xt_entry_target *target,
    186                           int numeric)
    187 {
    188 	const struct xt_mark_target_info_v1 *markinfo =
    189 		(const struct xt_mark_target_info_v1 *)target->data;
    190 
    191 	switch (markinfo->mode) {
    192 	case XT_MARK_SET:
    193 		printf(" MARK set");
    194 		break;
    195 	case XT_MARK_AND:
    196 		printf(" MARK and");
    197 		break;
    198 	case XT_MARK_OR:
    199 		printf(" MARK or");
    200 		break;
    201 	}
    202 	print_mark(markinfo->mark);
    203 }
    204 
    205 static void mark_tg_print(const void *ip, const struct xt_entry_target *target,
    206                           int numeric)
    207 {
    208 	const struct xt_mark_tginfo2 *info = (const void *)target->data;
    209 
    210 	if (info->mark == 0)
    211 		printf(" MARK and 0x%x", (unsigned int)(uint32_t)~info->mask);
    212 	else if (info->mark == info->mask)
    213 		printf(" MARK or 0x%x", info->mark);
    214 	else if (info->mask == 0)
    215 		printf(" MARK xor 0x%x", info->mark);
    216 	else if (info->mask == 0xffffffffU)
    217 		printf(" MARK set 0x%x", info->mark);
    218 	else
    219 		printf(" MARK xset 0x%x/0x%x", info->mark, info->mask);
    220 }
    221 
    222 static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
    223 {
    224 	const struct xt_mark_target_info_v1 *markinfo =
    225 		(const struct xt_mark_target_info_v1 *)target->data;
    226 
    227 	switch (markinfo->mode) {
    228 	case XT_MARK_SET:
    229 		printf(" --set-mark");
    230 		break;
    231 	case XT_MARK_AND:
    232 		printf(" --and-mark");
    233 		break;
    234 	case XT_MARK_OR:
    235 		printf(" --or-mark");
    236 		break;
    237 	}
    238 	print_mark(markinfo->mark);
    239 }
    240 
    241 static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
    242 {
    243 	const struct xt_mark_tginfo2 *info = (const void *)target->data;
    244 
    245 	printf(" --set-xmark 0x%x/0x%x", info->mark, info->mask);
    246 }
    247 
    248 static int mark_tg_xlate(struct xt_xlate *xl,
    249 			 const struct xt_xlate_tg_params *params)
    250 {
    251 	const struct xt_mark_tginfo2 *info = (const void *)params->target->data;
    252 
    253 	xt_xlate_add(xl, "meta mark set ");
    254 
    255 	if (info->mark == 0)
    256 		xt_xlate_add(xl, "mark and 0x%x ", ~info->mask);
    257 	else if (info->mark == info->mask)
    258 		xt_xlate_add(xl, "mark or 0x%x ", info->mark);
    259 	else if (info->mask == 0)
    260 		xt_xlate_add(xl, "mark xor 0x%x ", info->mark);
    261 	else if (info->mask == 0xffffffffU)
    262 		xt_xlate_add(xl, "0x%x ", info->mark);
    263 	else
    264 		xt_xlate_add(xl, "mark and 0x%x xor 0x%x ", ~info->mask,
    265 			     info->mark);
    266 
    267 	return 1;
    268 }
    269 
    270 static int MARK_xlate(struct xt_xlate *xl,
    271 		      const struct xt_xlate_tg_params *params)
    272 {
    273 	const struct xt_mark_target_info_v1 *markinfo =
    274 		(const struct xt_mark_target_info_v1 *)params->target->data;
    275 
    276 	xt_xlate_add(xl, "meta mark set ");
    277 
    278 	switch(markinfo->mode) {
    279 	case XT_MARK_SET:
    280 		xt_xlate_add(xl, "0x%x ", markinfo->mark);
    281 		break;
    282 	case XT_MARK_AND:
    283 		xt_xlate_add(xl, "mark and 0x%x ", markinfo->mark);
    284 		break;
    285 	case XT_MARK_OR:
    286 		xt_xlate_add(xl, "mark or 0x%x ", markinfo->mark);
    287 		break;
    288 	}
    289 
    290 	return 1;
    291 }
    292 
    293 static struct xtables_target mark_tg_reg[] = {
    294 	{
    295 		.family        = NFPROTO_UNSPEC,
    296 		.name          = "MARK",
    297 		.version       = XTABLES_VERSION,
    298 		.revision      = 0,
    299 		.size          = XT_ALIGN(sizeof(struct xt_mark_target_info)),
    300 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
    301 		.help          = MARK_help,
    302 		.print         = MARK_print_v0,
    303 		.save          = MARK_save_v0,
    304 		.x6_parse      = MARK_parse_v0,
    305 		.x6_fcheck     = MARK_check,
    306 		.x6_options    = MARK_opts,
    307 	},
    308 	{
    309 		.family        = NFPROTO_IPV4,
    310 		.name          = "MARK",
    311 		.version       = XTABLES_VERSION,
    312 		.revision      = 1,
    313 		.size          = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
    314 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
    315 		.help          = MARK_help,
    316 		.print         = MARK_print_v1,
    317 		.save          = MARK_save_v1,
    318 		.x6_parse      = MARK_parse_v1,
    319 		.x6_fcheck     = MARK_check,
    320 		.x6_options    = MARK_opts,
    321 		.xlate	       = MARK_xlate,
    322 	},
    323 	{
    324 		.version       = XTABLES_VERSION,
    325 		.name          = "MARK",
    326 		.revision      = 2,
    327 		.family        = NFPROTO_UNSPEC,
    328 		.size          = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
    329 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
    330 		.help          = mark_tg_help,
    331 		.print         = mark_tg_print,
    332 		.save          = mark_tg_save,
    333 		.x6_parse      = mark_tg_parse,
    334 		.x6_fcheck     = mark_tg_check,
    335 		.x6_options    = mark_tg_opts,
    336 		.xlate	       = mark_tg_xlate,
    337 	},
    338 };
    339 
    340 void _init(void)
    341 {
    342 	xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
    343 }
    344