libxt_mark.c revision 73866357e4a7a0fdc1b293bf8863fee2bd56da9e
1/* Shared library add-on to iptables to add NFMARK matching support. */ 2#include <stdbool.h> 3#include <stdio.h> 4#include <netdb.h> 5#include <string.h> 6#include <stdlib.h> 7#include <getopt.h> 8 9#include <xtables.h> 10#include <linux/netfilter/xt_mark.h> 11 12struct xt_mark_info { 13 unsigned long mark, mask; 14 uint8_t invert; 15}; 16 17enum { 18 F_MARK = 1 << 0, 19}; 20 21static void mark_mt_help(void) 22{ 23 printf( 24"mark match options:\n" 25"[!] --mark value[/mask] Match nfmark value with optional mask\n"); 26} 27 28static const struct option mark_mt_opts[] = { 29 {.name = "mark", .has_arg = true, .val = '1'}, 30 XT_GETOPT_TABLEEND, 31}; 32 33static int mark_mt_parse(int c, char **argv, int invert, unsigned int *flags, 34 const void *entry, struct xt_entry_match **match) 35{ 36 struct xt_mark_mtinfo1 *info = (void *)(*match)->data; 37 unsigned int mark, mask = UINT32_MAX; 38 char *end; 39 40 switch (c) { 41 case '1': /* --mark */ 42 xtables_param_act(XTF_ONLY_ONCE, "mark", "--mark", *flags & F_MARK); 43 if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX)) 44 xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg); 45 if (*end == '/') 46 if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) 47 xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg); 48 if (*end != '\0') 49 xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg); 50 51 if (invert) 52 info->invert = true; 53 info->mark = mark; 54 info->mask = mask; 55 *flags |= F_MARK; 56 return true; 57 } 58 return false; 59} 60 61static int 62mark_parse(int c, char **argv, int invert, unsigned int *flags, 63 const void *entry, struct xt_entry_match **match) 64{ 65 struct xt_mark_info *markinfo = (struct xt_mark_info *)(*match)->data; 66 67 switch (c) { 68 char *end; 69 case '1': 70 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 71 markinfo->mark = strtoul(optarg, &end, 0); 72 if (*end == '/') { 73 markinfo->mask = strtoul(end+1, &end, 0); 74 } else 75 markinfo->mask = 0xffffffff; 76 if (*end != '\0' || end == optarg) 77 xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg); 78 if (invert) 79 markinfo->invert = 1; 80 *flags = 1; 81 break; 82 } 83 return 1; 84} 85 86static void print_mark(unsigned int mark, unsigned int mask) 87{ 88 if (mask != 0xffffffffU) 89 printf(" 0x%x/0x%x", mark, mask); 90 else 91 printf(" 0x%x", mark); 92} 93 94static void mark_mt_check(unsigned int flags) 95{ 96 if (flags == 0) 97 xtables_error(PARAMETER_PROBLEM, 98 "mark match: The --mark option is required"); 99} 100 101static void 102mark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric) 103{ 104 const struct xt_mark_mtinfo1 *info = (const void *)match->data; 105 106 printf(" mark match"); 107 if (info->invert) 108 printf(" !"); 109 print_mark(info->mark, info->mask); 110} 111 112static void 113mark_print(const void *ip, const struct xt_entry_match *match, int numeric) 114{ 115 const struct xt_mark_info *info = (const void *)match->data; 116 117 printf(" MARK match"); 118 119 if (info->invert) 120 printf(" !"); 121 122 print_mark(info->mark, info->mask); 123} 124 125static void mark_mt_save(const void *ip, const struct xt_entry_match *match) 126{ 127 const struct xt_mark_mtinfo1 *info = (const void *)match->data; 128 129 if (info->invert) 130 printf(" !"); 131 132 printf(" --mark"); 133 print_mark(info->mark, info->mask); 134} 135 136static void 137mark_save(const void *ip, const struct xt_entry_match *match) 138{ 139 const struct xt_mark_info *info = (const void *)match->data; 140 141 if (info->invert) 142 printf(" !"); 143 144 printf(" --mark"); 145 print_mark(info->mark, info->mask); 146} 147 148static struct xtables_match mark_mt_reg[] = { 149 { 150 .family = NFPROTO_UNSPEC, 151 .name = "mark", 152 .revision = 0, 153 .version = XTABLES_VERSION, 154 .size = XT_ALIGN(sizeof(struct xt_mark_info)), 155 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_info)), 156 .help = mark_mt_help, 157 .parse = mark_parse, 158 .final_check = mark_mt_check, 159 .print = mark_print, 160 .save = mark_save, 161 .extra_opts = mark_mt_opts, 162 }, 163 { 164 .version = XTABLES_VERSION, 165 .name = "mark", 166 .revision = 1, 167 .family = NFPROTO_UNSPEC, 168 .size = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), 169 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), 170 .help = mark_mt_help, 171 .parse = mark_mt_parse, 172 .final_check = mark_mt_check, 173 .print = mark_mt_print, 174 .save = mark_mt_save, 175 .extra_opts = mark_mt_opts, 176 }, 177}; 178 179void _init(void) 180{ 181 xtables_register_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg)); 182} 183