PPTP Client Packet Reordering
The main goal of this patch is to support packet reordering, which allows packets to be received by the client out of order, and returns them to the correct order for pppd. The standard client will simplythrow away out-of-order packets, with a log message like
discarding out-of-order seq is 1657 seqrecv is 1658.
Normally, out-of-order packets are very rare on the Internet. However, one ISP in Britain, NTL's cable modem service, reorders small packets ahead of large ones. This is probably supposed to make interactive sessions respond better when large downloads are in progress, but it also makes pptpclientalmost unusable in some situations.
You can easily test this by running a command like 'ping -s 1510 188.8.131.52', where 184.108.40.206 is a host running pptpclient, on the other side of your tunnel, and 1510 is just higher than the MTU of the tunnel. This will cause a pattern of large-fragment small-fragment GRE packets to be sent to the other side. If the other side is an NTL cable modem, the small packets will almost always arrive before the large ones, and pptpclient will drop them.
We have added several new features to pptpclient:
Inclusion of pqueue.c and pqueue.h
Adds two new files, pqueue.c and pqueue.h, to the pptp executable. pqueue.c implements the packet queue used by the reordering code, and pqueue.h describes its public interface. The queue is implemented as a linked list. This is required for reordering.
Adds a new command-line option,
--debug, to pptpclient. Currently, all this does it prevent pptpclient from going into the background. It also tidies up the indenting of the option-handling code in pptp.c. This is optional.
Calls the daemon(3) function to change the current directory and close the standard file descriptors. This prevents your shell from hanging open if you start pptpclient remotely and leave it running.
Packets are added to the queue by decaps_gre if their sequence number is higher than expected, but within the window. The default window is defined as 30 packets.
Packets which are below the window (older than the most recent packet read) or above the window (too far ahead) are discarded, to protect against denial-of-service attacks.
The new function dequeue_gre retrieves packets from the head of the queue which are:
- Next in sequence (unwrapped or wrapped)
- Older than five seconds (assuming that the intermediate packets have been lost by the network).
The function will continue to read packets from the head of the queue until it finds one which doesn't match these criteria, and then stop.
There are some limitations with this patch:
- The receive window is hardcoded at 300 packets. I couldn't see where to get the negotiated and/or current window size from.
Another limitation of the original reordering code has now been remedied:
The timeout is now adjustable, and defaults to 0.3 seconds. A packet which was received and queued within the window, but which should have been preceded by other packets which never appeared, will be accepted anyway after this time (increasing the sequence number to its own). This has been changed in more recent versions so that the timeout can be adjusted on the command line, and the default is shorter (0.3 seconds).
There are no known memory leaks or other bugs in the reordering code.
We advise you to use a recent release from the PPTP Client project, which includes the reordering code. You can find their releases here. The version used in our FireRack firewalls is the CVS tree from 11/03/2004, which is very close to the released version 1.4.0.
The very latest version of the reordering code will always be available in pptpclient's own CVS. You can find instructions to download it here:
Please be aware that the CVS contains the very latest version of the software, and as such has not been extensively tested.