1 /* Shared library add-on to iptables to add static NAT support. 2 Author: Svenning Soerensen <svenning (at) post5.tele.dk> 3 */ 4 #include <stdio.h> 5 #include <netdb.h> 6 #include <string.h> 7 #include <stdlib.h> 8 #include <getopt.h> 9 #include <xtables.h> 10 #include <linux/netfilter/nf_nat.h> 11 12 #define MODULENAME "NETMAP" 13 14 enum { 15 O_TO = 0, 16 }; 17 18 static const struct xt_option_entry NETMAP_opts[] = { 19 {.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK, 20 .flags = XTOPT_MAND}, 21 XTOPT_TABLEEND, 22 }; 23 24 static void NETMAP_help(void) 25 { 26 printf(MODULENAME" target options:\n" 27 " --%s address[/mask]\n" 28 " Network address to map to.\n\n", 29 NETMAP_opts[0].name); 30 } 31 32 static int 33 netmask2bits(uint32_t netmask) 34 { 35 uint32_t bm; 36 int bits; 37 38 netmask = ntohl(netmask); 39 for (bits = 0, bm = 0x80000000; netmask & bm; netmask <<= 1) 40 bits++; 41 if (netmask) 42 return -1; /* holes in netmask */ 43 return bits; 44 } 45 46 static void NETMAP_init(struct xt_entry_target *t) 47 { 48 struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data; 49 50 /* Actually, it's 0, but it's ignored at the moment. */ 51 mr->rangesize = 1; 52 } 53 54 static void NETMAP_parse(struct xt_option_call *cb) 55 { 56 struct nf_nat_ipv4_multi_range_compat *mr = cb->data; 57 struct nf_nat_ipv4_range *range = &mr->range[0]; 58 59 xtables_option_parse(cb); 60 range->flags |= NF_NAT_RANGE_MAP_IPS; 61 range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip; 62 range->max_ip = range->min_ip | ~cb->val.hmask.ip; 63 } 64 65 static void __NETMAP_print(const void *ip, const struct xt_entry_target *target, 66 int numeric) 67 { 68 const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data; 69 const struct nf_nat_ipv4_range *r = &mr->range[0]; 70 struct in_addr a; 71 int bits; 72 73 a.s_addr = r->min_ip; 74 printf("%s", xtables_ipaddr_to_numeric(&a)); 75 a.s_addr = ~(r->min_ip ^ r->max_ip); 76 bits = netmask2bits(a.s_addr); 77 if (bits < 0) 78 printf("/%s", xtables_ipaddr_to_numeric(&a)); 79 else 80 printf("/%d", bits); 81 } 82 83 static void NETMAP_print(const void *ip, const struct xt_entry_target *target, 84 int numeric) 85 { 86 printf(" to:"); 87 __NETMAP_print(ip, target, numeric); 88 } 89 90 static void NETMAP_save(const void *ip, const struct xt_entry_target *target) 91 { 92 printf(" --%s ", NETMAP_opts[0].name); 93 __NETMAP_print(ip, target, 0); 94 } 95 96 static struct xtables_target netmap_tg_reg = { 97 .name = MODULENAME, 98 .version = XTABLES_VERSION, 99 .family = NFPROTO_IPV4, 100 .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), 101 .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)), 102 .help = NETMAP_help, 103 .init = NETMAP_init, 104 .x6_parse = NETMAP_parse, 105 .print = NETMAP_print, 106 .save = NETMAP_save, 107 .x6_options = NETMAP_opts, 108 }; 109 110 void _init(void) 111 { 112 xtables_register_target(&netmap_tg_reg); 113 } 114