kludge around problem with Netgear DM602 authentication
authorbodea <bodea>
Fri, 26 May 2006 07:33:52 +0000 (07:33 +0000)
committerbodea <bodea>
Fri, 26 May 2006 07:33:52 +0000 (07:33 +0000)
Changes
l2tpns.h
l2tpns.spec
ppp.c

diff --git a/Changes b/Changes
index 0029cfd..f416f58 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,9 +1,5 @@
-* Wed May 24 2006 Brendan O'Dea <bod@optus.net> 2.2.0
-- Only poll clifd if successfully bound.
-- Add "Practical VPNs" document from Liran Tal as Docs/vpn .
-- Add Multilink support from Khaled Al Hamwi.
-- Remove non-working setuid option.
-- Convert manual.html to Docbook.
+* Fri May 26 2006 Brendan O'Dea <bod@optus.net> 2.1.19
+- Kludge around problem with Netgear DM602 authentication.
 
 * Tue Apr 18 2006 Brendan O'Dea <bod@optus.net> 2.1.18
 - Don't shutdown on TerminateReq, wait for CDN.
index 3ad2cf5..c178a3b 100644 (file)
--- a/l2tpns.h
+++ b/l2tpns.h
@@ -1,5 +1,5 @@
 // L2TPNS Global Stuff
-// $Id: l2tpns.h,v 1.116 2006/04/27 14:37:28 bodea Exp $
+// $Id: l2tpns.h,v 1.113.2.1 2006/05/26 07:33:52 bodea Exp $
 
 #ifndef __L2TPNS_H__
 #define __L2TPNS_H__
 #include <sys/types.h>
 #include <libcli.h>
 
-#define VERSION        "2.2.0"
+#define VERSION        "2.1.19"
 
 // Limits
 #define MAXTUNNEL      500             // could be up to 65535
-#define MAXBUNDLE      300             // could be up to 65535
-#define MAXBUNDLESES   10              // Maximum number of member links in bundle
-#define MAXADDRESS     20              // Maximum length for the Endpoint Discrminiator address
-#define MAXFRAGNUM     1500            // Maximum number of Multilink fragment in a bundle
-#define MAXFRAGLEN      1000           // Maximum length for Multilink fragment
 #define MAXSESSION     60000           // could be up to 65535
 #define MAXTBFS                6000            // Maximum token bucket filters. Might need up to 2 * session.
 
 #define MAXIPPOOL      131072          // max number of ip addresses in pool
 #define RINGBUFFER_SIZE        10000           // Number of ringbuffer entries to allocate
 #define MAX_LOG_LENGTH 512             // Maximum size of log message
-#define ECHO_TIMEOUT   10              // Time between last packet sent and LCP ECHO generation
+#define ECHO_TIMEOUT   60              // Time between last packet sent and LCP ECHO generation
 #define IDLE_TIMEOUT   240             // Time between last packet sent and LCP ECHO generation
 #define BUSY_WAIT_TIME 3000            // 5 minutes in 1/10th seconds to wait for radius to cleanup on shutdown
 
-#define MP_BEGIN       0x80            // This value is used when (b)egin bit is set in MP header
-#define MP_END         0x40            // This value is used when (e)nd bit is set in MP header
-#define MP_BOTH_BITS   0xC0            // This value is used when both bits (begin and end) are set in MP header
-
-#define DEFAULT_EPDIS_ADDRESS  "L2TPNetServer"         // Company name may goes here!
-
 // Constants
 #ifndef ETCDIR
 #define ETCDIR         "/etc/l2tpns"
@@ -197,7 +186,6 @@ enum {
 
 // Types
 typedef uint16_t sessionidt;
-typedef uint16_t bundleidt;
 typedef uint16_t tunnelidt;
 typedef uint32_t clockt;
 typedef uint8_t hasht[16];
@@ -243,17 +231,6 @@ typedef struct controls            // control message
 }
 controlt;
 
-typedef struct {
-       uint8_t length;                 // Endpoint Discriminator length
-       uint8_t addr_class;             // Endpoint Discriminator class
-       uint8_t address[MAXADDRESS];    // Endpoint Discriminator address
-} epdist;
-
-typedef struct {
-       uint16_t length;                // Fragment length
-       uint8_t data[MAXFRAGLEN];       // Fragment data
-} fragmentt;
-
 typedef struct
 {
        sessionidt next;                // next session in linked list
@@ -296,11 +273,6 @@ typedef struct
        char calling[MAXTEL];           // calling number
        uint32_t tx_connect_speed;
        uint32_t rx_connect_speed;
-       clockt timeout;                 // Session timeout
-       uint32_t mrru;                  // Multilink Max-Receive-Reconstructed-Unit
-       uint8_t mssf;                   // Multilink Short Sequence Number Header Format
-       epdist epdis;                   // Multilink Endpoint Discriminator
-       bundleidt bundle;               // Multilink Bundle Identifier
        in_addr_t snoop_ip;             // Interception destination IP
        uint16_t snoop_port;            // Interception destination port
        uint8_t walled_garden;          // is this session gardened?
@@ -310,33 +282,6 @@ typedef struct
 }
 sessiont;
 
