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_2mark.h" 11 12 /* Function which prints out usage message. */ 13 static void 14 help(void) 15 { 16 printf( 17 "MARK match v%s options:\n" 18 "[!] --mark value[/mask] Match nfmark value with optional mask\n" 19 "\n", 20 IPTABLES_VERSION); 21 } 22 23 static 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 */ 30 static int 31 parse(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 69 static void 70 print_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 78 static void 79 print_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. */ 89 static void 90 final_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. */ 98 static void 99 print(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. */ 114 static void 115 save(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 126 static 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 140 void ipt_2mark_init(void) 141 { 142 register_match(&mark); 143 } 144