1/* Shared library add-on to iptables to add CONNMARK target support. */ 2#include <stdio.h> 3#include <string.h> 4#include <stdlib.h> 5#include <getopt.h> 6 7#include <iptables.h> 8#include <linux/netfilter_ipv4/ip_tables.h> 9#include <linux/netfilter_ipv4/ipt_CONNMARK.h> 10 11 12/* Function which prints out usage message. */ 13static void 14help(void) 15{ 16 printf( 17"CONNMARK target v%s options:\n" 18" --set-mark value Set conntrack mark value\n" 19" --save-mark Save the packet nfmark on the connection\n" 20" --restore-mark Restore saved nfmark value\n" 21"\n", 22IPTABLES_VERSION); 23} 24 25static struct option opts[] = { 26 { "set-mark", 1, 0, '1' }, 27 { "save-mark", 0, 0, '2' }, 28 { "restore-mark", 0, 0, '3' }, 29 { 0 } 30}; 31 32/* Initialize the target. */ 33static void 34init(struct ipt_entry_target *t, unsigned int *nfcache) 35{ 36} 37 38/* Function which parses command options; returns true if it 39 ate an option */ 40static int 41parse(int c, char **argv, int invert, unsigned int *flags, 42 const struct ipt_entry *entry, 43 struct ipt_entry_target **target) 44{ 45 struct ipt_connmark_target_info *markinfo 46 = (struct ipt_connmark_target_info *)(*target)->data; 47 48 switch (c) { 49 char *end; 50 case '1': 51 markinfo->mode = IPT_CONNMARK_SET; 52 markinfo->mark = strtoul(optarg, &end, 0); 53 if (*end != '\0' || end == optarg) 54 exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg); 55 if (*flags) 56 exit_error(PARAMETER_PROBLEM, 57 "CONNMARK target: Can't specify --set-mark twice"); 58 *flags = 1; 59 break; 60 case '2': 61 markinfo->mode = IPT_CONNMARK_SAVE; 62 if (*flags) 63 exit_error(PARAMETER_PROBLEM, 64 "CONNMARK target: Can't specify --save-mark twice"); 65 *flags = 1; 66 break; 67 case '3': 68 markinfo->mode = IPT_CONNMARK_RESTORE; 69 if (*flags) 70 exit_error(PARAMETER_PROBLEM, 71 "CONNMARK target: Can't specify --restore-mark twice"); 72 *flags = 1; 73 break; 74 default: 75 return 0; 76 } 77 78 return 1; 79} 80 81static void 82final_check(unsigned int flags) 83{ 84 if (!flags) 85 exit_error(PARAMETER_PROBLEM, 86 "CONNMARK target: Parameter --set-mark is required"); 87} 88 89static void 90print_mark(unsigned long mark, int numeric) 91{ 92 printf("0x%lx ", mark); 93} 94 95/* Prints out the targinfo. */ 96static void 97print(const struct ipt_ip *ip, 98 const struct ipt_entry_target *target, 99 int numeric) 100{ 101 const struct ipt_connmark_target_info *markinfo = 102 (const struct ipt_connmark_target_info *)target->data; 103 switch (markinfo->mode) { 104 case IPT_CONNMARK_SET: 105 printf("CONNMARK set "); 106 print_mark(markinfo->mark, numeric); 107 break; 108 case IPT_CONNMARK_SAVE: 109 printf("CONNMARK save "); 110 break; 111 case IPT_CONNMARK_RESTORE: 112 printf("CONNMARK restore "); 113 break; 114 default: 115 printf("ERROR: UNKNOWN CONNMARK MODE "); 116 break; 117 } 118} 119 120/* Saves the union ipt_targinfo in parsable form to stdout. */ 121static void 122save(const struct ipt_ip *ip, const struct ipt_entry_target *target) 123{ 124 const struct ipt_connmark_target_info *markinfo = 125 (const struct ipt_connmark_target_info *)target->data; 126 127 switch (markinfo->mode) { 128 case IPT_CONNMARK_SET: 129 printf("--set-mark 0x%lx ", markinfo->mark); 130 break; 131 case IPT_CONNMARK_SAVE: 132 printf("--save-mark "); 133 break; 134 case IPT_CONNMARK_RESTORE: 135 printf("--restore-mark "); 136 break; 137 default: 138 printf("ERROR: UNKNOWN CONNMARK MODE "); 139 break; 140 } 141} 142 143static 144struct iptables_target mark 145= { NULL, 146 "CONNMARK", 147 IPTABLES_VERSION, 148 IPT_ALIGN(sizeof(struct ipt_connmark_target_info)), 149 IPT_ALIGN(sizeof(struct ipt_connmark_target_info)), 150 &help, 151 &init, 152 &parse, 153 &final_check, 154 &print, 155 &save, 156 opts 157}; 158 159void _init(void) 160{ 161 register_target(&mark); 162} 163