Merge branch 'upstream'
This commit is contained in:
commit
fbd2194031
30 changed files with 5124 additions and 557 deletions
29
Changes
29
Changes
|
|
@ -1,16 +1,27 @@
|
|||
* Fri Dec 1 2006 Brendan O'Dea <bod@optus.net> 2.1.21
|
||||
- Security: Rhys Kidd identified a vulnerability in the handling of
|
||||
heartbeat packets. Drop oversize heartbeat packets.
|
||||
* Thu Jan 20 2011 Brendan O'Dea <bod@optus.net> 2.2.x
|
||||
- Apply MLPPP patch from Muhammad Tayseer Alquoatli.
|
||||
- Apply patch from Michael O to avoid sending multiple CDNs.
|
||||
- Apply patch from Cyril Elkaim to fix an issue with MacOS.
|
||||
- Apply patch from Geoffrey D. Bennett to fix retry of control packets.
|
||||
|
||||
* Thu Aug 3 2006 Brendan O'Dea <bod@optus.net> 2.1.20
|
||||
- Fix sign problem with reporting of unknown VSAs.
|
||||
- Allow DNS servers to be specified either using the old or new
|
||||
vendor-specific Ascend formats.
|
||||
|
||||
* Fri Jun 23 2006 Brendan O'Dea <bod@optus.net> 2.1.19
|
||||
* Mon Dec 18 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.
|
||||
- Kludge around problem with Netgear DM602 authentication.
|
||||
- Add session/idle timeouts (Graham Maltby).
|
||||
- Use result code AVP to set Acct-Terminate-Cause is disconnect cause
|
||||
AVP is not present.
|
||||
- Add radius_bind_{min,max} to simplify firewalling of RADIUS ports.
|
||||
- Fix sign problem with reporting of unknown RADIUS VSAs.
|
||||
- Allow DNS servers to be specified either using the old or new
|
||||
vendor-specific Ascend formats.
|
||||
- Security [CVE-2006-5873]: Rhys Kidd identified a vulnerability in the
|
||||
handling of heartbeat packets. Drop oversize heartbeat packets.
|
||||
- Don't send interim records before session start (Daryl Tester).
|
||||
- Add "shutdown" and "reload" CLI commands (Daryl Tester).
|
||||
|
||||
* Tue Apr 18 2006 Brendan O'Dea <bod@optus.net> 2.1.18
|
||||
- Don't shutdown on TerminateReq, wait for CDN.
|
||||
|
|
|
|||
4
Docs/common/config.xml
Normal file
4
Docs/common/config.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:param name="html.stylesheet" select="'../common/docbook.css'"/>
|
||||
</xsl:stylesheet>
|
||||
69
Docs/common/docbook.css
Normal file
69
Docs/common/docbook.css
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
div.article > div.titlepage {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.abstract {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: sans-serif;
|
||||
font-weight: bolder;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.sect2, .sect2, .sect3, .sect4 {
|
||||
margin-left: 2%;
|
||||
margin-right: 2%;
|
||||
}
|
||||
|
||||
.sect2 .title, .sect2 .title, .sect3 .title, .sect4 .title {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.synopsis, .screen, .programlisting {
|
||||
font-family: monospace;
|
||||
font-size: 1em;
|
||||
display: block;
|
||||
padding: 10px;
|
||||
border: 1px solid #bbb;
|
||||
background-color: #eee;
|
||||
color: #000;
|
||||
overflow: auto;
|
||||
border-radius: 2.5px;
|
||||
-moz-border-radius: 2.5px;
|
||||
margin: 0.5em 2em;
|
||||
}
|
||||
|
||||
.programlisting em {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.hanging-indent {
|
||||
margin-left: 4em;
|
||||
text-indent: -2em;
|
||||
}
|
||||
|
||||
table {
|
||||
margin: 0.5em 2em;
|
||||
border: 1px solid #bbb;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
thead {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
td table {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
td {
|
||||
border: 1px solid #bbb;
|
||||
}
|
||||
2163
Docs/manual/manual.xml
Normal file
2163
Docs/manual/manual.xml
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -2,7 +2,7 @@
|
|||
.de Id
|
||||
.ds Dt \\$4 \\$5
|
||||
..
|
||||
.Id $Id: startup-config.5,v 1.15 2005/09/16 05:04:31 bodea Exp $
|
||||
.Id $Id: startup-config.5,v 1.18 2006/07/01 12:40:17 bodea Exp $
|
||||
.TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions"
|
||||
.SH NAME
|
||||
startup\-config \- configuration file for l2tpns
|
||||
|
|
@ -77,17 +77,17 @@ 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
|
||||
.BR primary_dns , " secondary_dns"
|
||||
.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
|
||||
one will not be sent.
|
||||
.TP
|
||||
.BR primary_radius , " secondary_radius"
|
||||
.BR primary_radius ", " secondary_radius
|
||||
Sets the RADIUS servers used for both authentication and accounting.
|
||||
If the primary server does not respond, then the secondary RADIUS
|
||||
server will be tried.
|
||||
.TP
|
||||
.BR primary_radius_port , " secondary_radius_port"
|
||||
.BR primary_radius_port ", " secondary_radius_port
|
||||
Sets the authentication ports for the primary and secondary RADIUS
|
||||
servers. The accounting port is one more than the authentication
|
||||
port. If no ports are given, authentication defaults to 1645, and
|
||||
|
|
@ -118,11 +118,19 @@ A comma separated list of supported RADIUS authentication methods
|
|||
Port for DAE RADIUS (Packet of Death/Disconnect, Change of Authorization)
|
||||
requests (default: 3799).
|
||||
.TP
|
||||
.BR radius_bind_min ", " radius_bind_max
|
||||
Define a port range in which to bind sockets used to send and receive
|
||||
RADIUS packets. Must be at least RADIUS_FDS (64) wide. Simplifies
|
||||
firewalling of RADIUS ports (default: dynamically assigned).
|
||||
.TP
|
||||
.B allow_duplicate_users
|
||||
Allow multiple logins with the same username. If false (the default),
|
||||
any prior session with the same username will be dropped when a new
|
||||
session is established.
|
||||
.TP
|
||||
.B guest_account
|
||||
Allow multiple logins matching this specific username.
|
||||
.TP
|
||||
.B bind_address
|
||||
When the tun interface is created, it is assigned the address
|
||||
specified here. If no address is given, 1.1.1.1 is used. Packets
|
||||
|
|
@ -149,10 +157,6 @@ session requires two buckets (in and out).
|
|||
If set to a directory, then every 5 minutes the current usage for
|
||||
every connected use will be dumped to a file in this directory.
|
||||
.TP
|
||||
.B setuid
|
||||
After starting up and binding the interface, change UID to this. This
|
||||
doesn't work properly.
|
||||
.TP
|
||||
.B dump_speed
|
||||
If set to true, then the current bandwidth utilization will be logged
|
||||
every second. Even if this is disabled, you can see this information
|
||||
|
|
|
|||
1086
Docs/vpn/practical-vpns.xml
Normal file
1086
Docs/vpn/practical-vpns.xml
Normal file
File diff suppressed because it is too large
Load diff
BIN
Docs/vpn/site-to-site-vpn.png
Normal file
BIN
Docs/vpn/site-to-site-vpn.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
BIN
Docs/vpn/tunneling-process.png
Normal file
BIN
Docs/vpn/tunneling-process.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 134 KiB |
BIN
Docs/vpn/vpn-deployment.png
Normal file
BIN
Docs/vpn/vpn-deployment.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
BIN
Docs/vpn/vpn-process.png
Normal file
BIN
Docs/vpn/vpn-process.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 217 KiB |
6
THANKS
6
THANKS
|
|
@ -12,7 +12,7 @@ Yuri <yuri@actcom.net.il>
|
|||
Juergen Kammer <j.kammer@eurodata.de>
|
||||
Simon Talbot <simont@nse.co.uk>
|
||||
Jonathan McDowell <noodles@earth.li>
|
||||
Bjørn Augestad <augestad@users.sourceforge.net>
|
||||
Bjørn Augestad <augestad@users.sourceforge.net>
|
||||
Roberto Chostakovis <rchostakovis@users.sourceforge.net>
|
||||
Jordan Hrycaj <jordan@mjh.teddy-net.com>
|
||||
Vladislav Bjelic <vladislav@gmail.com>
|
||||
|
|
@ -26,4 +26,8 @@ Jon Morby <jon@fido.net>
|
|||
Paul Martin <pm@zetnet.net>
|
||||
Jonathan Yarden <jyarden@bluegrass.net>
|
||||
Patrick Cole <z@amused.net>
|
||||
Khaled Al Hamwi <kh.alhamwi@gmail.com>
|
||||
Graham Maltby <gmaltby+l2tpns@iig.com.au>
|
||||
Rhys Kidd <rhys.kidd@staff.westnet.com.au>
|
||||
Muhammad Tayseer Alquoatli <idoit.ief@gmail.com>
|
||||
Cyril Elkaim <cyrelk@users.sourceforge.net>
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
* lcp:interface-config#2=service-policy output N
|
||||
*
|
||||
* throttle=N
|
||||
* throttle=yes (use throttle_rate from config)
|
||||
* throttle=yes (use throttle_speed from config)
|
||||
* throttle=no
|
||||
*/
|
||||
|
||||
char const *cvs_id = "$Id: autothrottle.c,v 1.16 2005/10/11 09:04:53 bodea Exp $";
|
||||
char const *cvs_id = "$Id: autothrottle.c,v 1.17 2006/05/18 14:40:31 bodea Exp $";
|
||||
|
||||
int plugin_api_version = PLUGIN_API_VERSION;
|
||||
static struct pluginfuncs *f = 0;
|
||||
|
|
|
|||
42
cli.c
42
cli.c
|
|
@ -1,8 +1,8 @@
|
|||
// L2TPNS Command Line Interface
|
||||
// vim: sw=8 ts=8
|
||||
|
||||
char const *cvs_name = "$Name: release_2_1_21 $";
|
||||
char const *cvs_id_cli = "$Id: cli.c,v 1.71 2005/12/06 09:43:42 bodea Exp $";
|
||||
char const *cvs_name = "$Name: $";
|
||||
char const *cvs_id_cli = "$Id: cli.c,v 1.76 2006/12/18 12:08:28 bodea Exp $";
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
|
@ -36,6 +36,7 @@ char const *cvs_id_cli = "$Id: cli.c,v 1.71 2005/12/06 09:43:42 bodea Exp $";
|
|||
#endif
|
||||
|
||||
extern tunnelt *tunnel;
|
||||
extern bundlet *bundle;
|
||||
extern sessiont *session;
|
||||
extern radiust *radius;
|
||||
extern ippoolt *ip_address_pool;
|
||||
|
|
@ -99,6 +100,9 @@ static int cmd_set(struct cli_def *cli, char *command, char **argv, int argc);
|
|||
static int cmd_load_plugin(struct cli_def *cli, char *command, char **argv, int argc);
|
||||
static int cmd_remove_plugin(struct cli_def *cli, char *command, char **argv, int argc);
|
||||
static int cmd_uptime(struct cli_def *cli, char *command, char **argv, int argc);
|
||||
static int cmd_shutdown(struct cli_def *cli, char *command, char **argv, int argc);
|
||||
static int cmd_reload(struct cli_def *cli, char *command, char **argv, int argc);
|
||||
|
||||
|
||||
static int regular_stuff(struct cli_def *cli);
|
||||
|
||||
|
|
@ -175,6 +179,8 @@ void init_cli(char *hostname)
|
|||
#endif
|
||||
|
||||
cli_register_command(cli, NULL, "uptime", cmd_uptime, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show uptime and bandwidth utilisation");
|
||||
cli_register_command(cli, NULL, "shutdown", cmd_shutdown, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Shutdown l2tpns daemon and exit");
|
||||
cli_register_command(cli, NULL, "reload", cmd_reload, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Reload configuration");
|
||||
|
||||
c = cli_register_command(cli, NULL, "write", NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL);
|
||||
cli_register_command(cli, c, "memory", cmd_write_memory, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Save the running config to flash");
|
||||
|
|
@ -268,7 +274,7 @@ void init_cli(char *hostname)
|
|||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
clifd = socket(PF_INET, SOCK_STREAM, 6);
|
||||
clifd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
setsockopt(clifd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
{
|
||||
int flags;
|
||||
|
|
@ -425,6 +431,18 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
|
|||
cli_print(cli, "\tUnique SID:\t%u", session[s].unique_id);
|
||||
cli_print(cli, "\tOpened:\t\t%u seconds", session[s].opened ? abs(time_now - session[s].opened) : 0);
|
||||
cli_print(cli, "\tIdle time:\t%u seconds", session[s].last_packet ? abs(time_now - session[s].last_packet) : 0);
|
||||
if (session[s].session_timeout)
|
||||
{
|
||||
clockt opened = session[s].opened;
|
||||
if (session[s].bundle && bundle[session[s].bundle].num_of_links > 1)
|
||||
opened = bundle[session[s].bundle].online_time;
|
||||
|
||||
cli_print(cli, "\tSess Timeout:\t%u seconds", session[s].session_timeout - (opened ? abs(time_now - opened) : 0));
|
||||
}
|
||||
|
||||
if (session[s].idle_timeout)
|
||||
cli_print(cli, "\tIdle Timeout:\t%u seconds", session[s].idle_timeout - (session[s].last_data ? abs(time_now - session[s].last_data) : 0));
|
||||
|
||||
cli_print(cli, "\tBytes In/Out:\t%u/%u", session[s].cout, session[s].cin);
|
||||
cli_print(cli, "\tPkts In/Out:\t%u/%u", session[s].pout, session[s].pin);
|
||||
cli_print(cli, "\tMRU:\t\t%d", session[s].mru);
|
||||
|
|
@ -3064,3 +3082,21 @@ static int cmd_show_access_list(struct cli_def *cli, char *command, char **argv,
|
|||
|
||||
return CLI_OK;
|
||||
}
|
||||
|
||||
static int cmd_shutdown(struct cli_def *cli, char *command, char **argv, int argc)
|
||||
{
|
||||
if (CLI_HELP_REQUESTED)
|
||||
return CLI_HELP_NO_ARGS;
|
||||
|
||||
kill(getppid(), SIGQUIT);
|
||||
return CLI_OK;
|
||||
}
|
||||
|
||||
static int cmd_reload(struct cli_def *cli, char *command, char **argv, int argc)
|
||||
{
|
||||
if (CLI_HELP_REQUESTED)
|
||||
return CLI_HELP_NO_ARGS;
|
||||
|
||||
kill(getppid(), SIGHUP);
|
||||
return CLI_OK;
|
||||
}
|
||||
|
|
|
|||
167
cluster.c
167
cluster.c
|
|
@ -1,6 +1,6 @@
|
|||
// L2TPNS Clustering Stuff
|
||||
|
||||
char const *cvs_id_cluster = "$Id: cluster.c,v 1.50.2.1 2006/12/02 14:09:14 bodea Exp $";
|
||||
char const *cvs_id_cluster = "$Id: cluster.c,v 1.55 2009/12/08 14:49:28 bodea Exp $";
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -42,6 +42,7 @@ extern int cluster_sockfd; // The filedescriptor for the cluster communications
|
|||
|
||||
in_addr_t my_address = 0; // The network address of my ethernet port.
|
||||
static int walk_session_number = 0; // The next session to send when doing the slow table walk.
|
||||
static int walk_bundle_number = 0; // The next bundle to send when doing the slow table walk.
|
||||
static int walk_tunnel_number = 0; // The next tunnel to send when doing the slow table walk.
|
||||
int forked = 0; // Sanity check: CLI must not diddle with heartbeat table
|
||||
|
||||
|
|
@ -85,6 +86,7 @@ int cluster_init()
|
|||
int opt;
|
||||
|
||||
config->cluster_undefined_sessions = MAXSESSION-1;
|
||||
config->cluster_undefined_bundles = MAXBUNDLE-1;
|
||||
config->cluster_undefined_tunnels = MAXTUNNEL-1;
|
||||
|
||||
if (!config->cluster_address)
|
||||
|
|
@ -227,7 +229,7 @@ static void cluster_uptodate(void)
|
|||
if (config->cluster_iam_uptodate)
|
||||
return;
|
||||
|
||||
if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels)
|
||||
if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels || config->cluster_undefined_bundles)
|
||||
return;
|
||||
|
||||
config->cluster_iam_uptodate = 1;
|
||||
|
|
@ -400,7 +402,7 @@ void cluster_send_ping(time_t basetime)
|
|||
|
||||
x.ver = 1;
|
||||
x.addr = config->bind_address;
|
||||
x.undef = config->cluster_undefined_sessions + config->cluster_undefined_tunnels;
|
||||
x.undef = config->cluster_undefined_sessions + config->cluster_undefined_tunnels + config->cluster_undefined_bundles;
|
||||
x.basetime = basetime;
|
||||
|
||||
add_type(&p, C_PING, basetime, (uint8_t *) &x, sizeof(x));
|
||||
|
|
@ -520,7 +522,7 @@ void cluster_check_slaves(void)
|
|||
//
|
||||
void cluster_check_master(void)
|
||||
{
|
||||
int i, count, tcount, high_unique_id = 0;
|
||||
int i, count, tcount, bcount, high_unique_id = 0;
|
||||
int last_free = 0;
|
||||
clockt t = TIME;
|
||||
static int probed = 0;
|
||||
|
|
@ -614,6 +616,19 @@ void cluster_check_master(void)
|
|||
config->cluster_highest_tunnelid = i;
|
||||
}
|
||||
|
||||
//
|
||||
// Go through and mark all the bundles as defined.
|
||||
// Count the highest used bundle number as well.
|
||||
//
|
||||
config->cluster_highest_bundleid = 0;
|
||||
for (i = 0, bcount = 0; i < MAXBUNDLE; ++i) {
|
||||
if (bundle[i].state == BUNDLEUNDEF)
|
||||
bundle[i].state = BUNDLEFREE;
|
||||
|
||||
if (bundle[i].state != BUNDLEFREE && i > config->cluster_highest_bundleid)
|
||||
config->cluster_highest_bundleid = i;
|
||||
}
|
||||
|
||||
//
|
||||
// Go through and mark all the sessions as being defined.
|
||||
// reset the idle timeouts.
|
||||
|
|
@ -639,7 +654,7 @@ void cluster_check_master(void)
|
|||
}
|
||||
|
||||
// Reset idle timeouts..
|
||||
session[i].last_packet = time_now;
|
||||
session[i].last_packet = session[i].last_data = time_now;
|
||||
|
||||
// Reset die relative to our uptime rather than the old master's
|
||||
if (session[i].die) session[i].die = TIME;
|
||||
|
|
@ -679,6 +694,7 @@ void cluster_check_master(void)
|
|||
LOG(0, 0, 0, "Warning: Fixed %d uninitialized sessions in becoming master!\n", count);
|
||||
|
||||
config->cluster_undefined_sessions = 0;
|
||||
config->cluster_undefined_bundles = 0;
|
||||
config->cluster_undefined_tunnels = 0;
|
||||
config->cluster_iam_uptodate = 1; // assume all peers are up-to-date
|
||||
|
||||
|
|
@ -696,7 +712,7 @@ void cluster_check_master(void)
|
|||
// we fix it up here, and we ensure that the 'first free session'
|
||||
// pointer is valid.
|
||||
//
|
||||
static void cluster_check_sessions(int highsession, int freesession_ptr, int hightunnel)
|
||||
static void cluster_check_sessions(int highsession, int freesession_ptr, int highbundle, int hightunnel)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -705,7 +721,7 @@ static void cluster_check_sessions(int highsession, int freesession_ptr, int hig
|
|||
if (config->cluster_iam_uptodate)
|
||||
return;
|
||||
|
||||
if (highsession > config->cluster_undefined_sessions && hightunnel > config->cluster_undefined_tunnels)
|
||||
if (highsession > config->cluster_undefined_sessions && highbundle > config->cluster_undefined_bundles && hightunnel > config->cluster_undefined_tunnels)
|
||||
return;
|
||||
|
||||
// Clear out defined sessions, counting the number of
|
||||
|
|
@ -721,6 +737,19 @@ static void cluster_check_sessions(int highsession, int freesession_ptr, int hig
|
|||
++config->cluster_undefined_sessions;
|
||||
}
|
||||
|
||||
// Clear out defined bundles, counting the number of
|
||||
// undefs remaining.
|
||||
config->cluster_undefined_bundles = 0;
|
||||
for (i = 1 ; i < MAXBUNDLE; ++i) {
|
||||
if (i > highbundle) {
|
||||
if (bundle[i].state == BUNDLEUNDEF) bundle[i].state = BUNDLEFREE; // Defined.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bundle[i].state == BUNDLEUNDEF)
|
||||
++config->cluster_undefined_bundles;
|
||||
}
|
||||
|
||||
// Clear out defined tunnels, counting the number of
|
||||
// undefs remaining.
|
||||
config->cluster_undefined_tunnels = 0;
|
||||
|
|
@ -735,9 +764,9 @@ static void cluster_check_sessions(int highsession, int freesession_ptr, int hig
|
|||
}
|
||||
|
||||
|
||||
if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels) {
|
||||
LOG(2, 0, 0, "Cleared undefined sessions/tunnels. %d sess (high %d), %d tunn (high %d)\n",
|
||||
config->cluster_undefined_sessions, highsession, config->cluster_undefined_tunnels, hightunnel);
|
||||
if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels || config->cluster_undefined_bundles) {
|
||||
LOG(2, 0, 0, "Cleared undefined sessions/bundles/tunnels. %d sess (high %d), %d bund (high %d), %d tunn (high %d)\n",
|
||||
config->cluster_undefined_sessions, highsession, config->cluster_undefined_bundles, highbundle, config->cluster_undefined_tunnels, hightunnel);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -770,6 +799,27 @@ static int hb_add_type(uint8_t **p, int type, int id)
|
|||
add_type(p, C_SESSION, id, (uint8_t *) &session[id], sizeof(sessiont));
|
||||
break;
|
||||
|
||||
case C_CBUNDLE: { // Compressed C_BUNDLE
|
||||
uint8_t c[sizeof(bundlet) * 2]; // Bigger than worst case.
|
||||
uint8_t *d = (uint8_t *) &bundle[id];
|
||||
uint8_t *orig = d;
|
||||
int size;
|
||||
|
||||
size = rle_compress( &d, sizeof(bundlet), c, sizeof(c) );
|
||||
|
||||
// Did we compress the full structure, and is the size actually
|
||||
// reduced??
|
||||
if ( (d - orig) == sizeof(bundlet) && size < sizeof(bundlet) ) {
|
||||
add_type(p, C_CBUNDLE, id, c, size);
|
||||
break;
|
||||
}
|
||||
// Failed to compress : Fall through.
|
||||
}
|
||||
|
||||
case C_BUNDLE:
|
||||
add_type(p, C_BUNDLE, id, (uint8_t *) &bundle[id], sizeof(bundlet));
|
||||
break;
|
||||
|
||||
case C_CTUNNEL: { // Compressed C_TUNNEL
|
||||
uint8_t c[sizeof(tunnelt) * 2]; // Bigger than worst case.
|
||||
uint8_t *d = (uint8_t *) &tunnel[id];
|
||||
|
|
@ -802,7 +852,7 @@ static int hb_add_type(uint8_t **p, int type, int id)
|
|||
//
|
||||
void cluster_heartbeat()
|
||||
{
|
||||
int i, count = 0, tcount = 0;
|
||||
int i, count = 0, tcount = 0, bcount = 0;
|
||||
uint8_t buff[MAX_HEART_SIZE + sizeof(heartt) + sizeof(int) ];
|
||||
heartt h;
|
||||
uint8_t *p = buff;
|
||||
|
|
@ -823,7 +873,9 @@ void cluster_heartbeat()
|
|||
h.highsession = config->cluster_highest_sessionid;
|
||||
h.freesession = sessionfree;
|
||||
h.hightunnel = config->cluster_highest_tunnelid;
|
||||
h.highbundle = config->cluster_highest_bundleid;
|
||||
h.size_sess = sizeof(sessiont); // Just in case.
|
||||
h.size_bund = sizeof(bundlet);
|
||||
h.size_tunn = sizeof(tunnelt);
|
||||
h.interval = config->cluster_hb_interval;
|
||||
h.timeout = config->cluster_hb_timeout;
|
||||
|
|
@ -878,6 +930,21 @@ void cluster_heartbeat()
|
|||
++tcount;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill out the packet with bundles from the bundle table...
|
||||
while ( (p + sizeof(uint32_t) * 2 + sizeof(bundlet) ) < (buff + MAX_HEART_SIZE) ) {
|
||||
|
||||
if (!walk_bundle_number) // bundle #0 isn't valid.
|
||||
++walk_bundle_number;
|
||||
|
||||
if (bcount >= config->cluster_highest_bundleid)
|
||||
break;
|
||||
|
||||
hb_add_type(&p, C_CBUNDLE, walk_bundle_number);
|
||||
walk_bundle_number = (1+walk_bundle_number)%(config->cluster_highest_bundleid+1); // +1 avoids divide by zero.
|
||||
++bcount;
|
||||
}
|
||||
|
||||
//
|
||||
// Did we do something wrong?
|
||||
if (p > (buff + sizeof(buff))) { // Did we somehow manage to overun the buffer?
|
||||
|
|
@ -887,9 +954,9 @@ void cluster_heartbeat()
|
|||
}
|
||||
|
||||
LOG(3, 0, 0, "Sending v%d heartbeat #%d, change #%" PRIu64 " with %d changes "
|
||||
"(%d x-sess, %d x-tunnels, %d highsess, %d hightun, size %d)\n",
|
||||
"(%d x-sess, %d x-bundles, %d x-tunnels, %d highsess, %d highbund, %d hightun, size %d)\n",
|
||||
HB_VERSION, h.seq, h.table_version, config->cluster_num_changes,
|
||||
count, tcount, config->cluster_highest_sessionid,
|
||||
count, bcount, tcount, config->cluster_highest_sessionid, config->cluster_highest_bundleid,
|
||||
config->cluster_highest_tunnelid, (int) (p - buff));
|
||||
|
||||
config->cluster_num_changes = 0;
|
||||
|
|
@ -938,6 +1005,17 @@ int cluster_send_session(int sid)
|
|||
return type_changed(C_CSESSION, sid);
|
||||
}
|
||||
|
||||
// A particular bundle has been changed!
|
||||
int cluster_send_bundle(int bid)
|
||||
{
|
||||
if (!config->cluster_iam_master) {
|
||||
LOG(0, 0, bid, "I'm not a master, but I just tried to change a bundle!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return type_changed(C_CBUNDLE, bid);
|
||||
}
|
||||
|
||||
// A particular tunnel has been changed!
|
||||
int cluster_send_tunnel(int tid)
|
||||
{
|
||||
|
|
@ -1135,7 +1213,9 @@ static int cluster_handle_bytes(uint8_t *data, int size)
|
|||
session[b->sid].cout_delta += b->cout;
|
||||
|
||||
if (b->cin)
|
||||
session[b->sid].last_packet = time_now; // Reset idle timer!
|
||||
session[b->sid].last_packet = session[b->sid].last_data = time_now;
|
||||
else if (b->cout)
|
||||
session[b->sid].last_data = time_now;
|
||||
|
||||
size -= sizeof(*b);
|
||||
++b;
|
||||
|
|
@ -1175,6 +1255,31 @@ static int cluster_recv_session(int more, uint8_t *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cluster_recv_bundle(int more, uint8_t *p)
|
||||
{
|
||||
if (more >= MAXBUNDLE) {
|
||||
LOG(0, 0, 0, "DANGER: Received a bundle id > MAXBUNDLE!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bundle[more].state == BUNDLEUNDEF) {
|
||||
if (config->cluster_iam_uptodate) { // Sanity.
|
||||
LOG(0, 0, 0, "I thought I was uptodate but I just found an undefined bundle!\n");
|
||||
} else {
|
||||
--config->cluster_undefined_bundles;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&bundle[more], p, sizeof(bundle[more]) );
|
||||
|
||||
LOG(5, 0, more, "Received bundle update\n");
|
||||
|
||||
if (!config->cluster_iam_uptodate)
|
||||
cluster_uptodate(); // Check to see if we're up to date.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cluster_recv_tunnel(int more, uint8_t *p)
|
||||
{
|
||||
if (more >= MAXTUNNEL) {
|
||||
|
|
@ -1465,7 +1570,7 @@ static int cluster_process_heartbeat(uint8_t *data, int size, int more, uint8_t
|
|||
|
||||
// Check that we don't have too many undefined sessions, and
|
||||
// that the free session pointer is correct.
|
||||
cluster_check_sessions(h->highsession, h->freesession, h->hightunnel);
|
||||
cluster_check_sessions(h->highsession, h->freesession, h->highbundle, h->hightunnel);
|
||||
|
||||
if (h->interval != config->cluster_hb_interval)
|
||||
{
|
||||
|
|
@ -1573,6 +1678,34 @@ static int cluster_process_heartbeat(uint8_t *data, int size, int more, uint8_t
|
|||
p += sizeof(tunnel[more]);
|
||||
s -= sizeof(tunnel[more]);
|
||||
break;
|
||||
|
||||
case C_CBUNDLE: { // Compressed bundle structure.
|
||||
uint8_t c[ sizeof(bundlet) + 2];
|
||||
int size;
|
||||
uint8_t *orig_p = p;
|
||||
|
||||
size = rle_decompress((uint8_t **) &p, s, c, sizeof(c));
|
||||
s -= (p - orig_p);
|
||||
|
||||
if (size != sizeof(bundlet) ) { // Ouch! Very very bad!
|
||||
LOG(0, 0, 0, "DANGER: Received a CBUNDLE that didn't decompress correctly!\n");
|
||||
// Now what? Should exit! No-longer up to date!
|
||||
break;
|
||||
}
|
||||
|
||||
cluster_recv_bundle(more, c);
|
||||
break;
|
||||
|
||||
}
|
||||
case C_BUNDLE:
|
||||
if ( s < sizeof(bundle[more]))
|
||||
goto shortpacket;
|
||||
|
||||
cluster_recv_bundle(more, p);
|
||||
|
||||
p += sizeof(bundle[more]);
|
||||
s -= sizeof(bundle[more]);
|
||||
break;
|
||||
default:
|
||||
LOG(0, 0, 0, "DANGER: I received a heartbeat element where I didn't understand the type! (%d)\n", type);
|
||||
return -1; // can't process any more of the packet!!
|
||||
|
|
@ -1640,7 +1773,7 @@ int processcluster(uint8_t *data, int size, in_addr_t addr)
|
|||
case C_FORWARD_DAE: // Forwarded DAE packet. pass off to processdae.
|
||||
if (!config->cluster_iam_master)
|
||||
{
|
||||
LOG(0, 0, 0, "I'm not the master, but I got a C_FORWARD_%s from %s?\n",
|
||||
LOG(0, 0, 0, "I'm not the master, but I got a C_FORWARD%s from %s?\n",
|
||||
type == C_FORWARD_DAE ? "_DAE" : "", fmtaddr(addr, 0));
|
||||
|
||||
return -1;
|
||||
|
|
@ -1758,11 +1891,13 @@ int cmd_show_cluster(struct cli_def *cli, char *command, char **argv, int argc)
|
|||
cli_print(cli, "Table version # : %" PRIu64, config->cluster_table_version);
|
||||
cli_print(cli, "Next sequence number expected: %d", config->cluster_seq_number);
|
||||
cli_print(cli, "%d sessions undefined of %d", config->cluster_undefined_sessions, config->cluster_highest_sessionid);
|
||||
cli_print(cli, "%d bundles undefined of %d", config->cluster_undefined_bundles, config->cluster_highest_bundleid);
|
||||
cli_print(cli, "%d tunnels undefined of %d", config->cluster_undefined_tunnels, config->cluster_highest_tunnelid);
|
||||
} else {
|
||||
cli_print(cli, "Table version # : %" PRIu64, config->cluster_table_version);
|
||||
cli_print(cli, "Next heartbeat # : %d", config->cluster_seq_number);
|
||||
cli_print(cli, "Highest session : %d", config->cluster_highest_sessionid);
|
||||
cli_print(cli, "Highest bundle : %d", config->cluster_highest_bundleid);
|
||||
cli_print(cli, "Highest tunnel : %d", config->cluster_highest_tunnelid);
|
||||
cli_print(cli, "%d changes queued for sending", config->cluster_num_changes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// L2TPNS Clustering Stuff
|
||||
// $Id: cluster.h,v 1.14 2005/07/31 10:04:10 bodea Exp $
|
||||
// $Id: cluster.h,v 1.16 2006/12/04 20:54:51 bodea Exp $
|
||||
|
||||
#ifndef __CLUSTER_H__
|
||||
#define __CLUSTER_H__
|
||||
|
|
@ -21,6 +21,8 @@
|
|||
#define C_GARDEN 14 // Gardened packet
|
||||
#define C_MASTER 15 // Tell a slave the address of the master.
|
||||
#define C_FORWARD_DAE 16 // A DAE packet for the master to handle
|
||||
#define C_BUNDLE 17 // Bundle structure.
|
||||
#define C_CBUNDLE 18 // Compressed bundle structure.
|
||||
|
||||
#define HB_VERSION 5 // Protocol version number..
|
||||
#define HB_MAX_SEQ (1<<30) // Maximum sequence number. (MUST BE A POWER OF 2!)
|
||||
|
|
@ -43,16 +45,18 @@ typedef struct {
|
|||
|
||||
uint32_t highsession; // Id of the highest in-use session.
|
||||
uint32_t freesession; // Id of the first free session.
|
||||
uint32_t highbundle; // Id of the highest used bundle.
|
||||
uint32_t hightunnel; // Id of the highest used tunnel.
|
||||
uint32_t size_sess; // Size of the session structure.
|
||||
|
||||
uint32_t size_bund; // size of the bundle structure.
|
||||
uint32_t size_tunn; // size of the tunnel structure.
|
||||
uint32_t interval; // ping/heartbeat interval
|
||||
uint32_t timeout; // heartbeat timeout
|
||||
|
||||
uint64_t table_version; // # state changes processed by cluster
|
||||
|
||||
char reserved[128 - 13*sizeof(uint32_t)]; // Pad out to 128 bytes.
|
||||
char reserved[128 - 13*sizeof(uint32_t) - sizeof(uint64_t)]; // Pad out to 128 bytes.
|
||||
} heartt;
|
||||
|
||||
typedef struct { /* Used to update byte counters on the */
|
||||
|
|
@ -74,6 +78,7 @@ typedef struct {
|
|||
int cluster_init(void);
|
||||
int processcluster(uint8_t *buf, int size, in_addr_t addr);
|
||||
int cluster_send_session(int sid);
|
||||
int cluster_send_bundle(int bid);
|
||||
int cluster_send_tunnel(int tid);
|
||||
int master_forward_packet(uint8_t *data, int size, in_addr_t addr, int port);
|
||||
int master_forward_dae_packet(uint8_t *data, int size, in_addr_t addr, int port);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// L2TPNS: constants
|
||||
|
||||
char const *cvs_id_constants = "$Id: constants.c,v 1.7 2005/07/31 10:04:10 bodea Exp $";
|
||||
char const *cvs_id_constants = "$Id: constants.c,v 1.8 2009/12/08 14:49:28 bodea Exp $";
|
||||
|
||||
#include <stdio.h>
|
||||
#include "constants.h"
|
||||
|
|
@ -197,7 +197,8 @@ CONSTANT(radius_state,
|
|||
"RADIUSSTART", // 3
|
||||
"RADIUSSTOP", // 4
|
||||
"RADIUSINTERIM", // 5
|
||||
"RADIUSWAIT" // 6
|
||||
"RADIUSWAIT", // 6
|
||||
"RADIUSJUSTAUTH" // 7
|
||||
)
|
||||
|
||||
CONSTANT(radius_code,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,12 @@ set radius_secret "secret"
|
|||
# Allow multiple logins for the same username
|
||||
#set allow_duplicate_users no
|
||||
|
||||
# Kill timedout sessions ? (default yes)
|
||||
#set kill_timedout_sessions no
|
||||
|
||||
# Allow multiple logins for specific username
|
||||
#set guest_account ""
|
||||
|
||||
# Write usage accounting files into specified directory
|
||||
set accounting_dir "/var/run/l2tpns/acct"
|
||||
|
||||
|
|
@ -59,9 +65,6 @@ set accounting_dir "/var/run/l2tpns/acct"
|
|||
# Number of buckets to allocate for throttling
|
||||
#set throttle_buckets 3000
|
||||
|
||||
# If set to anything other than 0, setuid when initialised.
|
||||
#set setuid 0
|
||||
|
||||
# If set to true, dump current speed to stderr every second
|
||||
#set dump_speed no
|
||||
|
||||
|
|
@ -96,6 +99,9 @@ set accounting_dir "/var/run/l2tpns/acct"
|
|||
# Minimum number of slaves before master withdraws routes
|
||||
#set cluster_master_min_adv 1
|
||||
|
||||
# IPv6 address prefix
|
||||
#set ipv6_prefix ::
|
||||
|
||||
# Drop/kill sessions
|
||||
#load plugin "sessionctl"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* kludge up some limited epoll semantics using select for 2.4 kernels */
|
||||
/* $Id: fake_epoll.h,v 1.1 2005/06/04 15:42:35 bodea Exp $ */
|
||||
/* $Id: fake_epoll.h,v 1.2 2007/06/28 07:22:50 bodea Exp $ */
|
||||
|
||||
#ifndef __FAKE_EPOLL_H__
|
||||
#define __FAKE_EPOLL_H__
|
||||
|
|
@ -150,6 +150,9 @@ static int epoll_wait(int epfd __attribute__ ((unused)),
|
|||
tp = 0;
|
||||
|
||||
n = select(_epoll_fds, &r, &w, 0, tp);
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
if (n > maxevents)
|
||||
n = maxevents;
|
||||
|
||||
|
|
|
|||
4
icmp.c
4
icmp.c
|
|
@ -1,6 +1,6 @@
|
|||
// L2TPNS: icmp
|
||||
|
||||
char const *cvs_id_icmp = "$Id: icmp.c,v 1.10 2005/08/10 11:25:56 bodea Exp $";
|
||||
char const *cvs_id_icmp = "$Id: icmp.c,v 1.11 2006/04/27 09:53:49 bodea Exp $";
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
|
@ -114,7 +114,7 @@ void send_ipv6_ra(sessionidt s, tunnelidt t, struct in6_addr *ip)
|
|||
LOG(3, s, t, "Sending IPv6 RA\n");
|
||||
|
||||
memset(b, 0, sizeof(b));
|
||||
o = makeppp(b, sizeof(b), 0, 0, s, t, PPPIPV6);
|
||||
o = makeppp(b, sizeof(b), 0, 0, s, t, PPPIPV6, 0, 0, 0);
|
||||
|
||||
if (!o)
|
||||
{
|
||||
|
|
|
|||
121
l2tpns.h
121
l2tpns.h
|
|
@ -1,5 +1,5 @@
|
|||
// L2TPNS Global Stuff
|
||||
// $Id: l2tpns.h,v 1.113.2.3 2006/12/02 14:09:14 bodea Exp $
|
||||
// $Id: l2tpns.h,v 1.121 2009/12/08 14:49:28 bodea Exp $
|
||||
|
||||
#ifndef __L2TPNS_H__
|
||||
#define __L2TPNS_H__
|
||||
|
|
@ -14,10 +14,13 @@
|
|||
#include <sys/types.h>
|
||||
#include <libcli.h>
|
||||
|
||||
#define VERSION "2.1.21"
|
||||
#define VERSION "2.2.0"
|
||||
|
||||
// Limits
|
||||
#define MAXTUNNEL 500 // could be up to 65535
|
||||
#define MAXBUNDLE 300 // could be up to 65535
|
||||
#define MAXBUNDLESES 12 // Maximum number of member links in bundle
|
||||
#define MAXADDRESS 20 // Maximum length for the Endpoint Discrminiator address
|
||||
#define MAXSESSION 60000 // could be up to 65535
|
||||
#define MAXTBFS 6000 // Maximum token bucket filters. Might need up to 2 * session.
|
||||
|
||||
|
|
@ -43,10 +46,20 @@
|
|||
#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 60 // Time between last packet sent and LCP ECHO generation
|
||||
#define IDLE_TIMEOUT 240 // Time between last packet sent and LCP ECHO generation
|
||||
#define ECHO_TIMEOUT 10 // Time between last packet sent and LCP ECHO generation
|
||||
#define IDLE_TIMEOUT 240 // Time between last packet seen and session shutdown
|
||||
#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 MINFRAGLEN 64 // Minumum fragment length
|
||||
#define MAXFRAGLEN 750 // Maximum length for Multilink fragment (MTU / 2 sessions)
|
||||
#define MAXFRAGNUM 128 // Maximum number of Multilink fragment in a bundle (must be in the form of 2^X)
|
||||
// it's not expected to have a space for more than 10 unassembled packets = 10 * MAXBUNDLESES
|
||||
#define MAXFRAGNUM_MASK 127 // Must be equal to MAXFRAGNUM-1
|
||||
|
||||
// Constants
|
||||
#ifndef ETCDIR
|
||||
#define ETCDIR "/etc/l2tpns"
|
||||
|
|
@ -186,6 +199,7 @@ enum {
|
|||
|
||||
// Types
|
||||
typedef uint16_t sessionidt;
|
||||
typedef uint16_t bundleidt;
|
||||
typedef uint16_t tunnelidt;
|
||||
typedef uint32_t clockt;
|
||||
typedef uint8_t hasht[16];
|
||||
|
|
@ -231,6 +245,20 @@ 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 {
|
||||
sessionidt sid; // Fragment originating session
|
||||
uint8_t flags; // MP frame flags
|
||||
uint32_t seq; // fragment seq num
|
||||
uint16_t length; // Fragment length
|
||||
uint8_t data[MAXFRAGLEN]; // Fragment data
|
||||
} fragmentt;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sessionidt next; // next session in linked list
|
||||
|
|
@ -261,7 +289,10 @@ typedef struct
|
|||
uint16_t mru; // maximum receive unit
|
||||
clockt opened; // when started
|
||||
clockt die; // being closed, when to finally free
|
||||
uint32_t session_timeout; // Maximum session time in seconds
|
||||
uint32_t idle_timeout; // Maximum idle time in seconds
|
||||
time_t last_packet; // Last packet from the user (used for idle timeouts)
|
||||
time_t last_data; // Last data packet to/from the user (used for idle timeouts)
|
||||
in_addr_t dns1, dns2; // DNS servers
|
||||
routet route[MAXROUTE]; // static routes
|
||||
uint16_t tbf_in; // filter bucket for throttling in from the user.
|
||||
|
|
@ -273,6 +304,11 @@ 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?
|
||||
|
|
@ -282,6 +318,36 @@ typedef struct
|
|||
}
|
||||
sessiont;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int state; // current state (bundlestate enum)
|
||||
uint32_t seq_num_t; // Sequence Number (transmission)
|
||||
uint32_t timeout; // Session-Timeout for bundle
|
||||
uint32_t max_seq; // Max value of sequence number field
|
||||
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
|
||||
uint16_t re_frame_begin_index, re_frame_end_index; // reassembled frame begin index, end index respectively
|
||||
uint16_t start_index, end_index; // start and end sequence numbers available on the fragments array respectively
|
||||
uint32_t M; // Minumum frame sequence number received over all bundle members
|
||||
uint32_t start_seq; // Last received frame sequence number (bearing B bit)
|
||||
}
|
||||
fragmentationt;
|
||||
|
||||
#define AUTHPAP 1 // allow PAP
|
||||
#define AUTHCHAP 2 // allow CHAP
|
||||
|
||||
|
|
@ -311,6 +377,15 @@ 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;
|
||||
|
|
@ -324,6 +399,9 @@ typedef struct
|
|||
|
||||
// last LCP Echo
|
||||
time_t last_echo;
|
||||
|
||||
// Last Multilink frame sequence number received
|
||||
uint32_t last_seq;
|
||||
} sessionlocalt;
|
||||
|
||||
// session flags
|
||||
|
|
@ -407,6 +485,23 @@ 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
|
||||
|
|
@ -416,6 +511,7 @@ enum
|
|||
RADIUSSTOP, // sending stop accounting to RADIUS server
|
||||
RADIUSINTERIM, // sending interim accounting to RADIUS server
|
||||
RADIUSWAIT, // waiting timeout before available, in case delayed replies
|
||||
RADIUSJUSTAUTH, // sending auth to RADIUS server, just authentication, no ip assigning
|
||||
};
|
||||
|
||||
struct Tstats
|
||||
|
|
@ -554,13 +650,16 @@ typedef struct
|
|||
uint16_t radiusport[MAXRADSERVER]; // radius base ports
|
||||
uint8_t numradiusservers; // radius server count
|
||||
|
||||
uint16_t radius_dae_port; // local port for radius dae
|
||||
uint16_t radius_dae_port; // port for radius DAE
|
||||
uint16_t radius_bind_min; // port range for udp sockets used to send/recv radius packets
|
||||
uint16_t radius_bind_max;
|
||||
|
||||
char radius_authtypes_s[32]; // list of valid authentication types (chap, pap) in order of preference
|
||||
int radius_authtypes;
|
||||
int radius_authprefer;
|
||||
|
||||
int allow_duplicate_users; // allow multiple logins with the same username
|
||||
int kill_timedout_sessions; // kill authenticated sessions with "session_timeout == 0"
|
||||
|
||||
in_addr_t default_dns1, default_dns2;
|
||||
|
||||
|
|
@ -572,7 +671,6 @@ 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];
|
||||
|
|
@ -583,6 +681,7 @@ 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.
|
||||
|
|
@ -594,8 +693,10 @@ 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
|
||||
|
|
@ -611,6 +712,8 @@ typedef struct
|
|||
|
||||
int cluster_master_min_adv; // Master advertises routes while the number of up to date
|
||||
// slaves is less than this value.
|
||||
// Guest change
|
||||
char guest_user[MAXUSER]; // Guest account username
|
||||
|
||||
#ifdef BGP
|
||||
#define BGP_NUM_PEERS 2
|
||||
|
|
@ -727,14 +830,17 @@ 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 *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);
|
||||
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
|
||||
|
|
@ -802,6 +908,7 @@ 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;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Summary: A high-speed clustered L2TP LNS
|
||||
Name: l2tpns
|
||||
Version: 2.1.21
|
||||
Version: 2.2.0
|
||||
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
|
||||
* Fri Dec 1 2006 Brendan O'Dea <bod@optus.net> 2.1.21-1
|
||||
- 2.1.21 release, see /usr/share/doc/l2tpns-2.1.21/Changes
|
||||
* Mon Dec 18 2006 Brendan O'Dea <bod@optus.net> 2.2.0-1
|
||||
- 2.2.0 release, see /usr/share/doc/l2tpns-2.2.0/Changes
|
||||
|
|
|
|||
40
md5.c
40
md5.c
|
|
@ -15,10 +15,7 @@
|
|||
* and avoid compile-time configuration.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_OPENSSL
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
|
|
@ -49,10 +46,8 @@
|
|||
* doesn't work.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__vax__)
|
||||
#define SET(n) \
|
||||
(*(MD5_u32plus *)&ptr[(n) * 4])
|
||||
#define GET(n) \
|
||||
SET(n)
|
||||
# define SET(n) (*(MD5_u32plus *)&ptr[(n) * 4])
|
||||
# define GET(n) SET(n)
|
||||
#else
|
||||
# define SET(n) \
|
||||
(ctx->block[(n)] = \
|
||||
|
|
@ -164,8 +159,8 @@ static void *body(MD5_CTX *ctx, void *data, unsigned long size)
|
|||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
ptr += MD5_BLOCK_SZ;
|
||||
} while (size -= MD5_BLOCK_SZ);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
|
|
@ -194,14 +189,17 @@ void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
|
|||
saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
used = saved_lo & 0x3f;
|
||||
|
||||
if (used) {
|
||||
free = 64 - used;
|
||||
if (used)
|
||||
{
|
||||
free = MD5_BLOCK_SZ - used;
|
||||
|
||||
if (size < free) {
|
||||
if (size < free)
|
||||
{
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
|
@ -209,10 +207,11 @@ void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
|
|||
memcpy(&ctx->buffer[used], data, free);
|
||||
data = (unsigned char *)data + free;
|
||||
size -= free;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
body(ctx, ctx->buffer, MD5_BLOCK_SZ);
|
||||
}
|
||||
|
||||
if (size >= 64) {
|
||||
if (size >= MD5_BLOCK_SZ)
|
||||
{
|
||||
data = body(ctx, data, size & ~(unsigned long)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
|
@ -228,13 +227,14 @@ void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
|||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
free = 64 - used;
|
||||
free = MD5_BLOCK_SZ - used;
|
||||
|
||||
if (free < 8) {
|
||||
if (free < 8)
|
||||
{
|
||||
memset(&ctx->buffer[used], 0, free);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
body(ctx, ctx->buffer, MD5_BLOCK_SZ);
|
||||
used = 0;
|
||||
free = 64;
|
||||
free = MD5_BLOCK_SZ;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, free - 8);
|
||||
|
|
@ -249,7 +249,7 @@ void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
|||
ctx->buffer[62] = ctx->hi >> 16;
|
||||
ctx->buffer[63] = ctx->hi >> 24;
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
body(ctx, ctx->buffer, MD5_BLOCK_SZ);
|
||||
|
||||
result[0] = ctx->a;
|
||||
result[1] = ctx->a >> 8;
|
||||
|
|
@ -270,5 +270,3 @@ void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
|||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
15
md5.h
15
md5.h
|
|
@ -6,10 +6,11 @@
|
|||
* in the public domain. See md5.c for more information.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/md5.h>
|
||||
#elif !defined(_MD5_H)
|
||||
#define _MD5_H
|
||||
#ifndef __MD5_H__
|
||||
#define __MD5_H__
|
||||
|
||||
#define MD5_DIGEST_SZ 16
|
||||
#define MD5_BLOCK_SZ 64
|
||||
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
typedef unsigned long MD5_u32plus;
|
||||
|
|
@ -17,12 +18,12 @@ typedef unsigned long MD5_u32plus;
|
|||
typedef struct {
|
||||
MD5_u32plus lo, hi;
|
||||
MD5_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
MD5_u32plus block[16];
|
||||
unsigned char buffer[MD5_BLOCK_SZ];
|
||||
MD5_u32plus block[MD5_DIGEST_SZ];
|
||||
} MD5_CTX;
|
||||
|
||||
extern void MD5_Init(MD5_CTX *ctx);
|
||||
extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size);
|
||||
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
|
||||
|
||||
#endif
|
||||
#endif /* __MD5_H__ */
|
||||
|
|
|
|||
38
plugin.h
38
plugin.h
|
|
@ -8,8 +8,6 @@ enum
|
|||
{
|
||||
PLUGIN_PRE_AUTH = 1,
|
||||
PLUGIN_POST_AUTH,
|
||||
PLUGIN_PACKET_RX,
|
||||
PLUGIN_PACKET_TX,
|
||||
PLUGIN_TIMER,
|
||||
PLUGIN_NEW_SESSION,
|
||||
PLUGIN_KILL_SESSION,
|
||||
|
|
@ -62,37 +60,11 @@ struct param_post_auth
|
|||
int protocol;
|
||||
};
|
||||
|
||||
struct param_packet_rx
|
||||
{
|
||||
tunnelt *t;
|
||||
sessiont *s;
|
||||
char *buf;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct param_packet_tx
|
||||
{
|
||||
tunnelt *t;
|
||||
sessiont *s;
|
||||
char *buf;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct param_timer
|
||||
{
|
||||
time_t time_now;
|
||||
};
|
||||
|
||||
struct param_control
|
||||
{
|
||||
int iam_master;
|
||||
int argc;
|
||||
char **argv;
|
||||
// output
|
||||
int response;
|
||||
char *additional;
|
||||
};
|
||||
|
||||
struct param_new_session
|
||||
{
|
||||
tunnelt *t;
|
||||
|
|
@ -105,6 +77,16 @@ struct param_kill_session
|
|||
sessiont *s;
|
||||
};
|
||||
|
||||
struct param_control
|
||||
{
|
||||
int iam_master;
|
||||
int argc;
|
||||
char **argv;
|
||||
// output
|
||||
int response;
|
||||
char *additional;
|
||||
};
|
||||
|
||||
struct param_radius_response
|
||||
{
|
||||
tunnelt *t;
|
||||
|
|
|
|||
635
ppp.c
635
ppp.c
|
|
@ -1,6 +1,6 @@
|
|||
// L2TPNS PPP Stuff
|
||||
|
||||
char const *cvs_id_ppp = "$Id: ppp.c,v 1.99.2.1 2006/05/26 07:33:52 bodea Exp $";
|
||||
char const *cvs_id_ppp = "$Id: ppp.c,v 1.104 2009/12/08 14:49:28 bodea Exp $";
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
|
@ -15,6 +15,8 @@ char const *cvs_id_ppp = "$Id: ppp.c,v 1.99.2.1 2006/05/26 07:33:52 bodea Exp $"
|
|||
#include "cluster.h"
|
||||
|
||||
extern tunnelt *tunnel;
|
||||
extern bundlet *bundle;
|
||||
extern fragmentationt *frag;
|
||||
extern sessiont *session;
|
||||
extern radiust *radius;
|
||||
extern int tunfd;
|
||||
|
|
@ -24,6 +26,20 @@ 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);
|
||||
|
||||
static int first_session_in_bundle(sessionidt s)
|
||||
{
|
||||
bundleidt i;
|
||||
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))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Process PAP messages
|
||||
void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||
|
|
@ -90,7 +106,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);
|
||||
uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPPAP, 0, 0, 0);
|
||||
if (!p) return;
|
||||
|
||||
if (session[s].ip)
|
||||
|
|
@ -134,6 +150,9 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
|
||||
radius[r].id = p[1];
|
||||
LOG(3, s, t, "Sending login for %s/%s to RADIUS\n", user, pass);
|
||||
if ((session[s].mrru) && (!first_session_in_bundle(s)))
|
||||
radiussend(r, RADIUSJUSTAUTH);
|
||||
else
|
||||
radiussend(r, RADIUSAUTH);
|
||||
}
|
||||
}
|
||||
|
|
@ -251,6 +270,9 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
|
||||
radius[r].chap = 1;
|
||||
LOG(3, s, t, "CHAP login %s\n", session[s].user);
|
||||
if ((session[s].mrru) && (!first_session_in_bundle(s)))
|
||||
radiussend(r, RADIUSJUSTAUTH);
|
||||
else
|
||||
radiussend(r, RADIUSAUTH);
|
||||
}
|
||||
|
||||
|
|
@ -359,6 +381,8 @@ void lcp_open(sessionidt s, tunnelidt t)
|
|||
sendchap(s, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(session[s].bundle == 0 || bundle[session[s].bundle].num_of_links == 1)
|
||||
{
|
||||
// This-Layer-Up
|
||||
sendipcp(s, t);
|
||||
|
|
@ -371,6 +395,13 @@ void lcp_open(sessionidt s, tunnelidt t)
|
|||
|
||||
change_state(s, ccp, Stopped);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
ipcp_open(s, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lcp_restart(sessionidt s)
|
||||
|
|
@ -387,7 +418,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);
|
||||
queued = *response = makeppp(buf, blen, packet, 2, s, session[s].tunnel, mtype, 0, 0, 0);
|
||||
if (!queued)
|
||||
return 0;
|
||||
|
||||
|
|
@ -431,7 +462,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);
|
||||
queued = *response = makeppp(buf, blen, packet, 2, s, session[s].tunnel, mtype, 0, 0, 0);
|
||||
if (!queued)
|
||||
return 0;
|
||||
|
||||
|
|
@ -463,7 +494,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);
|
||||
q = makeppp(buf, size, 0, 0, s, t, proto, 0, 0, 0);
|
||||
if (!q) return;
|
||||
|
||||
*q = CodeRej;
|
||||
|
|
@ -575,6 +606,7 @@ 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)
|
||||
{
|
||||
|
|
@ -590,7 +622,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
if (mru >= MINMTU)
|
||||
{
|
||||
session[s].mru = mru;
|
||||
cluster_send_session(s);
|
||||
changed++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -663,6 +695,64 @@ 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);
|
||||
|
|
@ -671,6 +761,9 @@ 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
|
||||
|
|
@ -679,7 +772,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);
|
||||
response = makeppp(b, sizeof(b), p, l, s, t, PPPLCP, 0, 0, 0);
|
||||
if (!response) return;
|
||||
*response = ConfigAck;
|
||||
}
|
||||
|
|
@ -687,7 +780,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);
|
||||
response = makeppp(b, sizeof(b), p, 2, s, t, PPPLCP, 0, 0, 0);
|
||||
if (!response) return;
|
||||
*response = TerminateAck;
|
||||
*((uint16_t *) (response + 2)) = htons(l = 4);
|
||||
|
|
@ -820,6 +913,50 @@ 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);
|
||||
|
|
@ -843,7 +980,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);
|
||||
uint8_t *response = makeppp(b, sizeof(b), p, 2, s, t, PPPLCP, 0, 0, 0);
|
||||
if (!response) return;
|
||||
*response = TerminateAck;
|
||||
*((uint16_t *) (response + 2)) = htons(l = 4);
|
||||
|
|
@ -901,7 +1038,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);
|
||||
q = makeppp(b, sizeof(b), p, l, s, t, PPPLCP, 0, 0, 0);
|
||||
if (!q) return;
|
||||
|
||||
LOG(3, s, t, "LCP: send %s\n", ppp_code(*q));
|
||||
|
|
@ -937,7 +1074,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);
|
||||
q = makeppp(b, sizeof(b), p, l, s, t, PPPLCP, 0, 0, 0);
|
||||
if (!q) return;
|
||||
|
||||
LOG(4, s, t, "LCP: send %s\n", ppp_code(*q));
|
||||
|
|
@ -955,6 +1092,112 @@ 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))
|
||||
{
|
||||
sessionidt first_ses = bundle[i].members[0];
|
||||
if (bundle[i].mssf != session[s].mssf)
|
||||
{
|
||||
// uniformity of sequence number format must be insured
|
||||
LOG(3, s, session[s].tunnel, "MPPP: unable to bundle session %d in bundle %d cause of different mssf\n", s, i);
|
||||
return -1;
|
||||
}
|
||||
session[s].bundle = i;
|
||||
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;
|
||||
|
||||
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;
|
||||
// FIXME !!! to enable l2tpns reading mssf frames receiver_max_seq, sender_max_seq must be introduce
|
||||
// now session[s].mssf flag indecates that the receiver wish to receive frames in mssf, so max_seq (i.e. recv_max_seq) = 1<<24
|
||||
/*
|
||||
if (bundle[b].mssf)
|
||||
bundle[b].max_seq = 1 << 12;
|
||||
else */
|
||||
bundle[b].max_seq = 1 << 24;
|
||||
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;
|
||||
bundle[b].timeout = session[s].timeout;
|
||||
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
|
||||
memset(&frag[i], 0, sizeof(fragmentationt));
|
||||
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");
|
||||
|
|
@ -1113,7 +1356,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);
|
||||
response = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP, 0, 0, 0);
|
||||
if (!response) return;
|
||||
*response = ConfigAck;
|
||||
}
|
||||
|
|
@ -1127,7 +1370,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);
|
||||
response = makeppp(b, sizeof(b), p, 2, s, t, PPPIPCP, 0, 0, 0);
|
||||
if (!response) return;
|
||||
*response = TerminateAck;
|
||||
*((uint16_t *) (response + 2)) = htons(l = 4);
|
||||
|
|
@ -1200,7 +1443,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);
|
||||
q = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP, 0, 0, 0);
|
||||
if (!q) return;
|
||||
|
||||
LOG(3, s, t, "IPCP: send %s\n", ppp_code(*q));
|
||||
|
|
@ -1334,7 +1577,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);
|
||||
response = makeppp(b, sizeof(b), p, l, s, t, PPPIPV6CP, 0, 0, 0);
|
||||
if (!response) return;
|
||||
*response = ConfigAck;
|
||||
}
|
||||
|
|
@ -1348,7 +1591,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);
|
||||
response = makeppp(b, sizeof(b), p, 2, s, t, PPPIPV6CP, 0, 0, 0);
|
||||
if (!response) return;
|
||||
*response = TerminateAck;
|
||||
*((uint16_t *) (response + 2)) = htons(l = 4);
|
||||
|
|
@ -1421,7 +1664,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);
|
||||
q = makeppp(b, sizeof(b), p, l, s, t, PPPIPV6CP, 0, 0, 0);
|
||||
if (!q) return;
|
||||
|
||||
LOG(3, s, t, "IPV6CP: send %s\n", ppp_code(*q));
|
||||
|
|
@ -1433,6 +1676,39 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
}
|
||||
}
|
||||
|
||||
static void update_sessions_in_stat(sessionidt s, uint16_t l)
|
||||
{
|
||||
bundleidt b = session[s].bundle;
|
||||
if (!b)
|
||||
{
|
||||
increment_counter(&session[s].cin, &session[s].cin_wrap, l);
|
||||
session[s].cin_delta += l;
|
||||
session[s].pin++;
|
||||
|
||||
sess_local[s].cin += l;
|
||||
sess_local[s].pin++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = frag[b].re_frame_begin_index;
|
||||
int end = frag[b].re_frame_end_index;
|
||||
for (;;)
|
||||
{
|
||||
l = frag[b].fragment[i].length;
|
||||
s = frag[b].fragment[i].sid;
|
||||
increment_counter(&session[s].cin, &session[s].cin_wrap, l);
|
||||
session[s].cin_delta += l;
|
||||
session[s].pin++;
|
||||
|
||||
sess_local[s].cin += l;
|
||||
sess_local[s].pin++;
|
||||
if (i == end)
|
||||
return;
|
||||
i = (i + 1) & MAXFRAGNUM_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// process IP packet received
|
||||
//
|
||||
// This MUST be called with at least 4 byte behind 'p'.
|
||||
|
|
@ -1464,12 +1740,15 @@ 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)
|
||||
{
|
||||
LOG(5, s, t, "Dropping packet with spoofed IP %s\n", fmtaddr(htonl(ip), 0));
|
||||
LOG(4, s, t, "Dropping packet with spoofed IP %s\n", fmtaddr(htonl(ip), 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// run access-list if any
|
||||
if (session[s].filter_in && !ip_filter(p, l, session[s].filter_in - 1))
|
||||
|
|
@ -1488,17 +1767,13 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
*(uint32_t *) p = htonl(PKTIP);
|
||||
l += 4;
|
||||
|
||||
// Are we throttled and a slave?
|
||||
if (session[s].tbf_in && !config->cluster_iam_master) {
|
||||
// Pass it to the master for handling.
|
||||
master_throttle_packet(session[s].tbf_in, p, l);
|
||||
return;
|
||||
}
|
||||
|
||||
// Are we throttled and a master??
|
||||
if (session[s].tbf_in && config->cluster_iam_master) {
|
||||
// Actually handle the throttled packets.
|
||||
if (session[s].tbf_in)
|
||||
{
|
||||
// Are we throttling this session?
|
||||
if (config->cluster_iam_master)
|
||||
tbf_queue_packet(session[s].tbf_in, p, l);
|
||||
else
|
||||
master_throttle_packet(session[s].tbf_in, p, l);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1521,12 +1796,7 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
snoop_send_packet(p, l, session[s].snoop_ip, session[s].snoop_port);
|
||||
}
|
||||
|
||||
increment_counter(&session[s].cin, &session[s].cin_wrap, l);
|
||||
session[s].cin_delta += l;
|
||||
session[s].pin++;
|
||||
|
||||
sess_local[s].cin += l;
|
||||
sess_local[s].pin++;
|
||||
update_sessions_in_stat(s, l);
|
||||
|
||||
eth_tx += l;
|
||||
|
||||
|
|
@ -1534,6 +1804,195 @@ 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;
|
||||
bundlet * this_bundle = &bundle[b];
|
||||
uint32_t frag_offset, M_offset;
|
||||
uint16_t frag_index, M_index;
|
||||
fragmentationt *this_fragmentation = &frag[b];
|
||||
uint8_t begin_frame = (*p & MP_BEGIN);
|
||||
uint8_t end_frame = (*p & MP_END);
|
||||
uint32_t seq_num;
|
||||
uint8_t flags = *p;
|
||||
uint16_t begin_index, end_index;
|
||||
|
||||
// Perform length checking
|
||||
if(l > MAXFRAGLEN)
|
||||
{
|
||||
LOG(2, s, t, "MPPP: discarding fragment larger than MAXFRAGLEN\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!b)
|
||||
{
|
||||
LOG(2, s, t, "MPPP: Invalid bundle id: 0\n");
|
||||
return;
|
||||
}
|
||||
// FIXME !! session[s].mssf means that the receiver wants to receive frames in mssf not means the receiver will send frames in mssf
|
||||
/* if(session[s].mssf)
|
||||
{
|
||||
// Get 12 bit for seq number
|
||||
seq_num = ntohs((*(uint16_t *) p) & 0xFF0F);
|
||||
p += 2;
|
||||
l -= 2;
|
||||
// After this point the pointer should be advanced 2 bytes
|
||||
LOG(3, s, t, "MPPP: 12 bits, sequence number: %d\n",seq_num);
|
||||
}
|
||||
else */
|
||||
{
|
||||
// Get 24 bit for seq number
|
||||
seq_num = ntohl((*(uint32_t *) p) & 0xFFFFFF00);
|
||||
p += 4;
|
||||
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);
|
||||
}
|
||||
|
||||
// calculate this fragment's offset from the begin seq in the bundle
|
||||
frag_offset = (seq_num + this_bundle->max_seq - this_fragmentation->start_seq) & (this_bundle->max_seq-1);
|
||||
|
||||
// discard this fragment if frag_offset is bigger that the fragmentation buffer size
|
||||
if (frag_offset >= MAXFRAGNUM)
|
||||
{
|
||||
LOG(3, s, t, "MPPP: Index out of range, received more than MAXFRAGNUM fragment (lost frag) seq:%d, begin_seq:%d, bundle:%d, max:%d\n",seq_num, this_fragmentation->start_seq, b, this_bundle->max_seq);
|
||||
return;
|
||||
}
|
||||
|
||||
// update M
|
||||
sess_local[s].last_seq = seq_num;
|
||||
if (seq_num < this_fragmentation->M)
|
||||
this_fragmentation->M = seq_num;
|
||||
else
|
||||
{
|
||||
uint32_t i, min = sess_local[(this_bundle->members[0])].last_seq;;
|
||||
for (i = 1; i < this_bundle->num_of_links; i++)
|
||||
{
|
||||
uint32_t s_seq = sess_local[(this_bundle->members[i])].last_seq;
|
||||
if (s_seq < min)
|
||||
min = s_seq;
|
||||
}
|
||||
this_fragmentation->M = min;
|
||||
}
|
||||
|
||||
LOG(4, s, t, "MPPP: Setting M to %d\n", this_fragmentation->M);
|
||||
//calculate M's offset from the begin seq in the bundle
|
||||
M_offset = (this_fragmentation->M + this_bundle->max_seq - this_fragmentation->start_seq) & (this_bundle->max_seq-1);
|
||||
|
||||
//caculate M's index in the fragment array
|
||||
M_index = (M_offset + this_fragmentation->start_index) & MAXFRAGNUM_MASK;
|
||||
|
||||
//caculate received fragment's index in the fragment array
|
||||
frag_index = (frag_offset + this_fragmentation->start_index) & MAXFRAGNUM_MASK;
|
||||
|
||||
//frame with a single fragment
|
||||
if (begin_frame && end_frame)
|
||||
{
|
||||
// process and reset fragmentation
|
||||
LOG(4, s, t, "MPPP: Both bits are set (Begin and End).\n");
|
||||
this_fragmentation->fragment[frag_index].length = l;
|
||||
this_fragmentation->fragment[frag_index].sid = s;
|
||||
this_fragmentation->fragment[frag_index].flags = flags;
|
||||
this_fragmentation->fragment[frag_index].seq = seq_num;
|
||||
this_fragmentation->re_frame_begin_index = frag_index;
|
||||
this_fragmentation->re_frame_end_index = frag_index;
|
||||
processmpframe(s, t, p, l, 0);
|
||||
this_fragmentation->fragment[frag_index].length = 0;
|
||||
this_fragmentation->fragment[frag_index].flags = 0;
|
||||
end_index = frag_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
// insert the frame in it's place
|
||||
fragmentt *this_frag = &this_fragmentation->fragment[frag_index];
|
||||
this_frag->length = l;
|
||||
this_frag->sid = s;
|
||||
this_frag->flags = flags;
|
||||
this_frag->seq = seq_num;
|
||||
memcpy(this_frag->data, p, l);
|
||||
|
||||
// try to assemble the frame that has the received fragment as a member
|
||||
// get the beginning of this frame
|
||||
begin_index = end_index = frag_index;
|
||||
while (this_fragmentation->fragment[begin_index].length)
|
||||
{
|
||||
if (this_fragmentation->fragment[begin_index].flags & MP_BEGIN)
|
||||
break;
|
||||
begin_index = (begin_index ? (begin_index -1) : (MAXFRAGNUM -1));
|
||||
}
|
||||
|
||||
// return if a lost fragment is found
|
||||
if (!(this_fragmentation->fragment[begin_index].length))
|
||||
return; // assembling frame failed
|
||||
// get the end of his frame
|
||||
while (this_fragmentation->fragment[end_index].length)
|
||||
{
|
||||
if (this_fragmentation->fragment[end_index].flags & MP_END)
|
||||
break;
|
||||
end_index = (end_index +1) & MAXFRAGNUM_MASK;
|
||||
}
|
||||
|
||||
// return if a lost fragment is found
|
||||
if (!(this_fragmentation->fragment[end_index].length))
|
||||
return; // assembling frame failed
|
||||
|
||||
// assemble the packet
|
||||
//assemble frame, process it, reset fragmentation
|
||||
uint16_t cur_len = 4; // This is set to 4 to leave 4 bytes for function processipin
|
||||
uint32_t i;
|
||||
|
||||
LOG(4, s, t, "MPPP: processing fragments from %d to %d\n", begin_index, end_index);
|
||||
// Push to the receive buffer
|
||||
|
||||
for (i = begin_index;; i = (i + 1) & MAXFRAGNUM_MASK)
|
||||
{
|
||||
this_frag = &this_fragmentation->fragment[i];
|
||||
if(cur_len + this_frag->length > MAXETHER)
|
||||
{
|
||||
LOG(2, s, t, "MPPP: discarding reassembled frames larger than MAXETHER\n");
|
||||
break;
|
||||
}
|
||||
memcpy(this_fragmentation->reassembled_frame+cur_len, this_frag->data, this_frag->length);
|
||||
LOG(5, s, t, "MPPP: processing frame at %d, with len %d\n", i, this_frag->length);
|
||||
cur_len += this_frag->length;
|
||||
if (i == end_index)
|
||||
{
|
||||
this_fragmentation->re_frame_len = cur_len;
|
||||
this_fragmentation->re_frame_begin_index = begin_index;
|
||||
this_fragmentation->re_frame_end_index = end_index;
|
||||
// Process the resassembled frame
|
||||
LOG(5, s, t, "MPPP: Process the reassembled frame, len=%d\n",cur_len);
|
||||
processmpframe(s, t, this_fragmentation->reassembled_frame, this_fragmentation->re_frame_len, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Set reassembled frame length to zero after processing it
|
||||
this_fragmentation->re_frame_len = 0;
|
||||
for (i = begin_index;; i = (i + 1) & MAXFRAGNUM_MASK)
|
||||
{
|
||||
this_fragmentation->fragment[i].length = 0; // Indicates that this fragment has been consumed
|
||||
this_fragmentation->fragment[i].flags = 0;
|
||||
if (i == end_index)
|
||||
break;
|
||||
}
|
||||
}
|
||||
//discard fragments received before the recently assembled frame
|
||||
begin_index = this_fragmentation->start_index;
|
||||
this_fragmentation->start_index = (end_index + 1) & MAXFRAGNUM_MASK;
|
||||
this_fragmentation->start_seq = (this_fragmentation->fragment[end_index].seq + 1) & (this_bundle->max_seq-1);
|
||||
//clear length and flags of the discarded fragments
|
||||
while (begin_index != this_fragmentation->start_index)
|
||||
{
|
||||
this_fragmentation->fragment[begin_index].flags = 0;
|
||||
this_fragmentation->fragment[begin_index].length = 0;
|
||||
begin_index = (begin_index + 1) & MAXFRAGNUM_MASK;
|
||||
}
|
||||
|
||||
LOG(4, s, t, "MPPP after assembling: M index is =%d, start index is = %d, start seq=%d\n",M_index, this_fragmentation->start_index, this_fragmentation->start_seq);
|
||||
return;
|
||||
}
|
||||
|
||||
// process IPv6 packet received
|
||||
//
|
||||
// This MUST be called with at least 4 byte behind 'p'.
|
||||
|
|
@ -1617,12 +2076,7 @@ void processipv6in(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
snoop_send_packet(p, l, session[s].snoop_ip, session[s].snoop_port);
|
||||
}
|
||||
|
||||
increment_counter(&session[s].cin, &session[s].cin_wrap, l);
|
||||
session[s].cin_delta += l;
|
||||
session[s].pin++;
|
||||
|
||||
sess_local[s].cin += l;
|
||||
sess_local[s].pin++;
|
||||
update_sessions_in_stat(s, l);
|
||||
|
||||
eth_tx += l;
|
||||
|
||||
|
|
@ -1693,7 +2147,7 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
STAT(tunnel_rx_errors);
|
||||
}
|
||||
|
||||
LOG(3, s, t, "CCP: recv %s\n", ppp_code(*p));
|
||||
LOG(4, s, t, "CCP: recv %s\n", ppp_code(*p));
|
||||
if (*p == ConfigAck)
|
||||
{
|
||||
switch (session[s].ppp.ccp)
|
||||
|
|
@ -1726,13 +2180,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);
|
||||
q = makeppp(b, sizeof(b), p, l, s, t, PPPCCP, 0, 0, 0);
|
||||
if (!q) return;
|
||||
|
||||
switch (session[s].ppp.ccp)
|
||||
{
|
||||
case Closed:
|
||||
q = makeppp(b, sizeof(b), p, 2, s, t, PPPCCP);
|
||||
q = makeppp(b, sizeof(b), p, 2, s, t, PPPCCP, 0, 0, 0);
|
||||
if (!q) return;
|
||||
*q = TerminateAck;
|
||||
*((uint16_t *) (q + 2)) = htons(l = 4);
|
||||
|
|
@ -1778,13 +2232,13 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
return;
|
||||
}
|
||||
|
||||
LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
|
||||
LOG(4, 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);
|
||||
q = makeppp(b, sizeof(b), p, l, s, t, PPPCCP, 0, 0, 0);
|
||||
if (!q) return;
|
||||
LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
|
||||
tunnelsend(b, l + (q - b), t);
|
||||
|
|
@ -1828,7 +2282,7 @@ void sendchap(sessionidt s, tunnelidt t)
|
|||
STAT(tunnel_tx_errors);
|
||||
return ;
|
||||
}
|
||||
q = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP);
|
||||
q = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP, 0, 0, 0);
|
||||
if (!q) return;
|
||||
|
||||
*q = 1; // challenge
|
||||
|
|
@ -1842,37 +2296,86 @@ 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 *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)
|
||||
{
|
||||
if (size < 12) // Need more space than this!!
|
||||
uint16_t hdr = 0x0002; // L2TP with no options
|
||||
uint16_t type = mtype;
|
||||
uint8_t *start = b;
|
||||
|
||||
if (size < 16) // Need more space than this!!
|
||||
{
|
||||
LOG(0, s, t, "makeppp buffer too small for L2TP header (size=%d)\n", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*(uint16_t *) (b + 0) = htons(0x0002); // L2TP with no options
|
||||
if (prio) hdr |= 0x0100; // set priority bit
|
||||
|
||||
*(uint16_t *) (b + 0) = htons(hdr);
|
||||
*(uint16_t *) (b + 2) = htons(tunnel[t].far); // tunnel
|
||||
*(uint16_t *) (b + 4) = htons(session[s].far); // session
|
||||
b += 6;
|
||||
if (mtype == PPPLCP || !(session[s].flags & SESSION_ACFC))
|
||||
|
||||
// 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))
|
||||
{
|
||||
*(uint16_t *) b = htons(0xFF03); // HDLC header
|
||||
b += 2;
|
||||
}
|
||||
if (mtype < 0x100 && session[s].flags & SESSION_PFC)
|
||||
*b++ = mtype;
|
||||
|
||||
if (type < 0x100 && session[s].flags & SESSION_PFC)
|
||||
{
|
||||
*b++ = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(uint16_t *) b = htons(mtype);
|
||||
*(uint16_t *) b = htons(type);
|
||||
b += 2;
|
||||
}
|
||||
|
||||
if (l + 12 > size)
|
||||
if (bid)
|
||||
{
|
||||
LOG(2, s, t, "makeppp would overflow buffer (size=%d, header+payload=%d)\n", size, l + 12);
|
||||
// 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 & 0x0FFF)|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);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy the payload
|
||||
if (p && l)
|
||||
memcpy(b, p, l);
|
||||
|
||||
|
|
@ -1911,10 +2414,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)))
|
||||
if (!(q = makeppp(b, sizeof(b), NULL, 0, s, t, PPPLCP, 0, 0, 0)))
|
||||
return;
|
||||
|
||||
LOG(3, s, t, "LCP: send ConfigReq%s%s%s\n",
|
||||
LOG(3, s, t, "LCP: send ConfigReq%s%s%s including MP options\n",
|
||||
authtype ? " (" : "",
|
||||
authtype ? (authtype == AUTHCHAP ? "CHAP" : "PAP") : "",
|
||||
authtype ? ")" : "");
|
||||
|
|
@ -1941,6 +2444,20 @@ 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);
|
||||
|
|
@ -1955,7 +2472,7 @@ void sendccp(sessionidt s, tunnelidt t)
|
|||
{
|
||||
uint8_t b[500], *q;
|
||||
|
||||
if (!(q = makeppp(b, sizeof(b), NULL, 0, s, t, PPPCCP)))
|
||||
if (!(q = makeppp(b, sizeof(b), NULL, 0, s, t, PPPCCP, 0, 0, 0)))
|
||||
return;
|
||||
|
||||
LOG(3, s, t, "CCP: send ConfigReq (no compression)\n");
|
||||
|
|
@ -1982,7 +2499,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);
|
||||
q = makeppp(buf, sizeof(buf), 0, 0, s, t, PPPLCP, 0, 0, 0);
|
||||
if (!q) return;
|
||||
|
||||
*q = ProtocolRej;
|
||||
|
|
|
|||
114
radius.c
114
radius.c
|
|
@ -1,6 +1,6 @@
|
|||
// L2TPNS Radius Stuff
|
||||
|
||||
char const *cvs_id_radius = "$Id: radius.c,v 1.49.2.2 2006/08/02 14:17:20 bodea Exp $";
|
||||
char const *cvs_id_radius = "$Id: radius.c,v 1.56 2009/12/08 14:49:28 bodea Exp $";
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -45,6 +45,25 @@ static void calc_auth(const void *buf, size_t len, const uint8_t *in, uint8_t *o
|
|||
void initrad(void)
|
||||
{
|
||||
int i;
|
||||
uint16_t port = 0;
|
||||
uint16_t min = config->radius_bind_min;
|
||||
uint16_t max = config->radius_bind_max;
|
||||
int inc = 1;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
if (min)
|
||||
{
|
||||
port = min;
|
||||
if (!max)
|
||||
max = ~0 - 1;
|
||||
}
|
||||
else if (max) /* no minimum specified, bind from max down */
|
||||
{
|
||||
port = max;
|
||||
min = 1;
|
||||
inc = -1;
|
||||
}
|
||||
|
||||
LOG(3, 0, 0, "Creating %d sockets for RADIUS queries\n", RADIUS_FDS);
|
||||
radfds = calloc(sizeof(int), RADIUS_FDS);
|
||||
for (i = 0; i < RADIUS_FDS; i++)
|
||||
|
|
@ -53,6 +72,27 @@ void initrad(void)
|
|||
radfds[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
flags = fcntl(radfds[i], F_GETFL, 0);
|
||||
fcntl(radfds[i], F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
if (port)
|
||||
{
|
||||
int b;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
do {
|
||||
addr.sin_port = htons(port);
|
||||
if ((b = bind(radfds[i], (struct sockaddr *) &addr, sizeof(addr))) < 0)
|
||||
{
|
||||
if ((port += inc) < min || port > max)
|
||||
{
|
||||
LOG(0, 0, 0, "Can't bind RADIUS socket in range %u-%u\n", min, max);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} while (b < 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +177,7 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
return;
|
||||
}
|
||||
|
||||
if (state != RADIUSAUTH && !config->radius_accounting)
|
||||
if (state != RADIUSAUTH && state != RADIUSJUSTAUTH && !config->radius_accounting)
|
||||
{
|
||||
// Radius accounting is turned off
|
||||
radiusclear(r, s);
|
||||
|
|
@ -157,7 +197,7 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
{
|
||||
if (s)
|
||||
{
|
||||
if (state == RADIUSAUTH)
|
||||
if (state == RADIUSAUTH || state == RADIUSJUSTAUTH)
|
||||
sessionshutdown(s, "RADIUS timeout.", CDN_ADMIN_DISC, TERM_REAUTHENTICATION_FAILURE);
|
||||
else
|
||||
{
|
||||
|
|
@ -179,6 +219,7 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
switch (state)
|
||||
{
|
||||
case RADIUSAUTH:
|
||||
case RADIUSJUSTAUTH:
|
||||
b[0] = AccessRequest; // access request
|
||||
break;
|
||||
case RADIUSSTART:
|
||||
|
|
@ -199,7 +240,7 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
strcpy((char *) p + 2, session[s].user);
|
||||
p += p[1];
|
||||
}
|
||||
if (state == RADIUSAUTH)
|
||||
if (state == RADIUSAUTH || state == RADIUSJUSTAUTH)
|
||||
{
|
||||
if (radius[r].chap)
|
||||
{
|
||||
|
|
@ -330,6 +371,7 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s)
|
||||
{
|
||||
*p = 5; // NAS-Port
|
||||
|
|
@ -339,22 +381,23 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
|
||||
*p = 6; // Service-Type
|
||||
p[1] = 6;
|
||||
*(uint32_t *) (p + 2) = htonl(2); // Framed-User
|
||||
*(uint32_t *) (p + 2) = htonl((state == RADIUSJUSTAUTH ? 8 : 2)); // Authenticate only or Framed-User respectevily
|
||||
p += p[1];
|
||||
|
||||
*p = 7; // Framed-Protocol
|
||||
p[1] = 6;
|
||||
*(uint32_t *) (p + 2) = htonl(1); // PPP
|
||||
p[1] = htonl((state == RADIUSJUSTAUTH ? 0 : 6));
|
||||
*(uint32_t *) (p + 2) = htonl((state == RADIUSJUSTAUTH ? 0 : 1)); // PPP
|
||||
p += p[1];
|
||||
}
|
||||
if (s && session[s].ip)
|
||||
|
||||
if (session[s].ip)
|
||||
{
|
||||
*p = 8; // Framed-IP-Address
|
||||
p[1] = 6;
|
||||
*(uint32_t *) (p + 2) = htonl(session[s].ip);
|
||||
p += p[1];
|
||||
}
|
||||
if (s && session[s].route[0].ip)
|
||||
|
||||
if (session[s].route[0].ip)
|
||||
{
|
||||
int r;
|
||||
for (r = 0; s && r < MAXROUTE && session[s].route[r].ip; r++)
|
||||
|
|
@ -378,6 +421,23 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
p += p[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (session[s].session_timeout)
|
||||
{
|
||||
*p = 27; // Session-Timeout
|
||||
p[1] = 6;
|
||||
*(uint32_t *) (p + 2) = htonl(session[s].session_timeout);
|
||||
p += p[1];
|
||||
}
|
||||
|
||||
if (session[s].idle_timeout)
|
||||
{
|
||||
*p = 28; // Idle-Timeout
|
||||
p[1] = 6;
|
||||
*(uint32_t *) (p + 2) = htonl(session[s].idle_timeout);
|
||||
p += p[1];
|
||||
}
|
||||
|
||||
if (*session[s].called)
|
||||
{
|
||||
*p = 30; // called
|
||||
|
|
@ -385,6 +445,7 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
strcpy((char *) p + 2, session[s].called);
|
||||
p += p[1];
|
||||
}
|
||||
|
||||
if (*session[s].calling)
|
||||
{
|
||||
*p = 31; // calling
|
||||
|
|
@ -392,6 +453,8 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
strcpy((char *) p + 2, session[s].calling);
|
||||
p += p[1];
|
||||
}
|
||||
}
|
||||
|
||||
// NAS-IP-Address
|
||||
*p = 4;
|
||||
p[1] = 6;
|
||||
|
|
@ -400,7 +463,7 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
|
||||
// All AVpairs added
|
||||
*(uint16_t *) (b + 2) = htons(p - b);
|
||||
if (state != RADIUSAUTH)
|
||||
if (state != RADIUSAUTH && state != RADIUSJUSTAUTH)
|
||||
{
|
||||
// Build auth for accounting packet
|
||||
calc_auth(b, p - b, zero, b + 4);
|
||||
|
|
@ -413,7 +476,7 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
// get radius port
|
||||
uint16_t port = config->radiusport[(radius[r].try - 1) % config->numradiusservers];
|
||||
// assume RADIUS accounting port is the authentication port +1
|
||||
addr.sin_port = htons((state == RADIUSAUTH) ? port : port+1);
|
||||
addr.sin_port = htons((state == RADIUSAUTH || state == RADIUSJUSTAUTH) ? port : port+1);
|
||||
}
|
||||
|
||||
LOG_HEX(5, "RADIUS Send", b, (p - b));
|
||||
|
|
@ -496,7 +559,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
|||
LOG(1, s, session[s].tunnel, " Unexpected RADIUS response\n");
|
||||
return;
|
||||
}
|
||||
if (radius[r].state != RADIUSAUTH && radius[r].state != RADIUSSTART
|
||||
if (radius[r].state != RADIUSAUTH && radius[r].state != RADIUSJUSTAUTH && radius[r].state != RADIUSSTART
|
||||
&& radius[r].state != RADIUSSTOP && radius[r].state != RADIUSINTERIM)
|
||||
{
|
||||
LOG(1, s, session[s].tunnel, " Unexpected RADIUS response\n");
|
||||
|
|
@ -511,7 +574,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
|||
return; // Do nothing. On timeout, it will try the next radius server.
|
||||
}
|
||||
|
||||
if ((radius[r].state == RADIUSAUTH && r_code != AccessAccept && r_code != AccessReject) ||
|
||||
if (((radius[r].state == RADIUSAUTH ||radius[r].state == RADIUSJUSTAUTH) && r_code != AccessAccept && r_code != AccessReject) ||
|
||||
((radius[r].state == RADIUSSTART || radius[r].state == RADIUSSTOP || radius[r].state == RADIUSINTERIM) && r_code != AccountingResponse))
|
||||
{
|
||||
LOG(1, s, session[s].tunnel, " Unexpected RADIUS response %s\n", radius_code(r_code));
|
||||
|
|
@ -519,7 +582,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
|||
// care off finishing the radius session if that's really correct.
|
||||
}
|
||||
|
||||
if (radius[r].state == RADIUSAUTH)
|
||||
if (radius[r].state == RADIUSAUTH || radius[r].state == RADIUSJUSTAUTH)
|
||||
{
|
||||
// run post-auth plugin
|
||||
struct param_post_auth packet = {
|
||||
|
|
@ -537,7 +600,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
|||
if (radius[r].chap)
|
||||
{
|
||||
// CHAP
|
||||
uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP);
|
||||
uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP, 0, 0, 0);
|
||||
if (!p) return; // Abort!
|
||||
|
||||
*p = (r_code == AccessAccept) ? 3 : 4; // ack/nak
|
||||
|
|
@ -551,7 +614,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
|||
else
|
||||
{
|
||||
// PAP
|
||||
uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPPAP);
|
||||
uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPPAP, 0, 0, 0);
|
||||
if (!p) return; // Abort!
|
||||
|
||||
// ack/nak
|
||||
|
|
@ -715,6 +778,22 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
|||
ip_filters[f].used++;
|
||||
}
|
||||
}
|
||||
else if (*p == 27)
|
||||
{
|
||||
// Session-Timeout
|
||||
if (p[1] < 6) continue;
|
||||
session[s].session_timeout = ntohl(*(uint32_t *)(p + 2));
|
||||
LOG(3, s, session[s].tunnel, " Radius reply contains Session-Timeout = %u\n", session[s].session_timeout);
|
||||
if(!session[s].session_timeout && config->kill_timedout_sessions)
|
||||
sessionshutdown(s, "Session timeout is zero", CDN_ADMIN_DISC, 0);
|
||||
}
|
||||
else if (*p == 28)
|
||||
{
|
||||
// Idle-Timeout
|
||||
if (p[1] < 6) continue;
|
||||
session[s].idle_timeout = ntohl(*(uint32_t *)(p + 2));
|
||||
LOG(3, s, session[s].tunnel, " Radius reply contains Idle-Timeout = %u\n", session[s].idle_timeout);
|
||||
}
|
||||
else if (*p == 99)
|
||||
{
|
||||
// Framed-IPv6-Route
|
||||
|
|
@ -793,6 +872,7 @@ void radiusretry(uint16_t r)
|
|||
sendchap(s, t);
|
||||
break;
|
||||
case RADIUSAUTH: // sending auth to RADIUS server
|
||||
case RADIUSJUSTAUTH: // sending auth to RADIUS server
|
||||
case RADIUSSTART: // sending start accounting to RADIUS server
|
||||
case RADIUSSTOP: // sending stop accounting to RADIUS server
|
||||
case RADIUSINTERIM: // sending interim accounting to RADIUS server
|
||||
|
|
|
|||
11
test/Makefile
Normal file
11
test/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
CFLAGS = -g -Wall -W -std=c99 -pedantic
|
||||
TARGETS = bounce generateload radius
|
||||
|
||||
all: $(TARGETS)
|
||||
clean:
|
||||
rm -f $(TARGETS)
|
||||
|
||||
../md5.o: ../md5.c ../md5.h
|
||||
$(MAKE) -C .. md5.o
|
||||
|
||||
radius: radius.c ../md5.o
|
||||
|
|
@ -68,7 +68,8 @@ int main(int argc, char *argv[])
|
|||
while (1)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int alen = sizeof(addr), l;
|
||||
socklen_t alen = sizeof(addr);
|
||||
int l;
|
||||
unsigned int iseq;
|
||||
|
||||
l = recvfrom(s, packet, 65535, 0, (void *) &addr, &alen);
|
||||
|
|
@ -87,7 +88,7 @@ int main(int argc, char *argv[])
|
|||
free(packet);
|
||||
}
|
||||
|
||||
void sigalarm(int junk)
|
||||
void sigalarm(int unusedg __attribute__ ((unused)))
|
||||
{
|
||||
printf("Recv: %10llu %0.1fMbits/s (%lu pps) (%5ld dropped)\n", recv_count, (bytes / 1024.0 / 1024.0 * 8), pps, dropped);
|
||||
pps = bytes = 0;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
#define _POSIX_C_SOURCE 200112L
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#define __USE_XOPEN_EXTENDED
|
||||
#define __USE_MISC
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -6,11 +12,8 @@
|
|||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/udp.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -179,10 +182,10 @@ typedef struct
|
|||
} control_message;
|
||||
|
||||
typedef struct {
|
||||
unsigned long long send_count , recv_count ;
|
||||
unsigned long long spkt , rpkt ;
|
||||
unsigned int dropped;
|
||||
unsigned long sbytes , rbytes ;
|
||||
long long send_count, recv_count;
|
||||
long long spkt, rpkt ;
|
||||
int dropped;
|
||||
long sbytes, rbytes ;
|
||||
int quitit;
|
||||
struct sessiont
|
||||
{
|
||||
|
|
@ -210,7 +213,7 @@ void dump_control_message(control_message *c);
|
|||
u32 avp_get_32(control_message *c, int id);
|
||||
u16 avp_get_16(control_message *c, int id);
|
||||
char *avp_get_s(control_message *c, int id);
|
||||
void reader_thread(int udpfd);
|
||||
void reader_thread(void);
|
||||
void skip_zlb();
|
||||
void cm_free(control_message *m);
|
||||
controlt *ppp_new(u16 session, int protocol);
|
||||
|
|
@ -234,7 +237,7 @@ void print_report();
|
|||
int ns = 0, nr = 0;
|
||||
int udpfd;
|
||||
int t = 0;
|
||||
struct sockaddr_in gatewayaddr = {0};
|
||||
struct sockaddr_in gatewayaddr;
|
||||
int numsessions = NUM_SESSIONS;
|
||||
int packet_length = PACKET_LENGTH;
|
||||
int target_pps = TARGET_PPS;
|
||||
|
|
@ -251,7 +254,7 @@ char *suffix = "@optusnet.com.au";
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
int s;
|
||||
char *packet;
|
||||
unsigned char *packet;
|
||||
|
||||
ss = (sharedt*) mmap(NULL, sizeof(*ss), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
|
||||
|
||||
|
|
@ -377,6 +380,7 @@ int main(int argc, char *argv[])
|
|||
printf("Bound to port %d\n", htons(addr.sin_port));
|
||||
}/*}}}*/
|
||||
|
||||
memset(&gatewayaddr, 0, sizeof(gatewayaddr));
|
||||
gatewayaddr.sin_family = AF_INET;
|
||||
gatewayaddr.sin_port = htons(1701);
|
||||
inet_aton(gwaddr, &gatewayaddr.sin_addr);
|
||||
|
|
@ -400,7 +404,8 @@ int main(int argc, char *argv[])
|
|||
// Receive reply/*{{{*/
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int alen = sizeof(addr), l;
|
||||
int l;
|
||||
socklen_t alen = sizeof(addr);
|
||||
|
||||
l = recvfrom(udpfd, packet, 4096, 0, (void *) &addr, &alen);
|
||||
if (l < 0)
|
||||
|
|
@ -409,7 +414,7 @@ int main(int argc, char *argv[])
|
|||
return -1;
|
||||
}
|
||||
printf("Received ");
|
||||
r = parsecontrol(packet, l);
|
||||
r = parsecontrol((char *) packet, l);
|
||||
if (!r->first)
|
||||
{
|
||||
printf("Invalid packet.. no first avp\n");
|
||||
|
|
@ -446,7 +451,7 @@ int main(int argc, char *argv[])
|
|||
printf("All session create requests sent...\n");/*}}}*/
|
||||
|
||||
if ( fork() == 0) {
|
||||
reader_thread(udpfd);
|
||||
reader_thread();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
|
@ -529,7 +534,7 @@ int main(int argc, char *argv[])
|
|||
*(u16 *)(c->buf + 4) = htons(ss->sessions[i].remote_session); // Session ID
|
||||
iph->saddr = ss->sessions[i].addr;
|
||||
iph->check = 0;
|
||||
iph->check = ntohs(checksum((char *)iph, sizeof(struct iphdr)));
|
||||
iph->check = ntohs(checksum((unsigned char *)iph, sizeof(struct iphdr)));
|
||||
|
||||
*((unsigned int *) data) = seq++;
|
||||
ppp_send(c);
|
||||
|
|
@ -546,7 +551,8 @@ int main(int argc, char *argv[])
|
|||
nanosleep(&req, NULL);
|
||||
}
|
||||
|
||||
if (max_packets && ss->send_count >= max_packets) ss->quitit++;
|
||||
if (max_packets && ss->send_count >= max_packets)
|
||||
ss->quitit++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -602,22 +608,24 @@ void clean_shutdown()/*{{{*/
|
|||
}
|
||||
}/*}}}*/
|
||||
|
||||
void sigint(int signal)
|
||||
void sigint(int unused __attribute__ ((unused)))
|
||||
{
|
||||
ss->quitit++;
|
||||
}
|
||||
|
||||
void sigalarm(int junk)
|
||||
void sigalarm(int unused __attribute__ ((unused)))
|
||||
{
|
||||
static unsigned long long last_rpkts[AVG_SIZE], last_spkts[AVG_SIZE];
|
||||
static int last = 0, avg_count = 0;
|
||||
register unsigned int avg_s = 0, avg_r = 0, i;
|
||||
unsigned int avg_s = 0, avg_r = 0;
|
||||
int i;
|
||||
float loss;
|
||||
|
||||
last_rpkts[last] = ss->rpkt;
|
||||
last_spkts[last] = ss->spkt;
|
||||
last = (last + 1) % AVG_SIZE;
|
||||
if (avg_count < AVG_SIZE) avg_count++;
|
||||
if (avg_count < AVG_SIZE)
|
||||
avg_count++;
|
||||
|
||||
for (i = 0; i < avg_count; i++)
|
||||
{
|
||||
|
|
@ -867,7 +875,7 @@ void cm_free(control_message *m)
|
|||
|
||||
// }}}
|
||||
|
||||
void reader_thread(int updfd)/*{{{*/
|
||||
void reader_thread()/*{{{*/
|
||||
{
|
||||
unsigned char *packet;
|
||||
unsigned int seq = 0;
|
||||
|
|
@ -877,7 +885,7 @@ void reader_thread(int updfd)/*{{{*/
|
|||
while (!ss->quitit)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int alen = sizeof(addr);
|
||||
socklen_t alen = sizeof(addr);
|
||||
control_message *m;
|
||||
int l;
|
||||
int s;
|
||||
|
|
@ -906,7 +914,7 @@ void reader_thread(int updfd)/*{{{*/
|
|||
{
|
||||
// Control Packet
|
||||
printf("Reader Received ");
|
||||
m = parsecontrol(packet, l);
|
||||
m = parsecontrol((char *) packet, l);
|
||||
printf("\n");
|
||||
s = m->session;
|
||||
|
||||
|
|
@ -975,7 +983,7 @@ void reader_thread(int updfd)/*{{{*/
|
|||
if (protocol != PPPIP)
|
||||
{
|
||||
printf("Received ");
|
||||
dump_ppp_packet(packet + 6, l - 6);
|
||||
dump_ppp_packet((char *) (packet + 6), l - 6);
|
||||
}
|
||||
|
||||
if (protocol == PPPLCP)
|
||||
|
|
@ -1073,13 +1081,13 @@ void reader_thread(int updfd)/*{{{*/
|
|||
|
||||
if (iph->protocol == 17)
|
||||
{
|
||||
int iseq;
|
||||
unsigned int iseq;
|
||||
ss->recv_count++;
|
||||
ss->rpkt++;
|
||||
iseq = *((unsigned int *) data);
|
||||
if (seq != iseq) {
|
||||
if (seq != iseq)
|
||||
ss->dropped += (iseq - seq) ;
|
||||
}
|
||||
|
||||
seq = iseq + 1; // Next sequence number to expect.
|
||||
}
|
||||
}
|
||||
|
|
@ -1095,7 +1103,7 @@ void reader_thread(int updfd)/*{{{*/
|
|||
void skip_zlb() /*{{{*/
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int alen = sizeof(addr);
|
||||
socklen_t alen = sizeof(addr);
|
||||
char buf[1024];
|
||||
int l;
|
||||
l = recvfrom(udpfd, buf, 1024, MSG_PEEK, (void *) &addr, &alen);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue