Home | History | Annotate | Download | only in extensions
      1 /* Shared library add-on to iptables to add connmark matching support.
      2  *
      3  * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
      4  * by Henrik Nordstrom <hno (at) marasystems.com>
      5  *
      6  * Version 1.1
      7  *
      8  * This program is free software; you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License as published by
     10  * the Free Software Foundation; either version 2 of the License, or
     11  * (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, write to the Free Software
     20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     21  */
     22 #include <stdio.h>
     23 #include <netdb.h>
     24 #include <string.h>
     25 #include <stdlib.h>
     26 #include <getopt.h>
     27 
     28 #include <ip6tables.h>
     29 #include "../include/linux/netfilter_ipv4/ipt_2connmark.h"
     30 
     31 /* Function which prints out usage message. */
     32 static void
     33 help(void)
     34 {
     35 	printf(
     36 "CONNMARK match v%s options:\n"
     37 "[!] --mark value[/mask]         Match nfmark value with optional mask\n"
     38 "\n",
     39 IPTABLES_VERSION);
     40 }
     41 
     42 static struct option opts[] = {
     43 	{ "mark", 1, 0, '1' },
     44 	{0}
     45 };
     46 
     47 /* Initialize the match. */
     48 static void
     49 init(struct ip6t_entry_match *m, unsigned int *nfcache)
     50 {
     51 	/* Can't cache this. */
     52 	*nfcache |= NFC_UNKNOWN;
     53 }
     54 
     55 /* Function which parses command options; returns true if it
     56    ate an option */
     57 static int
     58 parse(int c, char **argv, int invert, unsigned int *flags,
     59       const struct ip6t_entry *entry,
     60       unsigned int *nfcache,
     61       struct ip6t_entry_match **match)
     62 {
     63 	struct ipt_connmark_info *markinfo = (struct ipt_connmark_info *)(*match)->data;
     64 
     65 	switch (c) {
     66 		char *end;
     67 	case '1':
     68 		check_inverse(optarg, &invert, &optind, 0);
     69 
     70 		markinfo->mark = strtoul(optarg, &end, 0);
     71 		markinfo->mask = 0xffffffffUL;
     72 
     73 		if (*end == '/')
     74 			markinfo->mask = strtoul(end+1, &end, 0);
     75 
     76 		if (*end != '\0' || end == optarg)
     77 			exit_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 
     89 static void
     90 print_mark(unsigned long mark, unsigned long mask, int numeric)
     91 {
     92 	if(mask != 0xffffffffUL)
     93 		printf("0x%lx/0x%lx ", mark, mask);
     94 	else
     95 		printf("0x%lx ", mark);
     96 }
     97 
     98 /* Final check; must have specified --mark. */
     99 static void
    100 final_check(unsigned int flags)
    101 {
    102 	if (!flags)
    103 		exit_error(PARAMETER_PROBLEM,
    104 			   "MARK match: You must specify `--mark'");
    105 }
    106 
    107 /* Prints out the matchinfo. */
    108 static void
    109 print(const struct ip6t_ip6 *ip,
    110       const struct ip6t_entry_match *match,
    111       int numeric)
    112 {
    113 	struct ipt_connmark_info *info = (struct ipt_connmark_info *)match->data;
    114 
    115 	printf("CONNMARK match ");
    116 	if (info->invert)
    117 		printf("!");
    118 	print_mark(info->mark, info->mask, numeric);
    119 }
    120 
    121 /* Saves the matchinfo in parsable form to stdout. */
    122 static void
    123 save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
    124 {
    125 	struct ipt_connmark_info *info = (struct ipt_connmark_info *)match->data;
    126 
    127 	if (info->invert)
    128 		printf("! ");
    129 
    130 	printf("--mark ");
    131 	print_mark(info->mark, info->mask, 0);
    132 }
    133 
    134 static struct ip6tables_match connmark_match = {
    135     .name          = "connmark",
    136     .version       = IPTABLES_VERSION,
    137     .size          = IP6T_ALIGN(sizeof(struct ipt_connmark_info)),
    138     .userspacesize = IP6T_ALIGN(sizeof(struct ipt_connmark_info)),
    139     .help          = &help,
    140     .init          = &init,
    141     .parse         = &parse,
    142     .final_check   = &final_check,
    143     .print         = &print,
    144     .save          = &save,
    145     .extra_opts    = opts
    146 };
    147 
    148 void _init(void)
    149 {
    150 	register_match6(&connmark_match);
    151 }
    152