- Add l2tp_mtu configuration option, used to define MRU, MSS.
authorBrendan O'Dea <bod@optus.net>
Fri, 16 Sep 2005 05:04:28 +0000 (05:04 +0000)
committerBrendan O'Dea <bod@optus.net>
Fri, 16 Sep 2005 05:04:28 +0000 (05:04 +0000)
- Adjust TCP MSS options in SYN and SYN,ACK packets to avoid
  fragmentation of tcp packets.

Changes
Docs/manual.html
Docs/startup-config.5
etc/startup-config.default
l2tpns.c
l2tpns.h
l2tpns.spec
ppp.c

diff --git a/Changes b/Changes
index a4cf2da..41c55be 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,8 +1,10 @@
-* Thu Sep 15 2005 Brendan O'Dea <bod@optus.net> 2.1.6
+* Fri Sep 16 2005 Brendan O'Dea <bod@optus.net> 2.1.6
 - Any traffic on a tunnel resets lastrec, not just control messages.
 - Use a unique identifier for LCP.
 - Fix Code-Reject/Protocol-Reject.
 - Any traffic on a tunnel resets lastrec, not just control messages.
 - Use a unique identifier for LCP.
 - Fix Code-Reject/Protocol-Reject.
-- Make MRU configurable, NAK config requests for larger values.
+- Add l2tp_mtu configuration option, used to define MRU, MSS.
+- Adjust TCP MSS options in SYN and SYN,ACK packets to avoid
+  fragmentation of tcp packets.
 
 * Sat Sep 3 2005 Brendan O'Dea <bod@optus.net> 2.1.5
 - Avoid Code-Reject loop.
 
 * Sat Sep 3 2005 Brendan O'Dea <bod@optus.net> 2.1.5
 - Avoid Code-Reject loop.
index a963e19..d09e667 100644 (file)
@@ -185,6 +185,11 @@ the same as the LAC, or authentication will fail.  Only actually be
 used if the LAC requests authentication.
 </LI>
 
 used if the LAC requests authentication.
 </LI>
 
+<LI><B>l2tp_mtu</B> (int)<BR>
+MTU of interface for L2TP traffic (default: 1500).  Used to set link
+MRU and adjust TCP MSS.
+</LI>
+
 <LI><B>ppp_restart_time</B> (int)<BR>
 <B>ppp_max_configure</B> (int)<BR>
 <B>ppp_max_failure</B> (int)<BR>
 <LI><B>ppp_restart_time</B> (int)<BR>
 <B>ppp_max_configure</B> (int)<BR>
 <B>ppp_max_failure</B> (int)<BR>
@@ -192,10 +197,6 @@ PPP counter and timer values, as described in &sect;4.1 of
 <a href="ftp://ftp.rfc-editor.org/in-notes/rfc1661.txt">RFC1661</a>.
 </LI>
 
 <a href="ftp://ftp.rfc-editor.org/in-notes/rfc1661.txt">RFC1661</a>.
 </LI>
 
-<LI><B>ppp_mru</B> (int)<BR>
-PPP link MRU (default: 1452).
-</LI>
-
 <LI><B>primary_dns</B> (ip address)
 <LI><B>secondary_dns</B> (ip address)<BR>
 Whenever a PPP connection is established, DNS servers will be sent to the
 <LI><B>primary_dns</B> (ip address)
 <LI><B>secondary_dns</B> (ip address)<BR>
 Whenever a PPP connection is established, DNS servers will be sent to the
index 4736e8c..97ebab9 100644 (file)
@@ -2,7 +2,7 @@
 .de Id
 .ds Dt \\$4 \\$5
 ..
 .de Id
 .ds Dt \\$4 \\$5
 ..
-.Id $Id: startup-config.5,v 1.14 2005-09-15 09:34:49 bodea Exp $
+.Id $Id: startup-config.5,v 1.15 2005-09-16 05:04:31 bodea Exp $
 .TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions"
 .SH NAME
 startup\-config \- configuration file for l2tpns
 .TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions"
 .SH NAME
 startup\-config \- configuration file for l2tpns
@@ -63,6 +63,10 @@ for authenticating tunnel request.  Must be the same as the LAC, or
 authentication will fail.  Only actually be used if the LAC requests
 authentication.
 .TP
 authentication will fail.  Only actually be used if the LAC requests
 authentication.
 .TP
