libipt_SAME.c revision afe6b357db60c7d70379a27360c10a352bf55203
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 <xtables.h> 8#include <linux/netfilter/nf_nat.h> 9/* For 64bit kernel / 32bit userspace */ 10#include <linux/netfilter_ipv4/ipt_SAME.h> 11 12static void SAME_help(void) 13{ 14 printf( 15"SAME target options:\n" 16" --to <ipaddr>-<ipaddr>\n" 17" Addresses to map source to.\n" 18" May be specified more than\n" 19" once for multiple ranges.\n" 20" --nodst\n" 21" Don't use destination-ip in\n" 22" source selection\n" 23" --random\n" 24" Randomize source port\n"); 25} 26 27static const struct option SAME_opts[] = { 28 { "to", 1, NULL, '1' }, 29 { "nodst", 0, NULL, '2'}, 30 { "random", 0, NULL, '3' }, 31 { .name = NULL } 32}; 33 34static void SAME_init(struct xt_entry_target *t) 35{ 36 struct ipt_same_info *mr = (struct ipt_same_info *)t->data; 37 38 /* Set default to 0 */ 39 mr->rangesize = 0; 40 mr->info = 0; 41 mr->ipnum = 0; 42 43} 44 45/* Parses range of IPs */ 46static void 47parse_to(char *arg, struct ip_nat_range *range) 48{ 49 char *dash; 50 const struct in_addr *ip; 51 52 range->flags |= IP_NAT_RANGE_MAP_IPS; 53 dash = strchr(arg, '-'); 54 55 if (dash) 56 *dash = '\0'; 57 58 ip = xtables_numeric_to_ipaddr(arg); 59 if (!ip) 60 xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", 61 arg); 62 range->min_ip = ip->s_addr; 63 64 if (dash) { 65 ip = xtables_numeric_to_ipaddr(dash+1); 66 if (!ip) 67 xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", 68 dash+1); 69 } 70 range->max_ip = ip->s_addr; 71 if (dash) 72 if (range->min_ip > range->max_ip) 73 xtables_error(PARAMETER_PROBLEM, "Bad IP range \"%s-%s\"\n", 74 arg, dash+1); 75} 76 77#define IPT_SAME_OPT_TO 0x01 78#define IPT_SAME_OPT_NODST 0x02 79#define IPT_SAME_OPT_RANDOM 0x04 80 81static int SAME_parse(int c, char **argv, int invert, unsigned int *flags, 82 const void *entry, struct xt_entry_target **target) 83{ 84 struct ipt_same_info *mr 85 = (struct ipt_same_info *)(*target)->data; 86 unsigned int count; 87 88 switch (c) { 89 case '1': 90 if (mr->rangesize == IPT_SAME_MAX_RANGE) 91 xtables_error(PARAMETER_PROBLEM, 92 "Too many ranges specified, maximum " 93 "is %i ranges.\n", 94 IPT_SAME_MAX_RANGE); 95 if (xtables_check_inverse(optarg, &invert, NULL, 0)) 96 xtables_error(PARAMETER_PROBLEM, 97 "Unexpected `!' after --to"); 98 99 parse_to(optarg, &mr->range[mr->rangesize]); 100 /* WTF do we need this for? */ 101 if (*flags & IPT_SAME_OPT_RANDOM) 102 mr->range[mr->rangesize].flags 103 |= IP_NAT_RANGE_PROTO_RANDOM; 104 mr->rangesize++; 105 *flags |= IPT_SAME_OPT_TO; 106 break; 107 108 case '2': 109 if (*flags & IPT_SAME_OPT_NODST) 110 xtables_error(PARAMETER_PROBLEM, 111 "Can't specify --nodst twice"); 112 113 mr->info |= IPT_SAME_NODST; 114 *flags |= IPT_SAME_OPT_NODST; 115 break; 116 117 case '3': 118 *flags |= IPT_SAME_OPT_RANDOM; 119 for (count=0; count < mr->rangesize; count++) 120 mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM; 121 break; 122 123 default: 124 return 0; 125 } 126 127 return 1; 128} 129 130static void SAME_check(unsigned int flags) 131{ 132 if (!(flags & IPT_SAME_OPT_TO)) 133 xtables_error(PARAMETER_PROBLEM, 134 "SAME needs --to"); 135} 136 137static void SAME_print(const void *ip, const struct xt_entry_target *target, 138 int numeric) 139{ 140 unsigned int count; 141 struct ipt_same_info *mr 142 = (struct ipt_same_info *)target->data; 143 int random_selection = 0; 144 145 printf("same:"); 146 147 for (count = 0; count < mr->rangesize; count++) { 148 struct ip_nat_range *r = &mr->range[count]; 149 struct in_addr a; 150 151 a.s_addr = r->min_ip; 152 153 printf("%s", xtables_ipaddr_to_numeric(&a)); 154 a.s_addr = r->max_ip; 155 156 if (r->min_ip == r->max_ip) 157 printf(" "); 158 else 159 printf("-%s ", xtables_ipaddr_to_numeric(&a)); 160 if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) 161 random_selection = 1; 162 } 163 164 if (mr->info & IPT_SAME_NODST) 165 printf("nodst "); 166 167 if (random_selection) 168 printf("random "); 169} 170 171static void SAME_save(const void *ip, const struct xt_entry_target *target) 172{ 173 unsigned int count; 174 struct ipt_same_info *mr 175 = (struct ipt_same_info *)target->data; 176 int random_selection = 0; 177 178 for (count = 0; count < mr->rangesize; count++) { 179 struct ip_nat_range *r = &mr->range[count]; 180 struct in_addr a; 181 182 a.s_addr = r->min_ip; 183 printf("--to %s", xtables_ipaddr_to_numeric(&a)); 184 a.s_addr = r->max_ip; 185 186 if (r->min_ip == r->max_ip) 187 printf(" "); 188 else 189 printf("-%s ", xtables_ipaddr_to_numeric(&a)); 190 if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) 191 random_selection = 1; 192 } 193 194 if (mr->info & IPT_SAME_NODST) 195 printf("--nodst "); 196 197 if (random_selection) 198 printf("--random "); 199} 200 201static struct xtables_target same_tg_reg = { 202 .name = "SAME", 203 .version = XTABLES_VERSION, 204 .family = NFPROTO_IPV4, 205 .size = XT_ALIGN(sizeof(struct ipt_same_info)), 206 .userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)), 207 .help = SAME_help, 208 .init = SAME_init, 209 .parse = SAME_parse, 210 .final_check = SAME_check, 211 .print = SAME_print, 212 .save = SAME_save, 213 .extra_opts = SAME_opts, 214}; 215 216void _init(void) 217{ 218 xtables_register_target(&same_tg_reg); 219} 220