-typedef struct
-{
-       int state;                              // current state (bundlestate enum)
-       uint32_t seq_num_t;                     // Sequence Number (transmission)
-       uint32_t seq_num_m;                     // Last received frame sequence number (bearing B bit)
-       uint32_t offset;                        // Offset between sequence number and array index
-       uint8_t pending_frag;                   // Indicate that there is pending fragments to reassemble
-       uint8_t num_of_links;                   // Number of links joint to this bundle
-       uint32_t online_time;                   // The time this bundle is online
-       clockt last_check;                      // Last time the timeout is checked
-       uint32_t mrru;                          // Multilink Max-Receive-Reconstructed-Unit
-       uint8_t mssf;                           // Multilink Short Sequence Number Header Format
-       epdist epdis;                           // Multilink Endpoint Discriminator
-       char user[MAXUSER];                     // Needed for matching member links
-       sessionidt current_ses;                 // Current session to use for sending (used in RR load-balancing)
-       sessionidt members[MAXBUNDLESES];       // Array for member links sessions
-}
-bundlet;
-
-typedef struct
-{
-       fragmentt fragment[MAXFRAGNUM];
-       uint8_t reassembled_frame[MAXETHER];    // The reassembled frame
-       uint16_t re_frame_len;                  // The reassembled frame length
-}
-fragmentationt;
-
 #define AUTHPAP                1       // allow PAP
 #define AUTHCHAP       2       // allow CHAP
 
@@ -366,15 +311,6 @@ typedef struct
        // our MRU
        uint16_t ppp_mru;
 
-       // our MRRU
-       uint16_t mp_mrru;
-
-       // our mssf
-       uint16_t mp_mssf;
-
-       // our Endpoint Discriminator
-       in_addr_t mp_epdis;
-
        // DoS prevention
        clockt last_packet_out;
        uint32_t packets_out;
@@ -471,23 +407,6 @@ enum
        TUNNELUNDEF,            // Undefined
 };
 
-enum
-{
-       BUNDLEFREE,             // Not in use
-       BUNDLEOPEN,             // Active bundle
-       BUNDLEUNDEF,            // Undefined
-};
-
-enum
-{
-       NULLCLASS = 0,          //End Point Discriminator classes
-       LOCALADDR,
-       IPADDR,
-       IEEEMACADDR,
-       PPPMAGIC,
-       PSNDN,
-};
-
 enum
 {
        RADIUSNULL,             // Not in use
@@ -642,7 +561,6 @@ typedef struct
        int             radius_authprefer;
 
        int             allow_duplicate_users;          // allow multiple logins with the same username
-       char            guest_user[MAXUSER];            // allow multiple logins to guest account username
 
        in_addr_t       default_dns1, default_dns2;
 
@@ -654,6 +572,7 @@ typedef struct
        in_addr_t       peer_address;
        int             send_garp;                      // Set to true to garp for vip address on startup
 
+       int             target_uid;
        int             dump_speed;
        char            plugins[64][MAXPLUGINS];
        char            old_plugins[64][MAXPLUGINS];
@@ -664,7 +583,6 @@ typedef struct
        int             lock_pages;                     // Lock pages into memory.
        int             icmp_rate;                      // Max number of ICMP unreachable per second to send
        int             max_packets;                    // DoS prevention: per session limit of packets/0.1s
-       char            epdis_addr[20];                 // MP Endpoint Discriminator address
 
        in_addr_t       cluster_address;                // Multicast address of cluster.
                                                        // Send to this address to have everyone hear.
@@ -676,10 +594,8 @@ typedef struct
        int             cluster_seq_number;             // Sequence number of the next heartbeat we'll send out
                                                        // (or the seq number we're next expecting if we're a slave).
        int             cluster_undefined_sessions;     // How many sessions we're yet to receive from the master.
-       int             cluster_undefined_bundles;      // How many bundles we're yet to receive from the master.
        int             cluster_undefined_tunnels;      // How many tunnels we're yet to receive from the master.
        int             cluster_highest_sessionid;
-       int             cluster_highest_bundleid;
        int             cluster_highest_tunnelid;
        clockt          cluster_last_hb;                // Last time we saw a heartbeat from the master.
        int             cluster_last_hb_ver;            // Heartbeat version last seen from master
@@ -689,11 +605,13 @@ typedef struct
        int             cluster_hb_interval;            // How often to send a heartbeat.
        int             cluster_hb_timeout;             // How many missed heartbeats trigger an election.
        uint64_t        cluster_table_version;          // # state changes processed by cluster
-       int             cluster_master_min_adv;         // Master advertises routes while the number of up to date
-                                                       // slaves is less than this value.
 
        struct in6_addr ipv6_prefix;                    // Our IPv6 network pool.
 
+
+       int             cluster_master_min_adv;         // Master advertises routes while the number of up to date
+                                                       // slaves is less than this value.
+
 #ifdef BGP
 #define BGP_NUM_PEERS  2
        uint16_t as_number;
@@ -809,17 +727,14 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
 void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
 void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
 void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
-void processmpin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
-void processmpframe(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l, uint8_t extra);
 void processipv6in(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
 void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
 void sendchap(sessionidt s, tunnelidt t);
-uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, sessionidt s, tunnelidt t, uint16_t mtype, uint8_t prio, bundleidt bid, uint8_t mp_bits);
+uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, sessionidt s, tunnelidt t, uint16_t mtype);
 void sendlcp(sessionidt s, tunnelidt t);
 void send_ipin(sessionidt s, uint8_t *buf, int len);
 void sendccp(sessionidt s, tunnelidt t);
 void protoreject(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l, uint16_t proto);
-int join_bundle(sessionidt s);
 
 
 // radius.c
@@ -887,7 +802,6 @@ void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, uint
 
 
 extern tunnelt *tunnel;
-extern bundlet *bundle;
 extern sessiont *session;
 extern sessionlocalt *sess_local;
 extern ippoolt *ip_address_pool;
index 15fffac..a59b462 100644 (file)
@@ -1,6 +1,6 @@
 Summary: A high-speed clustered L2TP LNS
 Name: l2tpns
-Version: 2.2.0
+Version: 2.1.19
 Release: 1
 License: GPL
 Group: System Environment/Daemons
