libipt_SAME.c revision 8115e5425721cd610b6390c3d4c24540773b0520
1/* Shared library add-on to iptables to add simple non load-balancing SNAT support. */ 2#include <stdio.h> 3#include <netdb.h> 4#include <string.h> 5#include <stdlib.h> 6#include <getopt.h> 7#include <iptables.h> 8#include <linux/netfilter_ipv4/ip_tables.h> 9#include <linux/netfilter_ipv4/ip_nat_rule.h> 10/* For 64bit kernel / 32bit userspace */ 11#include "../include/linux/netfilter_ipv4/ipt_SAME.h" 12 13/* Function which prints out usage message. */ 14static void 15help(void) 16{ 17 printf( 18"SAME v%s options:\n" 19" --to <ipaddr>-<ipaddr>\n" 20" Addresses to map source to.\n" 21" May be specified more than\n" 22" once for multiple ranges.\n" 23" --nodst\n" 24" Don't use destination-ip in\n" 25" source selection\n", 26IPTABLES_VERSION); 27} 28 29static struct option opts[] = { 30 { "to", 1, 0, '1' }, 31 { "nodst", 0, 0, '2'}, 32 { 0 } 33}; 34 35/* Initialize the target. */ 36static void 37init(struct ipt_entry_target *t, unsigned int *nfcache) 38{ 39 struct ipt_same_info *mr = (struct ipt_same_info *)t->data; 40 41 /* Set default to 0 */ 42 mr->rangesize = 0; 43 mr->info = 0; 44 mr->ipnum = 0; 45 46} 47 48/* Parses range of IPs */ 49static void 50parse_to(char *arg, struct ip_nat_range *range) 51{ 52 char *dash; 53 struct in_addr *ip; 54 55 range->flags |= IP_NAT_RANGE_MAP_IPS; 56 dash = strchr(arg, '-'); 57 58 if (dash) 59 *dash = '\0'; 60 61 ip = dotted_to_addr(arg); 62 if (!ip) 63 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", 64 arg); 65 range->min_ip = ip->s_addr; 66 67 if (dash) { 68 ip = dotted_to_addr(dash+1); 69 if (!ip) 70 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", 71 dash+1); 72 } 73 range->max_ip = ip->s_addr; 74 if (dash) 75 if (range->min_ip > range->max_ip) 76 exit_error(PARAMETER_PROBLEM, "Bad IP range `%s-%s'\n", 77 arg, dash+1); 78} 79 80#define IPT_SAME_OPT_TO 0x01 81#define IPT_SAME_OPT_NODST 0x02 82 83/* Function which parses command options; returns true if it 84 ate an option */ 85static int 86parse(int c, char **argv, int invert, unsigned int *flags, 87 const struct ipt_entry *entry, 88 struct ipt_entry_target **target) 89{ 90 struct ipt_same_info *mr 91 = (struct ipt_same_info *)(*target)->data; 92 93 switch (c) { 94 case '1': 95 if (mr->rangesize == IPT_SAME_MAX_RANGE) 96 exit_error(PARAMETER_PROBLEM, 97 "Too many ranges specified, maximum " 98 "is %i ranges.\n", 99 IPT_SAME_MAX_RANGE); 100 if (check_inverse(optarg, &invert, NULL, 0)) 101 exit_error(PARAMETER_PROBLEM, 102 "Unexpected `!' after --to"); 103 104 parse_to(optarg, &mr->range[mr->rangesize]); 105 mr->rangesize++; 106 *flags |= IPT_SAME_OPT_TO; 107 break; 108 109 case '2': 110 if (*flags & IPT_SAME_OPT_NODST) 111 exit_error(PARAMETER_PROBLEM, 112 "Can't specify --nodst twice"); 113 114 mr->info |= IPT_SAME_NODST; 115 *flags |= IPT_SAME_OPT_NODST; 116 break; 117 118 default: 119 return 0; 120 } 121 122 return 1; 123} 124 125/* Final check; need --to. */ 126static void final_check(unsigned int flags) 127{ 128 if (!(flags & IPT_SAME_OPT_TO)) 129 exit_error(PARAMETER_PROBLEM, 130 "SAME needs --to"); 131} 132 133/* Prints out the targinfo. */ 134static void 135print(const struct ipt_ip *ip, 136 const struct ipt_entry_target *target, 137 int numeric) 138{ 139 int count; 140 struct ipt_same_info *mr 141 = (struct ipt_same_info *)target->data; 142 143 printf("same:"); 144 145 for (count = 0; count < mr->rangesize; count++) { 146 struct ip_nat_range *r = &mr->range[count]; 147 struct in_addr a; 148 149 a.s_addr = r->min_ip; 150 151 printf("%s", addr_to_dotted(&a)); 152 a.s_addr = r->max_ip; 153 154 if (r->min_ip == r->max_ip) 155 printf(" "); 156 else 157 printf("-%s ", addr_to_dotted(&a)); 158 } 159 160 if (mr->info & IPT_SAME_NODST) 161 printf("nodst "); 162} 163 164/* Saves the union ipt_targinfo in parsable form to stdout. */ 165static void 166save(const struct ipt_ip *ip, const struct ipt_entry_target *target) 167{ 168 int count; 169 struct ipt_same_info *mr 170 = (struct ipt_same_info *)target->data; 171 172 for (count = 0; count < mr->rangesize; count++) { 173 struct ip_nat_range *r = &mr->range[count]; 174 struct in_addr a; 175 176 a.s_addr = r->min_ip; 177 printf("--to %s", addr_to_dotted(&a)); 178 a.s_addr = r->max_ip; 179 180 if (r->min_ip == r->max_ip) 181 printf(" "); 182 else 183 printf("-%s ", addr_to_dotted(&a)); 184 } 185 186 if (mr->info & IPT_SAME_NODST) 187 printf("--nodst "); 188} 189 190static struct iptables_target same = { 191 .next = NULL, 192 .name = "SAME", 193 .version = IPTABLES_VERSION, 194 .size = IPT_ALIGN(sizeof(struct ipt_same_info)), 195 .userspacesize = IPT_ALIGN(sizeof(struct ipt_same_info)), 196 .help = &help, 197 .init = &init, 198 .parse = &parse, 199 .final_check = &final_check, 200 .print = &print, 201 .save = &save, 202 .extra_opts = opts 203}; 204 205void _init(void) 206{ 207 register_target(&same); 208} 209