1aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger/* 2aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> 3aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * 4aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * Based on Rusty Russell's IPv4 DNAT target. Development of IPv6 NAT 5aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger * funded by Astaro. 6aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger */ 7aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 8aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <stdio.h> 9aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <netdb.h> 10aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <string.h> 11aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <stdlib.h> 12aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <xtables.h> 13aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <iptables.h> 14aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <limits.h> /* INT_MAX in ip_tables.h */ 15aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <linux/netfilter_ipv6/ip6_tables.h> 16aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger#include <linux/netfilter/nf_nat.h> 17aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 18aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerenum { 19aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger O_TO_DEST = 0, 20aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger O_RANDOM, 21aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger O_PERSISTENT, 22aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger O_X_TO_DEST, 23aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger F_TO_DEST = 1 << O_TO_DEST, 24aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger F_RANDOM = 1 << O_RANDOM, 25aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger F_X_TO_DEST = 1 << O_X_TO_DEST, 26aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}; 27aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 28aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic void DNAT_help(void) 29aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 30aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf( 31aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger"DNAT target options:\n" 32aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger" --to-destination [<ipaddr>[-<ipaddr>]][:port[-port]]\n" 33aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger" Address to map destination to.\n" 34aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger"[--random] [--persistent]\n"); 35aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 36aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 37aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic const struct xt_option_entry DNAT_opts[] = { 38aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger {.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING, 39aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .flags = XTOPT_MAND | XTOPT_MULTI}, 40aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, 41aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, 42aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger XTOPT_TABLEEND, 43aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}; 44aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 45aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger/* Ranges expected in network order. */ 46aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic void 47aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerparse_to(const char *orig_arg, int portok, struct nf_nat_range *range) 48aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 49aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger char *arg, *start, *end = NULL, *colon = NULL, *dash, *error; 50aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger const struct in6_addr *ip; 51aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 52aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger arg = strdup(orig_arg); 53aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (arg == NULL) 54aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(RESOURCE_PROBLEM, "strdup"); 55aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 56aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger start = strchr(arg, '['); 57aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (start == NULL) { 58aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger start = arg; 59aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger /* Lets assume one colon is port information. Otherwise its an IPv6 address */ 60aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger colon = strchr(arg, ':'); 61aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (colon && strchr(colon+1, ':')) 62aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger colon = NULL; 63aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 64aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger else { 65aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger start++; 66aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger end = strchr(start, ']'); 67aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (end == NULL) 68aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(PARAMETER_PROBLEM, 69aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger "Invalid address format"); 70aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 71aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *end = '\0'; 72aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger colon = strchr(end + 1, ':'); 73aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 74aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 75aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (colon) { 76aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int port; 77aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 78aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (!portok) 79aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(PARAMETER_PROBLEM, 80aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger "Need TCP, UDP, SCTP or DCCP with port specification"); 81aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 82aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; 83aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 84aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger port = atoi(colon+1); 85aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (port <= 0 || port > 65535) 86aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(PARAMETER_PROBLEM, 87aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger "Port `%s' not valid\n", colon+1); 88aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 89aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger error = strchr(colon+1, ':'); 90aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (error) 91aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(PARAMETER_PROBLEM, 92aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger "Invalid port:port syntax - use dash\n"); 93aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 94aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger dash = strchr(colon, '-'); 95aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (!dash) { 96aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger range->min_proto.tcp.port 97aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger = range->max_proto.tcp.port 98aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger = htons(port); 99aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } else { 100aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int maxport; 101aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 102aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger maxport = atoi(dash + 1); 103aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (maxport <= 0 || maxport > 65535) 104aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(PARAMETER_PROBLEM, 105aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger "Port `%s' not valid\n", dash+1); 106aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (maxport < port) 107aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger /* People are stupid. */ 108aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(PARAMETER_PROBLEM, 109aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger "Port range `%s' funky\n", colon+1); 110aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger range->min_proto.tcp.port = htons(port); 111aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger range->max_proto.tcp.port = htons(maxport); 112aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 113aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger /* Starts with colon or [] colon? No IP info...*/ 114aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (colon == arg || colon == arg+2) { 115aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger free(arg); 116aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return; 117aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 118aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *colon = '\0'; 119aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 120aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 121aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger range->flags |= NF_NAT_RANGE_MAP_IPS; 122aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger dash = strchr(start, '-'); 123aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (colon && dash && dash > colon) 124aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger dash = NULL; 125aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 126aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (dash) 127aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger *dash = '\0'; 128aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 129aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger ip = xtables_numeric_to_ip6addr(start); 130aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (!ip) 131aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", 132aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger start); 133aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger range->min_addr.in6 = *ip; 134aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (dash) { 135aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger ip = xtables_numeric_to_ip6addr(dash + 1); 136aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (!ip) 137aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", 138aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger dash+1); 139aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger range->max_addr.in6 = *ip; 140aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } else 141aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger range->max_addr = range->min_addr; 142aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 143aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger free(arg); 144aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger return; 145aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 146aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 147aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic void DNAT_parse(struct xt_option_call *cb) 148aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 149aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger const struct ip6t_entry *entry = cb->xt_entry; 150aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nf_nat_range *range = cb->data; 151aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int portok; 152aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 153aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (entry->ipv6.proto == IPPROTO_TCP || 154aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger entry->ipv6.proto == IPPROTO_UDP || 155aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger entry->ipv6.proto == IPPROTO_SCTP || 156aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger entry->ipv6.proto == IPPROTO_DCCP || 157aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger entry->ipv6.proto == IPPROTO_ICMP) 158aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger portok = 1; 159aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger else 160aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger portok = 0; 161aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 162aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_option_parse(cb); 163aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger switch (cb->entry->id) { 164aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger case O_TO_DEST: 165aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (cb->xflags & F_X_TO_DEST) { 166aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (!kernel_version) 167aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger get_kernel_version(); 168aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (kernel_version > LINUX_VERSION(2, 6, 10)) 169aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_error(PARAMETER_PROBLEM, 170aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger "DNAT: Multiple --to-destination not supported"); 171aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 172aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger parse_to(cb->arg, portok, range); 173aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger break; 174aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger case O_PERSISTENT: 175aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger range->flags |= NF_NAT_RANGE_PERSISTENT; 176aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger break; 177aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 178aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 179aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 180aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic void DNAT_fcheck(struct xt_fcheck_call *cb) 181aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 182aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger static const unsigned int f = F_TO_DEST | F_RANDOM; 183aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger struct nf_nat_range *mr = cb->data; 184aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 185aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if ((cb->xflags & f) == f) 186aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger mr->flags |= NF_NAT_RANGE_PROTO_RANDOM; 187aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 188aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 189aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic void print_range(const struct nf_nat_range *range) 190aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 191aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (range->flags & NF_NAT_RANGE_MAP_IPS) { 192aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) 193aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf("["); 194aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6)); 195aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (memcmp(&range->min_addr, &range->max_addr, 196aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger sizeof(range->min_addr))) 197aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6)); 198aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) 199aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf("]"); 200aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 201aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { 202aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf(":"); 203aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf("%hu", ntohs(range->min_proto.tcp.port)); 204aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (range->max_proto.tcp.port != range->min_proto.tcp.port) 205aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf("-%hu", ntohs(range->max_proto.tcp.port)); 206aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger } 207aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 208aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 209aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic void DNAT_print(const void *ip, const struct xt_entry_target *target, 210aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger int numeric) 211aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 212aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger const struct nf_nat_range *range = (const void *)target->data; 213aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 214aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf(" to:"); 215aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger print_range(range); 216aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) 217aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf(" random"); 218aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (range->flags & NF_NAT_RANGE_PERSISTENT) 219aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf(" persistent"); 220aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 221aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 222aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic void DNAT_save(const void *ip, const struct xt_entry_target *target) 223aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 224aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger const struct nf_nat_range *range = (const void *)target->data; 225aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 226aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf(" --to-destination "); 227aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger print_range(range); 228aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) 229aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf(" --random"); 230aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger if (range->flags & NF_NAT_RANGE_PERSISTENT) 231aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger printf(" --persistent"); 232aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 233aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 234aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingerstatic struct xtables_target snat_tg_reg = { 235aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .name = "DNAT", 236aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .version = XTABLES_VERSION, 237aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .family = NFPROTO_IPV6, 238aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .revision = 1, 239aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .size = XT_ALIGN(sizeof(struct nf_nat_range)), 240aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)), 241aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .help = DNAT_help, 242aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .x6_parse = DNAT_parse, 243aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .x6_fcheck = DNAT_fcheck, 244aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .print = DNAT_print, 245aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .save = DNAT_save, 246aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger .x6_options = DNAT_opts, 247aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger}; 248aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger 249aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemmingervoid _init(void) 250aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger{ 251aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger xtables_register_target(&snat_tg_reg); 252aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger} 253aba5acdfdb347d2c21fc67d613d83d4430ca3937osdl.org!shemminger