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
|
* Thu Jan 20 2011 Brendan O'Dea <bod@optus.net> 2.2.x
|
||||||
- Security: Rhys Kidd identified a vulnerability in the handling of
|
- Apply MLPPP patch from Muhammad Tayseer Alquoatli.
|
||||||
heartbeat packets. Drop oversize heartbeat packets.
|
- 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
|
* Mon Dec 18 2006 Brendan O'Dea <bod@optus.net> 2.2.0
|
||||||
- Fix sign problem with reporting of unknown VSAs.
|
- Only poll clifd if successfully bound.
|
||||||
- Allow DNS servers to be specified either using the old or new
|
- Add "Practical VPNs" document from Liran Tal as Docs/vpn .
|
||||||
vendor-specific Ascend formats.
|
- Add Multilink support from Khaled Al Hamwi.
|
||||||
|
- Remove non-working setuid option.
|
||||||
* Fri Jun 23 2006 Brendan O'Dea <bod@optus.net> 2.1.19
|
- Convert manual.html to Docbook.
|
||||||
- Kludge around problem with Netgear DM602 authentication.
|
- 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
|
- Use result code AVP to set Acct-Terminate-Cause is disconnect cause
|
||||||
AVP is not present.
|
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
|
* Tue Apr 18 2006 Brendan O'Dea <bod@optus.net> 2.1.18
|
||||||
- Don't shutdown on TerminateReq, wait for CDN.
|
- 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
|
.de Id
|
||||||
.ds Dt \\$4 \\$5
|
.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"
|
.TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
startup\-config \- configuration file for l2tpns
|
startup\-config \- configuration file for l2tpns
|
||||||
|
|
@ -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
|
Number of Configure-Nak requests to send before sending a
|
||||||
Configure-Reject (default: 5).
|
Configure-Reject (default: 5).
|
||||||
.TP
|
.TP
|
||||||
.BR primary_dns , " secondary_dns"
|
.BR primary_dns ", " secondary_dns
|
||||||
Whenever a PPP connection is established, DNS servers will be sent to the
|
Whenever a PPP connection is established, DNS servers will be sent to the
|
||||||
user, both a primary and a secondary. If either is set to 0.0.0.0, then that
|
user, both a primary and a secondary. If either is set to 0.0.0.0, then that
|
||||||
one will not be sent.
|
one will not be sent.
|
||||||
.TP
|
.TP
|
||||||
.BR primary_radius , " secondary_radius"
|
.BR primary_radius ", " secondary_radius
|
||||||
Sets the RADIUS servers used for both authentication and accounting.
|
Sets the RADIUS servers used for both authentication and accounting.
|
||||||
If the primary server does not respond, then the secondary RADIUS
|
If the primary server does not respond, then the secondary RADIUS
|
||||||
server will be tried.
|
server will be tried.
|
||||||
.TP
|
.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
|
Sets the authentication ports for the primary and secondary RADIUS
|
||||||
servers. The accounting port is one more than the authentication
|
servers. The accounting port is one more than the authentication
|
||||||
port. If no ports are given, authentication defaults to 1645, and
|
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)
|
Port for DAE RADIUS (Packet of Death/Disconnect, Change of Authorization)
|
||||||
requests (default: 3799).
|
requests (default: 3799).
|
||||||
.TP
|
.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
|
.B allow_duplicate_users
|
||||||
Allow multiple logins with the same username. If false (the default),
|
Allow multiple logins with the same username. If false (the default),
|
||||||
any prior session with the same username will be dropped when a new
|
any prior session with the same username will be dropped when a new
|
||||||
session is established.
|
session is established.
|
||||||
.TP
|
.TP
|
||||||
|
.B guest_account
|
||||||
|
Allow multiple logins matching this specific username.
|
||||||
|
.TP
|
||||||
.B bind_address
|
.B bind_address
|
||||||
When the tun interface is created, it is assigned the 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
|
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
|
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.
|
every connected use will be dumped to a file in this directory.
|
||||||
.TP
|
.TP
|
||||||
.B setuid
|
|
||||||
After starting up and binding the interface, change UID to this. This
|
|
||||||
doesn't work properly.
|
|
||||||
.TP
|
|
||||||
.B dump_speed
|
.B dump_speed
|
||||||
If set to true, then the current bandwidth utilization will be logged
|
If set to true, then the current bandwidth utilization will be logged
|
||||||
every second. Even if this is disabled, you can see this information
|
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>
|
Juergen Kammer <j.kammer@eurodata.de>
|
||||||
Simon Talbot <simont@nse.co.uk>
|
Simon Talbot <simont@nse.co.uk>
|
||||||
Jonathan McDowell <noodles@earth.li>
|
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>
|
Roberto Chostakovis <rchostakovis@users.sourceforge.net>
|
||||||
Jordan Hrycaj <jordan@mjh.teddy-net.com>
|
Jordan Hrycaj <jordan@mjh.teddy-net.com>
|
||||||
Vladislav Bjelic <vladislav@gmail.com>
|
Vladislav Bjelic <vladislav@gmail.com>
|
||||||
|
|
@ -26,4 +26,8 @@ Jon Morby <jon@fido.net>
|
||||||
Paul Martin <pm@zetnet.net>
|
Paul Martin <pm@zetnet.net>
|
||||||
Jonathan Yarden <jyarden@bluegrass.net>
|
Jonathan Yarden <jyarden@bluegrass.net>
|
||||||
Patrick Cole <z@amused.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>
|
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
|
* lcp:interface-config#2=service-policy output N
|
||||||
*
|
*
|
||||||
* throttle=N
|
* throttle=N
|
||||||
* throttle=yes (use throttle_rate from config)
|
* throttle=yes (use throttle_speed from config)
|
||||||
* throttle=no
|
* 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;
|
int plugin_api_version = PLUGIN_API_VERSION;
|
||||||
static struct pluginfuncs *f = 0;
|
static struct pluginfuncs *f = 0;
|
||||||
|
|
|
||||||
50
cli.c
50
cli.c
|
|
@ -1,8 +1,8 @@
|
||||||
// L2TPNS Command Line Interface
|
// L2TPNS Command Line Interface
|
||||||
// vim: sw=8 ts=8
|
// vim: sw=8 ts=8
|
||||||
|
|
||||||
char const *cvs_name = "$Name: release_2_1_21 $";
|
char const *cvs_name = "$Name: $";
|
||||||
char const *cvs_id_cli = "$Id: cli.c,v 1.71 2005/12/06 09:43:42 bodea Exp $";
|
char const *cvs_id_cli = "$Id: cli.c,v 1.76 2006/12/18 12:08:28 bodea Exp $";
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stddef.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
|
#endif
|
||||||
|
|
||||||
extern tunnelt *tunnel;
|
extern tunnelt *tunnel;
|
||||||
|
extern bundlet *bundle;
|
||||||
extern sessiont *session;
|
extern sessiont *session;
|
||||||
extern radiust *radius;
|
extern radiust *radius;
|
||||||
extern ippoolt *ip_address_pool;
|
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_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_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_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);
|
static int regular_stuff(struct cli_def *cli);
|
||||||
|
|
||||||
|
|
@ -175,6 +179,8 @@ void init_cli(char *hostname)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cli_register_command(cli, NULL, "uptime", cmd_uptime, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show uptime and bandwidth utilisation");
|
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);
|
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");
|
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));
|
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));
|
setsockopt(clifd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||||
{
|
{
|
||||||
int flags;
|
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, "\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, "\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);
|
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, "\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, "\tPkts In/Out:\t%u/%u", session[s].pout, session[s].pin);
|
||||||
cli_print(cli, "\tMRU:\t\t%d", session[s].mru);
|
cli_print(cli, "\tMRU:\t\t%d", session[s].mru);
|
||||||
|
|
@ -2016,7 +2034,7 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a
|
||||||
int keepalive;
|
int keepalive;
|
||||||
int hold;
|
int hold;
|
||||||
|
|
||||||
if (CLI_HELP_REQUESTED)
|
if (CLI_HELP_REQUESTED)
|
||||||
{
|
{
|
||||||
switch (argc)
|
switch (argc)
|
||||||
{
|
{
|
||||||
|
|
@ -2126,14 +2144,14 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a
|
||||||
config->neighbour[i].keepalive = keepalive;
|
config->neighbour[i].keepalive = keepalive;
|
||||||
config->neighbour[i].hold = hold;
|
config->neighbour[i].hold = hold;
|
||||||
|
|
||||||
return CLI_OK;
|
return CLI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_router_bgp_no_neighbour(struct cli_def *cli, char *command, char **argv, int argc)
|
static int cmd_router_bgp_no_neighbour(struct cli_def *cli, char *command, char **argv, int argc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (CLI_HELP_REQUESTED)
|
if (CLI_HELP_REQUESTED)
|
||||||
return cli_arg_help(cli, argc > 0,
|
return cli_arg_help(cli, argc > 0,
|
||||||
"A.B.C.D", "BGP neighbour address",
|
"A.B.C.D", "BGP neighbour address",
|
||||||
"NAME", "BGP neighbour name",
|
"NAME", "BGP neighbour name",
|
||||||
|
|
@ -2158,7 +2176,7 @@ static int cmd_router_bgp_no_neighbour(struct cli_def *cli, char *command, char
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&config->neighbour[i], 0, sizeof(config->neighbour[i]));
|
memset(&config->neighbour[i], 0, sizeof(config->neighbour[i]));
|
||||||
return CLI_OK;
|
return CLI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_show_bgp(struct cli_def *cli, char *command, char **argv, int argc)
|
static int cmd_show_bgp(struct cli_def *cli, char *command, char **argv, int argc)
|
||||||
|
|
@ -3064,3 +3082,21 @@ static int cmd_show_access_list(struct cli_def *cli, char *command, char **argv,
|
||||||
|
|
||||||
return CLI_OK;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
169
cluster.c
169
cluster.c
|
|
@ -1,6 +1,6 @@
|
||||||
// L2TPNS Clustering Stuff
|
// 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 <stdio.h>
|
||||||
#include <stdlib.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.
|
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_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.
|
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
|
int forked = 0; // Sanity check: CLI must not diddle with heartbeat table
|
||||||
|
|
||||||
|
|
@ -85,6 +86,7 @@ int cluster_init()
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
config->cluster_undefined_sessions = MAXSESSION-1;
|
config->cluster_undefined_sessions = MAXSESSION-1;
|
||||||
|
config->cluster_undefined_bundles = MAXBUNDLE-1;
|
||||||
config->cluster_undefined_tunnels = MAXTUNNEL-1;
|
config->cluster_undefined_tunnels = MAXTUNNEL-1;
|
||||||
|
|
||||||
if (!config->cluster_address)
|
if (!config->cluster_address)
|
||||||
|
|
@ -227,7 +229,7 @@ static void cluster_uptodate(void)
|
||||||
if (config->cluster_iam_uptodate)
|
if (config->cluster_iam_uptodate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels)
|
if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels || config->cluster_undefined_bundles)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
config->cluster_iam_uptodate = 1;
|
config->cluster_iam_uptodate = 1;
|
||||||
|
|
@ -400,7 +402,7 @@ void cluster_send_ping(time_t basetime)
|
||||||
|
|
||||||
x.ver = 1;
|
x.ver = 1;
|
||||||
x.addr = config->bind_address;
|
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;
|
x.basetime = basetime;
|
||||||
|
|
||||||
add_type(&p, C_PING, basetime, (uint8_t *) &x, sizeof(x));
|
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)
|
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;
|
int last_free = 0;
|
||||||
clockt t = TIME;
|
clockt t = TIME;
|
||||||
static int probed = 0;
|
static int probed = 0;
|
||||||
|
|
@ -614,6 +616,19 @@ void cluster_check_master(void)
|
||||||
config->cluster_highest_tunnelid = i;
|
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.
|
// Go through and mark all the sessions as being defined.
|
||||||
// reset the idle timeouts.
|
// reset the idle timeouts.
|
||||||
|
|
@ -639,7 +654,7 @@ void cluster_check_master(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset idle timeouts..
|
// 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
|
// Reset die relative to our uptime rather than the old master's
|
||||||
if (session[i].die) session[i].die = TIME;
|
if (session[i].die) session[i].die = TIME;
|
||||||
|
|
@ -675,10 +690,11 @@ void cluster_check_master(void)
|
||||||
rebuild_address_pool();
|
rebuild_address_pool();
|
||||||
|
|
||||||
// If we're not the very first master, this is a big issue!
|
// If we're not the very first master, this is a big issue!
|
||||||
if(count>0)
|
if (count > 0)
|
||||||
LOG(0, 0, 0, "Warning: Fixed %d uninitialized sessions in becoming master!\n", count);
|
LOG(0, 0, 0, "Warning: Fixed %d uninitialized sessions in becoming master!\n", count);
|
||||||
|
|
||||||
config->cluster_undefined_sessions = 0;
|
config->cluster_undefined_sessions = 0;
|
||||||
|
config->cluster_undefined_bundles = 0;
|
||||||
config->cluster_undefined_tunnels = 0;
|
config->cluster_undefined_tunnels = 0;
|
||||||
config->cluster_iam_uptodate = 1; // assume all peers are up-to-date
|
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'
|
// we fix it up here, and we ensure that the 'first free session'
|
||||||
// pointer is valid.
|
// 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;
|
int i;
|
||||||
|
|
||||||
|
|
@ -705,7 +721,7 @@ static void cluster_check_sessions(int highsession, int freesession_ptr, int hig
|
||||||
if (config->cluster_iam_uptodate)
|
if (config->cluster_iam_uptodate)
|
||||||
return;
|
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;
|
return;
|
||||||
|
|
||||||
// Clear out defined sessions, counting the number of
|
// 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;
|
++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
|
// Clear out defined tunnels, counting the number of
|
||||||
// undefs remaining.
|
// undefs remaining.
|
||||||
config->cluster_undefined_tunnels = 0;
|
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) {
|
if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels || config->cluster_undefined_bundles) {
|
||||||
LOG(2, 0, 0, "Cleared undefined sessions/tunnels. %d sess (high %d), %d tunn (high %d)\n",
|
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_tunnels, hightunnel);
|
config->cluster_undefined_sessions, highsession, config->cluster_undefined_bundles, highbundle, config->cluster_undefined_tunnels, hightunnel);
|
||||||
return;
|
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));
|
add_type(p, C_SESSION, id, (uint8_t *) &session[id], sizeof(sessiont));
|
||||||
break;
|
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
|
case C_CTUNNEL: { // Compressed C_TUNNEL
|
||||||
uint8_t c[sizeof(tunnelt) * 2]; // Bigger than worst case.
|
uint8_t c[sizeof(tunnelt) * 2]; // Bigger than worst case.
|
||||||
uint8_t *d = (uint8_t *) &tunnel[id];
|
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()
|
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) ];
|
uint8_t buff[MAX_HEART_SIZE + sizeof(heartt) + sizeof(int) ];
|
||||||
heartt h;
|
heartt h;
|
||||||
uint8_t *p = buff;
|
uint8_t *p = buff;
|
||||||
|
|
@ -823,7 +873,9 @@ void cluster_heartbeat()
|
||||||
h.highsession = config->cluster_highest_sessionid;
|
h.highsession = config->cluster_highest_sessionid;
|
||||||
h.freesession = sessionfree;
|
h.freesession = sessionfree;
|
||||||
h.hightunnel = config->cluster_highest_tunnelid;
|
h.hightunnel = config->cluster_highest_tunnelid;
|
||||||
|
h.highbundle = config->cluster_highest_bundleid;
|
||||||
h.size_sess = sizeof(sessiont); // Just in case.
|
h.size_sess = sizeof(sessiont); // Just in case.
|
||||||
|
h.size_bund = sizeof(bundlet);
|
||||||
h.size_tunn = sizeof(tunnelt);
|
h.size_tunn = sizeof(tunnelt);
|
||||||
h.interval = config->cluster_hb_interval;
|
h.interval = config->cluster_hb_interval;
|
||||||
h.timeout = config->cluster_hb_timeout;
|
h.timeout = config->cluster_hb_timeout;
|
||||||
|
|
@ -878,6 +930,21 @@ void cluster_heartbeat()
|
||||||
++tcount;
|
++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?
|
// Did we do something wrong?
|
||||||
if (p > (buff + sizeof(buff))) { // Did we somehow manage to overun the buffer?
|
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 "
|
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,
|
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_highest_tunnelid, (int) (p - buff));
|
||||||
|
|
||||||
config->cluster_num_changes = 0;
|
config->cluster_num_changes = 0;
|
||||||
|
|
@ -938,6 +1005,17 @@ int cluster_send_session(int sid)
|
||||||
return type_changed(C_CSESSION, 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!
|
// A particular tunnel has been changed!
|
||||||
int cluster_send_tunnel(int tid)
|
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;
|
session[b->sid].cout_delta += b->cout;
|
||||||
|
|
||||||
if (b->cin)
|
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);
|
size -= sizeof(*b);
|
||||||
++b;
|
++b;
|
||||||
|
|
@ -1175,6 +1255,31 @@ static int cluster_recv_session(int more, uint8_t *p)
|
||||||
return 0;
|
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)
|
static int cluster_recv_tunnel(int more, uint8_t *p)
|
||||||
{
|
{
|
||||||
if (more >= MAXTUNNEL) {
|
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
|
// Check that we don't have too many undefined sessions, and
|
||||||
// that the free session pointer is correct.
|
// 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)
|
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]);
|
p += sizeof(tunnel[more]);
|
||||||
s -= sizeof(tunnel[more]);
|
s -= sizeof(tunnel[more]);
|
||||||
break;
|
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:
|
default:
|
||||||
LOG(0, 0, 0, "DANGER: I received a heartbeat element where I didn't understand the type! (%d)\n", type);
|
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!!
|
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.
|
case C_FORWARD_DAE: // Forwarded DAE packet. pass off to processdae.
|
||||||
if (!config->cluster_iam_master)
|
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));
|
type == C_FORWARD_DAE ? "_DAE" : "", fmtaddr(addr, 0));
|
||||||
|
|
||||||
return -1;
|
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, "Table version # : %" PRIu64, config->cluster_table_version);
|
||||||
cli_print(cli, "Next sequence number expected: %d", config->cluster_seq_number);
|
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 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);
|
cli_print(cli, "%d tunnels undefined of %d", config->cluster_undefined_tunnels, config->cluster_highest_tunnelid);
|
||||||
} else {
|
} else {
|
||||||
cli_print(cli, "Table version # : %" PRIu64, config->cluster_table_version);
|
cli_print(cli, "Table version # : %" PRIu64, config->cluster_table_version);
|
||||||
cli_print(cli, "Next heartbeat # : %d", config->cluster_seq_number);
|
cli_print(cli, "Next heartbeat # : %d", config->cluster_seq_number);
|
||||||
cli_print(cli, "Highest session : %d", config->cluster_highest_sessionid);
|
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, "Highest tunnel : %d", config->cluster_highest_tunnelid);
|
||||||
cli_print(cli, "%d changes queued for sending", config->cluster_num_changes);
|
cli_print(cli, "%d changes queued for sending", config->cluster_num_changes);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// L2TPNS Clustering Stuff
|
// 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__
|
#ifndef __CLUSTER_H__
|
||||||
#define __CLUSTER_H__
|
#define __CLUSTER_H__
|
||||||
|
|
@ -21,6 +21,8 @@
|
||||||
#define C_GARDEN 14 // Gardened packet
|
#define C_GARDEN 14 // Gardened packet
|
||||||
#define C_MASTER 15 // Tell a slave the address of the master.
|
#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_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_VERSION 5 // Protocol version number..
|
||||||
#define HB_MAX_SEQ (1<<30) // Maximum sequence number. (MUST BE A POWER OF 2!)
|
#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 highsession; // Id of the highest in-use session.
|
||||||
uint32_t freesession; // Id of the first free 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 hightunnel; // Id of the highest used tunnel.
|
||||||
uint32_t size_sess; // Size of the session structure.
|
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 size_tunn; // size of the tunnel structure.
|
||||||
uint32_t interval; // ping/heartbeat interval
|
uint32_t interval; // ping/heartbeat interval
|
||||||
uint32_t timeout; // heartbeat timeout
|
uint32_t timeout; // heartbeat timeout
|
||||||
|
|
||||||
uint64_t table_version; // # state changes processed by cluster
|
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;
|
} heartt;
|
||||||
|
|
||||||
typedef struct { /* Used to update byte counters on the */
|
typedef struct { /* Used to update byte counters on the */
|
||||||
|
|
@ -74,6 +78,7 @@ typedef struct {
|
||||||
int cluster_init(void);
|
int cluster_init(void);
|
||||||
int processcluster(uint8_t *buf, int size, in_addr_t addr);
|
int processcluster(uint8_t *buf, int size, in_addr_t addr);
|
||||||
int cluster_send_session(int sid);
|
int cluster_send_session(int sid);
|
||||||
|
int cluster_send_bundle(int bid);
|
||||||
int cluster_send_tunnel(int tid);
|
int cluster_send_tunnel(int tid);
|
||||||
int master_forward_packet(uint8_t *data, int size, in_addr_t addr, int port);
|
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);
|
int master_forward_dae_packet(uint8_t *data, int size, in_addr_t addr, int port);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// L2TPNS: constants
|
// 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 <stdio.h>
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
|
@ -197,7 +197,8 @@ CONSTANT(radius_state,
|
||||||
"RADIUSSTART", // 3
|
"RADIUSSTART", // 3
|
||||||
"RADIUSSTOP", // 4
|
"RADIUSSTOP", // 4
|
||||||
"RADIUSINTERIM", // 5
|
"RADIUSINTERIM", // 5
|
||||||
"RADIUSWAIT" // 6
|
"RADIUSWAIT", // 6
|
||||||
|
"RADIUSJUSTAUTH" // 7
|
||||||
)
|
)
|
||||||
|
|
||||||
CONSTANT(radius_code,
|
CONSTANT(radius_code,
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,12 @@ set radius_secret "secret"
|
||||||
# Allow multiple logins for the same username
|
# Allow multiple logins for the same username
|
||||||
#set allow_duplicate_users no
|
#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
|
# Write usage accounting files into specified directory
|
||||||
set accounting_dir "/var/run/l2tpns/acct"
|
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
|
# Number of buckets to allocate for throttling
|
||||||
#set throttle_buckets 3000
|
#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
|
# If set to true, dump current speed to stderr every second
|
||||||
#set dump_speed no
|
#set dump_speed no
|
||||||
|
|
||||||
|
|
@ -96,6 +99,9 @@ set accounting_dir "/var/run/l2tpns/acct"
|
||||||
# Minimum number of slaves before master withdraws routes
|
# Minimum number of slaves before master withdraws routes
|
||||||
#set cluster_master_min_adv 1
|
#set cluster_master_min_adv 1
|
||||||
|
|
||||||
|
# IPv6 address prefix
|
||||||
|
#set ipv6_prefix ::
|
||||||
|
|
||||||
# Drop/kill sessions
|
# Drop/kill sessions
|
||||||
#load plugin "sessionctl"
|
#load plugin "sessionctl"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* kludge up some limited epoll semantics using select for 2.4 kernels */
|
/* 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__
|
#ifndef __FAKE_EPOLL_H__
|
||||||
#define __FAKE_EPOLL_H__
|
#define __FAKE_EPOLL_H__
|
||||||
|
|
@ -150,6 +150,9 @@ static int epoll_wait(int epfd __attribute__ ((unused)),
|
||||||
tp = 0;
|
tp = 0;
|
||||||
|
|
||||||
n = select(_epoll_fds, &r, &w, 0, tp);
|
n = select(_epoll_fds, &r, &w, 0, tp);
|
||||||
|
if (n < 0)
|
||||||
|
return n;
|
||||||
|
|
||||||
if (n > maxevents)
|
if (n > maxevents)
|
||||||
n = maxevents;
|
n = maxevents;
|
||||||
|
|
||||||
|
|
|
||||||
4
icmp.c
4
icmp.c
|
|
@ -1,6 +1,6 @@
|
||||||
// L2TPNS: icmp
|
// 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 <arpa/inet.h>
|
||||||
#include <netdb.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");
|
LOG(3, s, t, "Sending IPv6 RA\n");
|
||||||
|
|
||||||
memset(b, 0, sizeof(b));
|
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)
|
if (!o)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
121
l2tpns.h
121
l2tpns.h
|
|
@ -1,5 +1,5 @@
|
||||||
// L2TPNS Global Stuff
|
// 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__
|
#ifndef __L2TPNS_H__
|
||||||
#define __L2TPNS_H__
|
#define __L2TPNS_H__
|
||||||
|
|
@ -14,10 +14,13 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <libcli.h>
|
#include <libcli.h>
|
||||||
|
|
||||||
#define VERSION "2.1.21"
|
#define VERSION "2.2.0"
|
||||||
|
|
||||||
// Limits
|
// Limits
|
||||||
#define MAXTUNNEL 500 // could be up to 65535
|
#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 MAXSESSION 60000 // could be up to 65535
|
||||||
#define MAXTBFS 6000 // Maximum token bucket filters. Might need up to 2 * session.
|
#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 MAXIPPOOL 131072 // max number of ip addresses in pool
|
||||||
#define RINGBUFFER_SIZE 10000 // Number of ringbuffer entries to allocate
|
#define RINGBUFFER_SIZE 10000 // Number of ringbuffer entries to allocate
|
||||||
#define MAX_LOG_LENGTH 512 // Maximum size of log message
|
#define MAX_LOG_LENGTH 512 // Maximum size of log message
|
||||||
#define ECHO_TIMEOUT 60 // 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 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 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
|
// Constants
|
||||||
#ifndef ETCDIR
|
#ifndef ETCDIR
|
||||||
#define ETCDIR "/etc/l2tpns"
|
#define ETCDIR "/etc/l2tpns"
|
||||||
|
|
@ -186,6 +199,7 @@ enum {
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
typedef uint16_t sessionidt;
|
typedef uint16_t sessionidt;
|
||||||
|
typedef uint16_t bundleidt;
|
||||||
typedef uint16_t tunnelidt;
|
typedef uint16_t tunnelidt;
|
||||||
typedef uint32_t clockt;
|
typedef uint32_t clockt;
|
||||||
typedef uint8_t hasht[16];
|
typedef uint8_t hasht[16];
|
||||||
|
|
@ -231,6 +245,20 @@ typedef struct controls // control message
|
||||||
}
|
}
|
||||||
controlt;
|
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
|
typedef struct
|
||||||
{
|
{
|
||||||
sessionidt next; // next session in linked list
|
sessionidt next; // next session in linked list
|
||||||
|
|
@ -261,7 +289,10 @@ typedef struct
|
||||||
uint16_t mru; // maximum receive unit
|
uint16_t mru; // maximum receive unit
|
||||||
clockt opened; // when started
|
clockt opened; // when started
|
||||||
clockt die; // being closed, when to finally free
|
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_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
|
in_addr_t dns1, dns2; // DNS servers
|
||||||
routet route[MAXROUTE]; // static routes
|
routet route[MAXROUTE]; // static routes
|
||||||
uint16_t tbf_in; // filter bucket for throttling in from the user.
|
uint16_t tbf_in; // filter bucket for throttling in from the user.
|
||||||
|
|
@ -273,6 +304,11 @@ typedef struct
|
||||||
char calling[MAXTEL]; // calling number
|
char calling[MAXTEL]; // calling number
|
||||||
uint32_t tx_connect_speed;
|
uint32_t tx_connect_speed;
|
||||||
uint32_t rx_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
|
in_addr_t snoop_ip; // Interception destination IP
|
||||||
uint16_t snoop_port; // Interception destination port
|
uint16_t snoop_port; // Interception destination port
|
||||||
uint8_t walled_garden; // is this session gardened?
|
uint8_t walled_garden; // is this session gardened?
|
||||||
|
|
@ -282,6 +318,36 @@ typedef struct
|
||||||
}
|
}
|
||||||
sessiont;
|
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 AUTHPAP 1 // allow PAP
|
||||||
#define AUTHCHAP 2 // allow CHAP
|
#define AUTHCHAP 2 // allow CHAP
|
||||||
|
|
||||||
|
|
@ -311,6 +377,15 @@ typedef struct
|
||||||
// our MRU
|
// our MRU
|
||||||
uint16_t ppp_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
|
// DoS prevention
|
||||||
clockt last_packet_out;
|
clockt last_packet_out;
|
||||||
uint32_t packets_out;
|
uint32_t packets_out;
|
||||||
|
|
@ -324,6 +399,9 @@ typedef struct
|
||||||
|
|
||||||
// last LCP Echo
|
// last LCP Echo
|
||||||
time_t last_echo;
|
time_t last_echo;
|
||||||
|
|
||||||
|
// Last Multilink frame sequence number received
|
||||||
|
uint32_t last_seq;
|
||||||
} sessionlocalt;
|
} sessionlocalt;
|
||||||
|
|
||||||
// session flags
|
// session flags
|
||||||
|
|
@ -407,6 +485,23 @@ enum
|
||||||
TUNNELUNDEF, // Undefined
|
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
|
enum
|
||||||
{
|
{
|
||||||
RADIUSNULL, // Not in use
|
RADIUSNULL, // Not in use
|
||||||
|
|
@ -416,6 +511,7 @@ enum
|
||||||
RADIUSSTOP, // sending stop accounting to RADIUS server
|
RADIUSSTOP, // sending stop accounting to RADIUS server
|
||||||
RADIUSINTERIM, // sending interim accounting to RADIUS server
|
RADIUSINTERIM, // sending interim accounting to RADIUS server
|
||||||
RADIUSWAIT, // waiting timeout before available, in case delayed replies
|
RADIUSWAIT, // waiting timeout before available, in case delayed replies
|
||||||
|
RADIUSJUSTAUTH, // sending auth to RADIUS server, just authentication, no ip assigning
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Tstats
|
struct Tstats
|
||||||
|
|
@ -554,13 +650,16 @@ typedef struct
|
||||||
uint16_t radiusport[MAXRADSERVER]; // radius base ports
|
uint16_t radiusport[MAXRADSERVER]; // radius base ports
|
||||||
uint8_t numradiusservers; // radius server count
|
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
|
char radius_authtypes_s[32]; // list of valid authentication types (chap, pap) in order of preference
|
||||||
int radius_authtypes;
|
int radius_authtypes;
|
||||||
int radius_authprefer;
|
int radius_authprefer;
|
||||||
|
|
||||||
int allow_duplicate_users; // allow multiple logins with the same username
|
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;
|
in_addr_t default_dns1, default_dns2;
|
||||||
|
|
||||||
|
|
@ -572,7 +671,6 @@ typedef struct
|
||||||
in_addr_t peer_address;
|
in_addr_t peer_address;
|
||||||
int send_garp; // Set to true to garp for vip address on startup
|
int send_garp; // Set to true to garp for vip address on startup
|
||||||
|
|
||||||
int target_uid;
|
|
||||||
int dump_speed;
|
int dump_speed;
|
||||||
char plugins[64][MAXPLUGINS];
|
char plugins[64][MAXPLUGINS];
|
||||||
char old_plugins[64][MAXPLUGINS];
|
char old_plugins[64][MAXPLUGINS];
|
||||||
|
|
@ -583,6 +681,7 @@ typedef struct
|
||||||
int lock_pages; // Lock pages into memory.
|
int lock_pages; // Lock pages into memory.
|
||||||
int icmp_rate; // Max number of ICMP unreachable per second to send
|
int icmp_rate; // Max number of ICMP unreachable per second to send
|
||||||
int max_packets; // DoS prevention: per session limit of packets/0.1s
|
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.
|
in_addr_t cluster_address; // Multicast address of cluster.
|
||||||
// Send to this address to have everyone hear.
|
// 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
|
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).
|
// (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_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_undefined_tunnels; // How many tunnels we're yet to receive from the master.
|
||||||
int cluster_highest_sessionid;
|
int cluster_highest_sessionid;
|
||||||
|
int cluster_highest_bundleid;
|
||||||
int cluster_highest_tunnelid;
|
int cluster_highest_tunnelid;
|
||||||
clockt cluster_last_hb; // Last time we saw a heartbeat from the master.
|
clockt cluster_last_hb; // Last time we saw a heartbeat from the master.
|
||||||
int cluster_last_hb_ver; // Heartbeat version last seen from 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
|
int cluster_master_min_adv; // Master advertises routes while the number of up to date
|
||||||
// slaves is less than this value.
|
// slaves is less than this value.
|
||||||
|
// Guest change
|
||||||
|
char guest_user[MAXUSER]; // Guest account username
|
||||||
|
|
||||||
#ifdef BGP
|
#ifdef BGP
|
||||||
#define BGP_NUM_PEERS 2
|
#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 processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
|
||||||
void processipv6cp(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 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 processipv6in(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
|
||||||
void processccp(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);
|
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 sendlcp(sessionidt s, tunnelidt t);
|
||||||
void send_ipin(sessionidt s, uint8_t *buf, int len);
|
void send_ipin(sessionidt s, uint8_t *buf, int len);
|
||||||
void sendccp(sessionidt s, tunnelidt t);
|
void sendccp(sessionidt s, tunnelidt t);
|
||||||
void protoreject(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l, uint16_t proto);
|
void protoreject(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l, uint16_t proto);
|
||||||
|
int join_bundle(sessionidt s);
|
||||||
|
|
||||||
|
|
||||||
// radius.c
|
// 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 tunnelt *tunnel;
|
||||||
|
extern bundlet *bundle;
|
||||||
extern sessiont *session;
|
extern sessiont *session;
|
||||||
extern sessionlocalt *sess_local;
|
extern sessionlocalt *sess_local;
|
||||||
extern ippoolt *ip_address_pool;
|
extern ippoolt *ip_address_pool;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
Summary: A high-speed clustered L2TP LNS
|
Summary: A high-speed clustered L2TP LNS
|
||||||
Name: l2tpns
|
Name: l2tpns
|
||||||
Version: 2.1.21
|
Version: 2.2.0
|
||||||
Release: 1
|
Release: 1
|
||||||
License: GPL
|
License: GPL
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
|
|
@ -43,5 +43,5 @@ rm -rf %{buildroot}
|
||||||
%attr(644,root,root) /usr/share/man/man[58]/*
|
%attr(644,root,root) /usr/share/man/man[58]/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Fri Dec 1 2006 Brendan O'Dea <bod@optus.net> 2.1.21-1
|
* Mon Dec 18 2006 Brendan O'Dea <bod@optus.net> 2.2.0-1
|
||||||
- 2.1.21 release, see /usr/share/doc/l2tpns-2.1.21/Changes
|
- 2.2.0 release, see /usr/share/doc/l2tpns-2.2.0/Changes
|
||||||
|
|
|
||||||
362
md5.c
362
md5.c
|
|
@ -15,10 +15,7 @@
|
||||||
* and avoid compile-time configuration.
|
* and avoid compile-time configuration.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HAVE_OPENSSL
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -27,18 +24,18 @@
|
||||||
* F is optimized compared to its RFC 1321 definition just like in Colin
|
* F is optimized compared to its RFC 1321 definition just like in Colin
|
||||||
* Plumb's implementation.
|
* Plumb's implementation.
|
||||||
*/
|
*/
|
||||||
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||||
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
|
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
|
||||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The MD5 transformation for all four rounds.
|
* The MD5 transformation for all four rounds.
|
||||||
*/
|
*/
|
||||||
#define STEP(f, a, b, c, d, x, t, s) \
|
#define STEP(f, a, b, c, d, x, t, s) \
|
||||||
(a) += f((b), (c), (d)) + (x) + (t); \
|
(a) += f((b), (c), (d)) + (x) + (t); \
|
||||||
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
|
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
|
||||||
(a) += (b);
|
(a) += (b);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SET reads 4 input bytes in little-endian byte order and stores them
|
* SET reads 4 input bytes in little-endian byte order and stores them
|
||||||
|
|
@ -49,19 +46,17 @@
|
||||||
* doesn't work.
|
* doesn't work.
|
||||||
*/
|
*/
|
||||||
#if defined(__i386__) || defined(__vax__)
|
#if defined(__i386__) || defined(__vax__)
|
||||||
#define SET(n) \
|
# define SET(n) (*(MD5_u32plus *)&ptr[(n) * 4])
|
||||||
(*(MD5_u32plus *)&ptr[(n) * 4])
|
# define GET(n) SET(n)
|
||||||
#define GET(n) \
|
|
||||||
SET(n)
|
|
||||||
#else
|
#else
|
||||||
#define SET(n) \
|
# define SET(n) \
|
||||||
(ctx->block[(n)] = \
|
(ctx->block[(n)] = \
|
||||||
(MD5_u32plus)ptr[(n) * 4] | \
|
(MD5_u32plus)ptr[(n) * 4] | \
|
||||||
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
|
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
|
||||||
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
|
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
|
||||||
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
|
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
|
||||||
#define GET(n) \
|
# define GET(n) \
|
||||||
(ctx->block[(n)])
|
(ctx->block[(n)])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -70,205 +65,208 @@
|
||||||
*/
|
*/
|
||||||
static void *body(MD5_CTX *ctx, void *data, unsigned long size)
|
static void *body(MD5_CTX *ctx, void *data, unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
MD5_u32plus a, b, c, d;
|
MD5_u32plus a, b, c, d;
|
||||||
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
|
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
|
||||||
|
|
||||||
ptr = data;
|
ptr = data;
|
||||||
|
|
||||||
a = ctx->a;
|
a = ctx->a;
|
||||||
b = ctx->b;
|
b = ctx->b;
|
||||||
c = ctx->c;
|
c = ctx->c;
|
||||||
d = ctx->d;
|
d = ctx->d;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
saved_a = a;
|
saved_a = a;
|
||||||
saved_b = b;
|
saved_b = b;
|
||||||
saved_c = c;
|
saved_c = c;
|
||||||
saved_d = d;
|
saved_d = d;
|
||||||
|
|
||||||
/* Round 1 */
|
/* Round 1 */
|
||||||
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
|
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
|
||||||
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
|
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
|
||||||
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
|
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
|
||||||
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
|
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
|
||||||
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
|
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
|
||||||
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
|
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
|
||||||
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
|
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
|
||||||
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
|
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
|
||||||
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
|
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
|
||||||
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
|
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
|
||||||
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
|
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
|
||||||
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
|
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
|
||||||
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
|
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
|
||||||
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
|
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
|
||||||
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
|
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
|
||||||
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
|
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
|
||||||
|
|
||||||
/* Round 2 */
|
/* Round 2 */
|
||||||
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
|
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
|
||||||
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
|
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
|
||||||
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
|
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
|
||||||
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
|
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
|
||||||
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
|
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
|
||||||
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
|
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
|
||||||
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
|
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
|
||||||
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
|
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
|
||||||
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
|
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
|
||||||
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
|
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
|
||||||
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
|
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
|
||||||
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
|
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
|
||||||
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
|
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
|
||||||
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
|
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
|
||||||
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
|
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
|
||||||
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
|
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
|
||||||
|
|
||||||
/* Round 3 */
|
/* Round 3 */
|
||||||
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
|
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
|
||||||
STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
|
STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
|
||||||
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
|
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
|
||||||
STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
|
STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
|
||||||
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
|
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
|
||||||
STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
|
STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
|
||||||
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
|
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
|
||||||
STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
|
STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
|
||||||
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
|
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
|
||||||
STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
|
STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
|
||||||
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
|
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
|
||||||
STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
|
STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
|
||||||
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
|
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
|
||||||
STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
|
STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
|
||||||
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
|
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
|
||||||
STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
|
STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
|
||||||
|
|
||||||
/* Round 4 */
|
/* Round 4 */
|
||||||
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
|
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
|
||||||
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
|
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
|
||||||
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
|
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
|
||||||
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
|
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
|
||||||
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
|
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
|
||||||
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
|
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
|
||||||
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
|
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
|
||||||
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
|
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
|
||||||
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
|
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
|
||||||
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
|
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
|
||||||
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
|
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
|
||||||
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
|
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
|
||||||
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
|
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
|
||||||
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
|
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
|
||||||
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
|
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
|
||||||
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
|
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
|
||||||
|
|
||||||
a += saved_a;
|
a += saved_a;
|
||||||
b += saved_b;
|
b += saved_b;
|
||||||
c += saved_c;
|
c += saved_c;
|
||||||
d += saved_d;
|
d += saved_d;
|
||||||
|
|
||||||
ptr += 64;
|
ptr += MD5_BLOCK_SZ;
|
||||||
} while (size -= 64);
|
} while (size -= MD5_BLOCK_SZ);
|
||||||
|
|
||||||
ctx->a = a;
|
ctx->a = a;
|
||||||
ctx->b = b;
|
ctx->b = b;
|
||||||
ctx->c = c;
|
ctx->c = c;
|
||||||
ctx->d = d;
|
ctx->d = d;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5_Init(MD5_CTX *ctx)
|
void MD5_Init(MD5_CTX *ctx)
|
||||||
{
|
{
|
||||||
ctx->a = 0x67452301;
|
ctx->a = 0x67452301;
|
||||||
ctx->b = 0xefcdab89;
|
ctx->b = 0xefcdab89;
|
||||||
ctx->c = 0x98badcfe;
|
ctx->c = 0x98badcfe;
|
||||||
ctx->d = 0x10325476;
|
ctx->d = 0x10325476;
|
||||||
|
|
||||||
ctx->lo = 0;
|
ctx->lo = 0;
|
||||||
ctx->hi = 0;
|
ctx->hi = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
|
void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
|
||||||
{
|
{
|
||||||
MD5_u32plus saved_lo;
|
MD5_u32plus saved_lo;
|
||||||
unsigned long used, free;
|
unsigned long used, free;
|
||||||
|
|
||||||
saved_lo = ctx->lo;
|
saved_lo = ctx->lo;
|
||||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||||
ctx->hi++;
|
ctx->hi++;
|
||||||
ctx->hi += size >> 29;
|
|
||||||
|
|
||||||
used = saved_lo & 0x3f;
|
ctx->hi += size >> 29;
|
||||||
|
|
||||||
if (used) {
|
used = saved_lo & 0x3f;
|
||||||
free = 64 - used;
|
|
||||||
|
|
||||||
if (size < free) {
|
if (used)
|
||||||
memcpy(&ctx->buffer[used], data, size);
|
{
|
||||||
return;
|
free = MD5_BLOCK_SZ - used;
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&ctx->buffer[used], data, free);
|
if (size < free)
|
||||||
data = (unsigned char *)data + free;
|
{
|
||||||
size -= free;
|
memcpy(&ctx->buffer[used], data, size);
|
||||||
body(ctx, ctx->buffer, 64);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size >= 64) {
|
memcpy(&ctx->buffer[used], data, free);
|
||||||
data = body(ctx, data, size & ~(unsigned long)0x3f);
|
data = (unsigned char *)data + free;
|
||||||
size &= 0x3f;
|
size -= free;
|
||||||
}
|
body(ctx, ctx->buffer, MD5_BLOCK_SZ);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(ctx->buffer, data, size);
|
if (size >= MD5_BLOCK_SZ)
|
||||||
|
{
|
||||||
|
data = body(ctx, data, size & ~(unsigned long)0x3f);
|
||||||
|
size &= 0x3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctx->buffer, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
||||||
{
|
{
|
||||||
unsigned long used, free;
|
unsigned long used, free;
|
||||||
|
|
||||||
used = ctx->lo & 0x3f;
|
used = ctx->lo & 0x3f;
|
||||||
|
|
||||||
ctx->buffer[used++] = 0x80;
|
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);
|
memset(&ctx->buffer[used], 0, free);
|
||||||
used = 0;
|
body(ctx, ctx->buffer, MD5_BLOCK_SZ);
|
||||||
free = 64;
|
used = 0;
|
||||||
}
|
free = MD5_BLOCK_SZ;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&ctx->buffer[used], 0, free - 8);
|
memset(&ctx->buffer[used], 0, free - 8);
|
||||||
|
|
||||||
ctx->lo <<= 3;
|
ctx->lo <<= 3;
|
||||||
ctx->buffer[56] = ctx->lo;
|
ctx->buffer[56] = ctx->lo;
|
||||||
ctx->buffer[57] = ctx->lo >> 8;
|
ctx->buffer[57] = ctx->lo >> 8;
|
||||||
ctx->buffer[58] = ctx->lo >> 16;
|
ctx->buffer[58] = ctx->lo >> 16;
|
||||||
ctx->buffer[59] = ctx->lo >> 24;
|
ctx->buffer[59] = ctx->lo >> 24;
|
||||||
ctx->buffer[60] = ctx->hi;
|
ctx->buffer[60] = ctx->hi;
|
||||||
ctx->buffer[61] = ctx->hi >> 8;
|
ctx->buffer[61] = ctx->hi >> 8;
|
||||||
ctx->buffer[62] = ctx->hi >> 16;
|
ctx->buffer[62] = ctx->hi >> 16;
|
||||||
ctx->buffer[63] = ctx->hi >> 24;
|
ctx->buffer[63] = ctx->hi >> 24;
|
||||||
|
|
||||||
body(ctx, ctx->buffer, 64);
|
body(ctx, ctx->buffer, MD5_BLOCK_SZ);
|
||||||
|
|
||||||
result[0] = ctx->a;
|
result[0] = ctx->a;
|
||||||
result[1] = ctx->a >> 8;
|
result[1] = ctx->a >> 8;
|
||||||
result[2] = ctx->a >> 16;
|
result[2] = ctx->a >> 16;
|
||||||
result[3] = ctx->a >> 24;
|
result[3] = ctx->a >> 24;
|
||||||
result[4] = ctx->b;
|
result[4] = ctx->b;
|
||||||
result[5] = ctx->b >> 8;
|
result[5] = ctx->b >> 8;
|
||||||
result[6] = ctx->b >> 16;
|
result[6] = ctx->b >> 16;
|
||||||
result[7] = ctx->b >> 24;
|
result[7] = ctx->b >> 24;
|
||||||
result[8] = ctx->c;
|
result[8] = ctx->c;
|
||||||
result[9] = ctx->c >> 8;
|
result[9] = ctx->c >> 8;
|
||||||
result[10] = ctx->c >> 16;
|
result[10] = ctx->c >> 16;
|
||||||
result[11] = ctx->c >> 24;
|
result[11] = ctx->c >> 24;
|
||||||
result[12] = ctx->d;
|
result[12] = ctx->d;
|
||||||
result[13] = ctx->d >> 8;
|
result[13] = ctx->d >> 8;
|
||||||
result[14] = ctx->d >> 16;
|
result[14] = ctx->d >> 16;
|
||||||
result[15] = ctx->d >> 24;
|
result[15] = ctx->d >> 24;
|
||||||
|
|
||||||
memset(ctx, 0, sizeof(*ctx));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
19
md5.h
19
md5.h
|
|
@ -6,23 +6,24 @@
|
||||||
* in the public domain. See md5.c for more information.
|
* in the public domain. See md5.c for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL
|
#ifndef __MD5_H__
|
||||||
#include <openssl/md5.h>
|
#define __MD5_H__
|
||||||
#elif !defined(_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 */
|
/* Any 32-bit or wider unsigned integer data type will do */
|
||||||
typedef unsigned long MD5_u32plus;
|
typedef unsigned long MD5_u32plus;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MD5_u32plus lo, hi;
|
MD5_u32plus lo, hi;
|
||||||
MD5_u32plus a, b, c, d;
|
MD5_u32plus a, b, c, d;
|
||||||
unsigned char buffer[64];
|
unsigned char buffer[MD5_BLOCK_SZ];
|
||||||
MD5_u32plus block[16];
|
MD5_u32plus block[MD5_DIGEST_SZ];
|
||||||
} MD5_CTX;
|
} MD5_CTX;
|
||||||
|
|
||||||
extern void MD5_Init(MD5_CTX *ctx);
|
extern void MD5_Init(MD5_CTX *ctx);
|
||||||
extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size);
|
extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size);
|
||||||
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
|
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_PRE_AUTH = 1,
|
||||||
PLUGIN_POST_AUTH,
|
PLUGIN_POST_AUTH,
|
||||||
PLUGIN_PACKET_RX,
|
|
||||||
PLUGIN_PACKET_TX,
|
|
||||||
PLUGIN_TIMER,
|
PLUGIN_TIMER,
|
||||||
PLUGIN_NEW_SESSION,
|
PLUGIN_NEW_SESSION,
|
||||||
PLUGIN_KILL_SESSION,
|
PLUGIN_KILL_SESSION,
|
||||||
|
|
@ -62,37 +60,11 @@ struct param_post_auth
|
||||||
int protocol;
|
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
|
struct param_timer
|
||||||
{
|
{
|
||||||
time_t time_now;
|
time_t time_now;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct param_control
|
|
||||||
{
|
|
||||||
int iam_master;
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
// output
|
|
||||||
int response;
|
|
||||||
char *additional;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct param_new_session
|
struct param_new_session
|
||||||
{
|
{
|
||||||
tunnelt *t;
|
tunnelt *t;
|
||||||
|
|
@ -105,6 +77,16 @@ struct param_kill_session
|
||||||
sessiont *s;
|
sessiont *s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct param_control
|
||||||
|
{
|
||||||
|
int iam_master;
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
// output
|
||||||
|
int response;
|
||||||
|
char *additional;
|
||||||
|
};
|
||||||
|
|
||||||
struct param_radius_response
|
struct param_radius_response
|
||||||
{
|
{
|
||||||
tunnelt *t;
|
tunnelt *t;
|
||||||
|
|
|
||||||
665
ppp.c
665
ppp.c
|
|
@ -1,6 +1,6 @@
|
||||||
// L2TPNS PPP Stuff
|
// 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 <stdio.h>
|
||||||
#include <string.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"
|
#include "cluster.h"
|
||||||
|
|
||||||
extern tunnelt *tunnel;
|
extern tunnelt *tunnel;
|
||||||
|
extern bundlet *bundle;
|
||||||
|
extern fragmentationt *frag;
|
||||||
extern sessiont *session;
|
extern sessiont *session;
|
||||||
extern radiust *radius;
|
extern radiust *radius;
|
||||||
extern int tunfd;
|
extern int tunfd;
|
||||||
|
|
@ -24,6 +26,20 @@ extern time_t time_now;
|
||||||
extern configt *config;
|
extern configt *config;
|
||||||
|
|
||||||
static int add_lcp_auth(uint8_t *b, int size, int authtype);
|
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
|
// Process PAP messages
|
||||||
void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
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
|
// respond now, either no RADIUS available or already authenticated
|
||||||
uint8_t b[MAXETHER];
|
uint8_t b[MAXETHER];
|
||||||
uint8_t id = p[1];
|
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 (!p) return;
|
||||||
|
|
||||||
if (session[s].ip)
|
if (session[s].ip)
|
||||||
|
|
@ -134,7 +150,10 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
|
|
||||||
radius[r].id = p[1];
|
radius[r].id = p[1];
|
||||||
LOG(3, s, t, "Sending login for %s/%s to RADIUS\n", user, pass);
|
LOG(3, s, t, "Sending login for %s/%s to RADIUS\n", user, pass);
|
||||||
radiussend(r, RADIUSAUTH);
|
if ((session[s].mrru) && (!first_session_in_bundle(s)))
|
||||||
|
radiussend(r, RADIUSJUSTAUTH);
|
||||||
|
else
|
||||||
|
radiussend(r, RADIUSAUTH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -251,7 +270,10 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
|
|
||||||
radius[r].chap = 1;
|
radius[r].chap = 1;
|
||||||
LOG(3, s, t, "CHAP login %s\n", session[s].user);
|
LOG(3, s, t, "CHAP login %s\n", session[s].user);
|
||||||
radiussend(r, RADIUSAUTH);
|
if ((session[s].mrru) && (!first_session_in_bundle(s)))
|
||||||
|
radiussend(r, RADIUSJUSTAUTH);
|
||||||
|
else
|
||||||
|
radiussend(r, RADIUSAUTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dumplcp(uint8_t *p, int l)
|
static void dumplcp(uint8_t *p, int l)
|
||||||
|
|
@ -360,16 +382,25 @@ void lcp_open(sessionidt s, tunnelidt t)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This-Layer-Up
|
if(session[s].bundle == 0 || bundle[session[s].bundle].num_of_links == 1)
|
||||||
sendipcp(s, t);
|
{
|
||||||
change_state(s, ipcp, RequestSent);
|
// This-Layer-Up
|
||||||
// move to passive state for IPv6 (if configured), CCP
|
sendipcp(s, t);
|
||||||
if (config->ipv6_prefix.s6_addr[0])
|
change_state(s, ipcp, RequestSent);
|
||||||
change_state(s, ipv6cp, Stopped);
|
// move to passive state for IPv6 (if configured), CCP
|
||||||
else
|
if (config->ipv6_prefix.s6_addr[0])
|
||||||
change_state(s, ipv6cp, Closed);
|
change_state(s, ipv6cp, Stopped);
|
||||||
|
else
|
||||||
|
change_state(s, ipv6cp, Closed);
|
||||||
|
|
||||||
change_state(s, ccp, Stopped);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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)
|
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)
|
if (!queued)
|
||||||
return 0;
|
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)
|
if (*nak_sent >= config->ppp_max_failure)
|
||||||
return ppp_conf_rej(s, buf, blen, mtype, response, 0, packet, option);
|
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)
|
if (!queued)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -463,7 +494,7 @@ static void ppp_code_rej(sessionidt s, tunnelidt t, uint16_t proto,
|
||||||
l += 4;
|
l += 4;
|
||||||
if (l > mru) l = mru;
|
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;
|
if (!q) return;
|
||||||
|
|
||||||
*q = CodeRej;
|
*q = CodeRej;
|
||||||
|
|
@ -575,6 +606,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
uint8_t *response = 0;
|
uint8_t *response = 0;
|
||||||
static uint8_t asyncmap[4] = { 0, 0, 0, 0 }; // all zero
|
static uint8_t asyncmap[4] = { 0, 0, 0, 0 }; // all zero
|
||||||
static uint8_t authproto[5];
|
static uint8_t authproto[5];
|
||||||
|
int changed = 0;
|
||||||
|
|
||||||
while (x > 2)
|
while (x > 2)
|
||||||
{
|
{
|
||||||
|
|
@ -590,7 +622,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
if (mru >= MINMTU)
|
if (mru >= MINMTU)
|
||||||
{
|
{
|
||||||
session[s].mru = mru;
|
session[s].mru = mru;
|
||||||
cluster_send_session(s);
|
changed++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -663,6 +695,64 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
case 8: // Address-And-Control-Field-Compression
|
case 8: // Address-And-Control-Field-Compression
|
||||||
break;
|
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
|
default: // Reject any unknown options
|
||||||
LOG(3, s, t, " Rejecting unknown PPP LCP option %d\n", type);
|
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);
|
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;
|
o += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
cluster_send_session(s);
|
||||||
|
|
||||||
if (response)
|
if (response)
|
||||||
{
|
{
|
||||||
l = q - response; // LCP packet length
|
l = q - response; // LCP packet length
|
||||||
|
|
@ -679,7 +772,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Send packet back as ConfigAck
|
// 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;
|
if (!response) return;
|
||||||
*response = ConfigAck;
|
*response = ConfigAck;
|
||||||
}
|
}
|
||||||
|
|
@ -687,7 +780,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
switch (session[s].ppp.lcp)
|
switch (session[s].ppp.lcp)
|
||||||
{
|
{
|
||||||
case Closed:
|
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;
|
if (!response) return;
|
||||||
*response = TerminateAck;
|
*response = TerminateAck;
|
||||||
*((uint16_t *) (response + 2)) = htons(l = 4);
|
*((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);
|
cluster_send_session(s);
|
||||||
break;
|
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:
|
default:
|
||||||
LOG(2, s, t, "LCP: remote sent %s for type %u?\n", ppp_code(*p), type);
|
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);
|
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 Closed:
|
||||||
case Stopped:
|
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;
|
if (!response) return;
|
||||||
*response = TerminateAck;
|
*response = TerminateAck;
|
||||||
*((uint16_t *) (response + 2)) = htons(l = 4);
|
*((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
|
*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;
|
if (!q) return;
|
||||||
|
|
||||||
LOG(3, s, t, "LCP: send %s\n", ppp_code(*q));
|
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
|
*p = EchoReply; // reply
|
||||||
*(uint32_t *) (p + 4) = htonl(session[s].magic); // our magic number
|
*(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;
|
if (!q) return;
|
||||||
|
|
||||||
LOG(4, s, t, "LCP: send %s\n", ppp_code(*q));
|
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)
|
static void ipcp_open(sessionidt s, tunnelidt t)
|
||||||
{
|
{
|
||||||
LOG(3, s, t, "IPCP: Opened, session is now active\n");
|
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)
|
else if (gotip)
|
||||||
{
|
{
|
||||||
// Send packet back as ConfigAck
|
// 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;
|
if (!response) return;
|
||||||
*response = ConfigAck;
|
*response = ConfigAck;
|
||||||
}
|
}
|
||||||
|
|
@ -1127,7 +1370,7 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
switch (session[s].ppp.ipcp)
|
switch (session[s].ppp.ipcp)
|
||||||
{
|
{
|
||||||
case Closed:
|
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;
|
if (!response) return;
|
||||||
*response = TerminateAck;
|
*response = TerminateAck;
|
||||||
*((uint16_t *) (response + 2)) = htons(l = 4);
|
*((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
|
*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;
|
if (!q) return;
|
||||||
|
|
||||||
LOG(3, s, t, "IPCP: send %s\n", ppp_code(*q));
|
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)
|
else if (gotip)
|
||||||
{
|
{
|
||||||
// Send packet back as ConfigAck
|
// 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;
|
if (!response) return;
|
||||||
*response = ConfigAck;
|
*response = ConfigAck;
|
||||||
}
|
}
|
||||||
|
|
@ -1348,7 +1591,7 @@ void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
switch (session[s].ppp.ipv6cp)
|
switch (session[s].ppp.ipv6cp)
|
||||||
{
|
{
|
||||||
case Closed:
|
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;
|
if (!response) return;
|
||||||
*response = TerminateAck;
|
*response = TerminateAck;
|
||||||
*((uint16_t *) (response + 2)) = htons(l = 4);
|
*((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
|
*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;
|
if (!q) return;
|
||||||
|
|
||||||
LOG(3, s, t, "IPV6CP: send %s\n", ppp_code(*q));
|
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
|
// process IP packet received
|
||||||
//
|
//
|
||||||
// This MUST be called with at least 4 byte behind 'p'.
|
// This MUST be called with at least 4 byte behind 'p'.
|
||||||
|
|
@ -1464,11 +1740,14 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
if (session[s].ppp.phase != Network || session[s].ppp.ipcp != Opened)
|
if (session[s].ppp.phase != Network || session[s].ppp.ipcp != Opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// no spoof (do sessionbyip to handled statically routed subnets)
|
if (!session[s].bundle || bundle[session[s].bundle].num_of_links < 2) // FIXME:
|
||||||
if (ip != session[s].ip && sessionbyip(htonl(ip)) != s)
|
|
||||||
{
|
{
|
||||||
LOG(5, s, t, "Dropping packet with spoofed IP %s\n", fmtaddr(htonl(ip), 0));
|
// no spoof (do sessionbyip to handled statically routed subnets)
|
||||||
return;
|
if (ip != session[s].ip && sessionbyip(htonl(ip)) != s)
|
||||||
|
{
|
||||||
|
LOG(4, s, t, "Dropping packet with spoofed IP %s\n", fmtaddr(htonl(ip), 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// run access-list if any
|
// run access-list if any
|
||||||
|
|
@ -1488,17 +1767,13 @@ void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
*(uint32_t *) p = htonl(PKTIP);
|
*(uint32_t *) p = htonl(PKTIP);
|
||||||
l += 4;
|
l += 4;
|
||||||
|
|
||||||
// Are we throttled and a slave?
|
if (session[s].tbf_in)
|
||||||
if (session[s].tbf_in && !config->cluster_iam_master) {
|
{
|
||||||
// Pass it to the master for handling.
|
// Are we throttling this session?
|
||||||
master_throttle_packet(session[s].tbf_in, p, l);
|
if (config->cluster_iam_master)
|
||||||
return;
|
tbf_queue_packet(session[s].tbf_in, p, l);
|
||||||
}
|
else
|
||||||
|
master_throttle_packet(session[s].tbf_in, p, l);
|
||||||
// Are we throttled and a master??
|
|
||||||
if (session[s].tbf_in && config->cluster_iam_master) {
|
|
||||||
// Actually handle the throttled packets.
|
|
||||||
tbf_queue_packet(session[s].tbf_in, p, l);
|
|
||||||
return;
|
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);
|
snoop_send_packet(p, l, session[s].snoop_ip, session[s].snoop_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
increment_counter(&session[s].cin, &session[s].cin_wrap, l);
|
update_sessions_in_stat(s, l);
|
||||||
session[s].cin_delta += l;
|
|
||||||
session[s].pin++;
|
|
||||||
|
|
||||||
sess_local[s].cin += l;
|
|
||||||
sess_local[s].pin++;
|
|
||||||
|
|
||||||
eth_tx += 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);
|
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
|
// process IPv6 packet received
|
||||||
//
|
//
|
||||||
// This MUST be called with at least 4 byte behind 'p'.
|
// 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);
|
snoop_send_packet(p, l, session[s].snoop_ip, session[s].snoop_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
increment_counter(&session[s].cin, &session[s].cin_wrap, l);
|
update_sessions_in_stat(s, l);
|
||||||
session[s].cin_delta += l;
|
|
||||||
session[s].pin++;
|
|
||||||
|
|
||||||
sess_local[s].cin += l;
|
|
||||||
sess_local[s].pin++;
|
|
||||||
|
|
||||||
eth_tx += l;
|
eth_tx += l;
|
||||||
|
|
||||||
|
|
@ -1693,7 +2147,7 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
STAT(tunnel_rx_errors);
|
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)
|
if (*p == ConfigAck)
|
||||||
{
|
{
|
||||||
switch (session[s].ppp.ccp)
|
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
|
else // compression requested--reject
|
||||||
*p = ConfigRej;
|
*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;
|
if (!q) return;
|
||||||
|
|
||||||
switch (session[s].ppp.ccp)
|
switch (session[s].ppp.ccp)
|
||||||
{
|
{
|
||||||
case Closed:
|
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;
|
if (!q) return;
|
||||||
*q = TerminateAck;
|
*q = TerminateAck;
|
||||||
*((uint16_t *) (q + 2)) = htons(l = 4);
|
*((uint16_t *) (q + 2)) = htons(l = 4);
|
||||||
|
|
@ -1778,13 +2232,13 @@ void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||||
return;
|
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);
|
tunnelsend(b, l + (q - b), t);
|
||||||
}
|
}
|
||||||
else if (*p == TerminateReq)
|
else if (*p == TerminateReq)
|
||||||
{
|
{
|
||||||
*p = TerminateAck;
|
*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;
|
if (!q) return;
|
||||||
LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
|
LOG(3, s, t, "CCP: send %s\n", ppp_code(*q));
|
||||||
tunnelsend(b, l + (q - b), t);
|
tunnelsend(b, l + (q - b), t);
|
||||||
|
|
@ -1828,7 +2282,7 @@ void sendchap(sessionidt s, tunnelidt t)
|
||||||
STAT(tunnel_tx_errors);
|
STAT(tunnel_tx_errors);
|
||||||
return ;
|
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;
|
if (!q) return;
|
||||||
|
|
||||||
*q = 1; // challenge
|
*q = 1; // challenge
|
||||||
|
|
@ -1842,37 +2296,86 @@ void sendchap(sessionidt s, tunnelidt t)
|
||||||
|
|
||||||
// fill in a L2TP message with a PPP frame,
|
// fill in a L2TP message with a PPP frame,
|
||||||
// returns start of 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);
|
LOG(0, s, t, "makeppp buffer too small for L2TP header (size=%d)\n", size);
|
||||||
return NULL;
|
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 + 2) = htons(tunnel[t].far); // tunnel
|
||||||
*(uint16_t *) (b + 4) = htons(session[s].far); // session
|
*(uint16_t *) (b + 4) = htons(session[s].far); // session
|
||||||
b += 6;
|
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
|
*(uint16_t *) b = htons(0xFF03); // HDLC header
|
||||||
b += 2;
|
b += 2;
|
||||||
}
|
}
|
||||||
if (mtype < 0x100 && session[s].flags & SESSION_PFC)
|
|
||||||
*b++ = mtype;
|
if (type < 0x100 && session[s].flags & SESSION_PFC)
|
||||||
|
{
|
||||||
|
*b++ = type;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*(uint16_t *) b = htons(mtype);
|
*(uint16_t *) b = htons(type);
|
||||||
b += 2;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy the payload
|
||||||
if (p && l)
|
if (p && l)
|
||||||
memcpy(b, p, l);
|
memcpy(b, p, l);
|
||||||
|
|
||||||
|
|
@ -1911,10 +2414,10 @@ void sendlcp(sessionidt s, tunnelidt t)
|
||||||
uint8_t b[500], *q, *l;
|
uint8_t b[500], *q, *l;
|
||||||
int authtype = sess_local[s].lcp_authtype;
|
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;
|
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 ? (authtype == AUTHCHAP ? "CHAP" : "PAP") : "",
|
authtype ? (authtype == AUTHCHAP ? "CHAP" : "PAP") : "",
|
||||||
authtype ? ")" : "");
|
authtype ? ")" : "");
|
||||||
|
|
@ -1941,6 +2444,20 @@ void sendlcp(sessionidt s, tunnelidt t)
|
||||||
l += 4;
|
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
|
*(uint16_t *)(q + 2) = htons(l - q); // Length
|
||||||
|
|
||||||
LOG_HEX(5, "PPPLCP", q, l - q);
|
LOG_HEX(5, "PPPLCP", q, l - q);
|
||||||
|
|
@ -1955,7 +2472,7 @@ void sendccp(sessionidt s, tunnelidt t)
|
||||||
{
|
{
|
||||||
uint8_t b[500], *q;
|
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;
|
return;
|
||||||
|
|
||||||
LOG(3, s, t, "CCP: send ConfigReq (no compression)\n");
|
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;
|
l += 6;
|
||||||
if (l > mru) l = mru;
|
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;
|
if (!q) return;
|
||||||
|
|
||||||
*q = ProtocolRej;
|
*q = ProtocolRej;
|
||||||
|
|
|
||||||
184
radius.c
184
radius.c
|
|
@ -1,6 +1,6 @@
|
||||||
// L2TPNS Radius Stuff
|
// 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 <time.h>
|
||||||
#include <stdio.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)
|
void initrad(void)
|
||||||
{
|
{
|
||||||
int i;
|
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);
|
LOG(3, 0, 0, "Creating %d sockets for RADIUS queries\n", RADIUS_FDS);
|
||||||
radfds = calloc(sizeof(int), RADIUS_FDS);
|
radfds = calloc(sizeof(int), RADIUS_FDS);
|
||||||
for (i = 0; i < RADIUS_FDS; i++)
|
for (i = 0; i < RADIUS_FDS; i++)
|
||||||
|
|
@ -53,6 +72,27 @@ void initrad(void)
|
||||||
radfds[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
radfds[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
flags = fcntl(radfds[i], F_GETFL, 0);
|
flags = fcntl(radfds[i], F_GETFL, 0);
|
||||||
fcntl(radfds[i], F_SETFL, flags | O_NONBLOCK);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state != RADIUSAUTH && !config->radius_accounting)
|
if (state != RADIUSAUTH && state != RADIUSJUSTAUTH && !config->radius_accounting)
|
||||||
{
|
{
|
||||||
// Radius accounting is turned off
|
// Radius accounting is turned off
|
||||||
radiusclear(r, s);
|
radiusclear(r, s);
|
||||||
|
|
@ -157,7 +197,7 @@ void radiussend(uint16_t r, uint8_t state)
|
||||||
{
|
{
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
if (state == RADIUSAUTH)
|
if (state == RADIUSAUTH || state == RADIUSJUSTAUTH)
|
||||||
sessionshutdown(s, "RADIUS timeout.", CDN_ADMIN_DISC, TERM_REAUTHENTICATION_FAILURE);
|
sessionshutdown(s, "RADIUS timeout.", CDN_ADMIN_DISC, TERM_REAUTHENTICATION_FAILURE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -179,6 +219,7 @@ void radiussend(uint16_t r, uint8_t state)
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case RADIUSAUTH:
|
case RADIUSAUTH:
|
||||||
|
case RADIUSJUSTAUTH:
|
||||||
b[0] = AccessRequest; // access request
|
b[0] = AccessRequest; // access request
|
||||||
break;
|
break;
|
||||||
case RADIUSSTART:
|
case RADIUSSTART:
|
||||||
|
|
@ -199,7 +240,7 @@ void radiussend(uint16_t r, uint8_t state)
|
||||||
strcpy((char *) p + 2, session[s].user);
|
strcpy((char *) p + 2, session[s].user);
|
||||||
p += p[1];
|
p += p[1];
|
||||||
}
|
}
|
||||||
if (state == RADIUSAUTH)
|
if (state == RADIUSAUTH || state == RADIUSJUSTAUTH)
|
||||||
{
|
{
|
||||||
if (radius[r].chap)
|
if (radius[r].chap)
|
||||||
{
|
{
|
||||||
|
|
@ -330,6 +371,7 @@ void radiussend(uint16_t r, uint8_t state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
*p = 5; // NAS-Port
|
*p = 5; // NAS-Port
|
||||||
|
|
@ -339,59 +381,80 @@ void radiussend(uint16_t r, uint8_t state)
|
||||||
|
|
||||||
*p = 6; // Service-Type
|
*p = 6; // Service-Type
|
||||||
p[1] = 6;
|
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 += p[1];
|
||||||
|
|
||||||
*p = 7; // Framed-Protocol
|
*p = 7; // Framed-Protocol
|
||||||
p[1] = 6;
|
p[1] = htonl((state == RADIUSJUSTAUTH ? 0 : 6));
|
||||||
*(uint32_t *) (p + 2) = htonl(1); // PPP
|
*(uint32_t *) (p + 2) = htonl((state == RADIUSJUSTAUTH ? 0 : 1)); // PPP
|
||||||
p += p[1];
|
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)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
for (r = 0; s && r < MAXROUTE && session[s].route[r].ip; r++)
|
|
||||||
{
|
{
|
||||||
int width = 32;
|
*p = 8; // Framed-IP-Address
|
||||||
if (session[s].route[r].mask)
|
p[1] = 6;
|
||||||
|
*(uint32_t *) (p + 2) = htonl(session[s].ip);
|
||||||
|
p += p[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session[s].route[0].ip)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
for (r = 0; s && r < MAXROUTE && session[s].route[r].ip; r++)
|
||||||
{
|
{
|
||||||
int mask = session[s].route[r].mask;
|
int width = 32;
|
||||||
while (!(mask & 1))
|
if (session[s].route[r].mask)
|
||||||
{
|
{
|
||||||
width--;
|
int mask = session[s].route[r].mask;
|
||||||
mask >>= 1;
|
while (!(mask & 1))
|
||||||
}
|
{
|
||||||
|
width--;
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = 22; // Framed-Route
|
||||||
|
p[1] = sprintf((char *) p + 2, "%s/%d %s 1",
|
||||||
|
fmtaddr(htonl(session[s].route[r].ip), 0),
|
||||||
|
width, fmtaddr(htonl(session[s].ip), 1)) + 2;
|
||||||
|
|
||||||
|
p += p[1];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*p = 22; // Framed-Route
|
if (session[s].session_timeout)
|
||||||
p[1] = sprintf((char *) p + 2, "%s/%d %s 1",
|
{
|
||||||
fmtaddr(htonl(session[s].route[r].ip), 0),
|
*p = 27; // Session-Timeout
|
||||||
width, fmtaddr(htonl(session[s].ip), 1)) + 2;
|
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
|
||||||
|
p[1] = strlen(session[s].called) + 2;
|
||||||
|
strcpy((char *) p + 2, session[s].called);
|
||||||
|
p += p[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*session[s].calling)
|
||||||
|
{
|
||||||
|
*p = 31; // calling
|
||||||
|
p[1] = strlen(session[s].calling) + 2;
|
||||||
|
strcpy((char *) p + 2, session[s].calling);
|
||||||
p += p[1];
|
p += p[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*session[s].called)
|
|
||||||
{
|
|
||||||
*p = 30; // called
|
|
||||||
p[1] = strlen(session[s].called) + 2;
|
|
||||||
strcpy((char *) p + 2, session[s].called);
|
|
||||||
p += p[1];
|
|
||||||
}
|
|
||||||
if (*session[s].calling)
|
|
||||||
{
|
|
||||||
*p = 31; // calling
|
|
||||||
p[1] = strlen(session[s].calling) + 2;
|
|
||||||
strcpy((char *) p + 2, session[s].calling);
|
|
||||||
p += p[1];
|
|
||||||
}
|
|
||||||
// NAS-IP-Address
|
// NAS-IP-Address
|
||||||
*p = 4;
|
*p = 4;
|
||||||
p[1] = 6;
|
p[1] = 6;
|
||||||
|
|
@ -400,7 +463,7 @@ void radiussend(uint16_t r, uint8_t state)
|
||||||
|
|
||||||
// All AVpairs added
|
// All AVpairs added
|
||||||
*(uint16_t *) (b + 2) = htons(p - b);
|
*(uint16_t *) (b + 2) = htons(p - b);
|
||||||
if (state != RADIUSAUTH)
|
if (state != RADIUSAUTH && state != RADIUSJUSTAUTH)
|
||||||
{
|
{
|
||||||
// Build auth for accounting packet
|
// Build auth for accounting packet
|
||||||
calc_auth(b, p - b, zero, b + 4);
|
calc_auth(b, p - b, zero, b + 4);
|
||||||
|
|
@ -413,7 +476,7 @@ void radiussend(uint16_t r, uint8_t state)
|
||||||
// get radius port
|
// get radius port
|
||||||
uint16_t port = config->radiusport[(radius[r].try - 1) % config->numradiusservers];
|
uint16_t port = config->radiusport[(radius[r].try - 1) % config->numradiusservers];
|
||||||
// assume RADIUS accounting port is the authentication port +1
|
// 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));
|
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");
|
LOG(1, s, session[s].tunnel, " Unexpected RADIUS response\n");
|
||||||
return;
|
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)
|
&& radius[r].state != RADIUSSTOP && radius[r].state != RADIUSINTERIM)
|
||||||
{
|
{
|
||||||
LOG(1, s, session[s].tunnel, " Unexpected RADIUS response\n");
|
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.
|
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))
|
((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));
|
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.
|
// 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
|
// run post-auth plugin
|
||||||
struct param_post_auth packet = {
|
struct param_post_auth packet = {
|
||||||
|
|
@ -537,7 +600,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
||||||
if (radius[r].chap)
|
if (radius[r].chap)
|
||||||
{
|
{
|
||||||
// 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!
|
if (!p) return; // Abort!
|
||||||
|
|
||||||
*p = (r_code == AccessAccept) ? 3 : 4; // ack/nak
|
*p = (r_code == AccessAccept) ? 3 : 4; // ack/nak
|
||||||
|
|
@ -551,7 +614,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// PAP
|
// 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!
|
if (!p) return; // Abort!
|
||||||
|
|
||||||
// ack/nak
|
// ack/nak
|
||||||
|
|
@ -715,6 +778,22 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
||||||
ip_filters[f].used++;
|
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)
|
else if (*p == 99)
|
||||||
{
|
{
|
||||||
// Framed-IPv6-Route
|
// Framed-IPv6-Route
|
||||||
|
|
@ -793,6 +872,7 @@ void radiusretry(uint16_t r)
|
||||||
sendchap(s, t);
|
sendchap(s, t);
|
||||||
break;
|
break;
|
||||||
case RADIUSAUTH: // sending auth to RADIUS server
|
case RADIUSAUTH: // sending auth to RADIUS server
|
||||||
|
case RADIUSJUSTAUTH: // sending auth to RADIUS server
|
||||||
case RADIUSSTART: // sending start accounting to RADIUS server
|
case RADIUSSTART: // sending start accounting to RADIUS server
|
||||||
case RADIUSSTOP: // sending stop accounting to RADIUS server
|
case RADIUSSTOP: // sending stop accounting to RADIUS server
|
||||||
case RADIUSINTERIM: // sending interim 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)
|
while (1)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int alen = sizeof(addr), l;
|
socklen_t alen = sizeof(addr);
|
||||||
|
int l;
|
||||||
unsigned int iseq;
|
unsigned int iseq;
|
||||||
|
|
||||||
l = recvfrom(s, packet, 65535, 0, (void *) &addr, &alen);
|
l = recvfrom(s, packet, 65535, 0, (void *) &addr, &alen);
|
||||||
|
|
@ -87,7 +88,7 @@ int main(int argc, char *argv[])
|
||||||
free(packet);
|
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);
|
printf("Recv: %10llu %0.1fMbits/s (%lu pps) (%5ld dropped)\n", recv_count, (bytes / 1024.0 / 1024.0 * 8), pps, dropped);
|
||||||
pps = bytes = 0;
|
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 <arpa/inet.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
@ -6,11 +12,8 @@
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/udp.h>
|
#include <linux/udp.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -179,10 +182,10 @@ typedef struct
|
||||||
} control_message;
|
} control_message;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned long long send_count , recv_count ;
|
long long send_count, recv_count;
|
||||||
unsigned long long spkt , rpkt ;
|
long long spkt, rpkt ;
|
||||||
unsigned int dropped;
|
int dropped;
|
||||||
unsigned long sbytes , rbytes ;
|
long sbytes, rbytes ;
|
||||||
int quitit;
|
int quitit;
|
||||||
struct sessiont
|
struct sessiont
|
||||||
{
|
{
|
||||||
|
|
@ -210,7 +213,7 @@ void dump_control_message(control_message *c);
|
||||||
u32 avp_get_32(control_message *c, int id);
|
u32 avp_get_32(control_message *c, int id);
|
||||||
u16 avp_get_16(control_message *c, int id);
|
u16 avp_get_16(control_message *c, int id);
|
||||||
char *avp_get_s(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 skip_zlb();
|
||||||
void cm_free(control_message *m);
|
void cm_free(control_message *m);
|
||||||
controlt *ppp_new(u16 session, int protocol);
|
controlt *ppp_new(u16 session, int protocol);
|
||||||
|
|
@ -234,7 +237,7 @@ void print_report();
|
||||||
int ns = 0, nr = 0;
|
int ns = 0, nr = 0;
|
||||||
int udpfd;
|
int udpfd;
|
||||||
int t = 0;
|
int t = 0;
|
||||||
struct sockaddr_in gatewayaddr = {0};
|
struct sockaddr_in gatewayaddr;
|
||||||
int numsessions = NUM_SESSIONS;
|
int numsessions = NUM_SESSIONS;
|
||||||
int packet_length = PACKET_LENGTH;
|
int packet_length = PACKET_LENGTH;
|
||||||
int target_pps = TARGET_PPS;
|
int target_pps = TARGET_PPS;
|
||||||
|
|
@ -251,7 +254,7 @@ char *suffix = "@optusnet.com.au";
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
char *packet;
|
unsigned char *packet;
|
||||||
|
|
||||||
ss = (sharedt*) mmap(NULL, sizeof(*ss), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
|
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));
|
printf("Bound to port %d\n", htons(addr.sin_port));
|
||||||
}/*}}}*/
|
}/*}}}*/
|
||||||
|
|
||||||
|
memset(&gatewayaddr, 0, sizeof(gatewayaddr));
|
||||||
gatewayaddr.sin_family = AF_INET;
|
gatewayaddr.sin_family = AF_INET;
|
||||||
gatewayaddr.sin_port = htons(1701);
|
gatewayaddr.sin_port = htons(1701);
|
||||||
inet_aton(gwaddr, &gatewayaddr.sin_addr);
|
inet_aton(gwaddr, &gatewayaddr.sin_addr);
|
||||||
|
|
@ -400,7 +404,8 @@ int main(int argc, char *argv[])
|
||||||
// Receive reply/*{{{*/
|
// Receive reply/*{{{*/
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
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);
|
l = recvfrom(udpfd, packet, 4096, 0, (void *) &addr, &alen);
|
||||||
if (l < 0)
|
if (l < 0)
|
||||||
|
|
@ -409,7 +414,7 @@ int main(int argc, char *argv[])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
printf("Received ");
|
printf("Received ");
|
||||||
r = parsecontrol(packet, l);
|
r = parsecontrol((char *) packet, l);
|
||||||
if (!r->first)
|
if (!r->first)
|
||||||
{
|
{
|
||||||
printf("Invalid packet.. no first avp\n");
|
printf("Invalid packet.. no first avp\n");
|
||||||
|
|
@ -446,7 +451,7 @@ int main(int argc, char *argv[])
|
||||||
printf("All session create requests sent...\n");/*}}}*/
|
printf("All session create requests sent...\n");/*}}}*/
|
||||||
|
|
||||||
if ( fork() == 0) {
|
if ( fork() == 0) {
|
||||||
reader_thread(udpfd);
|
reader_thread();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -529,7 +534,7 @@ int main(int argc, char *argv[])
|
||||||
*(u16 *)(c->buf + 4) = htons(ss->sessions[i].remote_session); // Session ID
|
*(u16 *)(c->buf + 4) = htons(ss->sessions[i].remote_session); // Session ID
|
||||||
iph->saddr = ss->sessions[i].addr;
|
iph->saddr = ss->sessions[i].addr;
|
||||||
iph->check = 0;
|
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++;
|
*((unsigned int *) data) = seq++;
|
||||||
ppp_send(c);
|
ppp_send(c);
|
||||||
|
|
@ -546,7 +551,8 @@ int main(int argc, char *argv[])
|
||||||
nanosleep(&req, NULL);
|
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++;
|
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 unsigned long long last_rpkts[AVG_SIZE], last_spkts[AVG_SIZE];
|
||||||
static int last = 0, avg_count = 0;
|
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;
|
float loss;
|
||||||
|
|
||||||
last_rpkts[last] = ss->rpkt;
|
last_rpkts[last] = ss->rpkt;
|
||||||
last_spkts[last] = ss->spkt;
|
last_spkts[last] = ss->spkt;
|
||||||
last = (last + 1) % AVG_SIZE;
|
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++)
|
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 char *packet;
|
||||||
unsigned int seq = 0;
|
unsigned int seq = 0;
|
||||||
|
|
@ -877,7 +885,7 @@ void reader_thread(int updfd)/*{{{*/
|
||||||
while (!ss->quitit)
|
while (!ss->quitit)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int alen = sizeof(addr);
|
socklen_t alen = sizeof(addr);
|
||||||
control_message *m;
|
control_message *m;
|
||||||
int l;
|
int l;
|
||||||
int s;
|
int s;
|
||||||
|
|
@ -906,7 +914,7 @@ void reader_thread(int updfd)/*{{{*/
|
||||||
{
|
{
|
||||||
// Control Packet
|
// Control Packet
|
||||||
printf("Reader Received ");
|
printf("Reader Received ");
|
||||||
m = parsecontrol(packet, l);
|
m = parsecontrol((char *) packet, l);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
s = m->session;
|
s = m->session;
|
||||||
|
|
||||||
|
|
@ -975,7 +983,7 @@ void reader_thread(int updfd)/*{{{*/
|
||||||
if (protocol != PPPIP)
|
if (protocol != PPPIP)
|
||||||
{
|
{
|
||||||
printf("Received ");
|
printf("Received ");
|
||||||
dump_ppp_packet(packet + 6, l - 6);
|
dump_ppp_packet((char *) (packet + 6), l - 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protocol == PPPLCP)
|
if (protocol == PPPLCP)
|
||||||
|
|
@ -1073,13 +1081,13 @@ void reader_thread(int updfd)/*{{{*/
|
||||||
|
|
||||||
if (iph->protocol == 17)
|
if (iph->protocol == 17)
|
||||||
{
|
{
|
||||||
int iseq;
|
unsigned int iseq;
|
||||||
ss->recv_count++;
|
ss->recv_count++;
|
||||||
ss->rpkt++;
|
ss->rpkt++;
|
||||||
iseq = *((unsigned int *) data);
|
iseq = *((unsigned int *) data);
|
||||||
if (seq != iseq) {
|
if (seq != iseq)
|
||||||
ss->dropped += (iseq - seq) ;
|
ss->dropped += (iseq - seq) ;
|
||||||
}
|
|
||||||
seq = iseq + 1; // Next sequence number to expect.
|
seq = iseq + 1; // Next sequence number to expect.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1095,7 +1103,7 @@ void reader_thread(int updfd)/*{{{*/
|
||||||
void skip_zlb() /*{{{*/
|
void skip_zlb() /*{{{*/
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int alen = sizeof(addr);
|
socklen_t alen = sizeof(addr);
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int l;
|
int l;
|
||||||
l = recvfrom(udpfd, buf, 1024, MSG_PEEK, (void *) &addr, &alen);
|
l = recvfrom(udpfd, buf, 1024, MSG_PEEK, (void *) &addr, &alen);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue