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 struct xtables_target mark_tg_reg[] = {
    249 	{
    250 		.family        = NFPROTO_UNSPEC,
    251 		.name          = "MARK",
    252 		.version       = XTABLES_VERSION,
    253 		.revision      = 0,
    254 		.size          = XT_ALIGN(sizeof(struct xt_mark_target_info)),
    255 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
    256 		.help          = MARK_help,
    257 		.print         = MARK_print_v0,
    258 		.save          = MARK_save_v0,
    259 		.x6_parse      = MARK_parse_v0,
    260 		.x6_fcheck     = MARK_check,
    261 		.x6_options    = MARK_opts,
    262 	},
    263 	{
    264 		.family        = NFPROTO_IPV4,
    265 		.name          = "MARK",
    266 		.version       = XTABLES_VERSION,
    267 		.revision      = 1,
    268 		.size          = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
    269 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
    270 		.help          = MARK_help,
    271 		.print         = MARK_print_v1,
    272 		.save          = MARK_save_v1,
    273 		.x6_parse      = MARK_parse_v1,
    274 		.x6_fcheck     = MARK_check,
    275 		.x6_options    = MARK_opts,
    276 	},
    277 	{
    278 		.version       = XTABLES_VERSION,
    279 		.name          = "MARK",
    280 		.revision      = 2,
    281 		.family        = NFPROTO_UNSPEC,
    282 		.size          = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
    283 		.userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
    284 		.help          = mark_tg_help,
    285 		.print         = mark_tg_print,
    286 		.save          = mark_tg_save,
    287 		.x6_parse      = mark_tg_parse,
    288 		.x6_fcheck     = mark_tg_check,
    289 		.x6_options    = mark_tg_opts,
    290 	},
    291 };
    292 
    293 void _init(void)
    294 {
    295 	xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
    296 }
    297