1/* 2 * nf_nat_proto_gre.c 3 * 4 * NAT protocol helper module for GRE. 5 * 6 * GRE is a generic encapsulation protocol, which is generally not very 7 * suited for NAT, as it has no protocol-specific part as port numbers. 8 * 9 * It has an optional key field, which may help us distinguishing two 10 * connections between the same two hosts. 11 * 12 * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 13 * 14 * PPTP is built on top of a modified version of GRE, and has a mandatory 15 * field called "CallID", which serves us for the same purpose as the key 16 * field in plain GRE. 17 * 18 * Documentation about PPTP can be found in RFC 2637 19 * 20 * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org> 21 * 22 * Development of this code funded by Astaro AG (http://www.astaro.com/) 23 * 24 * (C) 2006-2012 Patrick McHardy <kaber@trash.net> 25 * 26 */ 27 28#include <linux/module.h> 29#include <linux/skbuff.h> 30#include <linux/ip.h> 31 32#include <net/netfilter/nf_nat.h> 33#include <net/netfilter/nf_nat_l4proto.h> 34#include <linux/netfilter/nf_conntrack_proto_gre.h> 35 36MODULE_LICENSE("GPL"); 37MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 38MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); 39 40/* generate unique tuple ... */ 41static void 42gre_unique_tuple(const struct nf_nat_l3proto *l3proto, 43 struct nf_conntrack_tuple *tuple, 44 const struct nf_nat_range *range, 45 enum nf_nat_manip_type maniptype, 46 const struct nf_conn *ct) 47{ 48 static u_int16_t key; 49 __be16 *keyptr; 50 unsigned int min, i, range_size; 51 52 /* If there is no master conntrack we are not PPTP, 53 do not change tuples */ 54 if (!ct->master) 55 return; 56 57 if (maniptype == NF_NAT_MANIP_SRC) 58 keyptr = &tuple->src.u.gre.key; 59 else 60 keyptr = &tuple->dst.u.gre.key; 61 62 if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) { 63 pr_debug("%p: NATing GRE PPTP\n", ct); 64 min = 1; 65 range_size = 0xffff; 66 } else { 67 min = ntohs(range->min_proto.gre.key); 68 range_size = ntohs(range->max_proto.gre.key) - min + 1; 69 } 70 71 pr_debug("min = %u, range_size = %u\n", min, range_size); 72 73 for (i = 0; ; ++key) { 74 *keyptr = htons(min + key % range_size); 75 if (++i == range_size || !nf_nat_used_tuple(tuple, ct)) 76 return; 77 } 78 79 pr_debug("%p: no NAT mapping\n", ct); 80 return; 81} 82 83/* manipulate a GRE packet according to maniptype */ 84static bool 85gre_manip_pkt(struct sk_buff *skb, 86 const struct nf_nat_l3proto *l3proto, 87 unsigned int iphdroff, unsigned int hdroff, 88 const struct nf_conntrack_tuple *tuple, 89 enum nf_nat_manip_type maniptype) 90{ 91 const struct gre_hdr *greh; 92 struct gre_hdr_pptp *pgreh; 93 94 /* pgreh includes two optional 32bit fields which are not required 95 * to be there. That's where the magic '8' comes from */ 96 if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8)) 97 return false; 98 99 greh = (void *)skb->data + hdroff; 100 pgreh = (struct gre_hdr_pptp *)greh; 101 102 /* we only have destination manip of a packet, since 'source key' 103 * is not present in the packet itself */ 104 if (maniptype != NF_NAT_MANIP_DST) 105 return true; 106 switch (greh->version) { 107 case GRE_VERSION_1701: 108 /* We do not currently NAT any GREv0 packets. 109 * Try to behave like "nf_nat_proto_unknown" */ 110 break; 111 case GRE_VERSION_PPTP: 112 pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key)); 113 pgreh->call_id = tuple->dst.u.gre.key; 114 break; 115 default: 116 pr_debug("can't nat unknown GRE version\n"); 117 return false; 118 } 119 return true; 120} 121 122static const struct nf_nat_l4proto gre = { 123 .l4proto = IPPROTO_GRE, 124 .manip_pkt = gre_manip_pkt, 125 .in_range = nf_nat_l4proto_in_range, 126 .unique_tuple = gre_unique_tuple, 127#if IS_ENABLED(CONFIG_NF_CT_NETLINK) 128 .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, 129#endif 130}; 131 132static int __init nf_nat_proto_gre_init(void) 133{ 134 return nf_nat_l4proto_register(NFPROTO_IPV4, &gre); 135} 136 137static void __exit nf_nat_proto_gre_fini(void) 138{ 139 nf_nat_l4proto_unregister(NFPROTO_IPV4, &gre); 140} 141 142module_init(nf_nat_proto_gre_init); 143module_exit(nf_nat_proto_gre_fini); 144 145void nf_nat_need_gre(void) 146{ 147 return; 148} 149EXPORT_SYMBOL_GPL(nf_nat_need_gre); 150