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