- 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.
This commit is contained in:
Brendan O'Dea 2005-09-16 05:04:28 +00:00
parent 0c678c5a03
commit bde7904f92
8 changed files with 132 additions and 55 deletions

View file

@ -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. - Any traffic on a tunnel resets lastrec, not just control messages.
- Use a unique identifier for LCP. - Use a unique identifier for LCP.
- Fix Code-Reject/Protocol-Reject. - 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 * Sat Sep 3 2005 Brendan O'Dea <bod@optus.net> 2.1.5
- Avoid Code-Reject loop. - Avoid Code-Reject loop.

View file

@ -185,6 +185,11 @@ the same as the LAC, or authentication will fail. Only actually be
used if the LAC requests authentication. used if the LAC requests authentication.
</LI> </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> <LI><B>ppp_restart_time</B> (int)<BR>
<B>ppp_max_configure</B> (int)<BR> <B>ppp_max_configure</B> (int)<BR>
<B>ppp_max_failure</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>. <a href="ftp://ftp.rfc-editor.org/in-notes/rfc1661.txt">RFC1661</a>.
</LI> </LI>
<LI><B>ppp_mru</B> (int)<BR>
PPP link MRU (default: 1452).
</LI>
<LI><B>primary_dns</B> (ip address) <LI><B>primary_dns</B> (ip address)
<LI><B>secondary_dns</B> (ip address)<BR> <LI><B>secondary_dns</B> (ip address)<BR>
Whenever a PPP connection is established, DNS servers will be sent to the Whenever a PPP connection is established, DNS servers will be sent to the

View file

@ -2,7 +2,7 @@
.de Id .de Id
.ds Dt \\$4 \\$5 .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" .TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions"
.SH NAME .SH NAME
startup\-config \- configuration file for l2tpns 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 will fail. Only actually be used if the LAC requests
authentication. authentication.
.TP .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 .B ppp_restart_time
Restart timer for PPP protocol negotiation in seconds (default: 3). Restart timer for PPP protocol negotiation in seconds (default: 3).
.TP .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 Number of Configure-Nak requests to send before sending a
Configure-Reject (default: 5). Configure-Reject (default: 5).
.TP .TP
.B ppp_mru
PPP link MRU (default: 1452).
.TP
.BR primary_dns , " secondary_dns" .BR primary_dns , " secondary_dns"
Whenever a PPP connection is established, DNS servers will be sent to the 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 user, both a primary and a secondary. If either is set to 0.0.0.0, then that

View file

@ -10,14 +10,14 @@ set pid_file "/var/run/l2tpns.pid"
# Shared secret with LAC # Shared secret with LAC
set l2tp_secret "secret" set l2tp_secret "secret"
# MTU of interface for L2TP traffic
#set l2tp_mtu 1500
# PPP counter and timer values # PPP counter and timer values
#set ppp_restart_time 3 #set ppp_restart_time 3
#set ppp_max_configure 10 #set ppp_max_configure 10
#set ppp_max_failure 5 #set ppp_max_failure 5
# Link MRU
#set ppp_mru 1452
# Only 2 DNS server entries are allowed # Only 2 DNS server entries are allowed
set primary_dns 10.0.0.1 set primary_dns 10.0.0.1
set secondary_dns 10.0.0.2 set secondary_dns 10.0.0.2

View file

