libipt_SAME.c revision bf97128c7262f17a02fec41cdae75b472ba77f88
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 <net/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 nf_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, argv)) 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 const struct ipt_same_info *mr = (const void *)target->data; 142 int random_selection = 0; 143 144 printf("same:"); 145 146 for (count = 0; count < mr->rangesize; count++) { 147 const struct nf_nat_range *r = &mr->range[count]; 148 struct in_addr a; 149 150 a.s_addr = r->min_ip; 151 152 printf("%s", xtables_ipaddr_to_numeric(&a)); 153 a.s_addr = r->max_ip; 154 155 if (r->min_ip == r->max_ip) 156 printf(" "); 157 else 158 printf("-%s ", xtables_ipaddr_to_numeric(&a)); 159 if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) 160 random_selection = 1; 161 } 162 163 if (mr->info & IPT_SAME_NODST) 164 printf("nodst "); 165 166 if (random_selection) 167 printf("random "); 168} 169 170static void SAME_save(const void *ip, const struct xt_entry_target *target) 171{ 172 unsigned int count; 173 const struct ipt_same_info *mr = (const void *)target->data; 174 int random_selection = 0; 175 176 for (count = 0; count < mr->rangesize; count++) { 177 const struct nf_nat_range *r = &mr->range[count]; 178 struct in_addr a; 179 180 a.s_addr = r->min_ip; 181 printf("--to %s", xtables_ipaddr_to_numeric(&a)); 182 a.s_addr = r->max_ip; 183 184 if (r->min_ip == r->max_ip) 185 printf(" "); 186 else 187 printf("-%s ", xtables_ipaddr_to_numeric(&a)); 188 if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) 189 random_selection = 1; 190 } 191 192 if (mr->info & IPT_SAME_NODST) 193 printf("--nodst "); 194 195 if (random_selection) 196 printf("--random "); 197} 198 199static struct xtables_target same_tg_reg = { 200 .name = "SAME", 201 .version = XTABLES_VERSION, 202 .family = NFPROTO_IPV4, 203 .size = XT_ALIGN(sizeof(struct ipt_same_info)), 204 .userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)), 205 .help = SAME_help, 206 .init = SAME_init, 207 .parse = SAME_parse, 208 .final_check = SAME_check, 209 .print = SAME_print, 210 .save = SAME_save, 211 .extra_opts = SAME_opts, 212}; 213 214void _init(void) 215{ 216 xtables_register_target(&same_tg_reg); 217} 218