]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.0-pptp-conntrack-nat-20031219.patch
- update for cset 20040707_...
[packages/kernel.git] / 2.6.0-pptp-conntrack-nat-20031219.patch
1 diff -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
3 +++ linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack.h     2003-12-19 14:14:23.000000000 +0100
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  
56 diff -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 */
373 diff -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 */
500 diff -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
502 +++ linux-2.6.0/include/linux/netfilter_ipv4/ip_conntrack_tuple.h       2003-12-19 14:14:23.000000000 +0100
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  
563 diff -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 */
578 diff -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
580 +++ linux-2.6.0/net/ipv4/netfilter/Makefile     2003-12-19 14:16:02.000000000 +0100
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
603 diff -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
605 +++ linux-2.6.0/net/ipv4/netfilter/ip_conntrack_core.c  2003-12-19 14:14:23.000000000 +0100
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 */
646 diff -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);
1287 diff -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
1315 diff -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);
1662 diff -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
1664 +++ linux-2.6.0/net/ipv4/netfilter/ip_nat_core.c        2003-12-19 14:14:23.000000000 +0100
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):
1686 diff -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);
2165 diff -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);
2394 diff -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
2396 +++ linux-2.6.0/net/ipv4/netfilter/Kconfig      2003-12-19 11:37:04.565557808 +0100
2397 @@ -68,6 +68,16 @@
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
2404 +       help
2405 +
2406 +config IP_NF_PPTP
2407 +       tristate " PPTP protocol support"
2408 +       depends on IP_NF_CT_PROTO_GRE!=n
2409 +       help
2410 +
2411  config IP_NF_QUEUE
2412         tristate "Userspace queueing via NETLINK"
2413         help
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
2426 +       depends on IP_NF_CT_PROTO_GRE!=n && IP_NF_PPTP!=n && IP_NF_NAT!=n
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.207435 seconds and 3 git commands to generate.