libxt_mark.c revision 5180032804c03225542368aaaf19060fe7a47a1c
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 12enum { 13 F_MARK = 1 << 0, 14}; 15 16static void mark_mt_help(void) 17{ 18 printf( 19"mark match options:\n" 20"[!] --mark value[/mask] Match nfmark value with optional mask\n" 21"\n"); 22} 23 24static const struct option mark_mt_opts[] = { 25 {.name = "mark", .has_arg = true, .val = '1'}, 26 { .name = NULL } 27}; 28 29static int mark_mt_parse(int c, char **argv, int invert, unsigned int *flags, 30 const void *entry, struct xt_entry_match **match) 31{ 32 struct xt_mark_mtinfo1 *info = (void *)(*match)->data; 33 unsigned int mark, mask = ~0U; 34 char *end; 35 36 switch (c) { 37 case '1': /* --mark */ 38 param_act(P_ONLY_ONCE, "mark", "--mark", *flags & F_MARK); 39 if (!strtonum(optarg, &end, &mark, 0, ~0U)) 40 param_act(P_BAD_VALUE, "mark", "--mark", optarg); 41 if (*end == '/') 42 if (!strtonum(end + 1, &end, &mask, 0, ~0U)) 43 param_act(P_BAD_VALUE, "mark", "--mark", optarg); 44 if (*end != '\0') 45 param_act(P_BAD_VALUE, "mark", "--mark", optarg); 46 47 if (invert) 48 info->invert = true; 49 info->mark = mark; 50 info->mask = mask; 51 *flags |= F_MARK; 52 return true; 53 } 54 return false; 55} 56 57/* Function which parses command options; returns true if it 58 ate an option */ 59static int 60mark_parse(int c, char **argv, int invert, unsigned int *flags, 61 const void *entry, struct xt_entry_match **match) 62{ 63 struct xt_mark_info *markinfo = (struct xt_mark_info *)(*match)->data; 64 65 switch (c) { 66 char *end; 67 case '1': 68 check_inverse(optarg, &invert, &optind, 0); 69 markinfo->mark = strtoul(optarg, &end, 0); 70 if (*end == '/') { 71 markinfo->mask = strtoul(end+1, &end, 0); 72 } else 73 markinfo->mask = 0xffffffff; 74 if (*end != '\0' || end == optarg) 75 exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg); 76 if (invert) 77 markinfo->invert = 1; 78 *flags = 1; 79 break; 80 81 default: 82 return 0; 83 } 84 return 1; 85} 86 87static void print_mark(unsigned int mark, unsigned int mask) 88{ 89 if (mask != 0xffffffffU) 90 printf("0x%x/0x%x ", mark, mask); 91 else 92 printf("0x%x ", mark); 93} 94 95static void mark_mt_check(unsigned int flags) 96{ 97 if (flags == 0) 98 exit_error(PARAMETER_PROBLEM, 99 "mark match: The --mark option is required"); 100} 101 102static void 103mark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric) 104{ 105 const struct xt_mark_mtinfo1 *info = (const void *)match->data; 106 107 printf("mark match "); 108 if (info->invert) 109 printf("!"); 110 print_mark(info->mark, info->mask); 111} 112 113/* Prints out the matchinfo. */ 114static void 115mark_print(const void *ip, const struct xt_entry_match *match, int numeric) 116{ 117 struct xt_mark_info *info = (struct xt_mark_info *)match->data; 118 119 printf("MARK match "); 120 121 if (info->invert) 122 printf("!"); 123 124 print_mark(info->mark, info->mask); 125} 126 127static void mark_mt_save(const void *ip, const struct xt_entry_match *match) 128{ 129 const struct xt_mark_mtinfo1 *info = (const void *)match->data; 130 131 if (info->invert) 132 printf("!"); 133 134 printf("--mark "); 135 print_mark(info->mark, info->mask); 136} 137 138/* Saves the union ipt_matchinfo in parsable form to stdout. */ 139static void 140mark_save(const void *ip, const struct xt_entry_match *match) 141{ 142 struct xt_mark_info *info = (struct xt_mark_info *)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_match = { 152 .family = AF_INET, 153 .name = "mark", 154 .revision = 0, 155 .version = IPTABLES_VERSION, 156 .size = XT_ALIGN(sizeof(struct xt_mark_info)), 157 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_info)), 158 .help = mark_mt_help, 159 .parse = mark_parse, 160 .final_check = mark_mt_check, 161 .print = mark_print, 162 .save = mark_save, 163 .extra_opts = mark_mt_opts, 164}; 165 166static struct xtables_match mark_match6 = { 167 .family = AF_INET6, 168 .name = "mark", 169 .revision = 0, 170 .version = IPTABLES_VERSION, 171 .size = XT_ALIGN(sizeof(struct xt_mark_info)), 172 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_info)), 173 .help = mark_mt_help, 174 .parse = mark_parse, 175 .final_check = mark_mt_check, 176 .print = mark_print, 177 .save = mark_save, 178 .extra_opts = mark_mt_opts, 179}; 180 181static struct xtables_match mark_mt_reg = { 182 .version = IPTABLES_VERSION, 183 .name = "mark", 184 .revision = 1, 185 .family = AF_INET, 186 .size = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), 187 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), 188 .help = mark_mt_help, 189 .parse = mark_mt_parse, 190 .final_check = mark_mt_check, 191 .print = mark_mt_print, 192 .save = mark_mt_save, 193 .extra_opts = mark_mt_opts, 194}; 195 196static struct xtables_match mark_mt6_reg = { 197 .version = IPTABLES_VERSION, 198 .name = "mark", 199 .revision = 1, 200 .family = AF_INET6, 201 .size = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), 202 .userspacesize = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), 203 .help = mark_mt_help, 204 .parse = mark_mt_parse, 205 .final_check = mark_mt_check, 206 .print = mark_mt_print, 207 .save = mark_mt_save, 208 .extra_opts = mark_mt_opts, 209}; 210 211void _init(void) 212{ 213 xtables_register_match(&mark_match); 214 xtables_register_match(&mark_match6); 215 xtables_register_match(&mark_mt_reg); 216 xtables_register_match(&mark_mt6_reg); 217} 218