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