+.B l2tp_mtu
+MTU of interface for L2TP traffic (default: 1500).  Used to set link
+MRU and adjust TCP MSS.
+.TP
 .B ppp_restart_time
 Restart timer for PPP protocol negotiation in seconds (default: 3).
 .TP
 .B ppp_restart_time
 Restart timer for PPP protocol negotiation in seconds (default: 3).
 .TP
@@ -73,9 +77,6 @@ Number of configure requests to send before giving up (default: 10).
 Number of Configure-Nak requests to send before sending a
 Configure-Reject (default: 5).
 .TP
 Number of Configure-Nak requests to send before sending a
 Configure-Reject (default: 5).
 .TP
-.B ppp_mru
-PPP link MRU (default: 1452).
-.TP
 .BR primary_dns , " secondary_dns"
 Whenever a PPP connection is established, DNS servers will be sent to the
 user, both a primary and a secondary.  If either is set to 0.0.0.0, then that
 .BR primary_dns , " secondary_dns"
 Whenever a PPP connection is established, DNS servers will be sent to the
 user, both a primary and a secondary.  If either is set to 0.0.0.0, then that
index 85f8bd1..0c5051c 100644 (file)
@@ -10,14 +10,14 @@ set pid_file "/var/run/l2tpns.pid"
 # Shared secret with LAC
 set l2tp_secret "secret"
 
 # Shared secret with LAC
 set l2tp_secret "secret"
 
+# MTU of interface for L2TP traffic
+#set l2tp_mtu 1500
+
 # PPP counter and timer values
 #set ppp_restart_time 3
 #set ppp_max_configure 10
 #set ppp_max_failure 5
 
 # PPP counter and timer values
 #set ppp_restart_time 3
 #set ppp_max_configure 10
 #set ppp_max_failure 5
 
-# Link MRU
-#set ppp_mru 1452
-
 # Only 2 DNS server entries are allowed
 set primary_dns 10.0.0.1
 set secondary_dns 10.0.0.2
 # Only 2 DNS server entries are allowed
 set primary_dns 10.0.0.1
 set secondary_dns 10.0.0.2
index 9671a69..de1aecc 100644 (file)
--- a/l2tpns.c
+++ b/l2tpns.c
@@ -4,7 +4,7 @@
 // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
 // vim: sw=8 ts=8
 
 // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
 // vim: sw=8 ts=8
 
-char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.132 2005-09-15 09:34:48 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.133 2005-09-16 05:04:29 bodea Exp $";
 
 #include <arpa/inet.h>
 #include <assert.h>
 
 #include <arpa/inet.h>
 #include <assert.h>
@@ -75,6 +75,10 @@ static int syslog_log = 0;   // are we logging to syslog
 static FILE *log_stream = 0;   // file handle for direct logging (i.e. direct into file, not via syslog).
 uint32_t last_id = 0;          // Unique ID for radius accounting
 
 static FILE *log_stream = 0;   // file handle for direct logging (i.e. direct into file, not via syslog).
 uint32_t last_id = 0;          // Unique ID for radius accounting
 
+// calculated from config->l2tp_mtu
+uint16_t MRU = 0;              // PPP MRU
+uint16_t MSS = 0;              // TCP MSS
+
 struct cli_session_actions *cli_session_actions = NULL;        // Pending session changes requested by CLI
 struct cli_tunnel_actions *cli_tunnel_actions = NULL;  // Pending tunnel changes required by CLI
 
 struct cli_session_actions *cli_session_actions = NULL;        // Pending session changes requested by CLI
 struct cli_tunnel_actions *cli_tunnel_actions = NULL;  // Pending tunnel changes required by CLI
 
