]> git.pld-linux.org Git - packages/kernel.git/blame - 2.6.0-pptp-conntrack-nat-20031219.patch
- CSZ scheduler removed from kernel tree.
[packages/kernel.git] / 2.6.0-pptp-conntrack-nat-20031219.patch
CommitLineData
6317ee85 1diff -Nur linux-2.6.0.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack.h
2--- linux-2.6.0.org/include/linux/netfilter_ipv4/ip_conntrack.h 2003-12-18 03:59:40.000000000 +0100
95cfd539 3+++ linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack.h 2003-12-19 14:14:23.000000000 +0100
6317ee85 4@@ -51,19 +51,23 @@
5
6 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
7 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
8+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
9
10 /* per conntrack: protocol private data */
11 union ip_conntrack_proto {
12 /* insert conntrack proto private data here */
13+ struct ip_ct_gre gre;
14 struct ip_ct_tcp tcp;
15 struct ip_ct_icmp icmp;
16 };
17
18 union ip_conntrack_expect_proto {
19 /* insert expect proto private data here */
20+ struct ip_ct_gre_expect gre;
21 };
22
23 /* Add protocol helper include file here */
24+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
25 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
26 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
27 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
28@@ -71,6 +75,7 @@
29 /* per expectation: application helper private data */
30 union ip_conntrack_expect_help {
31 /* insert conntrack helper private data (expect) here */
32+ struct ip_ct_pptp_expect exp_pptp_info;
33 struct ip_ct_amanda_expect exp_amanda_info;
34 struct ip_ct_ftp_expect exp_ftp_info;
35 struct ip_ct_irc_expect exp_irc_info;
36@@ -85,16 +90,19 @@
37 /* per conntrack: application helper private data */
38 union ip_conntrack_help {
39 /* insert conntrack helper private data (master) here */
40+ struct ip_ct_pptp_master ct_pptp_info;
41 struct ip_ct_ftp_master ct_ftp_info;
42 struct ip_ct_irc_master ct_irc_info;
43 };
44
45 #ifdef CONFIG_IP_NF_NAT_NEEDED
46 #include <linux/netfilter_ipv4/ip_nat.h>
47+#include <linux/netfilter_ipv4/ip_nat_pptp.h>
48
49 /* per conntrack: nat application helper private data */
50 union ip_conntrack_nat_help {
51 /* insert nat helper private data here */
52+ struct ip_nat_pptp nat_pptp_info;
53 };
54 #endif
55
95cfd539 56diff -Nur linux-2.6.0.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
57--- linux-2.6.0.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 1970-01-01 01:00:00.000000000 +0100
58+++ linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 2003-11-17 09:09:34.000000000 +0100
59@@ -0,0 +1,313 @@
60+/* PPTP constants and structs */
61+#ifndef _CONNTRACK_PPTP_H
62+#define _CONNTRACK_PPTP_H
63+
64+/* state of the control session */
65+enum pptp_ctrlsess_state {
66+ PPTP_SESSION_NONE, /* no session present */
67+ PPTP_SESSION_ERROR, /* some session error */
68+ PPTP_SESSION_STOPREQ, /* stop_sess request seen */
69+ PPTP_SESSION_REQUESTED, /* start_sess request seen */
70+ PPTP_SESSION_CONFIRMED, /* session established */
71+};
72+
73+/* state of the call inside the control session */
74+enum pptp_ctrlcall_state {
75+ PPTP_CALL_NONE,
76+ PPTP_CALL_ERROR,
77+ PPTP_CALL_OUT_REQ,
78+ PPTP_CALL_OUT_CONF,
79+ PPTP_CALL_IN_REQ,
80+ PPTP_CALL_IN_REP,
81+ PPTP_CALL_IN_CONF,
82+ PPTP_CALL_CLEAR_REQ,
83+};
84+
85+
86+/* conntrack private data */
87+struct ip_ct_pptp_master {
88+ enum pptp_ctrlsess_state sstate; /* session state */
89+
90+ /* everything below is going to be per-expectation in newnat,
91+ * since there could be more than one call within one session */
92+ enum pptp_ctrlcall_state cstate; /* call state */
93+ u_int16_t pac_call_id; /* call id of PAC, host byte order */
94+ u_int16_t pns_call_id; /* call id of PNS, host byte order */
95+};
96+
97+/* conntrack_expect private member */
98+struct ip_ct_pptp_expect {
99+ enum pptp_ctrlcall_state cstate; /* call state */
100+ u_int16_t pac_call_id; /* call id of PAC */
101+ u_int16_t pns_call_id; /* call id of PNS */
102+};
103+
104+
105+#ifdef __KERNEL__
106+
107+#include <linux/netfilter_ipv4/lockhelp.h>
108+DECLARE_LOCK_EXTERN(ip_pptp_lock);
109+
110+#define IP_CONNTR_PPTP PPTP_CONTROL_PORT
111+
112+union pptp_ctrl_union {
113+ void *rawreq;
114+ struct PptpStartSessionRequest *sreq;
115+ struct PptpStartSessionReply *srep;
116+ struct PptpStopSessionReqest *streq;
117+ struct PptpStopSessionReply *strep;
118+ struct PptpOutCallRequest *ocreq;
119+ struct PptpOutCallReply *ocack;
120+ struct PptpInCallRequest *icreq;
121+ struct PptpInCallReply *icack;
122+ struct PptpInCallConnected *iccon;
123+ struct PptpClearCallRequest *clrreq;
124+ struct PptpCallDisconnectNotify *disc;
125+ struct PptpWanErrorNotify *wanerr;
126+ struct PptpSetLinkInfo *setlink;
127+};
128+
129+
130+
131+#define PPTP_CONTROL_PORT 1723
132+
133+#define PPTP_PACKET_CONTROL 1
134+#define PPTP_PACKET_MGMT 2
135+
136+#define PPTP_MAGIC_COOKIE 0x1a2b3c4d
137+
138+struct pptp_pkt_hdr {
139+ __u16 packetLength;
140+ __u16 packetType;
141+ __u32 magicCookie;
142+};
143+
144+/* PptpControlMessageType values */
145+#define PPTP_START_SESSION_REQUEST 1
146+#define PPTP_START_SESSION_REPLY 2
147+#define PPTP_STOP_SESSION_REQUEST 3
148+#define PPTP_STOP_SESSION_REPLY 4
149+#define PPTP_ECHO_REQUEST 5
150+#define PPTP_ECHO_REPLY 6
151+#define PPTP_OUT_CALL_REQUEST 7
152+#define PPTP_OUT_CALL_REPLY 8
153+#define PPTP_IN_CALL_REQUEST 9
154+#define PPTP_IN_CALL_REPLY 10
155+#define PPTP_IN_CALL_CONNECT 11
156+#define PPTP_CALL_CLEAR_REQUEST 12
157+#define PPTP_CALL_DISCONNECT_NOTIFY 13
158+#define PPTP_WAN_ERROR_NOTIFY 14
159+#define PPTP_SET_LINK_INFO 15
160+
161+#define PPTP_MSG_MAX 15
162+
163+/* PptpGeneralError values */
164+#define PPTP_ERROR_CODE_NONE 0
165+#define PPTP_NOT_CONNECTED 1
166+#define PPTP_BAD_FORMAT 2
167+#define PPTP_BAD_VALUE 3
168+#define PPTP_NO_RESOURCE 4
169+#define PPTP_BAD_CALLID 5
170+#define PPTP_REMOVE_DEVICE_ERROR 6
171+
172+struct PptpControlHeader {
173+ __u16 messageType;
174+ __u16 reserved;
175+};
176+
177+/* FramingCapability Bitmap Values */
178+#define PPTP_FRAME_CAP_ASYNC 0x1
179+#define PPTP_FRAME_CAP_SYNC 0x2
180+
181+/* BearerCapability Bitmap Values */
182+#define PPTP_BEARER_CAP_ANALOG 0x1
183+#define PPTP_BEARER_CAP_DIGITAL 0x2
184+
185+struct PptpStartSessionRequest {
186+ __u16 protocolVersion;
187+ __u8 reserved1;
188+ __u8 reserved2;
189+ __u32 framingCapability;
190+ __u32 bearerCapability;
191+ __u16 maxChannels;
192+ __u16 firmwareRevision;
193+ __u8 hostName[64];
194+ __u8 vendorString[64];
195+};
196+
197+/* PptpStartSessionResultCode Values */
198+#define PPTP_START_OK 1
199+#define PPTP_START_GENERAL_ERROR 2
200+#define PPTP_START_ALREADY_CONNECTED 3
201+#define PPTP_START_NOT_AUTHORIZED 4
202+#define PPTP_START_UNKNOWN_PROTOCOL 5
203+
204+struct PptpStartSessionReply {
205+ __u16 protocolVersion;
206+ __u8 resultCode;
207+ __u8 generalErrorCode;
208+ __u32 framingCapability;
209+ __u32 bearerCapability;
210+ __u16 maxChannels;
211+ __u16 firmwareRevision;
212+ __u8 hostName[64];
213+ __u8 vendorString[64];
214+};
215+
216+/* PptpStopReasons */
217+#define PPTP_STOP_NONE 1
218+#define PPTP_STOP_PROTOCOL 2
219+#define PPTP_STOP_LOCAL_SHUTDOWN 3
220+
221+struct PptpStopSessionRequest {
222+ __u8 reason;
223+};
224+
225+/* PptpStopSessionResultCode */
226+#define PPTP_STOP_OK 1
227+#define PPTP_STOP_GENERAL_ERROR 2
228+
229+struct PptpStopSessionReply {
230+ __u8 resultCode;
231+ __u8 generalErrorCode;
232+};
233+
234+struct PptpEchoRequest {
235+ __u32 identNumber;
236+};
237+
238+/* PptpEchoReplyResultCode */
239+#define PPTP_ECHO_OK 1
240+#define PPTP_ECHO_GENERAL_ERROR 2
241+
242+struct PptpEchoReply {
243+ __u32 identNumber;
244+ __u8 resultCode;
245+ __u8 generalErrorCode;
246+ __u16 reserved;
247+};
248+
249+/* PptpFramingType */
250+#define PPTP_ASYNC_FRAMING 1
251+#define PPTP_SYNC_FRAMING 2
252+#define PPTP_DONT_CARE_FRAMING 3
253+
254+/* PptpCallBearerType */
255+#define PPTP_ANALOG_TYPE 1
256+#define PPTP_DIGITAL_TYPE 2
257+#define PPTP_DONT_CARE_BEARER_TYPE 3
258+
259+struct PptpOutCallRequest {
260+ __u16 callID;
261+ __u16 callSerialNumber;
262+ __u32 minBPS;
263+ __u32 maxBPS;
264+ __u32 bearerType;
265+ __u32 framingType;
266+ __u16 packetWindow;
267+ __u16 packetProcDelay;
268+ __u16 reserved1;
269+ __u16 phoneNumberLength;
270+ __u16 reserved2;
271+ __u8 phoneNumber[64];
272+ __u8 subAddress[64];
273+};
274+
275+/* PptpCallResultCode */
276+#define PPTP_OUTCALL_CONNECT 1
277+#define PPTP_OUTCALL_GENERAL_ERROR 2
278+#define PPTP_OUTCALL_NO_CARRIER 3
279+#define PPTP_OUTCALL_BUSY 4
280+#define PPTP_OUTCALL_NO_DIAL_TONE 5
281+#define PPTP_OUTCALL_TIMEOUT 6
282+#define PPTP_OUTCALL_DONT_ACCEPT 7
283+
284+struct PptpOutCallReply {
285+ __u16 callID;
286+ __u16 peersCallID;
287+ __u8 resultCode;
288+ __u8 generalErrorCode;
289+ __u16 causeCode;
290+ __u32 connectSpeed;
291+ __u16 packetWindow;
292+ __u16 packetProcDelay;
293+ __u32 physChannelID;
294+};
295+
296+struct PptpInCallRequest {
297+ __u16 callID;
298+ __u16 callSerialNumber;
299+ __u32 callBearerType;
300+ __u32 physChannelID;
301+ __u16 dialedNumberLength;
302+ __u16 dialingNumberLength;
303+ __u8 dialedNumber[64];
304+ __u8 dialingNumber[64];
305+ __u8 subAddress[64];
306+};
307+
308+/* PptpInCallResultCode */
309+#define PPTP_INCALL_ACCEPT 1
310+#define PPTP_INCALL_GENERAL_ERROR 2
311+#define PPTP_INCALL_DONT_ACCEPT 3
312+
313+struct PptpInCallReply {
314+ __u16 callID;
315+ __u16 peersCallID;
316+ __u8 resultCode;
317+ __u8 generalErrorCode;
318+ __u16 packetWindow;
319+ __u16 packetProcDelay;
320+ __u16 reserved;
321+};
322+
323+struct PptpInCallConnected {
324+ __u16 peersCallID;
325+ __u16 reserved;
326+ __u32 connectSpeed;
327+ __u16 packetWindow;
328+ __u16 packetProcDelay;
329+ __u32 callFramingType;
330+};
331+
332+struct PptpClearCallRequest {
333+ __u16 callID;
334+ __u16 reserved;
335+};
336+
337+struct PptpCallDisconnectNotify {
338+ __u16 callID;
339+ __u8 resultCode;
340+ __u8 generalErrorCode;
341+ __u16 causeCode;
342+ __u16 reserved;
343+ __u8 callStatistics[128];
344+};
345+
346+struct PptpWanErrorNotify {
347+ __u16 peersCallID;
348+ __u16 reserved;
349+ __u32 crcErrors;
350+ __u32 framingErrors;
351+ __u32 hardwareOverRuns;
352+ __u32 bufferOverRuns;
353+ __u32 timeoutErrors;
354+ __u32 alignmentErrors;
355+};
356+
357+struct PptpSetLinkInfo {
358+ __u16 peersCallID;
359+ __u16 reserved;
360+ __u32 sendAccm;
361+ __u32 recvAccm;
362+};
363+
364+
365+struct pptp_priv_data {
366+ __u16 call_id;
367+ __u16 mcall_id;
368+ __u16 pcall_id;
369+};
370+
371+#endif /* __KERNEL__ */
372+#endif /* _CONNTRACK_PPTP_H */
373diff -Nur linux-2.6.0.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
374--- linux-2.6.0.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 1970-01-01 01:00:00.000000000 +0100
375+++ linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 2003-11-17 09:09:34.000000000 +0100
376@@ -0,0 +1,123 @@
377+#ifndef _CONNTRACK_PROTO_GRE_H
378+#define _CONNTRACK_PROTO_GRE_H
379+#include <asm/byteorder.h>
380+
381+/* GRE PROTOCOL HEADER */
382+
383+/* GRE Version field */
384+#define GRE_VERSION_1701 0x0
385+#define GRE_VERSION_PPTP 0x1
386+
387+/* GRE Protocol field */
388+#define GRE_PROTOCOL_PPTP 0x880B
389+
390+/* GRE Flags */
391+#define GRE_FLAG_C 0x80
392+#define GRE_FLAG_R 0x40
393+#define GRE_FLAG_K 0x20
394+#define GRE_FLAG_S 0x10
395+#define GRE_FLAG_A 0x80
396+
397+#define GRE_IS_C(f) ((f)&GRE_FLAG_C)
398+#define GRE_IS_R(f) ((f)&GRE_FLAG_R)
399+#define GRE_IS_K(f) ((f)&GRE_FLAG_K)
400+#define GRE_IS_S(f) ((f)&GRE_FLAG_S)
401+#define GRE_IS_A(f) ((f)&GRE_FLAG_A)
402+
403+/* GRE is a mess: Four different standards */
404+struct gre_hdr {
405+#if defined(__LITTLE_ENDIAN_BITFIELD)
406+ __u16 rec:3,
407+ srr:1,
408+ seq:1,
409+ key:1,
410+ routing:1,
411+ csum:1,
412+ version:3,
413+ reserved:4,
414+ ack:1;
415+#elif defined(__BIG_ENDIAN_BITFIELD)
416+ __u16 csum:1,
417+ routing:1,
418+ key:1,
419+ seq:1,
420+ srr:1,
421+ rec:3,
422+ ack:1,
423+ reserved:4,
424+ version:3;
425+#else
426+#error "Adjust your <asm/byteorder.h> defines"
427+#endif
428+ __u16 protocol;
429+};
430+
431+/* modified GRE header for PPTP */
432+struct gre_hdr_pptp {
433+ __u8 flags; /* bitfield */
434+ __u8 version; /* should be GRE_VERSION_PPTP */
435+ __u16 protocol; /* should be GRE_PROTOCOL_PPTP */
436+ __u16 payload_len; /* size of ppp payload, not inc. gre header */
437+ __u16 call_id; /* peer's call_id for this session */
438+ __u32 seq; /* sequence number. Present if S==1 */
439+ __u32 ack; /* seq number of highest packet recieved by */
440+ /* sender in this session */
441+};
442+
443+
444+/* this is part of ip_conntrack */
445+struct ip_ct_gre {
446+ unsigned int stream_timeout;
447+ unsigned int timeout;
448+};
449+
450+/* this is part of ip_conntrack_expect */
451+struct ip_ct_gre_expect {
452+ struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
453+};
454+
455+#ifdef __KERNEL__
456+struct ip_conntrack_expect;
457+
458+/* structure for original <-> reply keymap */
459+struct ip_ct_gre_keymap {
460+ struct list_head list;
461+
462+ struct ip_conntrack_tuple tuple;
463+};
464+
465+
466+/* add new tuple->key_reply pair to keymap */
467+int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
468+ struct ip_conntrack_tuple *t,
469+ int reply);
470+
471+/* change an existing keymap entry */
472+void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
473+ struct ip_conntrack_tuple *t);
474+
475+/* delete keymap entries */
476+void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp);
477+
478+
479+/* get pointer to gre key, if present */
480+static inline u_int32_t *gre_key(struct gre_hdr *greh)
481+{
482+ if (!greh->key)
483+ return NULL;
484+ if (greh->csum || greh->routing)
485+ return (u_int32_t *) (greh+sizeof(*greh)+4);
486+ return (u_int32_t *) (greh+sizeof(*greh));
487+}
488+
489+/* get pointer ot gre csum, if present */
490+static inline u_int16_t *gre_csum(struct gre_hdr *greh)
491+{
492+ if (!greh->csum)
493+ return NULL;
494+ return (u_int16_t *) (greh+sizeof(*greh));
495+}
496+
497+#endif /* __KERNEL__ */
498+
499+#endif /* _CONNTRACK_PROTO_GRE_H */
6317ee85 500diff -Nur linux-2.6.0.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
501--- linux-2.6.0.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-12-18 03:59:16.000000000 +0100
95cfd539 502+++ linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-12-19 14:14:23.000000000 +0100
6317ee85 503@@ -14,7 +14,7 @@
504 union ip_conntrack_manip_proto
505 {
506 /* Add other protocols here. */
507- u_int16_t all;
508+ u_int32_t all;
509
510 struct {
511 u_int16_t port;
512@@ -25,6 +25,9 @@
513 struct {
514 u_int16_t id;
515 } icmp;
516+ struct {
517+ u_int32_t key;
518+ } gre;
519 };
520
521 /* The manipulable part of the tuple. */
522@@ -44,7 +47,7 @@
523 u_int32_t ip;
524 union {
525 /* Add other protocols here. */
526- u_int16_t all;
527+ u_int64_t all;
528
529 struct {
530 u_int16_t port;
531@@ -55,6 +58,11 @@
532 struct {
533 u_int8_t type, code;
534 } icmp;
535+ struct {
536+ u_int16_t protocol;
537+ u_int8_t version;
538+ u_int32_t key;
539+ } gre;
540 } u;
541
542 /* The protocol. */
543@@ -80,10 +88,16 @@
544 #ifdef __KERNEL__
545
546 #define DUMP_TUPLE(tp) \
547-DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \
548+DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", \
549 (tp), (tp)->dst.protonum, \
550- NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all), \
551- NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all))
552+ NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all), \
553+ NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all))
554+
555+#define DUMP_TUPLE_RAW(x) \
556+ DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\
557+ (x), (x)->dst.protonum, \
558+ NIPQUAD((x)->src.ip), ntohl((x)->src.u.all), \
559+ NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all))
560
561 #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
562
95cfd539 563diff -Nur linux-2.6.0.org/include/linux/netfilter_ipv4/ip_nat_pptp.h linux-2.6.0/include/linux/netfilter_ipv4/ip_nat_pptp.h
564--- linux-2.6.0.org/include/linux/netfilter_ipv4/ip_nat_pptp.h 1970-01-01 01:00:00.000000000 +0100
565+++ linux-2.6.0/include/linux/netfilter_ipv4/ip_nat_pptp.h 2003-11-17 09:09:34.000000000 +0100
566@@ -0,0 +1,11 @@
567+/* PPTP constants and structs */
568+#ifndef _NAT_PPTP_H
569+#define _NAT_PPTP_H
570+
571+/* conntrack private data */
572+struct ip_nat_pptp {
573+ u_int16_t pns_call_id; /* NAT'ed PNS call id */
574+ u_int16_t pac_call_id; /* NAT'ed PAC call id */
575+};
576+
577+#endif /* _NAT_PPTP_H */
6317ee85 578diff -Nur linux-2.6.0.org/net/ipv4/netfilter/Makefile linux-2.6.0/net/ipv4/netfilter/Makefile
579--- linux-2.6.0.org/net/ipv4/netfilter/Makefile 2003-12-18 03:58:28.000000000 +0100
95cfd539 580+++ linux-2.6.0/net/ipv4/netfilter/Makefile 2003-12-19 14:16:02.000000000 +0100
6317ee85 581@@ -19,13 +19,21 @@
582 # connection tracking
583 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
584
585+# connection tracking protocol helpers
586+obj-$(CONFIG_IP_NF_CT_PROTO_GRE) += ip_conntrack_proto_gre.o
587+
588+# NAT protocol helpers
589+obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o
590+
591 # connection tracking helpers
592+obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
593 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
594 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
595 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
596 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
597
598 # NAT helpers
599+obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
600 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
601 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
602 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
603diff -Nur linux-2.6.0.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.0/net/ipv4/netfilter/ip_conntrack_core.c
604--- linux-2.6.0.org/net/ipv4/netfilter/ip_conntrack_core.c 2003-12-18 03:57:57.000000000 +0100
95cfd539 605+++ linux-2.6.0/net/ipv4/netfilter/ip_conntrack_core.c 2003-12-19 14:14:23.000000000 +0100
6317ee85 606@@ -150,6 +150,8 @@
607 inverse->dst.ip = orig->src.ip;
608 inverse->dst.protonum = orig->dst.protonum;
609
610+ inverse->src.u.all = inverse->dst.u.all = 0;
611+
612 return protocol->invert_tuple(inverse, orig);
613 }
614
615@@ -925,8 +927,8 @@
616 * so there is no need to use the tuple lock too */
617
618 DEBUGP("ip_conntrack_expect_related %p\n", related_to);
619- DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
620- DEBUGP("mask: "); DUMP_TUPLE(&expect->mask);
621+ DEBUGP("tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
622+ DEBUGP("mask: "); DUMP_TUPLE_RAW(&expect->mask);
623
624 old = LIST_FIND(&ip_conntrack_expect_list, resent_expect,
625 struct ip_conntrack_expect *, &expect->tuple,
626@@ -1051,15 +1053,14 @@
627
628 MUST_BE_READ_LOCKED(&ip_conntrack_lock);
629 WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
630-
631 DEBUGP("change_expect:\n");
632- DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple);
633- DEBUGP("exp mask: "); DUMP_TUPLE(&expect->mask);
634- DEBUGP("newtuple: "); DUMP_TUPLE(newtuple);
635+ DEBUGP("exp tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
636+ DEBUGP("exp mask: "); DUMP_TUPLE_RAW(&expect->mask);
637+ DEBUGP("newtuple: "); DUMP_TUPLE_RAW(newtuple);
638 if (expect->ct_tuple.dst.protonum == 0) {
639 /* Never seen before */
640 DEBUGP("change expect: never seen before\n");
641- if (!ip_ct_tuple_equal(&expect->tuple, newtuple)
642+ if (!ip_ct_tuple_mask_cmp(&expect->tuple, newtuple, &expect->mask)
643 && LIST_FIND(&ip_conntrack_expect_list, expect_clash,
644 struct ip_conntrack_expect *, newtuple, &expect->mask)) {
645 /* Force NAT to find an unused tuple */
95cfd539 646diff -Nur linux-2.6.0.org/net/ipv4/netfilter/ip_conntrack_pptp.c linux-2.6.0/net/ipv4/netfilter/ip_conntrack_pptp.c
647--- linux-2.6.0.org/net/ipv4/netfilter/ip_conntrack_pptp.c 1970-01-01 01:00:00.000000000 +0100
648+++ linux-2.6.0/net/ipv4/netfilter/ip_conntrack_pptp.c 2003-11-17 09:09:34.000000000 +0100
649@@ -0,0 +1,637 @@
650+/*
651+ * ip_conntrack_pptp.c - Version 1.9
652+ *
653+ * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
654+ * PPTP is a a protocol for creating virtual private networks.
655+ * It is a specification defined by Microsoft and some vendors
656+ * working with Microsoft. PPTP is built on top of a modified
657+ * version of the Internet Generic Routing Encapsulation Protocol.
658+ * GRE is defined in RFC 1701 and RFC 1702. Documentation of
659+ * PPTP can be found in RFC 2637
660+ *
661+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
662+ *
663+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
664+ *
665+ * Limitations:
666+ * - We blindly assume that control connections are always
667+ * established in PNS->PAC direction. This is a violation
668+ * of RFFC2673
669+ *
670+ * TODO: - finish support for multiple calls within one session
671+ * (needs expect reservations in newnat)
672+ * - testing of incoming PPTP calls
673+ *
674+ * Changes:
675+ * 2002-02-05 - Version 1.3
676+ * - Call ip_conntrack_unexpect_related() from
677+ * pptp_timeout_related() to destroy expectations in case
678+ * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
679+ * (Philip Craig <philipc@snapgear.com>)
680+ * - Add Version information at module loadtime
681+ * 2002-02-10 - Version 1.6
682+ * - move to C99 style initializers
683+ * - remove second expectation if first arrives
684+ *
685+ */
686+
687+#include <linux/config.h>
688+#include <linux/module.h>
689+#include <linux/netfilter.h>
690+#include <linux/ip.h>
691+#include <net/checksum.h>
692+#include <net/tcp.h>
693+
694+#include <linux/netfilter_ipv4/lockhelp.h>
695+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
696+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
697+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
698+
699+#define IP_CT_PPTP_VERSION "1.9"
700+
701+MODULE_LICENSE("GPL");
702+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
703+MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
704+
705+DECLARE_LOCK(ip_pptp_lock);
706+
707+#if 0
708+#include "ip_conntrack_pptp_priv.h"
709+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
710+ ": " format, ## args)
711+#else
712+#define DEBUGP(format, args...)
713+#endif
714+
715+#define SECS *HZ
716+#define MINS * 60 SECS
717+#define HOURS * 60 MINS
718+#define DAYS * 24 HOURS
719+
720+#define PPTP_GRE_TIMEOUT (10 MINS)
721+#define PPTP_GRE_STREAM_TIMEOUT (5 DAYS)
722+
723+static int pptp_expectfn(struct ip_conntrack *ct)
724+{
725+ struct ip_conntrack *master;
726+ struct ip_conntrack_expect *exp;
727+
728+ DEBUGP("increasing timeouts\n");
729+ /* increase timeout of GRE data channel conntrack entry */
730+ ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
731+ ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
732+
733+ master = master_ct(ct);
734+ if (!master) {
735+ DEBUGP(" no master!!!\n");
736+ return 0;
737+ }
738+
739+ exp = ct->master;
740+ if (!exp) {
741+ DEBUGP("no expectation!!\n");
742+ return 0;
743+ }
744+
745+ DEBUGP("completing tuples with ct info\n");
746+ /* we can do this, since we're unconfirmed */
747+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
748+ htonl(master->help.ct_pptp_info.pac_call_id)) {
749+ /* assume PNS->PAC */
750+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
751+ htonl(master->help.ct_pptp_info.pns_call_id);
752+ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
753+ htonl(master->help.ct_pptp_info.pns_call_id);
754+ } else {
755+ /* assume PAC->PNS */
756+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
757+ htonl(master->help.ct_pptp_info.pac_call_id);
758+ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
759+ htonl(master->help.ct_pptp_info.pac_call_id);
760+ }
761+
762+ /* delete other expectation */
763+ if (exp->expected_list.next != &exp->expected_list) {
764+ struct ip_conntrack_expect *other_exp;
765+ struct list_head *cur_item, *next;
766+
767+ for (cur_item = master->sibling_list.next;
768+ cur_item != &master->sibling_list; cur_item = next) {
769+ next = cur_item->next;
770+ other_exp = list_entry(cur_item,
771+ struct ip_conntrack_expect,
772+ expected_list);
773+ /* remove only if occurred at same sequence number */
774+ if (other_exp != exp && other_exp->seq == exp->seq) {
775+ DEBUGP("unexpecting other direction\n");
776+ ip_ct_gre_keymap_destroy(other_exp);
777+ ip_conntrack_unexpect_related(other_exp);
778+ }
779+ }
780+ }
781+
782+ return 0;
783+}
784+
785+/* timeout GRE data connections */
786+static int pptp_timeout_related(struct ip_conntrack *ct)
787+{
788+ struct list_head *cur_item, *next;
789+ struct ip_conntrack_expect *exp;
790+
791+ /* FIXME: do we have to lock something ? */
792+ for (cur_item = ct->sibling_list.next;
793+ cur_item != &ct->sibling_list; cur_item = next) {
794+ next = cur_item->next;
795+ exp = list_entry(cur_item, struct ip_conntrack_expect,
796+ expected_list);
797+
798+ ip_ct_gre_keymap_destroy(exp);
799+ if (!exp->sibling) {
800+ ip_conntrack_unexpect_related(exp);
801+ continue;
802+ }
803+
804+ DEBUGP("setting timeout of conntrack %p to 0\n",
805+ exp->sibling);
806+ exp->sibling->proto.gre.timeout = 0;
807+ exp->sibling->proto.gre.stream_timeout = 0;
808+ ip_ct_refresh(exp->sibling, 0);
809+ }
810+
811+ return 0;
812+}
813+
814+/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
815+static inline int
816+exp_gre(struct ip_conntrack *master,
817+ u_int32_t seq,
818+ u_int16_t callid,
819+ u_int16_t peer_callid)
820+{
821+ struct ip_conntrack_expect exp;
822+ struct ip_conntrack_tuple inv_tuple;
823+
824+ memset(&exp, 0, sizeof(exp));
825+ /* tuple in original direction, PNS->PAC */
826+ exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
827+ exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
828+ exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
829+ exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
830+ exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP);
831+ exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP;
832+ exp.tuple.dst.protonum = IPPROTO_GRE;
833+
834+ exp.mask.src.ip = 0xffffffff;
835+ exp.mask.src.u.all = 0;
836+ exp.mask.dst.u.all = 0;
837+ exp.mask.dst.u.gre.key = 0xffffffff;
838+ exp.mask.dst.u.gre.version = 0xff;
839+ exp.mask.dst.u.gre.protocol = 0xffff;
840+ exp.mask.dst.ip = 0xffffffff;
841+ exp.mask.dst.protonum = 0xffff;
842+
843+ exp.seq = seq;
844+ exp.expectfn = pptp_expectfn;
845+
846+ exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
847+ exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
848+
849+ DEBUGP("calling expect_related ");
850+ DUMP_TUPLE_RAW(&exp.tuple);
851+
852+ /* Add GRE keymap entries */
853+ if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
854+ return 1;
855+
856+ invert_tuplepr(&inv_tuple, &exp.tuple);
857+ if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) {
858+ ip_ct_gre_keymap_destroy(&exp);
859+ return 1;
860+ }
861+
862+ if (ip_conntrack_expect_related(master, &exp) != 0) {
863+ ip_ct_gre_keymap_destroy(&exp);
864+ DEBUGP("cannot expect_related()\n");
865+ return 1;
866+ }
867+
868+ /* tuple in reply direction, PAC->PNS */
869+ exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
870+ exp.tuple.src.u.gre.key = htonl(ntohs(callid));
871+ exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
872+ exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));
873+
874+ DEBUGP("calling expect_related ");
875+ DUMP_TUPLE_RAW(&exp.tuple);
876+
877+ /* Add GRE keymap entries */
878+ ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
879+ invert_tuplepr(&inv_tuple, &exp.tuple);
880+ ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
881+ /* FIXME: cannot handle error correctly, since we need to free
882+ * the above keymap :( */
883+
884+ if (ip_conntrack_expect_related(master, &exp) != 0) {
885+ /* free the second pair of keypmaps */
886+ ip_ct_gre_keymap_destroy(&exp);
887+ DEBUGP("cannot expect_related():\n");
888+ return 1;
889+ }
890+
891+ return 0;
892+}
893+
894+static inline int
895+pptp_inbound_pkt(struct tcphdr *tcph,
896+ struct pptp_pkt_hdr *pptph,
897+ size_t datalen,
898+ struct ip_conntrack *ct,
899+ enum ip_conntrack_info ctinfo)
900+{
901+ struct PptpControlHeader *ctlh;
902+ union pptp_ctrl_union pptpReq;
903+
904+ struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
905+ u_int16_t msg, *cid, *pcid;
906+ u_int32_t seq;
907+
908+ ctlh = (struct PptpControlHeader *)
909+ ((char *) pptph + sizeof(struct pptp_pkt_hdr));
910+ pptpReq.rawreq = (void *)
911+ ((char *) ctlh + sizeof(struct PptpControlHeader));
912+
913+ msg = ntohs(ctlh->messageType);
914+ DEBUGP("inbound control message %s\n", strMName[msg]);
915+
916+ switch (msg) {
917+ case PPTP_START_SESSION_REPLY:
918+ /* server confirms new control session */
919+ if (info->sstate < PPTP_SESSION_REQUESTED) {
920+ DEBUGP("%s without START_SESS_REQUEST\n",
921+ strMName[msg]);
922+ break;
923+ }
924+ if (pptpReq.srep->resultCode == PPTP_START_OK)
925+ info->sstate = PPTP_SESSION_CONFIRMED;
926+ else
927+ info->sstate = PPTP_SESSION_ERROR;
928+ break;
929+
930+ case PPTP_STOP_SESSION_REPLY:
931+ /* server confirms end of control session */
932+ if (info->sstate > PPTP_SESSION_STOPREQ) {
933+ DEBUGP("%s without STOP_SESS_REQUEST\n",
934+ strMName[msg]);
935+ break;
936+ }
937+ if (pptpReq.strep->resultCode == PPTP_STOP_OK)
938+ info->sstate = PPTP_SESSION_NONE;
939+ else
940+ info->sstate = PPTP_SESSION_ERROR;
941+ break;
942+
943+ case PPTP_OUT_CALL_REPLY:
944+ /* server accepted call, we now expect GRE frames */
945+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
946+ DEBUGP("%s but no session\n", strMName[msg]);
947+ break;
948+ }
949+ if (info->cstate != PPTP_CALL_OUT_REQ &&
950+ info->cstate != PPTP_CALL_OUT_CONF) {
951+ DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]);
952+ break;
953+ }
954+ if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) {
955+ info->cstate = PPTP_CALL_NONE;
956+ break;
957+ }
958+
959+ cid = &pptpReq.ocack->callID;
960+ pcid = &pptpReq.ocack->peersCallID;
961+
962+ info->pac_call_id = ntohs(*cid);
963+
964+ if (htons(info->pns_call_id) != *pcid) {
965+ DEBUGP("%s for unknown callid %u\n",
966+ strMName[msg], ntohs(*pcid));
967+ break;
968+ }
969+
970+ DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg],
971+ ntohs(*cid), ntohs(*pcid));
972+
973+ info->cstate = PPTP_CALL_OUT_CONF;
974+
975+ seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
976+ if (exp_gre(ct, seq, *cid, *pcid) != 0)
977+ printk("ip_conntrack_pptp: error during exp_gre\n");
978+ break;
979+
980+ case PPTP_IN_CALL_REQUEST:
981+ /* server tells us about incoming call request */
982+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
983+ DEBUGP("%s but no session\n", strMName[msg]);
984+ break;
985+ }
986+ pcid = &pptpReq.icack->peersCallID;
987+ DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
988+ info->cstate = PPTP_CALL_IN_REQ;
989+ info->pac_call_id= ntohs(*pcid);
990+ break;
991+
992+ case PPTP_IN_CALL_CONNECT:
993+ /* server tells us about incoming call established */
994+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
995+ DEBUGP("%s but no session\n", strMName[msg]);
996+ break;
997+ }
998+ if (info->sstate != PPTP_CALL_IN_REP
999+ && info->sstate != PPTP_CALL_IN_CONF) {
1000+ DEBUGP("%s but never sent IN_CALL_REPLY\n",
1001+ strMName[msg]);
1002+ break;
1003+ }
1004+
1005+ pcid = &pptpReq.iccon->peersCallID;
1006+ cid = &info->pac_call_id;
1007+
1008+ if (info->pns_call_id != ntohs(*pcid)) {
1009+ DEBUGP("%s for unknown CallID %u\n",
1010+ strMName[msg], ntohs(*cid));
1011+ break;
1012+ }
1013+
1014+ DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
1015+ info->cstate = PPTP_CALL_IN_CONF;
1016+
1017+ /* we expect a GRE connection from PAC to PNS */
1018+ seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
1019+ if (exp_gre(ct, seq, *cid, *pcid) != 0)
1020+ printk("ip_conntrack_pptp: error during exp_gre\n");
1021+
1022+ break;
1023+
1024+ case PPTP_CALL_DISCONNECT_NOTIFY:
1025+ /* server confirms disconnect */
1026+ cid = &pptpReq.disc->callID;
1027+ DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
1028+ info->cstate = PPTP_CALL_NONE;
1029+
1030+ /* untrack this call id, unexpect GRE packets */
1031+ pptp_timeout_related(ct);
1032+ break;
1033+
1034+ case PPTP_WAN_ERROR_NOTIFY:
1035+ break;
1036+
1037+ case PPTP_ECHO_REQUEST:
1038+ case PPTP_ECHO_REPLY:
1039+ /* I don't have to explain these ;) */
1040+ break;
1041+ default:
1042+ DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
1043+ ? strMName[msg]:strMName[0], msg);
1044+ break;
1045+ }
1046+
1047+ return NF_ACCEPT;
1048+
1049+}
1050+
1051+static inline int
1052+pptp_outbound_pkt(struct tcphdr *tcph,
1053+ struct pptp_pkt_hdr *pptph,
1054+ size_t datalen,
1055+ struct ip_conntrack *ct,
1056+ enum ip_conntrack_info ctinfo)
1057+{
1058+ struct PptpControlHeader *ctlh;
1059+ union pptp_ctrl_union pptpReq;
1060+ struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
1061+ u_int16_t msg, *cid, *pcid;
1062+
1063+ ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
1064+ pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
1065+
1066+ msg = ntohs(ctlh->messageType);
1067+ DEBUGP("outbound control message %s\n", strMName[msg]);
1068+
1069+ switch (msg) {
1070+ case PPTP_START_SESSION_REQUEST:
1071+ /* client requests for new control session */
1072+ if (info->sstate != PPTP_SESSION_NONE) {
1073+ DEBUGP("%s but we already have one",
1074+ strMName[msg]);
1075+ }
1076+ info->sstate = PPTP_SESSION_REQUESTED;
1077+ break;
1078+ case PPTP_STOP_SESSION_REQUEST:
1079+ /* client requests end of control session */
1080+ info->sstate = PPTP_SESSION_STOPREQ;
1081+ break;
1082+
1083+ case PPTP_OUT_CALL_REQUEST:
1084+ /* client initiating connection to server */
1085+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
1086+ DEBUGP("%s but no session\n",
1087+ strMName[msg]);
1088+ break;
1089+ }
1090+ info->cstate = PPTP_CALL_OUT_REQ;
1091+ /* track PNS call id */
1092+ cid = &pptpReq.ocreq->callID;
1093+ DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
1094+ info->pns_call_id = ntohs(*cid);
1095+ break;
1096+ case PPTP_IN_CALL_REPLY:
1097+ /* client answers incoming call */
1098+ if (info->cstate != PPTP_CALL_IN_REQ
1099+ && info->cstate != PPTP_CALL_IN_REP) {
1100+ DEBUGP("%s without incall_req\n",
1101+ strMName[msg]);
1102+ break;
1103+ }
1104+ if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) {
1105+ info->cstate = PPTP_CALL_NONE;
1106+ break;
1107+ }
1108+ pcid = &pptpReq.icack->peersCallID;
1109+ if (info->pac_call_id != ntohs(*pcid)) {
1110+ DEBUGP("%s for unknown call %u\n",
1111+ strMName[msg], ntohs(*pcid));
1112+ break;
1113+ }
1114+ DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid));
1115+ /* part two of the three-way handshake */
1116+ info->cstate = PPTP_CALL_IN_REP;
1117+ info->pns_call_id = ntohs(pptpReq.icack->callID);
1118+ break;
1119+
1120+ case PPTP_CALL_CLEAR_REQUEST:
1121+ /* client requests hangup of call */
1122+ if (info->sstate != PPTP_SESSION_CONFIRMED) {
1123+ DEBUGP("CLEAR_CALL but no session\n");
1124+ break;
1125+ }
1126+ /* FUTURE: iterate over all calls and check if
1127+ * call ID is valid. We don't do this without newnat,
1128+ * because we only know about last call */
1129+ info->cstate = PPTP_CALL_CLEAR_REQ;
1130+ break;
1131+ case PPTP_SET_LINK_INFO:
1132+ break;
1133+ case PPTP_ECHO_REQUEST:
1134+ case PPTP_ECHO_REPLY:
1135+ /* I don't have to explain these ;) */
1136+ break;
1137+ default:
1138+ DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)?
1139+ strMName[msg]:strMName[0], msg);
1140+ /* unknown: no need to create GRE masq table entry */
1141+ break;
1142+ }
1143+
1144+ return NF_ACCEPT;
1145+}
1146+
1147+
1148+/* track caller id inside control connection, call expect_related */
1149+static int
1150+conntrack_pptp_help(const struct iphdr *iph, size_t len,
1151+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
1152+
1153+{
1154+ struct pptp_pkt_hdr *pptph;
1155+
1156+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
1157+ u_int32_t tcplen = len - iph->ihl * 4;
1158+ u_int32_t datalen = tcplen - tcph->doff * 4;
1159+ void *datalimit;
1160+ int dir = CTINFO2DIR(ctinfo);
1161+ struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
1162+
1163+ int oldsstate, oldcstate;
1164+ int ret;
1165+
1166+ /* don't do any tracking before tcp handshake complete */
1167+ if (ctinfo != IP_CT_ESTABLISHED
1168+ && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
1169+ DEBUGP("ctinfo = %u, skipping\n", ctinfo);
1170+ return NF_ACCEPT;
1171+ }
1172+
1173+ /* not a complete TCP header? */
1174+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
1175+ DEBUGP("tcplen = %u\n", tcplen);
1176+ return NF_ACCEPT;
1177+ }
1178+
1179+ /* checksum invalid? */
1180+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
1181+ csum_partial((char *) tcph, tcplen, 0))) {
1182+ printk(KERN_NOTICE __FILE__ ": bad csum\n");
1183+ /* W2K PPTP server sends TCP packets with wrong checksum :(( */
1184+ //return NF_ACCEPT;
1185+ }
1186+
1187+ if (tcph->fin || tcph->rst) {
1188+ DEBUGP("RST/FIN received, timeouting GRE\n");
1189+ /* can't do this after real newnat */
1190+ info->cstate = PPTP_CALL_NONE;
1191+
1192+ /* untrack this call id, unexpect GRE packets */
1193+ pptp_timeout_related(ct);
1194+ }
1195+
1196+
1197+ pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4);
1198+ datalimit = (void *) pptph + datalen;
1199+
1200+ /* not a full pptp packet header? */
1201+ if ((void *) pptph+sizeof(*pptph) >= datalimit) {
1202+ DEBUGP("no full PPTP header, can't track\n");
1203+ return NF_ACCEPT;
1204+ }
1205+
1206+ /* if it's not a control message we can't do anything with it */
1207+ if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
1208+ ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
1209+ DEBUGP("not a control packet\n");
1210+ return NF_ACCEPT;
1211+ }
1212+
1213+ oldsstate = info->sstate;
1214+ oldcstate = info->cstate;
1215+
1216+ LOCK_BH(&ip_pptp_lock);
1217+
1218+ /* FIXME: We just blindly assume that the control connection is always
1219+ * established from PNS->PAC. However, RFC makes no guarantee */
1220+ if (dir == IP_CT_DIR_ORIGINAL)
1221+ /* client -> server (PNS -> PAC) */
1222+ ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo);
1223+ else
1224+ /* server -> client (PAC -> PNS) */
1225+ ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo);
1226+ DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
1227+ oldsstate, info->sstate, oldcstate, info->cstate);
1228+ UNLOCK_BH(&ip_pptp_lock);
1229+
1230+ return ret;
1231+}
1232+
1233+/* control protocol helper */
1234+static struct ip_conntrack_helper pptp = {
1235+ .list = { NULL, NULL },
1236+ .name = "pptp",
1237+ .flags = IP_CT_HELPER_F_REUSE_EXPECT,
1238+ .me = THIS_MODULE,
1239+ .max_expected = 2,
1240+ .timeout = 0,
1241+ .tuple = { .src = { .ip = 0,
1242+ .u = { .tcp = { .port =
1243+ __constant_htons(PPTP_CONTROL_PORT) } }
1244+ },
1245+ .dst = { .ip = 0,
1246+ .u = { .all = 0 },
1247+ .protonum = IPPROTO_TCP
1248+ }
1249+ },
1250+ .mask = { .src = { .ip = 0,
1251+ .u = { .tcp = { .port = 0xffff } }
1252+ },
1253+ .dst = { .ip = 0,
1254+ .u = { .all = 0 },
1255+ .protonum = 0xffff
1256+ }
1257+ },
1258+ .help = conntrack_pptp_help
1259+};
1260+
1261+/* ip_conntrack_pptp initialization */
1262+static int __init init(void)
1263+{
1264+ int retcode;
1265+
1266+ DEBUGP(__FILE__ ": registering helper\n");
1267+ if ((retcode = ip_conntrack_helper_register(&pptp))) {
1268+ printk(KERN_ERR "Unable to register conntrack application "
1269+ "helper for pptp: %d\n", retcode);
1270+ return -EIO;
1271+ }
1272+
1273+ printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
1274+ return 0;
1275+}
1276+
1277+static void __exit fini(void)
1278+{
1279+ ip_conntrack_helper_unregister(&pptp);
1280+ printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
1281+}
1282+
1283+module_init(init);
1284+module_exit(fini);
1285+
1286+EXPORT_SYMBOL(ip_pptp_lock);
1287diff -Nur linux-2.6.0.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h linux-2.6.0/net/ipv4/netfilter/ip_conntrack_pptp_priv.h
1288--- linux-2.6.0.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h 1970-01-01 01:00:00.000000000 +0100
1289+++ linux-2.6.0/net/ipv4/netfilter/ip_conntrack_pptp_priv.h 2003-11-17 09:09:34.000000000 +0100
1290@@ -0,0 +1,24 @@
1291+#ifndef _IP_CT_PPTP_PRIV_H
1292+#define _IP_CT_PPTP_PRIV_H
1293+
1294+/* PptpControlMessageType names */
1295+static const char *strMName[] = {
1296+ "UNKNOWN_MESSAGE",
1297+ "START_SESSION_REQUEST",
1298+ "START_SESSION_REPLY",
1299+ "STOP_SESSION_REQUEST",
1300+ "STOP_SESSION_REPLY",
1301+ "ECHO_REQUEST",
1302+ "ECHO_REPLY",
1303+ "OUT_CALL_REQUEST",
1304+ "OUT_CALL_REPLY",
1305+ "IN_CALL_REQUEST",
1306+ "IN_CALL_REPLY",
1307+ "IN_CALL_CONNECT",
1308+ "CALL_CLEAR_REQUEST",
1309+ "CALL_DISCONNECT_NOTIFY",
1310+ "WAN_ERROR_NOTIFY",
1311+ "SET_LINK_INFO"
1312+};
1313+
1314+#endif
1315diff -Nur linux-2.6.0.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c linux-2.6.0/net/ipv4/netfilter/ip_conntrack_proto_gre.c
1316--- linux-2.6.0.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c 1970-01-01 01:00:00.000000000 +0100
1317+++ linux-2.6.0/net/ipv4/netfilter/ip_conntrack_proto_gre.c 2003-11-17 09:09:34.000000000 +0100
1318@@ -0,0 +1,343 @@
1319+/*
1320+ * ip_conntrack_proto_gre.c - Version 1.2
1321+ *
1322+ * Connection tracking protocol helper module for GRE.
1323+ *
1324+ * GRE is a generic encapsulation protocol, which is generally not very
1325+ * suited for NAT, as it has no protocol-specific part as port numbers.
1326+ *
1327+ * It has an optional key field, which may help us distinguishing two
1328+ * connections between the same two hosts.
1329+ *
1330+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
1331+ *
1332+ * PPTP is built on top of a modified version of GRE, and has a mandatory
1333+ * field called "CallID", which serves us for the same purpose as the key
1334+ * field in plain GRE.
1335+ *
1336+ * Documentation about PPTP can be found in RFC 2637
1337+ *
1338+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
1339+ *
1340+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
1341+ *
1342+ */
1343+
1344+#include <linux/config.h>
1345+#include <linux/module.h>
1346+#include <linux/types.h>
1347+#include <linux/timer.h>
1348+#include <linux/netfilter.h>
1349+#include <linux/ip.h>
1350+#include <linux/in.h>
1351+#include <linux/list.h>
1352+
1353+#include <linux/netfilter_ipv4/lockhelp.h>
1354+
1355+DECLARE_RWLOCK(ip_ct_gre_lock);
1356+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_ct_gre_lock)
1357+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_ct_gre_lock)
1358+
1359+#include <linux/netfilter_ipv4/listhelp.h>
1360+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
1361+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1362+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
1363+
1364+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
1365+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
1366+
1367+MODULE_LICENSE("GPL");
1368+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
1369+MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
1370+
1371+/* shamelessly stolen from ip_conntrack_proto_udp.c */
1372+#define GRE_TIMEOUT (30*HZ)
1373+#define GRE_STREAM_TIMEOUT (180*HZ)
1374+
1375+#if 0
1376+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
1377+ ": " format, ## args)
1378+#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x:%u:0x%x\n", \
1379+ NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \
1380+ NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key), \
1381+ (x)->dst.u.gre.version, \
1382+ ntohs((x)->dst.u.gre.protocol))
1383+#else
1384+#define DEBUGP(x, args...)
1385+#define DUMP_TUPLE_GRE(x)
1386+#endif
1387+
1388+/* GRE KEYMAP HANDLING FUNCTIONS */
1389+static LIST_HEAD(gre_keymap_list);
1390+
1391+static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
1392+ const struct ip_conntrack_tuple *t)
1393+{
1394+ return ((km->tuple.src.ip == t->src.ip) &&
1395+ (km->tuple.dst.ip == t->dst.ip) &&
1396+ (km->tuple.dst.protonum == t->dst.protonum) &&
1397+ (km->tuple.dst.u.all == t->dst.u.all));
1398+}
1399+
1400+/* look up the source key for a given tuple */
1401+static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
1402+{
1403+ struct ip_ct_gre_keymap *km;
1404+ u_int32_t key;
1405+
1406+ READ_LOCK(&ip_ct_gre_lock);
1407+ km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
1408+ struct ip_ct_gre_keymap *, t);
1409+ if (!km) {
1410+ READ_UNLOCK(&ip_ct_gre_lock);
1411+ return 0;
1412+ }
1413+
1414+ key = km->tuple.src.u.gre.key;
1415+ READ_UNLOCK(&ip_ct_gre_lock);
1416+
1417+ return key;
1418+}
1419+
1420+/* add a single keymap entry, associate with specified expect */
1421+int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
1422+ struct ip_conntrack_tuple *t, int reply)
1423+{
1424+ struct ip_ct_gre_keymap *km;
1425+
1426+ km = kmalloc(sizeof(*km), GFP_ATOMIC);
1427+ if (!km)
1428+ return -1;
1429+
1430+ /* initializing list head should be sufficient */
1431+ memset(km, 0, sizeof(*km));
1432+
1433+ memcpy(&km->tuple, t, sizeof(*t));
1434+
1435+ if (!reply)
1436+ exp->proto.gre.keymap_orig = km;
1437+ else
1438+ exp->proto.gre.keymap_reply = km;
1439+
1440+ DEBUGP("adding new entry %p: ", km);
1441+ DUMP_TUPLE_GRE(&km->tuple);
1442+
1443+ WRITE_LOCK(&ip_ct_gre_lock);
1444+ list_append(&gre_keymap_list, km);
1445+ WRITE_UNLOCK(&ip_ct_gre_lock);
1446+
1447+ return 0;
1448+}
1449+
1450+/* change the tuple of a keymap entry (used by nat helper) */
1451+void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
1452+ struct ip_conntrack_tuple *t)
1453+{
1454+ DEBUGP("changing entry %p to: ", km);
1455+ DUMP_TUPLE_GRE(t);
1456+
1457+ WRITE_LOCK(&ip_ct_gre_lock);
1458+ memcpy(&km->tuple, t, sizeof(km->tuple));
1459+ WRITE_UNLOCK(&ip_ct_gre_lock);
1460+}
1461+
1462+/* destroy the keymap entries associated with specified expect */
1463+void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp)
1464+{
1465+ DEBUGP("entering for exp %p\n", exp);
1466+ WRITE_LOCK(&ip_ct_gre_lock);
1467+ if (exp->proto.gre.keymap_orig) {
1468+ DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig);
1469+ list_del(&exp->proto.gre.keymap_orig->list);
1470+ kfree(exp->proto.gre.keymap_orig);
1471+ exp->proto.gre.keymap_orig = NULL;
1472+ }
1473+ if (exp->proto.gre.keymap_reply) {
1474+ DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply);
1475+ list_del(&exp->proto.gre.keymap_reply->list);
1476+ kfree(exp->proto.gre.keymap_reply);
1477+ exp->proto.gre.keymap_reply = NULL;
1478+ }
1479+ WRITE_UNLOCK(&ip_ct_gre_lock);
1480+}
1481+
1482+
1483+/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
1484+
1485+/* invert gre part of tuple */
1486+static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
1487+ const struct ip_conntrack_tuple *orig)
1488+{
1489+ tuple->dst.u.gre.protocol = orig->dst.u.gre.protocol;
1490+ tuple->dst.u.gre.version = orig->dst.u.gre.version;
1491+
1492+ tuple->dst.u.gre.key = orig->src.u.gre.key;
1493+ tuple->src.u.gre.key = orig->dst.u.gre.key;
1494+
1495+ return 1;
1496+}
1497+
1498+/* gre hdr info to tuple */
1499+static int gre_pkt_to_tuple(const void *datah, size_t datalen,
1500+ struct ip_conntrack_tuple *tuple)
1501+{
1502+ struct gre_hdr *grehdr = (struct gre_hdr *) datah;
1503+ struct gre_hdr_pptp *pgrehdr = (struct gre_hdr_pptp *) datah;
1504+ u_int32_t srckey;
1505+
1506+ /* core guarantees 8 protocol bytes, no need for size check */
1507+
1508+ tuple->dst.u.gre.version = grehdr->version;
1509+ tuple->dst.u.gre.protocol = grehdr->protocol;
1510+
1511+ switch (grehdr->version) {
1512+ case GRE_VERSION_1701:
1513+ if (!grehdr->key) {
1514+ DEBUGP("Can't track GRE without key\n");
1515+ return 0;
1516+ }
1517+ tuple->dst.u.gre.key = *(gre_key(grehdr));
1518+ break;
1519+
1520+ case GRE_VERSION_PPTP:
1521+ if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
1522+ DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
1523+ return 0;
1524+ }
1525+ tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id));
1526+ break;
1527+
1528+ default:
1529+ printk(KERN_WARNING "unknown GRE version %hu\n",
1530+ tuple->dst.u.gre.version);
1531+ return 0;
1532+ }
1533+
1534+ srckey = gre_keymap_lookup(tuple);
1535+
1536+#if 0
1537+ DEBUGP("found src key %x for tuple ", ntohl(srckey));
1538+ DUMP_TUPLE_GRE(tuple);
1539+#endif
1540+ tuple->src.u.gre.key = srckey;
1541+
1542+ return 1;
1543+}
1544+
1545+/* print gre part of tuple */
1546+static unsigned int gre_print_tuple(char *buffer,
1547+ const struct ip_conntrack_tuple *tuple)
1548+{
1549+ return sprintf(buffer, "version=%d protocol=0x%04x srckey=0x%x dstkey=0x%x ",
1550+ tuple->dst.u.gre.version,
1551+ ntohs(tuple->dst.u.gre.protocol),
1552+ ntohl(tuple->src.u.gre.key),
1553+ ntohl(tuple->dst.u.gre.key));
1554+}
1555+
1556+/* print private data for conntrack */
1557+static unsigned int gre_print_conntrack(char *buffer,
1558+ const struct ip_conntrack *ct)
1559+{
1560+ return sprintf(buffer, "timeout=%u, stream_timeout=%u ",
1561+ (ct->proto.gre.timeout / HZ),
1562+ (ct->proto.gre.stream_timeout / HZ));
1563+}
1564+
1565+/* Returns verdict for packet, and may modify conntrack */
1566+static int gre_packet(struct ip_conntrack *ct,
1567+ struct iphdr *iph, size_t len,
1568+ enum ip_conntrack_info conntrackinfo)
1569+{
1570+ /* If we've seen traffic both ways, this is a GRE connection.
1571+ * Extend timeout. */
1572+ if (ct->status & IPS_SEEN_REPLY) {
1573+ ip_ct_refresh(ct, ct->proto.gre.stream_timeout);
1574+ /* Also, more likely to be important, and not a probe. */
1575+ set_bit(IPS_ASSURED_BIT, &ct->status);
1576+ } else
1577+ ip_ct_refresh(ct, ct->proto.gre.timeout);
1578+
1579+ return NF_ACCEPT;
1580+}
1581+
1582+/* Called when a new connection for this protocol found. */
1583+static int gre_new(struct ip_conntrack *ct,
1584+ struct iphdr *iph, size_t len)
1585+{
1586+ DEBUGP(": ");
1587+ DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
1588+
1589+ /* initialize to sane value. Ideally a conntrack helper
1590+ * (e.g. in case of pptp) is increasing them */
1591+ ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
1592+ ct->proto.gre.timeout = GRE_TIMEOUT;
1593+
1594+ return 1;
1595+}
1596+
1597+/* Called when a conntrack entry has already been removed from the hashes
1598+ * and is about to be deleted from memory */
1599+static void gre_destroy(struct ip_conntrack *ct)
1600+{
1601+ struct ip_conntrack_expect *master = ct->master;
1602+
1603+ DEBUGP(" entering\n");
1604+
1605+ if (!master) {
1606+ DEBUGP("no master exp for ct %p\n", ct);
1607+ return;
1608+ }
1609+
1610+ ip_ct_gre_keymap_destroy(master);
1611+}
1612+
1613+/* protocol helper struct */
1614+static struct ip_conntrack_protocol gre = { { NULL, NULL }, IPPROTO_GRE,
1615+ "gre",
1616+ gre_pkt_to_tuple,
1617+ gre_invert_tuple,
1618+ gre_print_tuple,
1619+ gre_print_conntrack,
1620+ gre_packet,
1621+ gre_new,
1622+ gre_destroy,
1623+ NULL,
1624+ THIS_MODULE };
1625+
1626+/* ip_conntrack_proto_gre initialization */
1627+static int __init init(void)
1628+{
1629+ int retcode;
1630+
1631+ if ((retcode = ip_conntrack_protocol_register(&gre))) {
1632+ printk(KERN_ERR "Unable to register conntrack protocol "
1633+ "helper for gre: %d\n", retcode);
1634+ return -EIO;
1635+ }
1636+
1637+ return 0;
1638+}
1639+
1640+static void __exit fini(void)
1641+{
1642+ struct list_head *pos, *n;
1643+
1644+ /* delete all keymap entries */
1645+ WRITE_LOCK(&ip_ct_gre_lock);
1646+ list_for_each_safe(pos, n, &gre_keymap_list) {
1647+ DEBUGP("deleting keymap %p at module unload time\n", pos);
1648+ list_del(pos);
1649+ kfree(pos);
1650+ }
1651+ WRITE_UNLOCK(&ip_ct_gre_lock);
1652+
1653+ ip_conntrack_protocol_unregister(&gre);
1654+}
1655+
1656+EXPORT_SYMBOL(ip_ct_gre_keymap_add);
1657+EXPORT_SYMBOL(ip_ct_gre_keymap_change);
1658+EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
1659+
1660+module_init(init);
1661+module_exit(fini);
6317ee85 1662diff -Nur linux-2.6.0.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.0/net/ipv4/netfilter/ip_nat_core.c
1663--- linux-2.6.0.org/net/ipv4/netfilter/ip_nat_core.c 2003-12-18 03:58:16.000000000 +0100
95cfd539 1664+++ linux-2.6.0/net/ipv4/netfilter/ip_nat_core.c 2003-12-19 14:14:23.000000000 +0100
6317ee85 1665@@ -432,7 +432,7 @@
1666 *tuple = *orig_tuple;
1667 while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
1668 != NULL) {
1669- DEBUGP("Found best for "); DUMP_TUPLE(tuple);
1670+ DEBUGP("Found best for "); DUMP_TUPLE_RAW(tuple);
1671 /* 3) The per-protocol part of the manip is made to
1672 map into the range to make a unique tuple. */
1673
1674@@ -573,9 +573,9 @@
1675 HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",
1676 conntrack);
1677 DEBUGP("Original: ");
1678- DUMP_TUPLE(&orig_tp);
1679+ DUMP_TUPLE_RAW(&orig_tp);
1680 DEBUGP("New: ");
1681- DUMP_TUPLE(&new_tuple);
1682+ DUMP_TUPLE_RAW(&new_tuple);
1683 #endif
1684
1685 /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
95cfd539 1686diff -Nur linux-2.6.0.org/net/ipv4/netfilter/ip_nat_pptp.c linux-2.6.0/net/ipv4/netfilter/ip_nat_pptp.c
1687--- linux-2.6.0.org/net/ipv4/netfilter/ip_nat_pptp.c 1970-01-01 01:00:00.000000000 +0100
1688+++ linux-2.6.0/net/ipv4/netfilter/ip_nat_pptp.c 2003-11-17 09:09:34.000000000 +0100
1689@@ -0,0 +1,475 @@
1690+/*
1691+ * ip_nat_pptp.c - Version 1.5
1692+ *
1693+ * NAT support for PPTP (Point to Point Tunneling Protocol).
1694+ * PPTP is a a protocol for creating virtual private networks.
1695+ * It is a specification defined by Microsoft and some vendors
1696+ * working with Microsoft. PPTP is built on top of a modified
1697+ * version of the Internet Generic Routing Encapsulation Protocol.
1698+ * GRE is defined in RFC 1701 and RFC 1702. Documentation of
1699+ * PPTP can be found in RFC 2637
1700+ *
1701+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
1702+ *
1703+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
1704+ *
1705+ * TODO: - Support for multiple calls within one session
1706+ * (needs netfilter newnat code)
1707+ * - NAT to a unique tuple, not to TCP source port
1708+ * (needs netfilter tuple reservation)
1709+ *
1710+ * Changes:
1711+ * 2002-02-10 - Version 1.3
1712+ * - Use ip_nat_mangle_tcp_packet() because of cloned skb's
1713+ * in local connections (Philip Craig <philipc@snapgear.com>)
1714+ * - add checks for magicCookie and pptp version
1715+ * - make argument list of pptp_{out,in}bound_packet() shorter
1716+ * - move to C99 style initializers
1717+ * - print version number at module loadtime
1718+ * 2003-09-22 - Version 1.5
1719+ * - use SNATed tcp sourceport as callid, since we get called before
1720+ * TCP header is mangled (Philip Craig <philipc@snapgear.com>)
1721+ *
1722+ */
1723+
1724+#include <linux/config.h>
1725+#include <linux/module.h>
1726+#include <linux/ip.h>
1727+#include <linux/tcp.h>
1728+#include <net/tcp.h>
1729+#include <linux/netfilter_ipv4/ip_nat.h>
1730+#include <linux/netfilter_ipv4/ip_nat_rule.h>
1731+#include <linux/netfilter_ipv4/ip_nat_helper.h>
1732+#include <linux/netfilter_ipv4/ip_nat_pptp.h>
1733+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1734+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
1735+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
1736+
1737+#define IP_NAT_PPTP_VERSION "1.5"
1738+
1739+MODULE_LICENSE("GPL");
1740+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
1741+MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
1742+
1743+
1744+#if 0
1745+#include "ip_conntrack_pptp_priv.h"
1746+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
1747+ ": " format, ## args)
1748+#else
1749+#define DEBUGP(format, args...)
1750+#endif
1751+
1752+static unsigned int
1753+pptp_nat_expected(struct sk_buff **pskb,
1754+ unsigned int hooknum,
1755+ struct ip_conntrack *ct,
1756+ struct ip_nat_info *info)
1757+{
1758+ struct ip_conntrack *master = master_ct(ct);
1759+ struct ip_nat_multi_range mr;
1760+ struct ip_ct_pptp_master *ct_pptp_info;
1761+ struct ip_nat_pptp *nat_pptp_info;
1762+ u_int32_t newip, newcid;
1763+ int ret;
1764+
1765+ IP_NF_ASSERT(info);
1766+ IP_NF_ASSERT(master);
1767+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
1768+
1769+ DEBUGP("we have a connection!\n");
1770+
1771+ LOCK_BH(&ip_pptp_lock);
1772+ ct_pptp_info = &master->help.ct_pptp_info;
1773+ nat_pptp_info = &master->nat.help.nat_pptp_info;
1774+
1775+ /* need to alter GRE tuple because conntrack expectfn() used 'wrong'
1776+ * (unmanipulated) values */
1777+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
1778+ DEBUGP("completing tuples with NAT info \n");
1779+ /* we can do this, since we're unconfirmed */
1780+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
1781+ htonl(ct_pptp_info->pac_call_id)) {
1782+ /* assume PNS->PAC */
1783+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
1784+ htonl(nat_pptp_info->pns_call_id);
1785+ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
1786+ htonl(nat_pptp_info->pns_call_id);
1787+ newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
1788+ newcid = htonl(nat_pptp_info->pac_call_id);
1789+ } else {
1790+ /* assume PAC->PNS */
1791+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
1792+ htonl(nat_pptp_info->pac_call_id);
1793+ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
1794+ htonl(nat_pptp_info->pac_call_id);
1795+ newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
1796+ newcid = htonl(nat_pptp_info->pns_call_id);
1797+ }
1798+ } else {
1799+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
1800+ htonl(ct_pptp_info->pac_call_id)) {
1801+ /* assume PNS->PAC */
1802+ newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
1803+ newcid = htonl(ct_pptp_info->pns_call_id);
1804+ }
1805+ else {
1806+ /* assume PAC->PNS */
1807+ newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
1808+ newcid = htonl(ct_pptp_info->pac_call_id);
1809+ }
1810+ }
1811+
1812+ mr.rangesize = 1;
1813+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
1814+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
1815+ mr.range[0].min = mr.range[0].max =
1816+ ((union ip_conntrack_manip_proto ) { newcid });
1817+ DEBUGP("change ip to %u.%u.%u.%u\n",
1818+ NIPQUAD(newip));
1819+ DEBUGP("change key to 0x%x\n", ntohl(newcid));
1820+ ret = ip_nat_setup_info(ct, &mr, hooknum);
1821+
1822+ UNLOCK_BH(&ip_pptp_lock);
1823+
1824+ return ret;
1825+
1826+}
1827+
1828+/* outbound packets == from PNS to PAC */
1829+static inline unsigned int
1830+pptp_outbound_pkt(struct sk_buff **pskb,
1831+ struct ip_conntrack *ct,
1832+ enum ip_conntrack_info ctinfo,
1833+ struct ip_conntrack_expect *exp)
1834+
1835+{
1836+ struct iphdr *iph = (*pskb)->nh.iph;
1837+ struct tcphdr *tcph = (void *) iph + iph->ihl*4;
1838+ struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
1839+ ((void *)tcph + tcph->doff*4);
1840+
1841+ struct PptpControlHeader *ctlh;
1842+ union pptp_ctrl_union pptpReq;
1843+ struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
1844+ struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
1845+
1846+ u_int16_t msg, *cid = NULL, new_callid;
1847+
1848+ /* FIXME: size checks !!! */
1849+ ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
1850+ pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
1851+
1852+ new_callid = htons(ct_pptp_info->pns_call_id);
1853+
1854+ switch (msg = ntohs(ctlh->messageType)) {
1855+ case PPTP_OUT_CALL_REQUEST:
1856+ cid = &pptpReq.ocreq->callID;
1857+ /* FIXME: ideally we would want to reserve a call ID
1858+ * here. current netfilter NAT core is not able to do
1859+ * this :( For now we use TCP source port. This breaks
1860+ * multiple calls within one control session */
1861+
1862+ /* save original call ID in nat_info */
1863+ nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
1864+
1865+ /* don't use tcph->source since we are at a DSTmanip
1866+ * hook (e.g. PREROUTING) and pkt is not mangled yet */
1867+ new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
1868+
1869+ /* save new call ID in ct info */
1870+ ct_pptp_info->pns_call_id = ntohs(new_callid);
1871+ break;
1872+ case PPTP_IN_CALL_REPLY:
1873+ cid = &pptpReq.icreq->callID;
1874+ break;
1875+ case PPTP_CALL_CLEAR_REQUEST:
1876+ cid = &pptpReq.clrreq->callID;
1877+ break;
1878+ default:
1879+ DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
1880+ (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
1881+ /* fall through */
1882+
1883+ case PPTP_SET_LINK_INFO:
1884+ /* only need to NAT in case PAC is behind NAT box */
1885+ case PPTP_START_SESSION_REQUEST:
1886+ case PPTP_START_SESSION_REPLY:
1887+ case PPTP_STOP_SESSION_REQUEST:
1888+ case PPTP_STOP_SESSION_REPLY:
1889+ case PPTP_ECHO_REQUEST:
1890+ case PPTP_ECHO_REPLY:
1891+ /* no need to alter packet */
1892+ return NF_ACCEPT;
1893+ }
1894+
1895+ IP_NF_ASSERT(cid);
1896+
1897+ DEBUGP("altering call id from 0x%04x to 0x%04x\n",
1898+ ntohs(*cid), ntohs(new_callid));
1899+
1900+ /* mangle packet */
1901+ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph,
1902+ sizeof(new_callid), (char *)&new_callid,
1903+ sizeof(new_callid));
1904+
1905+ return NF_ACCEPT;
1906+}
1907+
1908+/* inbound packets == from PAC to PNS */
1909+static inline unsigned int
1910+pptp_inbound_pkt(struct sk_buff **pskb,
1911+ struct ip_conntrack *ct,
1912+ enum ip_conntrack_info ctinfo,
1913+ struct ip_conntrack_expect *oldexp)
1914+{
1915+ struct iphdr *iph = (*pskb)->nh.iph;
1916+ struct tcphdr *tcph = (void *) iph + iph->ihl*4;
1917+ struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
1918+ ((void *)tcph + tcph->doff*4);
1919+
1920+ struct PptpControlHeader *ctlh;
1921+ union pptp_ctrl_union pptpReq;
1922+ struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
1923+ struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
1924+
1925+ u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
1926+ u_int32_t old_dst_ip;
1927+
1928+ struct ip_conntrack_tuple t, inv_t;
1929+ struct ip_conntrack_tuple *orig_t, *reply_t;
1930+
1931+ /* FIXME: size checks !!! */
1932+ ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
1933+ pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
1934+
1935+ new_pcid = htons(nat_pptp_info->pns_call_id);
1936+
1937+ switch (msg = ntohs(ctlh->messageType)) {
1938+ case PPTP_OUT_CALL_REPLY:
1939+ pcid = &pptpReq.ocack->peersCallID;
1940+ cid = &pptpReq.ocack->callID;
1941+ if (!oldexp) {
1942+ DEBUGP("outcall but no expectation\n");
1943+ break;
1944+ }
1945+ old_dst_ip = oldexp->tuple.dst.ip;
1946+ t = oldexp->tuple;
1947+ invert_tuplepr(&inv_t, &t);
1948+
1949+ /* save original PAC call ID in nat_info */
1950+ nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
1951+
1952+ /* alter expectation */
1953+ orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
1954+ reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
1955+ if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) {
1956+ /* expectation for PNS->PAC direction */
1957+ t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
1958+ t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
1959+ inv_t.src.ip = reply_t->src.ip;
1960+ inv_t.dst.ip = reply_t->dst.ip;
1961+ inv_t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
1962+ inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
1963+ } else {
1964+ /* expectation for PAC->PNS direction */
1965+ t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
1966+ t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
1967+ inv_t.src.ip = orig_t->src.ip;
1968+ inv_t.dst.ip = orig_t->dst.ip;
1969+ inv_t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
1970+ inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
1971+ }
1972+
1973+ if (!ip_conntrack_change_expect(oldexp, &t)) {
1974+ DEBUGP("successfully changed expect\n");
1975+ } else {
1976+ DEBUGP("can't change expect\n");
1977+ }
1978+ ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig, &t);
1979+ ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, &inv_t);
1980+ break;
1981+ case PPTP_IN_CALL_CONNECT:
1982+ pcid = &pptpReq.iccon->peersCallID;
1983+ if (!oldexp)
1984+ break;
1985+ old_dst_ip = oldexp->tuple.dst.ip;
1986+ t = oldexp->tuple;
1987+
1988+ /* alter expectation, no need for callID */
1989+ if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) {
1990+ /* expectation for PNS->PAC direction */
1991+ t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
1992+ } else {
1993+ /* expectation for PAC->PNS direction */
1994+ t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
1995+ }
1996+
1997+ if (!ip_conntrack_change_expect(oldexp, &t)) {
1998+ DEBUGP("successfully changed expect\n");
1999+ } else {
2000+ DEBUGP("can't change expect\n");
2001+ }
2002+ break;
2003+ case PPTP_IN_CALL_REQUEST:
2004+ /* only need to nat in case PAC is behind NAT box */
2005+ break;
2006+ case PPTP_WAN_ERROR_NOTIFY:
2007+ pcid = &pptpReq.wanerr->peersCallID;
2008+ break;
2009+ case PPTP_CALL_DISCONNECT_NOTIFY:
2010+ pcid = &pptpReq.disc->callID;
2011+ break;
2012+
2013+ default:
2014+ DEBUGP("unknown inbound packet %s\n",
2015+ (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
2016+ /* fall through */
2017+
2018+ case PPTP_START_SESSION_REQUEST:
2019+ case PPTP_START_SESSION_REPLY:
2020+ case PPTP_STOP_SESSION_REQUEST:
2021+ case PPTP_STOP_SESSION_REPLY:
2022+ case PPTP_ECHO_REQUEST:
2023+ case PPTP_ECHO_REPLY:
2024+ /* no need to alter packet */
2025+ return NF_ACCEPT;
2026+ }
2027+
2028+ /* mangle packet */
2029+ IP_NF_ASSERT(pcid);
2030+ DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
2031+ ntohs(*pcid), ntohs(new_pcid));
2032+ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph,
2033+ sizeof(new_pcid), (char *)&new_pcid,
2034+ sizeof(new_pcid));
2035+
2036+ if (new_cid) {
2037+ IP_NF_ASSERT(cid);
2038+ DEBUGP("altering call id from 0x%04x to 0x%04x\n",
2039+ ntohs(*cid), ntohs(new_cid));
2040+ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
2041+ (void *)cid - (void *)pptph,
2042+ sizeof(new_cid), (char *)&new_cid,
2043+ sizeof(new_cid));
2044+ }
2045+
2046+ /* great, at least we don't need to resize packets */
2047+ return NF_ACCEPT;
2048+}
2049+
2050+
2051+static unsigned int tcp_help(struct ip_conntrack *ct,
2052+ struct ip_conntrack_expect *exp,
2053+ struct ip_nat_info *info,
2054+ enum ip_conntrack_info ctinfo,
2055+ unsigned int hooknum, struct sk_buff **pskb)
2056+{
2057+ struct iphdr *iph = (*pskb)->nh.iph;
2058+ struct tcphdr *tcph = (void *) iph + iph->ihl*4;
2059+ unsigned int datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
2060+ struct pptp_pkt_hdr *pptph;
2061+
2062+ int dir;
2063+
2064+ DEBUGP("entering\n");
2065+
2066+ /* Only mangle things once: DST for original direction
2067+ and SRC for reply direction. */
2068+ dir = CTINFO2DIR(ctinfo);
2069+ if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
2070+ && dir == IP_CT_DIR_ORIGINAL)
2071+ || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST
2072+ && dir == IP_CT_DIR_REPLY))) {
2073+ DEBUGP("Not touching dir %s at hook %s\n",
2074+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
2075+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
2076+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
2077+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
2078+ : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
2079+ return NF_ACCEPT;
2080+ }
2081+
2082+ /* if packet is too small, just skip it */
2083+ if (datalen < sizeof(struct pptp_pkt_hdr)+
2084+ sizeof(struct PptpControlHeader)) {
2085+ DEBUGP("pptp packet too short\n");
2086+ return NF_ACCEPT;
2087+ }
2088+
2089+ pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
2090+
2091+ /* if it's not a control message, we can't handle it */
2092+ if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
2093+ ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
2094+ DEBUGP("not a pptp control packet\n");
2095+ return NF_ACCEPT;
2096+ }
2097+
2098+ LOCK_BH(&ip_pptp_lock);
2099+
2100+ if (dir == IP_CT_DIR_ORIGINAL) {
2101+ /* reuqests sent by client to server (PNS->PAC) */
2102+ pptp_outbound_pkt(pskb, ct, ctinfo, exp);
2103+ } else {
2104+ /* response from the server to the client (PAC->PNS) */
2105+ pptp_inbound_pkt(pskb, ct, ctinfo, exp);
2106+ }
2107+
2108+ UNLOCK_BH(&ip_pptp_lock);
2109+
2110+ return NF_ACCEPT;
2111+}
2112+
2113+/* nat helper struct for control connection */
2114+static struct ip_nat_helper pptp_tcp_helper = {
2115+ .list = { NULL, NULL },
2116+ .name = "pptp",
2117+ .flags = IP_NAT_HELPER_F_ALWAYS,
2118+ .me = THIS_MODULE,
2119+ .tuple = { .src = { .ip = 0,
2120+ .u = { .tcp = { .port =
2121+ __constant_htons(PPTP_CONTROL_PORT) }
2122+ }
2123+ },
2124+ .dst = { .ip = 0,
2125+ .u = { .all = 0 },
2126+ .protonum = IPPROTO_TCP
2127+ }
2128+ },
2129+
2130+ .mask = { .src = { .ip = 0,
2131+ .u = { .tcp = { .port = 0xFFFF } }
2132+ },
2133+ .dst = { .ip = 0,
2134+ .u = { .all = 0 },
2135+ .protonum = 0xFFFF
2136+ }
2137+ },
2138+ .help = tcp_help,
2139+ .expect = pptp_nat_expected
2140+};
2141+
2142+
2143+static int __init init(void)
2144+{
2145+ DEBUGP("%s: registering NAT helper\n", __FILE__);
2146+ if (ip_nat_helper_register(&pptp_tcp_helper)) {
2147+ printk(KERN_ERR "Unable to register NAT application helper "
2148+ "for pptp\n");
2149+ return -EIO;
2150+ }
2151+
2152+ printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
2153+ return 0;
2154+}
2155+
2156+static void __exit fini(void)
2157+{
2158+ DEBUGP("cleanup_module\n" );
2159+ ip_nat_helper_unregister(&pptp_tcp_helper);
2160+ printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
2161+}
2162+
2163+module_init(init);
2164+module_exit(fini);
2165diff -Nur linux-2.6.0.org/net/ipv4/netfilter/ip_nat_proto_gre.c linux-2.6.0/net/ipv4/netfilter/ip_nat_proto_gre.c
2166--- linux-2.6.0.org/net/ipv4/netfilter/ip_nat_proto_gre.c 1970-01-01 01:00:00.000000000 +0100
2167+++ linux-2.6.0/net/ipv4/netfilter/ip_nat_proto_gre.c 2003-11-17 09:09:34.000000000 +0100
2168@@ -0,0 +1,225 @@
2169+/*
2170+ * ip_nat_proto_gre.c - Version 1.2
2171+ *
2172+ * NAT protocol helper module for GRE.
2173+ *
2174+ * GRE is a generic encapsulation protocol, which is generally not very
2175+ * suited for NAT, as it has no protocol-specific part as port numbers.
2176+ *
2177+ * It has an optional key field, which may help us distinguishing two
2178+ * connections between the same two hosts.
2179+ *
2180+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
2181+ *
2182+ * PPTP is built on top of a modified version of GRE, and has a mandatory
2183+ * field called "CallID", which serves us for the same purpose as the key
2184+ * field in plain GRE.
2185+ *
2186+ * Documentation about PPTP can be found in RFC 2637
2187+ *
2188+ * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
2189+ *
2190+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
2191+ *
2192+ */
2193+
2194+#include <linux/config.h>
2195+#include <linux/module.h>
2196+#include <linux/ip.h>
2197+#include <linux/netfilter_ipv4/ip_nat.h>
2198+#include <linux/netfilter_ipv4/ip_nat_rule.h>
2199+#include <linux/netfilter_ipv4/ip_nat_protocol.h>
2200+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
2201+
2202+MODULE_LICENSE("GPL");
2203+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
2204+MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
2205+
2206+#if 0
2207+#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
2208+ ": " format, ## args)
2209+#else
2210+#define DEBUGP(x, args...)
2211+#endif
2212+
2213+/* is key in given range between min and max */
2214+static int
2215+gre_in_range(const struct ip_conntrack_tuple *tuple,
2216+ enum ip_nat_manip_type maniptype,
2217+ const union ip_conntrack_manip_proto *min,
2218+ const union ip_conntrack_manip_proto *max)
2219+{
2220+ u_int32_t key;
2221+
2222+ if (maniptype == IP_NAT_MANIP_SRC)
2223+ key = tuple->src.u.gre.key;
2224+ else
2225+ key = tuple->dst.u.gre.key;
2226+
2227+ return ntohl(key) >= ntohl(min->gre.key)
2228+ && ntohl(key) <= ntohl(max->gre.key);
2229+}
2230+
2231+/* generate unique tuple ... */
2232+static int
2233+gre_unique_tuple(struct ip_conntrack_tuple *tuple,
2234+ const struct ip_nat_range *range,
2235+ enum ip_nat_manip_type maniptype,
2236+ const struct ip_conntrack *conntrack)
2237+{
2238+ u_int32_t min, i, range_size;
2239+ u_int32_t key = 0, *keyptr;
2240+
2241+ if (maniptype == IP_NAT_MANIP_SRC)
2242+ keyptr = &tuple->src.u.gre.key;
2243+ else
2244+ keyptr = &tuple->dst.u.gre.key;
2245+
2246+ if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
2247+
2248+ switch (tuple->dst.u.gre.version) {
2249+ case 0:
2250+ DEBUGP("NATing GRE version 0 (ct=%p)\n",
2251+ conntrack);
2252+ min = 1;
2253+ range_size = 0xffffffff;
2254+ break;
2255+ case GRE_VERSION_PPTP:
2256+ DEBUGP("%p: NATing GRE PPTP\n",
2257+ conntrack);
2258+ min = 1;
2259+ range_size = 0xffff;
2260+ break;
2261+ default:
2262+ printk(KERN_WARNING "nat_gre: unknown GRE version\n");
2263+ return 0;
2264+ break;
2265+ }
2266+
2267+ } else {
2268+ min = ntohl(range->min.gre.key);
2269+ range_size = ntohl(range->max.gre.key) - min + 1;
2270+ }
2271+
2272+ DEBUGP("min = %u, range_size = %u\n", min, range_size);
2273+
2274+ for (i = 0; i < range_size; i++, key++) {
2275+ *keyptr = htonl(min + key % range_size);
2276+ if (!ip_nat_used_tuple(tuple, conntrack))
2277+ return 1;
2278+ }
2279+
2280+ DEBUGP("%p: no NAT mapping\n", conntrack);
2281+
2282+ return 0;
2283+}
2284+
2285+/* manipulate a GRE packet according to maniptype */
2286+static void
2287+gre_manip_pkt(struct iphdr *iph, size_t len,
2288+ const struct ip_conntrack_manip *manip,
2289+ enum ip_nat_manip_type maniptype)
2290+{
2291+ struct gre_hdr *greh = (struct gre_hdr *)((u_int32_t *)iph+iph->ihl);
2292+ struct gre_hdr_pptp *pgreh = (struct gre_hdr_pptp *) greh;
2293+
2294+ /* we only have destination manip of a packet, since 'source key'
2295+ * is not present in the packet itself */
2296+ if (maniptype == IP_NAT_MANIP_DST) {
2297+ /* key manipulation is always dest */
2298+ switch (greh->version) {
2299+ case 0:
2300+ if (!greh->key) {
2301+ DEBUGP("can't nat GRE w/o key\n");
2302+ break;
2303+ }
2304+ if (greh->csum) {
2305+ /* FIXME: Never tested this code... */
2306+ *(gre_csum(greh)) =
2307+ ip_nat_cheat_check(~*(gre_key(greh)),
2308+ manip->u.gre.key,
2309+ *(gre_csum(greh)));
2310+ }
2311+ *(gre_key(greh)) = manip->u.gre.key;
2312+ break;
2313+ case GRE_VERSION_PPTP:
2314+ DEBUGP("call_id -> 0x%04x\n",
2315+ ntohl(manip->u.gre.key));
2316+ pgreh->call_id = htons(ntohl(manip->u.gre.key));
2317+ break;
2318+ default:
2319+ DEBUGP("can't nat unknown GRE version\n");
2320+ break;
2321+ }
2322+ }
2323+}
2324+
2325+/* print out a nat tuple */
2326+static unsigned int
2327+gre_print(char *buffer,
2328+ const struct ip_conntrack_tuple *match,
2329+ const struct ip_conntrack_tuple *mask)
2330+{
2331+ unsigned int len = 0;
2332+
2333+ if (mask->dst.u.gre.version)
2334+ len += sprintf(buffer + len, "version=%d ",
2335+ ntohs(match->dst.u.gre.version));
2336+
2337+ if (mask->dst.u.gre.protocol)
2338+ len += sprintf(buffer + len, "protocol=0x%x ",
2339+ ntohs(match->dst.u.gre.protocol));
2340+
2341+ if (mask->src.u.gre.key)
2342+ len += sprintf(buffer + len, "srckey=0x%x ",
2343+ ntohl(match->src.u.gre.key));
2344+
2345+ if (mask->dst.u.gre.key)
2346+ len += sprintf(buffer + len, "dstkey=0x%x ",
2347+ ntohl(match->src.u.gre.key));
2348+
2349+ return len;
2350+}
2351+
2352+/* print a range of keys */
2353+static unsigned int
2354+gre_print_range(char *buffer, const struct ip_nat_range *range)
2355+{
2356+ if (range->min.gre.key != 0
2357+ || range->max.gre.key != 0xFFFF) {
2358+ if (range->min.gre.key == range->max.gre.key)
2359+ return sprintf(buffer, "key 0x%x ",
2360+ ntohl(range->min.gre.key));
2361+ else
2362+ return sprintf(buffer, "keys 0x%u-0x%u ",
2363+ ntohl(range->min.gre.key),
2364+ ntohl(range->max.gre.key));
2365+ } else
2366+ return 0;
2367+}
2368+
2369+/* nat helper struct */
2370+static struct ip_nat_protocol gre =
2371+ { { NULL, NULL }, "GRE", IPPROTO_GRE,
2372+ gre_manip_pkt,
2373+ gre_in_range,
2374+ gre_unique_tuple,
2375+ gre_print,
2376+ gre_print_range
2377+ };
2378+
2379+static int __init init(void)
2380+{
2381+ if (ip_nat_protocol_register(&gre))
2382+ return -EIO;
2383+
2384+ return 0;
2385+}
2386+
2387+static void __exit fini(void)
2388+{
2389+ ip_nat_protocol_unregister(&gre);
2390+}
2391+
2392+module_init(init);
2393+module_exit(fini);
2394diff -Nur linux-2.6.0.org/net/ipv4/netfilter/Kconfig linux-2.6.0/net/ipv4/netfilter/Kconfig
2395--- linux-2.6.0.org/net/ipv4/netfilter/Kconfig 2003-12-18 03:59:25.000000000 +0100
c1dfa972 2396+++ linux-2.6.0/net/ipv4/netfilter/Kconfig 2003-12-19 11:37:04.565557808 +0100
83e42fff 2397@@ -68,6 +68,16 @@
c1dfa972 2398
2399 To compile it as a module, choose M here. If unsure, say Y.
2400
2401+config IP_NF_CT_PROTO_GRE
2402+ tristate " GRE protocol support"
2403+ depends on IP_NF_CONNTRACK!=n
c1dfa972 2404+ help
2405+
2406+config IP_NF_PPTP
2407+ tristate " PPTP protocol support"
83e42fff 2408+ depends on IP_NF_CT_PROTO_GRE!=n
c1dfa972 2409+ help
2410+
2411 config IP_NF_QUEUE
2412 tristate "Userspace queueing via NETLINK"
2413 help
83e42fff 2414@@ -390,6 +400,18 @@
2415
2416 # If they want FTP, set to $CONFIG_IP_NF_NAT (m or y),
2417 # or $CONFIG_IP_NF_FTP (m or y), whichever is weaker. Argh.
2418+config IP_NF_NAT_PROTO_GRE
2419+ tristate
2420+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2421+ default IP_NF_NAT_PROTO_GRE if IP_NF_CT_PROTO_GRE=y
2422+ default m if IP_NF_CT_PROTO_GRE=m
2423+
2424+config IP_NF_NAT_PPTP
2425+ tristate
76b83a0c 2426+ depends on IP_NF_CT_PROTO_GRE!=n && IP_NF_PPTP!=n && IP_NF_NAT!=n
83e42fff 2427+ default IP_NF_NAT_PPTP if IP_NF_PPTP=y
2428+ default m if IP_NF_PPTP=m
2429+
2430 config IP_NF_NAT_FTP
2431 tristate
2432 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
This page took 0.634782 seconds and 4 git commands to generate.