@@ -43,5 +43,5 @@ rm -rf %{buildroot}
 %attr(644,root,root) /usr/share/man/man[58]/*
 
 %changelog
-* Wed May 24 2006 Brendan O'Dea <bod@optus.net> 2.2.0-1
-- 2.2.0 release, see /usr/share/doc/l2tpns-2.2.0/Changes
+* Fri May 26 2006 Brendan O'Dea <bod@optus.net> 2.1.19-1
+- 2.1.19 release, see /usr/share/doc/l2tpns-2.1.19/Changes
diff --git a/ppp.c b/ppp.c
index afacd90..d903496 100644 (file)
--- a/ppp.c
+++ b/ppp.c
@@ -1,6 +1,6 @@
 // L2TPNS PPP Stuff
 
-char const *cvs_id_ppp = "$Id: ppp.c,v 1.100 2006/04/27 09:53:50 bodea Exp $";
+char const *cvs_id_ppp = "$Id: ppp.c,v 1.99.2.1 2006/05/26 07:33:52 bodea Exp $";
 
 #include <stdio.h>
 #include <string.h>
@@ -15,8 +15,6 @@ char const *cvs_id_ppp = "$Id: ppp.c,v 1.100 2006/04/27 09:53:50 bodea Exp $";
 #include "cluster.h"
 
 extern tunnelt *tunnel;
-extern bundlet *bundle;
-extern fragmentationt *frag;
 extern sessiont *session;
 extern radiust *radius;
 extern int tunfd;
@@ -26,10 +24,6 @@ extern time_t time_now;
 extern configt *config;
 
 static int add_lcp_auth(uint8_t *b, int size, int authtype);
-static bundleidt new_bundle(void);
-static int epdiscmp(epdist, epdist);
-static void setepdis(epdist *, epdist);
-static void ipcp_open(sessionidt s, tunnelidt t);
 
 // Process PAP messages
 void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
@@ -96,7 +90,7 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                // respond now, either no RADIUS available or already authenticated
                uint8_t b[MAXETHER];
                uint8_t id = p[1];
-               uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPPAP, 0, 0, 0);
+               uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPPAP);
                if (!p) return;
 
                if (session[s].ip)
@@ -179,16 +173,24 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                return;
        }
 
-       r = sess_local[s].radius;
-       if (!r)
+       if (session[s].ppp.phase != Authenticate)
        {
-               LOG(3, s, t, "Unexpected CHAP message\n");
+               LOG(2, s, t, "CHAP ignored in %s phase\n", ppp_phase(session[s].ppp.phase));
                return;
        }
 
-       if (session[s].ppp.phase != Authenticate)
+       r = sess_local[s].radius;
+       if (!r)
        {
-               LOG(2, s, t, "CHAP ignored in %s phase\n", ppp_phase(session[s].ppp.phase));
+               LOG(3, s, t, "Unexpected CHAP message\n");
+
+               // Some modems (Netgear DM602, possibly others) persist in using CHAP even
+               // after ACKing our ConfigReq for PAP.
+               if (sess_local[s].lcp_authtype == AUTHPAP && config->radius_authtypes & AUTHCHAP)
+               {
+                       sess_local[s].lcp_authtype = AUTHCHAP;
+                       sendchap(s, t);
+               }
                return;
        }
 
@@ -358,29 +360,16 @@ void lcp_open(sessionidt s, tunnelidt t)
        }
        else
        {
-               if (session[s].bundle && bundle[session[s].bundle].num_of_links > 1)
-               {
-                       sessionidt first_ses = bundle[session[s].bundle].members[0];
-                       LOG(3, s, t, "MPPP: Skipping IPCP negotiation for session:%d, first session of bundle is:%d\n", s, first_ses);
-                       session[s].ip = session[first_ses].ip;
-                       session[s].dns1 = session[first_ses].dns1;
-                       session[s].dns2 = session[first_ses].dns2;
-                       session[s].timeout = session[first_ses].timeout;
-                       ipcp_open(s, t);
-               }
+               // This-Layer-Up
+               sendipcp(s, t);
+               change_state(s, ipcp, RequestSent);
+               // move to passive state for IPv6 (if configured), CCP
+               if (config->ipv6_prefix.s6_addr[0])
+                       change_state(s, ipv6cp, Stopped);
                else
-               {
-                       // This-Layer-Up
-                       sendipcp(s, t);
-                       change_state(s, ipcp, RequestSent);
-                       // move to passive state for IPv6 (if configured), CCP
-                       if (config->ipv6_prefix.s6_addr[0])
-                               change_state(s, ipv6cp, Stopped);
-                       else
-                               change_state(s, ipv6cp, Closed);
+                       change_state(s, ipv6cp, Closed);
 
-                       change_state(s, ccp, Stopped);
-               }
+               change_state(s, ccp, Stopped);
        }
 }
 
@@ -398,7 +387,7 @@ static uint8_t *ppp_conf_rej(sessionidt s, uint8_t *buf, size_t blen, uint16_t m
 {
        if (!*response || **response != ConfigRej)
        {
-               queued = *response = makeppp(buf, blen, packet, 2, s, session[s].tunnel, mtype, 0, 0, 0);
+               queued = *response = makeppp(buf, blen, packet, 2, s, session[s].tunnel, mtype);
                if (!queued)
                        return 0;
 
@@ -442,7 +431,7 @@ static uint8_t *ppp_conf_nak(sessionidt s, uint8_t *buf, size_t blen, uint16_t m
                if (*nak_sent >= config->ppp_max_failure)
                        return ppp_conf_rej(s, buf, blen, mtype, response, 0, packet, option);
 
-               queued = *response = makeppp(buf, blen, packet, 2, s, session[s].tunnel, mtype, 0, 0, 0);
+               queued = *response = makeppp(buf, blen, packet, 2, s, session[s].tunnel, mtype);
                if (!queued)
                        return 0;
 
@@ -474,7 +463,7 @@ static void ppp_code_rej(sessionidt s, tunnelidt t, uint16_t proto,
        l += 4;
        if (l > mru) l = mru;
 
-       q = makeppp(buf, size, 0, 0, s, t, proto, 0, 0, 0);
+       q = makeppp(buf, size, 0, 0, s, t, proto);
        if (!q) return;
 
        *q = CodeRej;
@@ -586,7 +575,6 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                uint8_t *response = 0;
                static uint8_t asyncmap[4] = { 0, 0, 0, 0 }; // all zero
                static uint8_t authproto[5];
-               int changed = 0;
 
                while (x > 2)
                {
@@ -602,7 +590,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                                if (mru >= MINMTU)
                                                {
                                                        session[s].mru = mru;
-                                                       changed++;
+                                                       cluster_send_session(s);
                                                        break;
                                                }
 
@@ -675,64 +663,6 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                case 8: // Address-And-Control-Field-Compression
                                        break;
 
-                               case 17: // Multilink Max-Receive-Reconstructed-Unit
-                                       {
-                                               uint16_t mrru = ntohs(*(uint16_t *)(o + 2));
-                                               session[s].mrru = mrru;
-                                               changed++;
-                                               LOG(3, s, t, "    Received PPP LCP option MRRU: %d\n",mrru);
-                                       }
-                                       break;
-                                       
-                               case 18: // Multilink Short Sequence Number Header Format
-                                       {
-                                               session[s].mssf = 1;
-                                               changed++;
-                                               LOG(3, s, t, "    Received PPP LCP option MSSN format\n");
-                                       }
-                                       break;
-                                       
-                               case 19: // Multilink Endpoint Discriminator
-                                       {
-                                               uint8_t epdis_class = o[2];
-                                               int addr;
-
-                                               session[s].epdis.addr_class = epdis_class;
-                                               session[s].epdis.length = length - 3;
-                                               if (session[s].epdis.length > 20)
-                                               {
-                                                       LOG(1, s, t, "Error: received EndDis Address Length more than 20: %d\n", session[s].epdis.length);
-                                                       session[s].epdis.length = 20;
-                                               }
-
-                                               for (addr = 0; addr < session[s].epdis.length; addr++)
-                                                       session[s].epdis.address[addr] = o[3+addr];
-
-                                               changed++;
-
-                                               switch (epdis_class)
-                                               {
-                                               case LOCALADDR:
-                                                       LOG(3, s, t, "    Received PPP LCP option Multilink EndDis Local Address Class: %d\n",epdis_class);
-                                                       break;
-                                               case IPADDR:
-                                                       LOG(3, s, t, "    Received PPP LCP option Multilink EndDis IP Address Class: %d\n",epdis_class);
-                                                       break;
-                                               case IEEEMACADDR:
-                                                       LOG(3, s, t, "    Received PPP LCP option Multilink EndDis IEEE MAC Address Class: %d\n",epdis_class);
-                                                       break;
-                                               case PPPMAGIC:
-                                                       LOG(3, s, t, "    Received PPP LCP option Multilink EndDis PPP Magic No Class: %d\n",epdis_class);
-                                                       break;
-                                               case PSNDN:
-                                                       LOG(3, s, t, "    Received PPP LCP option Multilink EndDis PSND No Class: %d\n",epdis_class);
-                                                       break;
-                                               default:
-                                                       LOG(3, s, t, "    Received PPP LCP option Multilink EndDis NULL Class %d\n",epdis_class);
-                                               }
-                                       }
-                                       break;
-
                                default: // Reject any unknown options
                                        LOG(3, s, t, "    Rejecting unknown PPP LCP option %d\n", type);
                                        q = ppp_conf_rej(s, b, sizeof(b), PPPLCP, &response, q, p, o);
@@ -741,9 +671,6 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                        o += length;
                }
 
-               if (changed)
-                       cluster_send_session(s);
-
                if (response)
                {
                        l = q - response; // LCP packet length
@@ -752,7 +679,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                else
                {
                        // Send packet back as ConfigAck
-                       response = makeppp(b, sizeof(b), p, l, s, t, PPPLCP, 0, 0, 0);
+                       response = makeppp(b, sizeof(b), p, l, s, t, PPPLCP);
                        if (!response) return;
                        *response = ConfigAck;
                }
@@ -760,7 +687,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                switch (session[s].ppp.lcp)
                {
                case Closed:
-                       response = makeppp(b, sizeof(b), p, 2, s, t, PPPLCP, 0, 0, 0);
+                       response = makeppp(b, sizeof(b), p, 2, s, t, PPPLCP);
                        if (!response) return;
                        *response = TerminateAck;
                        *((uint16_t *) (response + 2)) = htons(l = 4);
@@ -893,50 +820,6 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                        cluster_send_session(s);
                                        break;
 
-                               case 17: // Multilink Max-Receive-Reconstructed-Unit
-                               {
-                                       if (*p == ConfigNak)
-                                       {
-                                               sess_local[s].mp_mrru = ntohs(*(uint16_t *)(o + 2));
-                                               LOG(3, s, t, "    Remote requested MRRU of %u\n", sess_local[s].mp_mrru);
-                                       }
-                                       else
-                                       {
-                                               sess_local[s].mp_mrru = 0;
-                                               LOG(3, s, t, "    Remote rejected MRRU negotiation\n");
-                                       }
-                               }
-                               break;
-
-                               case 18: // Multilink Short Sequence Number Header Format
-                               {
-                                       if (*p == ConfigNak)
-                                       {
-                                               sess_local[s].mp_mssf = 0;
-                                               LOG(3, s, t, "    Remote requested Naked mssf\n");
-                                       }
-                                       else
-                                       {
-                                               sess_local[s].mp_mssf = 0;
-                                               LOG(3, s, t, "    Remote rejected mssf\n");
-                                       }
-                               }
-                               break;
-
-                               case 19: // Multilink Endpoint Discriminator
-                               {
-                                       if (*p == ConfigNak)
-                                       {
-                                               LOG(2, s, t, "    Remote should not configNak Endpoint Dis!\n");
-                                       }
-                                       else
-                                       {
-                                               sess_local[s].mp_epdis = 0;
-                                               LOG(3, s, t, "    Remote rejected Endpoint Discriminator\n");
-                                       }
-                               }
-                               break;
-
                                default:
                                        LOG(2, s, t, "LCP: remote sent %s for type %u?\n", ppp_code(*p), type);
                                        sessionshutdown(s, "Unable to negotiate LCP.", CDN_ADMIN_DISC, TERM_USER_ERROR);
@@ -960,7 +843,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                case Closed:
                case Stopped:
                        {
-                               uint8_t *response = makeppp(b, sizeof(b), p, 2, s, t, PPPLCP, 0, 0, 0);
+                               uint8_t *response = makeppp(b, sizeof(b), p, 2, s, t, PPPLCP);
                                if (!response) return;
                                *response = TerminateAck;
                                *((uint16_t *) (response + 2)) = htons(l = 4);
@@ -1018,7 +901,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                }
 
                *p = TerminateAck;      // send ack
-               q = makeppp(b, sizeof(b),  p, l, s, t, PPPLCP, 0, 0, 0);
+               q = makeppp(b, sizeof(b),  p, l, s, t, PPPLCP);
                if (!q) return;
 
                LOG(3, s, t, "LCP: send %s\n", ppp_code(*q));
@@ -1054,7 +937,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
        {
                *p = EchoReply;         // reply
                *(uint32_t *) (p + 4) = htonl(session[s].magic); // our magic number
-               q = makeppp(b, sizeof(b), p, l, s, t, PPPLCP, 0, 0, 0);
+               q = makeppp(b, sizeof(b), p, l, s, t, PPPLCP);
                if (!q) return;
 
                LOG(4, s, t, "LCP: send %s\n", ppp_code(*q));
@@ -1072,93 +955,6 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
        }
 }
 
-int join_bundle(sessionidt s)
-{
-       // Search for a bundle to join
-       bundleidt i;
-       bundleidt b;
-       for (i = 1; i < MAXBUNDLE; i++)
-       {
-               if (bundle[i].state != BUNDLEFREE)
-               {
-                       if (epdiscmp(session[s].epdis,bundle[i].epdis) && !strcmp(session[s].user, bundle[i].user))
-                       {
-                               session[s].bundle = i;
-                               bundle[i].mrru = session[s].mrru;
-                               bundle[i].mssf = session[s].mssf;
-                               if (session[s].epdis.length > 0)
-                                       setepdis(&bundle[i].epdis, session[s].epdis);
-
-                               strcpy(bundle[i].user, session[s].user);
-                               bundle[i].members[bundle[i].num_of_links] = s;
-                               bundle[i].num_of_links++;
-                               LOG(3, s, session[s].tunnel, "MPPP: Bundling additional line in bundle (%d), lines:%d\n",i,bundle[i].num_of_links);
-                               return i;
-                       }
-               }
-       }
-
-       // No previously created bundle was found for this session, so create a new one
-       if (!(b = new_bundle())) return 0;
-
-       session[s].bundle = b;
-       bundle[b].mrru = session[s].mrru;
-       bundle[b].mssf = session[s].mssf;
-       if (session[s].epdis.length > 0)
-               setepdis(&bundle[b].epdis, session[s].epdis);
-
-       strcpy(bundle[b].user, session[s].user);
-       bundle[b].members[0] = s;
-       LOG(3, s, session[s].tunnel, "MPPP: Created a new bundle (%d)\n", b);
-       return b;
-}
-
-static int epdiscmp(epdist ep1, epdist ep2)
-{
-       int ad;
-       if (ep1.length != ep2.length)
-               return 0;
-
-       if (ep1.addr_class != ep2.addr_class)
-               return 0;
-
-       for (ad = 0; ad < ep1.length; ad++)
-               if (ep1.address[ad] != ep2.address[ad])
-                       return 0;
-
-       return 1;
-}
-
-static void setepdis(epdist *ep1, epdist ep2)
-{
-       int ad;
-       ep1->length = ep2.length;
-       ep1->addr_class = ep2.addr_class;
-       for (ad = 0; ad < ep2.length; ad++)
-               ep1->address[ad] = ep2.address[ad];
-}
-
-static bundleidt new_bundle()
-{
-       bundleidt i;
-       for (i = 1; i < MAXBUNDLE; i++)
-       {
-               if (bundle[i].state == BUNDLEFREE)
-               {
-                       LOG(4, 0, 0, "MPPP: Assigning bundle ID %d\n", i);
-                       bundle[i].num_of_links = 1;
-                       bundle[i].last_check = time_now;        // Initialize last_check value
-                       bundle[i].state = BUNDLEOPEN;
-                       bundle[i].current_ses = -1;     // This is to enforce the first session 0 to be used at first
-                       if (i > config->cluster_highest_bundleid)
-                               config->cluster_highest_bundleid = i;
-                       return i;
-               }
-       }
-       LOG(0, 0, 0, "MPPP: Can't find a free bundle! There shouldn't be this many in use!\n");
-       return 0;
-}
-
 static void ipcp_open(sessionidt s, tunnelidt t)
 {
        LOG(3, s, t, "IPCP: Opened, session is now active\n");
@@ -1317,7 +1113,7 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                else if (gotip)
                {
                        // Send packet back as ConfigAck
-                       response = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP, 0, 0, 0);
+                       response = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP);
                        if (!response) return;
                        *response = ConfigAck;
                }
@@ -1331,7 +1127,7 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                switch (session[s].ppp.ipcp)
                {
                case Closed:
-                       response = makeppp(b, sizeof(b), p, 2, s, t, PPPIPCP, 0, 0, 0);
+                       response = makeppp(b, sizeof(b), p, 2, s, t, PPPIPCP);
                        if (!response) return;
                        *response = TerminateAck;
                        *((uint16_t *) (response + 2)) = htons(l = 4);
@@ -1404,7 +1200,7 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                }
 
                *p = TerminateAck;      // send ack
-               q = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP, 0, 0, 0);
+               q = makeppp(b, sizeof(b),  p, l, s, t, PPPIPCP);
                if (!q) return;
 
                LOG(3, s, t, "IPCP: send %s\n", ppp_code(*q));
@@ -1538,7 +1334,7 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                else if (gotip)
                {
                        // Send packet back as ConfigAck
-                       response = makeppp(b, sizeof(b), p, l, s, t, PPPIPV6CP, 0, 0, 0);
+                       response = makeppp(b, sizeof(b), p, l, s, t, PPPIPV6CP);
                        if (!response) return;
                        *response = ConfigAck;
                }
@@ -1552,7 +1348,7 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                switch (session[s].ppp.ipv6cp)
                {
                case Closed:
-                       response = makeppp(b, sizeof(b), p, 2, s, t, PPPIPV6CP, 0, 0, 0);
+                       response = makeppp(b, sizeof(b), p, 2, s, t, PPPIPV6CP);
                        if (!response) return;
                        *response = TerminateAck;
                        *((uint16_t *) (response + 2)) = htons(l = 4);
@@ -1625,7 +1421,7 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                }
 
                *p = TerminateAck;      // send ack
-               q = makeppp(b, sizeof(b),  p, l, s, t, PPPIPV6CP, 0, 0, 0);
+               q = makeppp(b, sizeof(b),  p, l, s, t, PPPIPV6CP);
                if (!q) return;
 
                LOG(3, s, t, "IPV6CP: send %s\n", ppp_code(*q));
@@ -1668,14 +1464,11 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
        if (session[s].ppp.phase != Network || session[s].ppp.ipcp != Opened)
                return;
 
-       if (!session[s].bundle || bundle[session[s].bundle].num_of_links < 2) // FIXME: 
+       // no spoof (do sessionbyip to handled statically routed subnets)
+       if (ip != session[s].ip && sessionbyip(htonl(ip)) != s)
        {
-               // no spoof (do sessionbyip to handled statically routed subnets)
-               if (ip != session[s].ip && sessionbyip(htonl(ip)) != s)
-               {
-                       LOG(4, s, t, "Dropping packet with spoofed IP %s\n", fmtaddr(htonl(ip), 0));
-                       return;
-               }
+               LOG(5, s, t, "Dropping packet with spoofed IP %s\n", fmtaddr(htonl(ip), 0));
+               return;
        }
 
        // run access-list if any
@@ -1741,167 +1534,6 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
        INC_STAT(tun_tx_bytes, l);
 }
 
-// process Multilink PPP packet received
-void processmpin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
-{
-       bundleidt b = session[s].bundle;
-       uint8_t begin_frame;
-       uint8_t end_frame;
-       uint32_t seq_num;
-       uint32_t offset;
-
-       if (!b)
-       {
-               LOG(3, s, t, "MPPP: Invalid bundle id: 0\n");
-               return;
-       }
-
-       begin_frame = (*p & 0x80);
-       end_frame = (*p & 0x40);
-       if (session[s].mssf)
-       {
-               // Get 12 bit for seq number
-               uint16_t short_seq_num = ntohs((*(uint16_t *) p) & 0xFF0F);
-               uint16_t short_seq_num2 = short_seq_num >> 4;
-               p += 2;
-               l -= 2;
-               seq_num = short_seq_num2;
-               // After this point the pointer should be advanced 2 bytes
-               LOG(3, s, t, "MPPP: 12 bits, sequence number: %d, short1: %d, short2: %d\n",seq_num, short_seq_num, short_seq_num2);
-       }
-       else
-       {
-               // Get 24 bit for seq number
-               p++;
-               seq_num = ntohl((*(uint32_t *) p) & 0xFFFFFF00);
-               seq_num = seq_num >> 8;
-               p += 3;
-               l -= 4;
-               // After this point the pointer should be advanced 4 bytes
-               LOG(4, s, t, "MPPP: 24 bits sequence number:%d\n",seq_num);
-       }
-
-       if (seq_num - bundle[b].offset < 0)
-       {
-               bundle[b].offset = 0;
-               bundle[b].pending_frag = 0;
-       }
-
-       offset = bundle[b].offset;
-       if (begin_frame)
-       {
-               // Check for previous non-assembled frames
-               int error = 0;
-               if (bundle[b].pending_frag)
-               {
-                       uint32_t fn = bundle[b].seq_num_m - offset;
-                       uint16_t cur_len;
-                       bundle[b].pending_frag = 0;
-                       // Check for array indexes
-                       if (fn < 0 || fn > MAXFRAGNUM)
-                       {
-                               LOG(2, s, t, "ERROR: Index out of range fn:%d, bundle:%d\n",fn,b);
-                               return;
-                       }
-
-                       if (seq_num-offset < 0 || seq_num-offset > MAXFRAGNUM)
-                       {
-                               LOG(2, s, t, "ERROR: Index out of range fn(last):%d, bundle:%d\n",fn,b);
-                               return;
-                       }
-                       /////////////////////////////////////////////////////
-                       cur_len = 4;   // This is set to 4 to leave 4 bytes for function processipin
-                       for (fn = bundle[b].seq_num_m - offset; fn < seq_num - offset; fn++)
-                       {
-                               if (!frag[b].fragment[fn].length)
-                               {
-                                       LOG(4, s, t, "MPPP: Found lost fragment while reassembling frame %d in (%d,%d)\n",fn, bundle[b].seq_num_m-offset, seq_num-offset);
-                                       error = 1;
-                                       break;
-                               }
-
-                               if (cur_len + frag[b].fragment[fn].length > MAXETHER)
-                               {
-                                       LOG(2, s, t, "MPPP: ERROR: very long frame after assembling %d\n", frag[b].fragment[fn].length+cur_len);
-                                       error = 1;
-                                       break;
-                               }
-
-                               memcpy(frag[b].reassembled_frame+cur_len, frag[b].fragment[fn].data, frag[b].fragment[fn].length);
-                               cur_len += frag[b].fragment[fn].length; 
-                               frag[b].fragment[fn].length = 0;      // Indicates that this fragment has been consumed
-                               // This is usefull for compression
-                               memset(frag[b].fragment[fn].data, 0, sizeof(frag[b].fragment[fn].data));
-                       }
-
-                       if (!error)
-                       {
-                               frag[b].re_frame_len = cur_len;
-                               // Process the resassembled frame
-                               LOG(4, s, t, "MPPP: Process the reassembled frame, len=%d\n",cur_len);
-                               processmpframe(s, t, frag[b].reassembled_frame, frag[b].re_frame_len, 1);
-                               // Set reassembled frame length to zero after processing it
-                               frag[b].re_frame_len = 0;
-                               memset(frag[b].reassembled_frame, 0, sizeof(frag[b].reassembled_frame));
-                       }
-               }
-               //////////////////////////////////////////
-               bundle[b].seq_num_m = seq_num;
-               if (end_frame)
-               {
-                       // Both bits are set
-                       LOG(4, s, t, "MPPP: Both bits are set (Begin and End).\n");
-                       processmpframe(s, t, p, l, 0);
-                       // The maximum number of fragments is 1500
-                       if (seq_num - bundle[b].offset >= 1400)
-                       {
-                               bundle[b].offset = seq_num;
-                               LOG(4, s, t, "MPPP: Setting offset to: %d\n",bundle[b].offset);
-                       }
-               }
-               else
-               {
-                       bundle[b].pending_frag = 1;
-                       // End bit is clear
-                       LOG(4, s, t, "MPPP: Push to receive buffer\n");
-                       // Push to the receive buffer
-                       // Array indexes checking
-                       if (seq_num-offset < 0 || seq_num-offset >= MAXFRAGNUM)
-                       {
-                               LOG(2, s, t, "ERROR: Index out of range, push to receive buffer(1) seq:%d, offset:%d, bundle:%d\n",seq_num,offset,b);
-                               return;
-                       }
-                       // Perform length checking
-                       if (l > MAXFRAGLEN)
-                       {
-                               LOG(2, s, t, "MPPP: ERROR: very long fragment length (1)\n");
-                               return;
-                       }
-                       frag[b].fragment[seq_num - offset].length = l;
-                       memcpy(frag[b].fragment[seq_num - offset].data, p, l);
-               }
-       }
-       else
-       {
-               LOG(4, s, t, "MPPP: Push to receive buffer\n");
-               // Push to the receive buffer
-               // Array indexes checking
-               if (seq_num-offset < 0 || seq_num-offset >= MAXFRAGNUM)
-               {
-                       LOG(2, s, t, "ERROR: Index out of range, push to receive buffer(2) seq:%d, offset:%d, bundle:%d\n",seq_num,offset,b);
-                       return;
-               }
-               // Perform length checking
-               if (l > MAXFRAGLEN)
-               {
-                       LOG(2, s, t, "MPPP: ERROR: very long fragment length (2).\n");
-                       return;
-               }
-               frag[b].fragment[seq_num - offset].length = l;
-               memcpy(frag[b].fragment[seq_num - offset].data, p, l);
-       }
-}
-
 // process IPv6 packet received
 //
 // This MUST be called with at least 4 byte behind 'p'.
@@ -2061,7 +1693,7 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                STAT(tunnel_rx_errors);
        }
 
-       LOG(4, s, t, "CCP: recv %s\n", ppp_code(*p));
+       LOG(3, s, t, "CCP: recv %s\n", ppp_code(*p));
        if (*p == ConfigAck)
        {
                switch (session[s].ppp.ccp)
@@ -2094,13 +1726,13 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                else // compression requested--reject
                        *p = ConfigRej;
 
-               q = makeppp(b, sizeof(b), p, l, s, t, PPPCCP, 0, 0, 0);
+               q = makeppp(b, sizeof(b), p, l, s, t, PPPCCP);
                if (!q) return;
 
                switch (session[s].ppp.ccp)
                {
                case Closed:
-                       q = makeppp(b, sizeof(b), p, 2, s, t, PPPCCP, 0, 0, 0);
+                       q = makeppp(b, sizeof(b), p, 2, s, t, PPPCCP);
                        if (!q) return;
                        *q = TerminateAck;
                        *((uint16_t *) (q + 2)) = htons(l = 4);
@@ -2146,13 +1778,13 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                        return;
                }
 
-               LOG(4, s, t, "CCP: send %s\n", ppp_code(*q));
+               LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
                tunnelsend(b, l + (q - b), t);
        }
        else if (*p == TerminateReq)
        {
                *p = TerminateAck;
-               q = makeppp(b, sizeof(b),  p, l, s, t, PPPCCP, 0, 0, 0);
+               q = makeppp(b, sizeof(b),  p, l, s, t, PPPCCP);
                if (!q) return;
                LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
                tunnelsend(b, l + (q - b), t);
@@ -2196,7 +1828,7 @@ void sendchap(sessionidt s, tunnelidt t)
                STAT(tunnel_tx_errors);
                return ;
        }
-       q = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP, 0, 0, 0);
+       q = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP);
        if (!q) return;
 
        *q = 1;                                 // challenge
@@ -2210,86 +1842,37 @@ void sendchap(sessionidt s, tunnelidt t)
 
 // fill in a L2TP message with a PPP frame,
 // returns start of PPP frame
-uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, sessionidt s, tunnelidt t, uint16_t mtype, uint8_t prio, bundleidt bid, uint8_t mp_bits)
+uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, sessionidt s, tunnelidt t, uint16_t mtype)
 {
-       uint16_t hdr = 0x0002; // L2TP with no options
-       uint16_t type = mtype;
-       uint8_t *start = b;
-
-       if (size < 16) // Need more space than this!!
+       if (size < 12) // Need more space than this!!
        {
                LOG(0, s, t, "makeppp buffer too small for L2TP header (size=%d)\n", size);
                return NULL;
        }
 
-       if (prio) hdr |= 0x0100; // set priority bit
-
-       *(uint16_t *) (b + 0) = htons(hdr);
+       *(uint16_t *) (b + 0) = htons(0x0002); // L2TP with no options
        *(uint16_t *) (b + 2) = htons(tunnel[t].far); // tunnel
        *(uint16_t *) (b + 4) = htons(session[s].far); // session
        b += 6;
-
-       // Check whether this session is part of multilink
-       if (bid)
-       {
-               if (bundle[bid].num_of_links > 1)
-                       type = PPPMP; // Change PPP message type to the PPPMP
-               else
-                       bid = 0;
-       }
-
-       if (type == PPPLCP || !(session[s].flags & SESSION_ACFC))
+       if (mtype == PPPLCP || !(session[s].flags & SESSION_ACFC))
        {
                *(uint16_t *) b = htons(0xFF03); // HDLC header
                b += 2;
        }
-
-       if (type < 0x100 && session[s].flags & SESSION_PFC)
-       {
-               *b++ = type;
-       }
+       if (mtype < 0x100 && session[s].flags & SESSION_PFC)
+               *b++ = mtype;
        else
        {
-               *(uint16_t *) b = htons(type);
+               *(uint16_t *) b = htons(mtype);
                b += 2;
        }
 
-       if (bid)
+       if (l + 12 > size)
        {
-               // Set the sequence number and (B)egin (E)nd flags
-               if (session[s].mssf)
-               {
-                       // Set the multilink bits
-                       uint16_t bits_send = mp_bits;
-                       *(uint16_t *) b = htons((bundle[bid].seq_num_t & 0xFF0F)|bits_send);
-                       b += 2;
-               }
-               else
-               {
-                       *(uint32_t *) b = htonl(bundle[bid].seq_num_t);
-                       // Set the multilink bits
-                       *b = mp_bits;
-                       b += 4;
-               }
-
-               bundle[bid].seq_num_t++;
-
-               // Add the message type if this fragment has the begin bit set
-               if (mp_bits & MP_BEGIN)
-               {
-                       //*b++ = mtype; // The next two lines are instead of this 
-                       *(uint16_t *) b = htons(mtype); // Message type
-                       b += 2;
-               }
-       }
-
-       if ((b - start) + l > size)
-       {
-               LOG(2, s, t, "makeppp would overflow buffer (size=%d, header+payload=%d)\n", size, (b - start) + l);
+               LOG(2, s, t, "makeppp would overflow buffer (size=%d, header+payload=%d)\n", size, l + 12);
                return NULL;
        }
 
-       // Copy the payload
        if (p && l)
                memcpy(b, p, l);
 
@@ -2328,10 +1911,10 @@ void sendlcp(sessionidt s, tunnelidt t)
        uint8_t b[500], *q, *l;
        int authtype = sess_local[s].lcp_authtype;
 
-        if (!(q = makeppp(b, sizeof(b), NULL, 0, s, t, PPPLCP, 0, 0, 0)))
+       if (!(q = makeppp(b, sizeof(b), NULL, 0, s, t, PPPLCP)))
                return;
 
-        LOG(3, s, t, "LCP: send ConfigReq%s%s%s including MP options\n",
+       LOG(3, s, t, "LCP: send ConfigReq%s%s%s\n",
            authtype ? " (" : "",
            authtype ? (authtype == AUTHCHAP ? "CHAP" : "PAP") : "",
            authtype ? ")" : "");
@@ -2358,20 +1941,6 @@ void sendlcp(sessionidt s, tunnelidt t)
                l += 4;
        }
 
-        if (sess_local[s].mp_mrru)
-        {
-               *l++ = 17; *l++ = 4; // Multilink Max-Receive-Reconstructed-Unit (length 4)
-               *(uint16_t *) l = htons(sess_local[s].mp_mrru); l += 2;
-       }
-
-        if (sess_local[s].mp_epdis)
-        {
-               *l++ = 19; *l++ = 7;    // Multilink Endpoint Discriminator (length 7)
-               *l++ = IPADDR;  // Endpoint Discriminator class
-               *(uint32_t *) l = htonl(sess_local[s].mp_epdis);
-               l += 4;
-       }
-
        *(uint16_t *)(q + 2) = htons(l - q); // Length
 
        LOG_HEX(5, "PPPLCP", q, l - q);
@@ -2386,7 +1955,7 @@ void sendccp(sessionidt s, tunnelidt t)
 {
        uint8_t b[500], *q;
 
-       if (!(q = makeppp(b, sizeof(b), NULL, 0, s, t, PPPCCP, 0, 0, 0)))
+       if (!(q = makeppp(b, sizeof(b), NULL, 0, s, t, PPPCCP)))
                return;
 
        LOG(3, s, t, "CCP: send ConfigReq (no compression)\n");
@@ -2413,7 +1982,7 @@ void protoreject(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l, uint16_t pro
        l += 6;
        if (l > mru) l = mru;
 
-       q = makeppp(buf, sizeof(buf), 0, 0, s, t, PPPLCP, 0, 0, 0);
+       q = makeppp(buf, sizeof(buf), 0, 0, s, t, PPPLCP);
        if (!q) return;
 
        *q = ProtocolRej;