@@ -104,11 +108,11 @@ config_descriptt config_values[] = {
        CONFIG("log_file", log_filename, STRING),
        CONFIG("pid_file", pid_file, STRING),
        CONFIG("random_device", random_device, STRING),
        CONFIG("log_file", log_filename, STRING),
        CONFIG("pid_file", pid_file, STRING),
        CONFIG("random_device", random_device, STRING),
-       CONFIG("l2tp_secret", l2tpsecret, STRING),
+       CONFIG("l2tp_secret", l2tp_secret, STRING),
+       CONFIG("l2tp_mtu", l2tp_mtu, INT),
        CONFIG("ppp_restart_time", ppp_restart_time, INT),
        CONFIG("ppp_max_configure", ppp_max_configure, INT),
        CONFIG("ppp_max_failure", ppp_max_failure, INT),
        CONFIG("ppp_restart_time", ppp_restart_time, INT),
        CONFIG("ppp_max_configure", ppp_max_configure, INT),
        CONFIG("ppp_max_failure", ppp_max_failure, INT),
-       CONFIG("ppp_mru", ppp_mru, INT),
        CONFIG("primary_dns", default_dns1, IPv4),
        CONFIG("secondary_dns", default_dns2, IPv4),
        CONFIG("primary_radius", radiusserver[0], IPv4),
        CONFIG("primary_dns", default_dns1, IPv4),
        CONFIG("secondary_dns", default_dns2, IPv4),
        CONFIG("primary_radius", radiusserver[0], IPv4),
@@ -979,6 +983,50 @@ int tun_write(uint8_t * data, int size)
        return write(tunfd, data, size);
 }
 
        return write(tunfd, data, size);
 }
 
+// adjust tcp mss to avoid fragmentation (called only for tcp packets with syn set)
+void adjust_tcp_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp)
+{
+       int d = (tcp[12] >> 4) * 4;
+       uint8_t *mss = 0;
+       uint8_t *data;
+
+       if ((tcp[13] & 0x3f) & ~(TCP_FLAG_SYN|TCP_FLAG_ACK)) // only want SYN and SYN,ACK
+               return;
+
+       if (tcp + d > buf + len) // short?
+               return;
+
+       data = tcp + d;
+       tcp += 20;
+
+       while (tcp < data)
+       {
+               if (*tcp == 2 && tcp[1] == 4) // mss option (2), length 4
+               {
+                       mss = tcp + 2;
+                       if (mss + 2 > data) return; // short?
+                       break;
+               }
+
+               if (*tcp == 0) return; // end of options
+               if (*tcp == 1 || !tcp[1]) // no op (one byte), or no length (prevent loop)
+                       tcp++;
+               else
+                       tcp += tcp[1]; // skip over option
+       }
+
+       if (!mss) return; // not found
+       if (ntohl(*(uint16_t *) mss) <= MSS) return; // mss OK
+
+       LOG(5, s, t, "TCP: %s:%u -> %s:%u SYN%s, adjusted mss from %u to %u\n",
+               fmtaddr(*(in_addr_t *)(buf + 12), 0), *(uint16_t *)tcp,
+               fmtaddr(*(in_addr_t *)(buf + 16), 1), *(uint16_t *)(tcp + 2),
+               (tcp[13] & TCP_FLAG_ACK) ? ",ACK" : "",
+               ntohl(*(uint16_t *) mss), MSS);
+
+       // FIXME
+}
+
 // process outgoing (to tunnel) IP
 //
 static void processipout(uint8_t *buf, int len)
 // process outgoing (to tunnel) IP
 //
 static void processipout(uint8_t *buf, int len)
@@ -1086,6 +1134,14 @@ static void processipout(uint8_t *buf, int len)
        if (session[s].filter_out && !ip_filter(buf, len, session[s].filter_out - 1))
                return;
 
        if (session[s].filter_out && !ip_filter(buf, len, session[s].filter_out - 1))
                return;
 
