Home | History | Annotate | Download | only in extensions
      1 /* Shared library add-on to ip6tables 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 <ip6tables.h>
      9 /* For 64bit kernel / 32bit userspace */
     10 #include "../include/linux/netfilter_ipv6/ip6t_mark.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 ip6t_entry *entry,
     33       unsigned int *nfcache,
     34       struct ip6t_entry_match **match)
     35 {
     36 	struct ip6t_mark_info *markinfo = (struct ip6t_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 ip6t_ip6 *ip,
    100       const struct ip6t_entry_match *match,
    101       int numeric)
    102 {
    103 	struct ip6t_mark_info *info = (struct ip6t_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 ip6t_matchinfo in parsable form to stdout. */
    114 static void
    115 save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
    116 {
    117 	struct ip6t_mark_info *info = (struct ip6t_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 ip6tables_match mark = {
    127 	.name		= "mark",
    128 	.version	= IPTABLES_VERSION,
    129 	.size		= IP6T_ALIGN(sizeof(struct ip6t_mark_info)),
    130 	.userspacesize	= IP6T_ALIGN(sizeof(struct ip6t_mark_info)),
    131 	.help		= &help,
    132 	.parse		= &parse,
    133 	.final_check	= &final_check,
    134 	.print		= &print,
    135 	.save		= &save,
    136 	.extra_opts	= opts,
    137 };
    138 
    139 void _init(void)
    140 {
    141 	register_match6(&mark);
    142 }
    143