1/* Shared library add-on to iptables to add NFMARK matching support. */ 2#include <stdio.h> 3#include <netdb.h> 4#include <string.h> 5#include <stdlib.h> 6#include <getopt.h> 7 8#include <iptables.h> 9/* For 64bit kernel / 32bit userspace */ 10#include "../include/linux/netfilter_ipv4/ipt_mark.h" 11 12/* Function which prints out usage message. */ 13static void 14help(void) 15{ 16 printf( 17"MARK match v%s options:\n" 18"[!] --mark value[/mask] Match nfmark value with optional mask\n" 19"\n", 20IPTABLES_VERSION); 21} 22 23static struct option opts[] = { 24 { "mark", 1, 0, '1' }, 25 {0} 26}; 27 28/* Function which parses command options; returns true if it 29 ate an option */ 30static int 31parse(int c, char **argv, int invert, unsigned int *flags, 32 const struct ipt_entry *entry, 33 unsigned int *nfcache, 34 struct ipt_entry_match **match) 35{ 36 struct ipt_mark_info *markinfo = (struct ipt_mark_info *)(*match)->data; 37 38 switch (c) { 39 char *end; 40 case '1': 41 check_inverse(optarg, &invert, &optind, 0); 42#ifdef KERNEL_64_USERSPACE_32 43 markinfo->mark = strtoull(optarg, &end, 0); 44 if (*end == '/') { 45 markinfo->mask = strtoull(end+1, &end, 0); 46 } else 47 markinfo->mask = 0xffffffffffffffffULL; 48#else 49 markinfo->mark = strtoul(optarg, &end, 0); 50 if (*end == '/') { 51 markinfo->mask = strtoul(end+1, &end, 0); 52 } else 53 markinfo->mask = 0xffffffff; 54#endif 55 if (*end != '\0' || end == optarg) 56 exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg); 57 if (invert) 58 markinfo->invert = 1; 59 *flags = 1; 60 break; 61 62 default: 63 return 0; 64 } 65 return 1; 66} 67 68#ifdef KERNEL_64_USERSPACE_32 69static void 70print_mark(unsigned long long mark, unsigned long long mask, int numeric) 71{ 72 if(mask != 0xffffffffffffffffULL) 73 printf("0x%llx/0x%llx ", mark, mask); 74 else 75 printf("0x%llx ", mark); 76} 77#else 78static void 79print_mark(unsigned long mark, unsigned long mask, int numeric) 80{ 81 if(mask != 0xffffffff) 82 printf("0x%lx/0x%lx ", mark, mask); 83 else 84 printf("0x%lx ", mark); 85} 86#endif 87 88/* Final check; must have specified --mark. */ 89static void 90final_check(unsigned int flags) 91{ 92 if (!flags) 93 exit_error(PARAMETER_PROBLEM, 94 "MARK match: You must specify `--mark'"); 95} 96 97/* Prints out the matchinfo. */ 98static void 99print(const struct ipt_ip *ip, 100 const struct ipt_entry_match *match, 101 int numeric) 102{ 103 struct ipt_mark_info *info = (struct ipt_mark_info *)match->data; 104 105 printf("MARK match "); 106 107 if (info->invert) 108 printf("!"); 109 110 print_mark(info->mark, info->mask, numeric); 111} 112 113/* Saves the union ipt_matchinfo in parsable form to stdout. */ 114static void 115save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 116{ 117 struct ipt_mark_info *info = (struct ipt_mark_info *)match->data; 118 119 if (info->invert) 120 printf("! "); 121 122 printf("--mark "); 123 print_mark(info->mark, info->mask, 0); 124} 125 126static struct iptables_match mark = { 127 .next = NULL, 128 .name = "mark", 129 .version = IPTABLES_VERSION, 130 .size = IPT_ALIGN(sizeof(struct ipt_mark_info)), 131 .userspacesize = IPT_ALIGN(sizeof(struct ipt_mark_info)), 132 .help = &help, 133 .parse = &parse, 134 .final_check = &final_check, 135 .print = &print, 136 .save = &save, 137 .extra_opts = opts 138}; 139 140void _init(void) 141{ 142 register_match(&mark); 143} 144