+       // adjust MSS on SYN and SYN,ACK packets with options
+       if ((ntohs(*(uint16_t *) (buf + 6)) & 0x1fff) == 0 && buf[9] == IPPROTO_TCP) // first tcp fragment
+       {
+               int ihl = (buf[0] & 0xf) * 4; // length of IP header
+               if (len >= ihl + 20 && (buf[ihl + 13] & TCP_FLAG_SYN) && ((buf[ihl + 12] >> 4) > 5))
+                       adjust_tcp_mss(s, t, buf, len, buf + ihl);
+       }
+
        if (sp->tbf_out)
        {
                // Are we throttling this session?
        if (sp->tbf_out)
        {
                // Are we throttling this session?
@@ -2009,7 +2065,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
                                        uint16_t orig_len;
 
                                        // handle hidden AVPs
                                        uint16_t orig_len;
 
                                        // handle hidden AVPs
-                                       if (!*config->l2tpsecret)
+                                       if (!*config->l2tp_secret)
                                        {
                                                LOG(1, s, t, "Hidden AVP requested, but no L2TP secret.\n");
                                                fatal = flags;
                                        {
                                                LOG(1, s, t, "Hidden AVP requested, but no L2TP secret.\n");
                                                fatal = flags;
@@ -2382,7 +2438,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
                                        if (amagic == 0) amagic = time_now;
                                        session[s].magic = amagic; // set magic number
                                        session[s].l2tp_flags = aflags; // set flags received
                                        if (amagic == 0) amagic = time_now;
                                        session[s].magic = amagic; // set magic number
                                        session[s].l2tp_flags = aflags; // set flags received
-                                       session[s].mru = config->ppp_mru;
+                                       session[s].mru = PPPMTU; // default
                                        controlnull(t); // ack
 
                                        // start LCP
                                        controlnull(t); // ack
 
                                        // start LCP
@@ -2390,6 +2446,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
                                        sess_local[s].lcp.conf_sent = 1;
                                        sess_local[s].lcp.nak_sent = 0;
                                        sess_local[s].lcp_authtype = config->radius_authprefer;
                                        sess_local[s].lcp.conf_sent = 1;
                                        sess_local[s].lcp.nak_sent = 0;
                                        sess_local[s].lcp_authtype = config->radius_authprefer;
+                                       sess_local[s].ppp_mru = MRU;
                                        session[s].ppp.lcp = RequestSent;
                                        sendlcp(s, t);
 
                                        session[s].ppp.lcp = RequestSent;
                                        sendlcp(s, t);
 
@@ -2535,8 +2592,6 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
                        uint8_t buf[MAXETHER];
                        uint8_t *q;
                        int mru = session[s].mru;
                        uint8_t buf[MAXETHER];
                        uint8_t *q;
                        int mru = session[s].mru;
-
-                       if (!mru) mru = MAXMRU;
                        if (mru > sizeof(buf)) mru = sizeof(buf);
 
                        l += 6;
                        if (mru > sizeof(buf)) mru = sizeof(buf);
 
                        l += 6;
@@ -3501,7 +3556,6 @@ static void initdata(int optdebug, char *optconfig)
        config->ppp_restart_time = 3;
        config->ppp_max_configure = 10;
        config->ppp_max_failure = 5;
        config->ppp_restart_time = 3;
        config->ppp_max_configure = 10;
        config->ppp_max_failure = 5;
-       config->ppp_mru = DEFAULT_MRU;
        strcpy(config->random_device, RANDOMDEVICE);
 
        log_stream = stderr;
        strcpy(config->random_device, RANDOMDEVICE);
 
        log_stream = stderr;
@@ -4171,7 +4225,7 @@ static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challen
        MD5_CTX ctx;
        *challenge_response = NULL;
 
        MD5_CTX ctx;
        *challenge_response = NULL;
 
-       if (!*config->l2tpsecret)
+       if (!*config->l2tp_secret)
        {
                LOG(0, 0, 0, "LNS requested CHAP authentication, but no l2tp secret is defined\n");
                return;
        {
                LOG(0, 0, 0, "LNS requested CHAP authentication, but no l2tp secret is defined\n");
                return;
@@ -4183,7 +4237,7 @@ static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challen
 
        MD5_Init(&ctx);
        MD5_Update(&ctx, &id, 1);
 
        MD5_Init(&ctx);
        MD5_Update(&ctx, &id, 1);
-       MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
+       MD5_Update(&ctx, config->l2tp_secret, strlen(config->l2tp_secret));
        MD5_Update(&ctx, challenge, challenge_length);
        MD5_Final(*challenge_response, &ctx);
 
        MD5_Update(&ctx, challenge, challenge_length);
        MD5_Final(*challenge_response, &ctx);
 
@@ -4250,7 +4304,16 @@ static void update_config()
                setbuf(log_stream, NULL);
        }
 
                setbuf(log_stream, NULL);
        }
 
-       if (config->ppp_mru < 0) config->ppp_mru = 0;
+#define L2TP_HDRS              (20+8+6+4)      // L2TP data encaptulation: ip + udp + l2tp (data) + ppp (inc hdlc)
+#define TCP_HDRS               (20+20)         // TCP encapsulation: ip + tcp
+
+       if (config->l2tp_mtu <= 0)              config->l2tp_mtu = PPPMTU;
+       else if (config->l2tp_mtu < MINMTU)     config->l2tp_mtu = MINMTU;
+       else if (config->l2tp_mtu > MAXMTU)     config->l2tp_mtu = MAXMTU;
+
+       // reset MRU/MSS globals
+       MRU = config->l2tp_mtu - L2TP_HDRS;
+       MSS = MRU - TCP_HDRS;
 
        // Update radius
        config->numradiusservers = 0;
 
        // Update radius
        config->numradiusservers = 0;
@@ -5150,7 +5213,7 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec
        // Compute initial pad
        MD5_Init(&ctx);
        MD5_Update(&ctx, (unsigned char *) &m, 2);
        // Compute initial pad
        MD5_Init(&ctx);
        MD5_Update(&ctx, (unsigned char *) &m, 2);
-       MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
+       MD5_Update(&ctx, config->l2tp_secret, strlen(config->l2tp_secret));
        MD5_Update(&ctx, vector, vec_len);
        MD5_Final(digest, &ctx);
 
        MD5_Update(&ctx, vector, vec_len);
        MD5_Final(digest, &ctx);
 
@@ -5163,7 +5226,7 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec
                if (d >= sizeof(digest))
                {
                        MD5_Init(&ctx);
                if (d >= sizeof(digest))
                {
                        MD5_Init(&ctx);
-                       MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
+                       MD5_Update(&ctx, config->l2tp_secret, strlen(config->l2tp_secret));
                        MD5_Update(&ctx, last, sizeof(digest));
                        MD5_Final(digest, &ctx);
 
                        MD5_Update(&ctx, last, sizeof(digest));
                        MD5_Final(digest, &ctx);
 
index 71f8ddc..577de9c 100644 (file)
--- a/l2tpns.h
+++ b/l2tpns.h
@@ -1,5 +1,5 @@
 // L2TPNS Global Stuff
 // L2TPNS Global Stuff
-// $Id: l2tpns.h,v 1.90 2005-09-15 09:34:49 bodea Exp $
+// $Id: l2tpns.h,v 1.91 2005-09-16 05:04:29 bodea Exp $
 
 #ifndef __L2TPNS_H__
 #define __L2TPNS_H__
 
 #ifndef __L2TPNS_H__
 #define __L2TPNS_H__
 #define T_FREE         (0)             // A tunnel ID that won't ever be used. Mark session as free.
 
 #define        MAXCONTROL      1000            // max length control message we ever send...
 #define T_FREE         (0)             // A tunnel ID that won't ever be used. Mark session as free.
 
 #define        MAXCONTROL      1000            // max length control message we ever send...
-#define MAXMRU         1500            // max MRU as defined by RFC1661
-#define        MAXETHER        (MAXMRU+18)     // max packet we try sending to tun
+#define MINMTU         576             // minimum recommended MTU (rfc1063)
+#define PPPMTU         1500            // default PPP MTU
+#define MAXMTU         2600            // arbitrary maximum MTU
+#define        MAXETHER        (MAXMTU+18)     // max packet we try sending to tun
 #define        MAXTEL          96              // telephone number
 #define MAXUSER                128             // username
 #define MAXPASS                128             // password
 #define        MAXTEL          96              // telephone number
 #define MAXUSER                128             // username
 #define MAXPASS                128             // password
@@ -45,7 +47,6 @@
 #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 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 DEFAULT_MRU    1452            // maximum packet size to avoid fragmentation when LNS ethernet MTU is 1500
 
 // Constants
 #ifndef ETCDIR
 
 // Constants
 #ifndef ETCDIR
@@ -293,6 +294,9 @@ typedef struct
        // authentication to use
        int lcp_authtype;
 
        // authentication to use
        int lcp_authtype;
 
+       // our MRU
+       uint16_t ppp_mru;
+
        // DoS prevention
        clockt last_packet_out;
        uint32_t packets_out;
        // DoS prevention
        clockt last_packet_out;
        uint32_t packets_out;
@@ -512,14 +516,15 @@ typedef struct
 
        char            tundevice[10];                  // tun device name
        char            log_filename[128];
 
        char            tundevice[10];                  // tun device name
        char            log_filename[128];
-       char            l2tpsecret[64];
+
+       char            l2tp_secret[64];                // L2TP shared secret
+       int             l2tp_mtu;                       // MTU of interface used for L2TP
 
        char            random_device[256];             // random device path, defaults to RANDOMDEVICE
 
        int             ppp_restart_time;               // timeout for PPP restart
        int             ppp_max_configure;              // max lcp configure requests to send
        int             ppp_max_failure;                // max lcp configure naks to send
 
        char            random_device[256];             // random device path, defaults to RANDOMDEVICE
 
        int             ppp_restart_time;               // timeout for PPP restart
        int             ppp_max_configure;              // max lcp configure requests to send
        int             ppp_max_failure;                // max lcp configure naks to send
-       int             ppp_mru;                        // MRU to advertise
 
        char            radiussecret[64];
        int             radius_accounting;
 
        char            radiussecret[64];
        int             radius_accounting;
@@ -704,6 +709,8 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error);
 void filter_session(sessionidt s, int filter_in, int filter_out);
 void send_garp(in_addr_t ip);
 void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
 void filter_session(sessionidt s, int filter_in, int filter_out);
 void send_garp(in_addr_t ip);
 void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
+int tun_write(uint8_t *data, int size);
+void adjust_tcp_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp);
 void sendipcp(sessionidt s, tunnelidt t);
 void sendipv6cp(sessionidt s, tunnelidt t);
 void processudp(uint8_t *buf, int len, struct sockaddr_in *addr);
 void sendipcp(sessionidt s, tunnelidt t);
 void sendipv6cp(sessionidt s, tunnelidt t);
 void processudp(uint8_t *buf, int len, struct sockaddr_in *addr);
@@ -770,7 +777,6 @@ extern char main_quit;
 extern uint32_t last_id;
 extern struct Tstats *_statistics;
 extern in_addr_t my_address;
 extern uint32_t last_id;
 extern struct Tstats *_statistics;
 extern in_addr_t my_address;
-extern int tun_write(uint8_t *data, int size);
 extern int clifd;
 extern int epollfd;
 
 extern int clifd;
 extern int epollfd;
 
@@ -790,6 +796,9 @@ struct event_data {
 
 #define TIME (config->current_time)
 
 
 #define TIME (config->current_time)
 
+extern uint16_t MRU;
+extern uint16_t MSS;
+
 // macros for handling help in cli commands
 #define CLI_HELP_REQUESTED     (argc > 0 && argv[argc-1][strlen(argv[argc-1])-1] == '?')
 #define CLI_HELP_NO_ARGS       (argc > 1 || argv[0][1]) ? CLI_OK : cli_arg_help(cli, 1, NULL)
 // macros for handling help in cli commands
 #define CLI_HELP_REQUESTED     (argc > 0 && argv[argc-1][strlen(argv[argc-1])-1] == '?')
 #define CLI_HELP_NO_ARGS       (argc > 1 || argv[0][1]) ? CLI_OK : cli_arg_help(cli, 1, NULL)
index 2acc203..fc0141b 100644 (file)
@@ -43,5 +43,5 @@ rm -rf %{buildroot}
 %attr(644,root,root) /usr/share/man/man[58]/*
 
 %changelog
 %attr(644,root,root) /usr/share/man/man[58]/*
 
 %changelog
-* Thu Sep 15 2005 Brendan O'Dea <bod@optus.net> 2.1.6-1
+* Fri Sep 16 2005 Brendan O'Dea <bod@optus.net> 2.1.6-1
 - 2.1.6 release, see /usr/share/doc/l2tpns-2.1.6/Changes
 - 2.1.6 release, see /usr/share/doc/l2tpns-2.1.6/Changes
diff --git a/ppp.c b/ppp.c
index 9f0a713..fd5f460 100644 (file)
--- a/ppp.c
+++ b/ppp.c
@@ -1,6 +1,6 @@
 // L2TPNS PPP Stuff
 
 // L2TPNS PPP Stuff
 
-char const *cvs_id_ppp = "$Id: ppp.c,v 1.81 2005-09-15 09:34:49 bodea Exp $";
+char const *cvs_id_ppp = "$Id: ppp.c,v 1.82 2005-09-16 05:04:29 bodea Exp $";
 
 #include <stdio.h>
 #include <string.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -449,8 +449,6 @@ static void ppp_code_rej(sessionidt s, tunnelidt t, uint16_t proto,
 {
        uint8_t *q;
        int mru = session[s].mru;
 {
        uint8_t *q;
        int mru = session[s].mru;
-
-       if (!mru) mru = MAXMRU;
        if (mru > size) mru = size;
 
        l += 4;
        if (mru > size) mru = size;
 
        l += 4;
@@ -577,18 +575,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                        switch (type)
                        {
                                case 1: // Maximum-Receive-Unit
                        switch (type)
                        {
                                case 1: // Maximum-Receive-Unit
-                                       {
-                                               uint16_t mru = ntohs(*(uint16_t *)(o + 2));
-                                               if (!config->ppp_mru || mru <= config->ppp_mru)
-                                               {
-                                                       session[s].mru = mru;
-                                                       break;
-                                               }
-
-                                               LOG(3, s, t, "    Remote requesting MRU of %u.  Rejecting.\n", mru);
-                                               mru = htons(config->ppp_mru);
-                                               q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, (uint8_t *) &mru, sizeof(mru));
-                                       }
+                                       session[s].mru = ntohs(*(uint16_t *)(o + 2));
                                        break;
 
                                case 2: // Async-Control-Character-Map
                                        break;
 
                                case 2: // Async-Control-Character-Map
@@ -749,13 +736,12 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
                                case 1: // Maximum-Receive-Unit
                                        if (*p == ConfigNak)
                                        {
                                case 1: // Maximum-Receive-Unit
                                        if (*p == ConfigNak)
                                        {
-                                               session[s].mru = 0;
-                                               LOG(3, s, t, "    Remote requested MRU of %u; removing option\n",
-                                                       ntohs(*(uint16_t *)(o + 2)));
+                                               sess_local[s].ppp_mru = ntohs(*(uint16_t *)(o + 2));
+                                               LOG(3, s, t, "    Remote requested MRU of %u\n", sess_local[s].ppp_mru);
                                        }
                                        else
                                        {
                                        }
                                        else
                                        {
-                                               session[s].mru = 0;
+                                               sess_local[s].ppp_mru = 0;
                                                LOG(3, s, t, "    Remote rejected MRU negotiation\n");
                                        }
 
                                                LOG(3, s, t, "    Remote rejected MRU negotiation\n");
                                        }
 
@@ -1349,6 +1335,13 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
 
        LOG_HEX(5, "IP", p, l);
 
 
        LOG_HEX(5, "IP", p, l);
 
+       if (l < 20 || l < ntohl(*(uint32_t *)(p + 2)))
+       {
+               LOG(1, s, t, "IP packet too short %d\n", l);
+               STAT(tunnel_rx_errors);
+               return ;
+       }
+
        ip = ntohl(*(uint32_t *)(p + 12));
 
        if (l > MAXETHER)
        ip = ntohl(*(uint32_t *)(p + 12));
 
        if (l > MAXETHER)
@@ -1372,6 +1365,14 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
        if (session[s].filter_in && !ip_filter(p, l, session[s].filter_in - 1))
                return;
 
        if (session[s].filter_in && !ip_filter(p, l, session[s].filter_in - 1))
                return;
 
+       // adjust MSS on SYN and SYN,ACK packets with options
+       if ((ntohs(*(uint16_t *) (p + 6)) & 0x1fff) == 0 && p[9] == IPPROTO_TCP) // first tcp fragment
+       {
+               int ihl = (p[0] & 0xf) * 4; // length of IP header
+               if (l >= ihl + 20 && (p[ihl + 13] & TCP_FLAG_SYN) && ((p[ihl + 12] >> 4) > 5))
+                       adjust_tcp_mss(s, t, p, l, p + ihl);
+       }
+
        // Add on the tun header
        p -= 4;
        *(uint32_t *) p = htonl(PKTIP);
        // Add on the tun header
        p -= 4;
        *(uint32_t *) p = htonl(PKTIP);
@@ -1819,10 +1820,10 @@ void sendlcp(sessionidt s, tunnelidt t)
 
        l += 2; //Save space for length
 
 
        l += 2; //Save space for length
 
-       if (session[s].mru)
+       if (sess_local[s].ppp_mru)
        {
                *l++ = 1; *l++ = 4; // Maximum-Receive-Unit (length 4)
        {
                *l++ = 1; *l++ = 4; // Maximum-Receive-Unit (length 4)
-               *(uint16_t *) l = htons(session[s].mru); l += 2;
+               *(uint16_t *) l = htons(sess_local[s].ppp_mru); l += 2;
        }
 
        if (authtype)
        }
 
        if (authtype)