2 * ip_nat_proto_gre.c - Version 2.0
4 * NAT protocol helper module for GRE.
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.
9 * It has an optional key field, which may help us distinguishing two
10 * connections between the same two hosts.
12 * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
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
18 * Documentation about PPTP can be found in RFC 2637
20 * (C) 2000-2004 by Harald Welte <laforge@gnumonks.org>
22 * Development of this code funded by Astaro AG (http://www.astaro.com/)
26 #include <linux/config.h>
27 #include <linux/module.h>
29 #include <linux/netfilter_ipv4/ip_nat.h>
30 #include <linux/netfilter_ipv4/ip_nat_rule.h>
31 #include <linux/netfilter_ipv4/ip_nat_protocol.h>
32 #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
34 MODULE_LICENSE("GPL");
35 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
36 MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
39 #define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
42 #define DEBUGP(x, args...)
45 /* is key in given range between min and max */
47 gre_in_range(const struct ip_conntrack_tuple *tuple,
48 enum ip_nat_manip_type maniptype,
49 const union ip_conntrack_manip_proto *min,
50 const union ip_conntrack_manip_proto *max)
54 if (maniptype == IP_NAT_MANIP_SRC)
55 key = tuple->src.u.gre.key;
57 key = tuple->dst.u.gre.key;
59 return ntohl(key) >= ntohl(min->gre.key)
60 && ntohl(key) <= ntohl(max->gre.key);
63 /* generate unique tuple ... */
65 gre_unique_tuple(struct ip_conntrack_tuple *tuple,
66 const struct ip_nat_range *range,
67 enum ip_nat_manip_type maniptype,
68 const struct ip_conntrack *conntrack)
70 u_int32_t min, i, range_size;
71 u_int32_t key = 0, *keyptr;
73 if (maniptype == IP_NAT_MANIP_SRC)
74 keyptr = &tuple->src.u.gre.key;
76 keyptr = &tuple->dst.u.gre.key;
78 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
79 DEBUGP("%p: NATing GRE PPTP\n", conntrack);
83 min = ntohl(range->min.gre.key);
84 range_size = ntohl(range->max.gre.key) - min + 1;
87 DEBUGP("min = %u, range_size = %u\n", min, range_size);
89 for (i = 0; i < range_size; i++, key++) {
90 *keyptr = htonl(min + key % range_size);
91 if (!ip_nat_used_tuple(tuple, conntrack))
95 DEBUGP("%p: no NAT mapping\n", conntrack);
100 /* manipulate a GRE packet according to maniptype */
102 gre_manip_pkt(struct sk_buff **pskb,
104 const struct ip_conntrack_manip *manip,
105 enum ip_nat_manip_type maniptype)
107 struct gre_hdr *greh;
108 struct gre_hdr_pptp *pgreh;
110 if (!skb_ip_make_writable(pskb, hdroff + sizeof(*pgreh)))
113 greh = (void *)(*pskb)->data + hdroff;
114 pgreh = (struct gre_hdr_pptp *) greh;
116 /* we only have destination manip of a packet, since 'source key'
117 * is not present in the packet itself */
118 if (maniptype == IP_NAT_MANIP_DST) {
119 /* key manipulation is always dest */
120 switch (greh->version) {
123 DEBUGP("can't nat GRE w/o key\n");
127 /* FIXME: Never tested this code... */
129 ip_nat_cheat_check(~*(gre_key(greh)),
133 *(gre_key(greh)) = manip->u.gre.key;
135 case GRE_VERSION_PPTP:
136 DEBUGP("call_id -> 0x%04x\n",
137 ntohl(manip->u.gre.key));
138 pgreh->call_id = htons(ntohl(manip->u.gre.key));
141 DEBUGP("can't nat unknown GRE version\n");
149 /* print out a nat tuple */
151 gre_print(char *buffer,
152 const struct ip_conntrack_tuple *match,
153 const struct ip_conntrack_tuple *mask)
155 unsigned int len = 0;
157 if (mask->src.u.gre.key)
158 len += sprintf(buffer + len, "srckey=0x%x ",
159 ntohl(match->src.u.gre.key));
161 if (mask->dst.u.gre.key)
162 len += sprintf(buffer + len, "dstkey=0x%x ",
163 ntohl(match->src.u.gre.key));
168 /* print a range of keys */
170 gre_print_range(char *buffer, const struct ip_nat_range *range)
172 if (range->min.gre.key != 0
173 || range->max.gre.key != 0xFFFF) {
174 if (range->min.gre.key == range->max.gre.key)
175 return sprintf(buffer, "key 0x%x ",
176 ntohl(range->min.gre.key));
178 return sprintf(buffer, "keys 0x%u-0x%u ",
179 ntohl(range->min.gre.key),
180 ntohl(range->max.gre.key));
185 /* nat helper struct */
186 static struct ip_nat_protocol gre = {
188 .protonum = IPPROTO_GRE,
189 .manip_pkt = gre_manip_pkt,
190 .in_range = gre_in_range,
191 .unique_tuple = gre_unique_tuple,
193 .print_range = gre_print_range
196 static int __init init(void)
198 if (ip_nat_protocol_register(&gre))
204 static void __exit fini(void)
206 ip_nat_protocol_unregister(&gre);