@ -4,7 +4,7 @@
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
// vim: sw=8 ts=8 // 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 <arpa/inet.h>
#include <assert.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). 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 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_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_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("log_file", log_filename, STRING),
CONFIG("pid_file", pid_file, STRING), CONFIG("pid_file", pid_file, STRING),
CONFIG("random_device", random_device, 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_restart_time", ppp_restart_time, INT),
CONFIG("ppp_max_configure", ppp_max_configure, INT), CONFIG("ppp_max_configure", ppp_max_configure, INT),
CONFIG("ppp_max_failure", ppp_max_failure, INT), CONFIG("ppp_max_failure", ppp_max_failure, INT),
CONFIG("ppp_mru", ppp_mru, INT),
CONFIG("primary_dns", default_dns1, IPv4), CONFIG("primary_dns", default_dns1, IPv4),
CONFIG("secondary_dns", default_dns2, IPv4), CONFIG("secondary_dns", default_dns2, IPv4),
CONFIG("primary_radius", radiusserver[0], 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 // process outgoing (to tunnel) IP
// //
static void processipout(uint8_t *buf, int len) 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)) if (session[s].filter_out && !ip_filter(buf, len, session[s].filter_out - 1))
return; 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) if (sp->tbf_out)
{ {
// Are we throttling this session? // Are we throttling this session?
@ -2009,7 +2065,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
uint16_t orig_len; uint16_t orig_len;
// handle hidden AVPs // handle hidden AVPs
if (!*config->l2tpsecret) if (!*config->l2tp_secret)
{ {
LOG(1, s, t, "Hidden AVP requested, but no L2TP secret.\n"); LOG(1, s, t, "Hidden AVP requested, but no L2TP secret.\n");
fatal = flags; fatal = flags;
@ -2382,7 +2438,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
if (amagic == 0) amagic = time_now; if (amagic == 0) amagic = time_now;
session[s].magic = amagic; // set magic number session[s].magic = amagic; // set magic number
session[s].l2tp_flags = aflags; // set flags received session[s].l2tp_flags = aflags; // set flags received
session[s].mru = config->ppp_mru; session[s].mru = PPPMTU; // default
controlnull(t); // ack controlnull(t); // ack
// start LCP // 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.conf_sent = 1;
sess_local[s].lcp.nak_sent = 0; sess_local[s].lcp.nak_sent = 0;
sess_local[s].lcp_authtype = config->radius_authprefer; sess_local[s].lcp_authtype = config->radius_authprefer;
sess_local[s].ppp_mru = MRU;
session[s].ppp.lcp = RequestSent; session[s].ppp.lcp = RequestSent;
sendlcp(s, t); sendlcp(s, t);
@ -2535,8 +2592,6 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
uint8_t buf[MAXETHER]; uint8_t buf[MAXETHER];
uint8_t *q; uint8_t *q;
int mru = session[s].mru; int mru = session[s].mru;
if (!mru) mru = MAXMRU;
if (mru > sizeof(buf)) mru = sizeof(buf); if (mru > sizeof(buf)) mru = sizeof(buf);
l += 6; l += 6;
@ -3501,7 +3556,6 @@ static void initdata(int optdebug, char *optconfig)
config->ppp_restart_time = 3; config->ppp_restart_time = 3;
config->ppp_max_configure = 10; config->ppp_max_configure = 10;
config->ppp_max_failure = 5; config->ppp_max_failure = 5;
config->ppp_mru = DEFAULT_MRU;
strcpy(config->random_device, RANDOMDEVICE); strcpy(config->random_device, RANDOMDEVICE);
log_stream = stderr; log_stream = stderr;
@ -4171,7 +4225,7 @@ static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challen
MD5_CTX ctx; MD5_CTX ctx;
*challenge_response = NULL; *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"); LOG(0, 0, 0, "LNS requested CHAP authentication, but no l2tp secret is defined\n");
return; return;
@ -4183,7 +4237,7 @@ static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challen
MD5_Init(&ctx); MD5_Init(&ctx);
MD5_Update(&ctx, &id, 1); 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_Update(&ctx, challenge, challenge_length);
MD5_Final(*challenge_response, &ctx); 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 // Update radius
config->numradiusservers = 0; 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 // Compute initial pad
MD5_Init(&ctx); MD5_Init(&ctx);
MD5_Update(&ctx, (unsigned char *) &m, 2); 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_Update(&ctx, vector, vec_len);
MD5_Final(digest, &ctx); 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)) if (d >= sizeof(digest))
{ {
MD5_Init(&ctx); 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_Update(&ctx, last, sizeof(digest));
MD5_Final(digest, &ctx); MD5_Final(digest, &ctx);

View file

@ -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__ #ifndef __L2TPNS_H__
#define __L2TPNS_H__ #define __L2TPNS_H__
@ -31,8 +31,10 @@
#define T_FREE (0) // A tunnel ID that won't ever be used. Mark session as free. #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 MAXCONTROL 1000 // max length control message we ever send...
#define MAXMRU 1500 // max MRU as defined by RFC1661 #define MINMTU 576 // minimum recommended MTU (rfc1063)
#define MAXETHER (MAXMRU+18) // max packet we try sending to tun #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 MAXTEL 96 // telephone number
#define MAXUSER 128 // username #define MAXUSER 128 // username
#define MAXPASS 128 // password #define MAXPASS 128 // password
@ -45,7 +47,6 @@
#define ECHO_TIMEOUT 60 // 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 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 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 // Constants
#ifndef ETCDIR #ifndef ETCDIR
@ -293,6 +294,9 @@ typedef struct
// authentication to use // authentication to use
int lcp_authtype; int lcp_authtype;
// our MRU
uint16_t ppp_mru;
// DoS prevention // DoS prevention
clockt last_packet_out; clockt last_packet_out;
uint32_t packets_out; uint32_t packets_out;
@ -512,14 +516,15 @@ typedef struct
char tundevice[10]; // tun device name char tundevice[10]; // tun device name
char log_filename[128]; 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 char random_device[256]; // random device path, defaults to RANDOMDEVICE
int ppp_restart_time; // timeout for PPP restart int ppp_restart_time; // timeout for PPP restart
int ppp_max_configure; // max lcp configure requests to send int ppp_max_configure; // max lcp configure requests to send
int ppp_max_failure; // max lcp configure naks to send int ppp_max_failure; // max lcp configure naks to send
int ppp_mru; // MRU to advertise
char radiussecret[64]; char radiussecret[64];
int radius_accounting; 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 filter_session(sessionidt s, int filter_in, int filter_out);
void send_garp(in_addr_t ip); void send_garp(in_addr_t ip);
void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t); 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 sendipcp(sessionidt s, tunnelidt t);
void sendipv6cp(sessionidt s, tunnelidt t); void sendipv6cp(sessionidt s, tunnelidt t);
void processudp(uint8_t *buf, int len, struct sockaddr_in *addr); 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 uint32_t last_id;
extern struct Tstats *_statistics; extern struct Tstats *_statistics;
extern in_addr_t my_address; extern in_addr_t my_address;
extern int tun_write(uint8_t *data, int size);
extern int clifd; extern int clifd;
extern int epollfd; 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 // macros for handling help in cli commands
#define CLI_HELP_REQUESTED (argc > 0 && argv[argc-1][strlen(argv[argc-1])-1] == '?') #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) #define CLI_HELP_NO_ARGS (argc > 1 || argv[0][1]) ? CLI_OK : cli_arg_help(cli, 1, NULL)

View file

@ -43,5 +43,5 @@ rm -rf %{buildroot}
%attr(644,root,root) /usr/share/man/man[58]/* %attr(644,root,root) /usr/share/man/man[58]/*
%changelog %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

43
ppp.c
View file

@ -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 <stdio.h>
#include <string.h> #include <string.h>
@ -449,8 +449,6 @@ static void ppp_code_rej(sessionidt s, tunnelidt t, uint16_t proto,
{ {
uint8_t *q; uint8_t *q;
int mru = session[s].mru; int mru = session[s].mru;
if (!mru) mru = MAXMRU;
if (mru > size) mru = size; if (mru > size) mru = size;
l += 4; l += 4;
@ -577,18 +575,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
switch (type) switch (type)
{ {
case 1: // Maximum-Receive-Unit case 1: // Maximum-Receive-Unit
{ session[s].mru = ntohs(*(uint16_t *)(o + 2));
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));
}
break; break;
case 2: // Async-Control-Character-Map 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 case 1: // Maximum-Receive-Unit
if (*p == ConfigNak) if (*p == ConfigNak)
{ {
session[s].mru = 0; sess_local[s].ppp_mru = ntohs(*(uint16_t *)(o + 2));
LOG(3, s, t, " Remote requested MRU of %u; removing option\n", LOG(3, s, t, " Remote requested MRU of %u\n", sess_local[s].ppp_mru);
ntohs(*(uint16_t *)(o + 2)));
} }
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)); ip = ntohl(*(uint32_t *)(p + 12));
if (l > MAXETHER) 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)) if (session[s].filter_in && !ip_filter(p, l, session[s].filter_in - 1))
return; 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 // Add on the tun header
p -= 4; p -= 4;
*(uint32_t *) p = htonl(PKTIP); *(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)