Home | History | Annotate | Download | only in extensions
      1 /* Shared library add-on to iptables to add CONNMARK target 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 <string.h>
     24 #include <stdlib.h>
     25 #include <getopt.h>
     26 
     27 #include <ip6tables.h>
     28 #include <linux/netfilter_ipv6/ip6_tables.h>
     29 #include "../include/linux/netfilter_ipv4/ipt_CONNMARK.h"
     30 
     31 #if 0
     32 struct markinfo {
     33 	struct ipt_entry_target t;
     34 	struct ipt_connmark_target_info mark;
     35 };
     36 #endif
     37 
     38 /* Function which prints out usage message. */
     39 static void
     40 help(void)
     41 {
     42 	printf(
     43 "CONNMARK target v%s options:\n"
     44 "  --set-mark value[/mask]       Set conntrack mark value\n"
     45 "  --save-mark [--mask mask]     Save the packet nfmark in the connection\n"
     46 "  --restore-mark [--mask mask]  Restore saved nfmark value\n"
     47 "\n",
     48 IPTABLES_VERSION);
     49 }
     50 
     51 static struct option opts[] = {
     52 	{ "set-mark", 1, 0, '1' },
     53 	{ "save-mark", 0, 0, '2' },
     54 	{ "restore-mark", 0, 0, '3' },
     55 	{ "mask", 1, 0, '4' },
     56 	{ 0 }
     57 };
     58 
     59 /* Initialize the target. */
     60 static void
     61 init(struct ip6t_entry_target *t, unsigned int *nfcache)
     62 {
     63 }
     64 
     65 /* Function which parses command options; returns true if it
     66    ate an option */
     67 static int
     68 parse(int c, char **argv, int invert, unsigned int *flags,
     69       const struct ip6t_entry *entry,
     70       struct ip6t_entry_target **target)
     71 {
     72 	struct ipt_connmark_target_info *markinfo
     73 		= (struct ipt_connmark_target_info *)(*target)->data;
     74 
     75 	markinfo->mask = 0xffffffffUL;
     76 
     77 	switch (c) {
     78 		char *end;
     79 	case '1':
     80 		markinfo->mode = IPT_CONNMARK_SET;
     81 
     82 		markinfo->mark = strtoul(optarg, &end, 0);
     83 		if (*end == '/' && end[1] != '\0')
     84 		    markinfo->mask = strtoul(end+1, &end, 0);
     85 
     86 		if (*end != '\0' || end == optarg)
     87 			exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
     88 		if (*flags)
     89 			exit_error(PARAMETER_PROBLEM,
     90 			           "CONNMARK target: Can't specify --set-mark twice");
     91 		*flags = 1;
     92 		break;
     93 	case '2':
     94 		markinfo->mode = IPT_CONNMARK_SAVE;
     95 		if (*flags)
     96 			exit_error(PARAMETER_PROBLEM,
     97 			           "CONNMARK target: Can't specify --save-mark twice");
     98 		*flags = 1;
     99 		break;
    100 	case '3':
    101 		markinfo->mode = IPT_CONNMARK_RESTORE;
    102 		if (*flags)
    103 			exit_error(PARAMETER_PROBLEM,
    104 			           "CONNMARK target: Can't specify --restore-mark twice");
    105 		*flags = 1;
    106 		break;
    107 	case '4':
    108 		if (!*flags)
    109 			exit_error(PARAMETER_PROBLEM,
    110 			           "CONNMARK target: Can't specify --mask without a operation");
    111 		markinfo->mask = strtoul(optarg, &end, 0);
    112 
    113 		if (*end != '\0' || end == optarg)
    114 			exit_error(PARAMETER_PROBLEM, "Bad MASK value `%s'", optarg);
    115 		break;
    116 	default:
    117 		return 0;
    118 	}
    119 
    120 	return 1;
    121 }
    122 
    123 static void
    124 final_check(unsigned int flags)
    125 {
    126 	if (!flags)
    127 		exit_error(PARAMETER_PROBLEM,
    128 		           "CONNMARK target: No operation specified");
    129 }
    130 
    131 static void
    132 print_mark(unsigned long mark)
    133 {
    134 	printf("0x%lx", mark);
    135 }
    136 
    137 static void
    138 print_mask(const char *text, unsigned long mask)
    139 {
    140 	if (mask != 0xffffffffUL)
    141 		printf("%s0x%lx", text, mask);
    142 }
    143 
    144 
    145 /* Prints out the target info. */
    146 static void
    147 print(const struct ip6t_ip6 *ip,
    148       const struct ip6t_entry_target *target,
    149       int numeric)
    150 {
    151 	const struct ipt_connmark_target_info *markinfo =
    152 		(const struct ipt_connmark_target_info *)target->data;
    153 	switch (markinfo->mode) {
    154 	case IPT_CONNMARK_SET:
    155 	    printf("CONNMARK set ");
    156 	    print_mark(markinfo->mark);
    157 	    print_mask("/", markinfo->mask);
    158 	    printf(" ");
    159 	    break;
    160 	case IPT_CONNMARK_SAVE:
    161 	    printf("CONNMARK save ");
    162 	    print_mask("mask ", markinfo->mask);
    163 	    printf(" ");
    164 	    break;
    165 	case IPT_CONNMARK_RESTORE:
    166 	    printf("CONNMARK restore ");
    167 	    print_mask("mask ", markinfo->mask);
    168 	    break;
    169 	default:
    170 	    printf("ERROR: UNKNOWN CONNMARK MODE ");
    171 	    break;
    172 	}
    173 }
    174 
    175 /* Saves the target into in parsable form to stdout. */
    176 static void
    177 save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
    178 {
    179 	const struct ipt_connmark_target_info *markinfo =
    180 		(const struct ipt_connmark_target_info *)target->data;
    181 
    182 	switch (markinfo->mode) {
    183 	case IPT_CONNMARK_SET:
    184 	    printf("--set-mark ");
    185 	    print_mark(markinfo->mark);
    186 	    print_mask("/", markinfo->mask);
    187 	    printf(" ");
    188 	    break;
    189 	case IPT_CONNMARK_SAVE:
    190 	    printf("--save-mark ");
    191 	    print_mask("--mask ", markinfo->mask);
    192 	    break;
    193 	case IPT_CONNMARK_RESTORE:
    194 	    printf("--restore-mark ");
    195 	    print_mask("--mask ", markinfo->mask);
    196 	    break;
    197 	default:
    198 	    printf("ERROR: UNKNOWN CONNMARK MODE ");
    199 	    break;
    200 	}
    201 }
    202 
    203 static struct ip6tables_target connmark_target = {
    204     .name          = "CONNMARK",
    205     .version       = IPTABLES_VERSION,
    206     .size          = IP6T_ALIGN(sizeof(struct ipt_connmark_target_info)),
    207     .userspacesize = IP6T_ALIGN(sizeof(struct ipt_connmark_target_info)),
    208     .help          = &help,
    209     .init          = &init,
    210     .parse         = &parse,
    211     .final_check   = &final_check,
    212     .print         = &print,
    213     .save          = &save,
    214     .extra_opts    = opts
    215 };
    216 
    217 void _init(void)
    218 {
    219 	register_target6(&connmark_target);
    220 }
    221