libipt_SAME.c revision 8d14aeb8c4c3dc8ce9264b04b97f2e8634c1f381
1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#include <xtables.h> 5#include <net/netfilter/nf_nat.h> 6#include <linux/netfilter_ipv4/ipt_SAME.h> 7 8enum { 9 O_TO_ADDR = 0, 10 O_NODST, 11 O_RANDOM, 12 F_RANDOM = 1 << O_RANDOM, 13}; 14 15static void SAME_help(void) 16{ 17 printf( 18"SAME target 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" 26" --random\n" 27" Randomize source port\n"); 28} 29 30static const struct xt_option_entry SAME_opts[] = { 31 {.name = "to", .id = O_TO_ADDR, .type = XTTYPE_STRING, 32 .flags = XTOPT_MAND}, 33 {.name = "nodst", .id = O_NODST, .type = XTTYPE_NONE}, 34 {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, 35 XTOPT_TABLEEND, 36}; 37 38/* Parses range of IPs */ 39static void parse_to(const char *orig_arg, struct nf_nat_range *range) 40{ 41 char *dash, *arg; 42 const struct in_addr *ip; 43 44 arg = strdup(orig_arg); 45 if (arg == NULL) 46 xtables_error(RESOURCE_PROBLEM, "strdup"); 47 range->flags |= IP_NAT_RANGE_MAP_IPS; 48 dash = strchr(arg, '-'); 49 50 if (dash) 51 *dash = '\0'; 52 53 ip = xtables_numeric_to_ipaddr(arg); 54 if (!ip) 55 xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", 56 arg); 57 range->min_ip = ip->s_addr; 58 59 if (dash) { 60 ip = xtables_numeric_to_ipaddr(dash+1); 61 if (!ip) 62 xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", 63 dash+1); 64 } 65 range->max_ip = ip->s_addr; 66 if (dash) 67 if (range->min_ip > range->max_ip) 68 xtables_error(PARAMETER_PROBLEM, "Bad IP range \"%s-%s\"\n", 69 arg, dash+1); 70 free(arg); 71} 72 73static void SAME_parse(struct xt_option_call *cb) 74{ 75 struct ipt_same_info *mr = cb->data; 76 unsigned int count; 77 78 xtables_option_parse(cb); 79 switch (cb->entry->id) { 80 case O_TO_ADDR: 81 if (mr->rangesize == IPT_SAME_MAX_RANGE) 82 xtables_error(PARAMETER_PROBLEM, 83 "Too many ranges specified, maximum " 84 "is %i ranges.\n", 85 IPT_SAME_MAX_RANGE); 86 parse_to(cb->arg, &mr->range[mr->rangesize]); 87 /* WTF do we need this for? */ 88 if (cb->xflags & F_RANDOM) 89 mr->range[mr->rangesize].flags 90 |= IP_NAT_RANGE_PROTO_RANDOM; 91 mr->rangesize++; 92 break; 93 case O_NODST: 94 mr->info |= IPT_SAME_NODST; 95 break; 96 case O_RANDOM: 97 for (count=0; count < mr->rangesize; count++) 98 mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM; 99 break; 100 } 101} 102 103static void SAME_print(const void *ip, const struct xt_entry_target *target, 104 int numeric) 105{ 106 unsigned int count; 107 const struct ipt_same_info *mr = (const void *)target->data; 108 int random_selection = 0; 109 110 printf(" same:"); 111 112 for (count = 0; count < mr->rangesize; count++) { 113 const struct nf_nat_range *r = &mr->range[count]; 114 struct in_addr a; 115 116 a.s_addr = r->min_ip; 117 118 printf("%s", xtables_ipaddr_to_numeric(&a)); 119 a.s_addr = r->max_ip; 120 121 if (r->min_ip != r->max_ip) 122 printf("-%s", xtables_ipaddr_to_numeric(&a)); 123 if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) 124 random_selection = 1; 125 } 126 127 if (mr->info & IPT_SAME_NODST) 128 printf(" nodst"); 129 130 if (random_selection) 131 printf(" random"); 132} 133 134static void SAME_save(const void *ip, const struct xt_entry_target *target) 135{ 136 unsigned int count; 137 const struct ipt_same_info *mr = (const void *)target->data; 138 int random_selection = 0; 139 140 for (count = 0; count < mr->rangesize; count++) { 141 const struct nf_nat_range *r = &mr->range[count]; 142 struct in_addr a; 143 144 a.s_addr = r->min_ip; 145 printf(" --to %s", xtables_ipaddr_to_numeric(&a)); 146 a.s_addr = r->max_ip; 147 148 if (r->min_ip != r->max_ip) 149 printf("-%s", xtables_ipaddr_to_numeric(&a)); 150 if (r->flags & IP_NAT_RANGE_PROTO_RANDOM) 151 random_selection = 1; 152 } 153 154 if (mr->info & IPT_SAME_NODST) 155 printf(" --nodst"); 156 157 if (random_selection) 158 printf(" --random"); 159} 160 161static struct xtables_target same_tg_reg = { 162 .name = "SAME", 163 .version = XTABLES_VERSION, 164 .family = NFPROTO_IPV4, 165 .size = XT_ALIGN(sizeof(struct ipt_same_info)), 166 .userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)), 167 .help = SAME_help, 168 .x6_parse = SAME_parse, 169 .print = SAME_print, 170 .save = SAME_save, 171 .x6_options = SAME_opts, 172}; 173 174void _init(void) 175{ 176 xtables_register_target(&same_tg_reg); 177} 178