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 8 enum { 9 O_TO_ADDR = 0, 10 O_NODST, 11 O_RANDOM, 12 F_RANDOM = 1 << O_RANDOM, 13 }; 14 15 static 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 30 static 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 */ 39 static 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 73 static 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 103 static 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 134 static 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 161 static 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 174 void _init(void) 175 { 176 xtables_register_target(&same_tg_reg); 177 } 178