libipt_NETMAP.c revision e44ea7faa17c10c68f14f5338a7cc6e3291a0ce7
1/* Shared library add-on to iptables to add static NAT support. 2 Author: Svenning Soerensen <svenning@post5.tele.dk> 3*/ 4 5#include <stdio.h> 6#include <netdb.h> 7#include <string.h> 8#include <stdlib.h> 9#include <getopt.h> 10#include <xtables.h> 11#include <linux/netfilter_ipv4/ip_tables.h> 12#include <linux/netfilter/nf_nat.h> 13 14#define MODULENAME "NETMAP" 15 16static const struct option NETMAP_opts[] = { 17 { "to", 1, NULL, '1' }, 18 { .name = NULL } 19}; 20 21static void NETMAP_help(void) 22{ 23 printf(MODULENAME" target options:\n" 24 " --%s address[/mask]\n" 25 " Network address to map to.\n\n", 26 NETMAP_opts[0].name); 27} 28 29static u_int32_t 30bits2netmask(int bits) 31{ 32 u_int32_t netmask, bm; 33 34 if (bits >= 32 || bits < 0) 35 return(~0); 36 for (netmask = 0, bm = 0x80000000; bits; bits--, bm >>= 1) 37 netmask |= bm; 38 return htonl(netmask); 39} 40 41static int 42netmask2bits(u_int32_t netmask) 43{ 44 u_int32_t bm; 45 int bits; 46 47 netmask = ntohl(netmask); 48 for (bits = 0, bm = 0x80000000; netmask & bm; netmask <<= 1) 49 bits++; 50 if (netmask) 51 return -1; /* holes in netmask */ 52 return bits; 53} 54 55static void NETMAP_init(struct xt_entry_target *t) 56{ 57 struct ip_nat_multi_range *mr = (struct ip_nat_multi_range *)t->data; 58 59 /* Actually, it's 0, but it's ignored at the moment. */ 60 mr->rangesize = 1; 61 62} 63 64/* Parses network address */ 65static void 66parse_to(char *arg, struct ip_nat_range *range) 67{ 68 char *slash; 69 const struct in_addr *ip; 70 u_int32_t netmask; 71 unsigned int bits; 72 73 range->flags |= IP_NAT_RANGE_MAP_IPS; 74 slash = strchr(arg, '/'); 75 if (slash) 76 *slash = '\0'; 77 78 ip = numeric_to_ipaddr(arg); 79 if (!ip) 80 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", 81 arg); 82 range->min_ip = ip->s_addr; 83 if (slash) { 84 if (strchr(slash+1, '.')) { 85 ip = numeric_to_ipmask(slash+1); 86 if (!ip) 87 exit_error(PARAMETER_PROBLEM, "Bad netmask `%s'\n", 88 slash+1); 89 netmask = ip->s_addr; 90 } 91 else { 92 if (!xtables_strtoui(slash+1, NULL, &bits, 0, 32)) 93 exit_error(PARAMETER_PROBLEM, "Bad netmask `%s'\n", 94 slash+1); 95 netmask = bits2netmask(bits); 96 } 97 /* Don't allow /0 (/1 is probably insane, too) */ 98 if (netmask == 0) 99 exit_error(PARAMETER_PROBLEM, "Netmask needed\n"); 100 } 101 else 102 netmask = ~0; 103 104 if (range->min_ip & ~netmask) { 105 if (slash) 106 *slash = '/'; 107 exit_error(PARAMETER_PROBLEM, "Bad network address `%s'\n", 108 arg); 109 } 110 range->max_ip = range->min_ip | ~netmask; 111} 112 113static int NETMAP_parse(int c, char **argv, int invert, unsigned int *flags, 114 const void *entry, struct xt_entry_target **target) 115{ 116 struct ip_nat_multi_range *mr 117 = (struct ip_nat_multi_range *)(*target)->data; 118 119 switch (c) { 120 case '1': 121 if (check_inverse(optarg, &invert, NULL, 0)) 122 exit_error(PARAMETER_PROBLEM, 123 "Unexpected `!' after --%s", NETMAP_opts[0].name); 124 125 parse_to(optarg, &mr->range[0]); 126 *flags = 1; 127 return 1; 128 129 default: 130 return 0; 131 } 132} 133 134static void NETMAP_check(unsigned int flags) 135{ 136 if (!flags) 137 exit_error(PARAMETER_PROBLEM, 138 MODULENAME" needs --%s", NETMAP_opts[0].name); 139} 140 141static void NETMAP_print(const void *ip, const struct xt_entry_target *target, 142 int numeric) 143{ 144 struct ip_nat_multi_range *mr 145 = (struct ip_nat_multi_range *)target->data; 146 struct ip_nat_range *r = &mr->range[0]; 147 struct in_addr a; 148 int bits; 149 150 a.s_addr = r->min_ip; 151 printf("%s", xtables_ipaddr_to_numeric(&a)); 152 a.s_addr = ~(r->min_ip ^ r->max_ip); 153 bits = netmask2bits(a.s_addr); 154 if (bits < 0) 155 printf("/%s", xtables_ipaddr_to_numeric(&a)); 156 else 157 printf("/%d", bits); 158} 159 160static void NETMAP_save(const void *ip, const struct xt_entry_target *target) 161{ 162 printf("--%s ", NETMAP_opts[0].name); 163 NETMAP_print(ip, target, 0); 164} 165 166static struct xtables_target netmap_tg_reg = { 167 .name = MODULENAME, 168 .version = XTABLES_VERSION, 169 .family = NFPROTO_IPV4, 170 .size = XT_ALIGN(sizeof(struct ip_nat_multi_range)), 171 .userspacesize = XT_ALIGN(sizeof(struct ip_nat_multi_range)), 172 .help = NETMAP_help, 173 .init = NETMAP_init, 174 .parse = NETMAP_parse, 175 .final_check = NETMAP_check, 176 .print = NETMAP_print, 177 .save = NETMAP_save, 178 .extra_opts = NETMAP_opts, 179}; 180 181void _init(void) 182{ 183 xtables_register_target(&netmap_tg_reg); 184} 185