libxt_mark.c revision 350661a6eb089f3e54e67e022db9e16ea280499f
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 u_int8_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 { .name = NULL } 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 default: 84 return 0; 85 } 86 return 1; 87} 88 89static void print_mark(unsigned int mark, unsigned int mask) 90{ 91 if (mask != 0xffffffffU) 92 printf("0x%x/0x%x ", mark, mask); 93 else 94 printf("0x%x ", mark); 95} 96 97static void mark_mt_check(unsigned int flags) 98{ 99 if (flags == 0) 100 xtables_error(PARAMETER_PROBLEM, 101 "mark match: The --mark option is required"); 102} 103 104static void 105mark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric) 106{ 107 const struct xt_mark_mtinfo1 *info = (const void *)match->data; 108 109 printf("mark match "); 110 if (info->invert) 111 printf("!"); 112 print_mark(info->mark, info->mask); 113} 114 115static void 116mark_print(const void *ip, const struct xt_entry_match *match, int numeric) 117{ 118 const struct xt_mark_info *info = (const void *)match->data; 119 120 printf("MARK match "); 121 122 if (info->invert) 123 printf("!"); 124 125 print_mark(info->mark, info->mask); 126} 127 128static void mark_mt_save(const void *ip, const struct xt_entry_match *match) 129{ 130 const struct xt_mark_mtinfo1 *info = (const void *)match->data; 131 132 if (info->invert) 133 printf("! "); 134 135 printf("--mark "); 136 print_mark(info->mark, info->mask); 137} 138 139static void 140mark_save(const void *ip, const struct xt_entry_match *match) 141{ 142 const struct xt_mark_info *info = (const void *)match->data; 143 144 if (info->invert) 145 printf("! "); 146 147 printf("--mark "); 148 print_mark(info->mark, info->mask); 149} 150 151static struct xtables_match mark_mt_reg[] = { 152 { 153 .family = NFPROTO_UNSPEC, 154 .name = "mark", 155 .revision = 0, 156 .version = XTABLES_VERSION, 157 .size = XT_ALIGN(sizeof(struct xt_mark_info)), 158 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_info)), 159 .help = mark_mt_help, 160 .parse = mark_parse, 161 .final_check = mark_mt_check, 162 .print = mark_print, 163 .save = mark_save, 164 .extra_opts = mark_mt_opts, 165 }, 166 { 167 .version = XTABLES_VERSION, 168 .name = "mark", 169 .revision = 1, 170 .family = NFPROTO_UNSPEC, 171 .size = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), 172 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), 173 .help = mark_mt_help, 174 .parse = mark_mt_parse, 175 .final_check = mark_mt_check, 176 .print = mark_mt_print, 177 .save = mark_mt_save, 178 .extra_opts = mark_mt_opts, 179 }, 180}; 181 182void _init(void) 183{ 184 xtables_register_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg)); 185} 186