- Revise CCP, send ConfigReq once only.

- Check control serial before clearing window, prevents looping tunnel
  setup in some instances.
- Add configuration syntax for adding named access lists (work in progress).
This commit is contained in:
bodea 2004-11-27 05:19:53 +00:00
parent 98e9766a66
commit 12f16f60c1
9 changed files with 920 additions and 94 deletions

View file

@ -1,8 +1,11 @@
* Thu Nov 25 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.9 * Sat Nov 27 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.9
- Revise CCP, send ConfigReq once only. - Revise CCP, send ConfigReq once only.
- Don't copy the old buffer into Config{Nak,Rej} LCP responses (oops); - Don't copy the old buffer into Config{Nak,Rej} LCP responses (oops);
add length checks when appending. add length checks when appending.
- Have makeppp print a backtrace on overflow. - Have makeppp print a backtrace on overflow.
- Check control serial before clearing window, prevents looping tunnel
setup in some instances.
- Add configuration syntax for adding named access lists (work in progress).
* Sat Nov 20 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.8 * Sat Nov 20 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.8
- Ignore gateway address in Framed-Route (from Jonathan McDowell). - Ignore gateway address in Framed-Route (from Jonathan McDowell).

View file

@ -53,6 +53,7 @@ H3 {
<LI><A HREF="#Authentication">Authentication</A></LI> <LI><A HREF="#Authentication">Authentication</A></LI>
<LI><A HREF="#Plugins">Plugins</A></LI> <LI><A HREF="#Plugins">Plugins</A></LI>
<LI><A HREF="#WalledGarden">Walled Garden</A></LI> <LI><A HREF="#WalledGarden">Walled Garden</A></LI>
<LI><A HREF="#Filtering">Filtering</A></LI>
<LI><A HREF="#Clustering">Clustering</A></LI> <LI><A HREF="#Clustering">Clustering</A></LI>
<LI><A HREF="#Routing">Routing</A></LI> <LI><A HREF="#Routing">Routing</A></LI>
<LI><A HREF="#Performance">Performance</A></LI> <LI><A HREF="#Performance">Performance</A></LI>
@ -200,29 +201,34 @@ software upgrade.
<LI><B>primary_radius</B> (ip address) <LI><B>primary_radius</B> (ip address)
<LI><B>secondary_radius</B> (ip address)<BR> <LI><B>secondary_radius</B> (ip address)<BR>
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.<br>
<strong>Note:</strong> in addition to the source IP address and
identifier, the RADIUS server <strong>must</strong> include the source
port when detecting duplicates to supress (in order to cope with a
large number of sessions comming on-line simultaneously l2tpns uses a
set of udp sockets, each with a seperate identifier).
</LI> </LI>
<LI><B>primary_radius_port</B> (short) <LI><B>primary_radius_port</B> (short)
<LI><B>secondary_radius_port</B> (short)<BR> <LI><B>secondary_radius_port</B> (short)<BR>
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 radius ports are given, the authentication port defaults port. If no RADIUS ports are given, the authentication port defaults
to 1645, and the accounting port to 1646. to 1645, and the accounting port to 1646.
</LI> </LI>
<LI><B>radius_accounting</B> (boolean)<BR> <LI><B>radius_accounting</B> (boolean)<BR>
If set to true, then radius accounting packets will be sent. This If set to true, then RADIUS accounting packets will be sent. This
means that a Start record will be sent when the session is means that a Start record will be sent when the session is
successfully authenticated, and a Stop record will be sent when the successfully authenticated, and a Stop record will be sent when the
session is closed. session is closed.
</LI> </LI>
<LI><B>radius_secret</B> (string)<BR> <LI><B>radius_secret</B> (string)<BR>
This secret will be used in all radius queries. If this is not set then This secret will be used in all RADIUS queries. If this is not set then
radius queries will fail. RADIUS queries will fail.
</LI> </LI>
<LI><B>bind_address</B> (ip address)<BR> <LI><B>bind_address</B> (ip address)<BR>
@ -338,6 +344,40 @@ Where <I>peer</I> specifies the BGP neighbour as either a hostname or
IP address, <I>as</I> is the remote AS number and <I>keepalive</I>, IP address, <I>as</I> is the remote AS number and <I>keepalive</I>,
<I>hold</I> are the timer values in seconds. <I>hold</I> are the timer values in seconds.
<P>Named access-lists are configured using one of the commands:
<DL>
<DD><B>ip access-list standard</B> <I>name</I>
<DD><B>ip access-list extended</B> <I>name</I>
</DL>
<P>Subsequent lines prefixed with <B>permit</B> or <B>deny</B>
define the body of the access-list. Standard access-list syntax:
<DL>
<DD>{<B>permit</B>|<B>deny</B>}
{<I>host</I>|<I>source source-wildcard</I>|<B>any</B>}
[{<I>host</I>|<I>destination destination-wildcard</I>|<B>any</B>}]
</DL>
Extended access-lists:
<DL>
<DD>{<B>permit</B>|<B>deny</B>} <B>ip</B>
{<I>host</I>|<I>source source-wildcard</I>|<B>any</B>}
{<I>host</I>|<I>destination destination-wildcard</I>|<B>any</B>}
<DD>{<B>permit</B>|<B>deny</B>} <B>udp</B>
{<I>host</I>|<I>source source-wildcard</I>|<B>any</B>}
[{<B>eq</B>|<B>neq</B>|<B>gt</B>|<B>lt</B>} <I>port</I>|<B>range</B> <I>from</I> <I>to</I>]
{<I>host</I>|<I>destination destination-wildcard</I>|<B>any</B>}
[{<B>eq</B>|<B>neq</B>|<B>gt</B>|<B>lt</B>} <I>port</I>|<B>range</B> <I>from</I> <I>to</I>]
<DD>{<B>permit</B>|<B>deny</B>} <B>tcp</B>
{<I>host</I>|<I>source source-wildcard</I>|<B>any</B>}
[{<B>eq</B>|<B>neq</B>|<B>gt</B>|<B>lt</B>} <I>port</I>|<B>range</B> <I>from</I> <I>to</I>]
{<I>host</I>|<I>destination destination-wildcard</I>|<B>any</B>}
[{<B>eq</B>|<B>neq</B>|<B>gt</B>|<B>lt</B>} <I>port</I>|<B>range</B> <I>from</I> <I>to</I>]
[{<B>established</B>|{<B>match-any</B>|<B>match-all</B>}
{<B>+</B>|<B>-</B>}{<B>fin</B>|<B>syn</B>|<B>rst</B>|<B>psh</B>|<B>ack</B>|<B>urg</B>} ...]
</DL>
<H3 ID="users">users</H3> <H3 ID="users">users</H3>
Usernames and passwords for the command-line interface are stored in Usernames and passwords for the command-line interface are stored in
@ -500,19 +540,19 @@ IP Address Used Session User
</LI> </LI>
<LI><B>show radius</B><BR> <LI><B>show radius</B><BR>
Show a summary of the in-use radius sessions. This list should not be very Show a summary of the in-use RADIUS sessions. This list should not be very
long, as radius sessions should be cleaned up as soon as they are used. The long, as RADIUS sessions should be cleaned up as soon as they are used. The
columns listed are: columns listed are:
<TABLE> <TABLE>
<TR><TD><B>Radius</B></TD><TD>The ID of the radius request. This is <TR><TD><B>Radius</B></TD><TD>The ID of the RADIUS request. This is
sent in the packet to the radius server for identification.</TD></TR> sent in the packet to the RADIUS server for identification.</TD></TR>
<TR><TD><B>State</B></TD><TD>The state of the request - WAIT, CHAP, <TR><TD><B>State</B></TD><TD>The state of the request - WAIT, CHAP,
AUTH, IPCP, START, STOP, NULL.</TD></TR> AUTH, IPCP, START, STOP, NULL.</TD></TR>
<TR><TD><B>Session</B></TD><TD>The session ID that this radius <TR><TD><B>Session</B></TD><TD>The session ID that this RADIUS
request is associated with</TD></TR> request is associated with</TD></TR>
<TR><TD><B>Retry</B></TD><TD>If a response does not appear to the <TR><TD><B>Retry</B></TD><TD>If a response does not appear to the
request, it will retry at this time. This is a unix timestamp.</TD></TR> request, it will retry at this time. This is a unix timestamp.</TD></TR>
<TR><TD><B>Try</B></TD><TD>Retry count. The radius request is <TR><TD><B>Try</B></TD><TD>Retry count. The RADIUS request is
discarded after 3 retries.</TD></TR> discarded after 3 retries.</TD></TR>
</TABLE> </TABLE>
<P> <P>
@ -553,7 +593,7 @@ current session for that username will be forwarded to the given
host/port. Specify <EM>no snoop username</EM> to disable interception host/port. Specify <EM>no snoop username</EM> to disable interception
for the session.<P> for the session.<P>
If you want interception to be permanent, you will have to modify the radius If you want interception to be permanent, you will have to modify the RADIUS
response for the user. See <A HREF="#Interception">Interception</A>. response for the user. See <A HREF="#Interception">Interception</A>.
<P> <P>
</LI> </LI>
@ -564,7 +604,7 @@ session. Specify <EM>no throttle username</EM> to disable throttling
for the current session.<P> for the current session.<P>
If you want throttling to be permanent, you will have to modify the If you want throttling to be permanent, you will have to modify the
radius response for the user. See <A HREF="#THrottling">Throttling</A>. RADIUS response for the user. See <A HREF="#Throttling">Throttling</A>.
<P> <P>
</LI> </LI>
@ -660,7 +700,7 @@ desire. You must first enable the global setting <EM>throttle_speed</EM>
before this will be activated.<P> before this will be activated.<P>
If you wish a session to be throttled permanently, you should set the If you wish a session to be throttled permanently, you should set the
Vendor-Specific radius value <B>Cisco-Avpair="throttle=yes"</B>, which Vendor-Specific RADIUS value <B>Cisco-Avpair="throttle=yes"</B>, which
will be handled by the <EM>autothrottle</EM> module.<P> will be handled by the <EM>autothrottle</EM> module.<P>
Otherwise, you can enable and disable throttling an active session using Otherwise, you can enable and disable throttling an active session using
@ -684,7 +724,7 @@ and <EM>no snoop username</EM> CLI commands. These will enable interception
immediately.<P> immediately.<P>
If you wish the user to be intercepted whenever they reconnect, you will If you wish the user to be intercepted whenever they reconnect, you will
need to modify the radius response to include the Vendor-Specific value need to modify the RADIUS response to include the Vendor-Specific value
<B>Cisco-Avpair="intercept=yes"</B>. For this feature to be enabled, <B>Cisco-Avpair="intercept=yes"</B>. For this feature to be enabled,
you need to have the <EM>autosnoop</EM> module loaded.<P> you need to have the <EM>autosnoop</EM> module loaded.<P>
@ -694,11 +734,11 @@ Whenever a session connects, it is not fully set up until authentication is
completed. The remote end must send a PPP CHAP or PPP PAP authentication completed. The remote end must send a PPP CHAP or PPP PAP authentication
request to l2tpns.<P> request to l2tpns.<P>
This request is sent to the radius server, which will hopefully respond with This request is sent to the RADIUS server, which will hopefully respond with
Auth-Accept or Auth-Reject.<P> Auth-Accept or Auth-Reject.<P>
If Auth-Accept is received, the session is set up and an IP address is If Auth-Accept is received, the session is set up and an IP address is
assigned. The radius server can include a Framed-IP-Address field in the assigned. The RADIUS server can include a Framed-IP-Address field in the
reply, and that address will be assigned to the client. It can also include reply, and that address will be assigned to the client. It can also include
specific DNS servers, and a Framed-Route if that is required.<P> specific DNS servers, and a Framed-Route if that is required.<P>
@ -708,7 +748,7 @@ walled garden module is loaded, in which case the user still receives the
PPP AUTHACK, but their session is flagged as being a garden'd user, and they PPP AUTHACK, but their session is flagged as being a garden'd user, and they
should not receive any service.<P> should not receive any service.<P>
The radius reply can also contain a Vendor-Specific attribute called The RADIUS reply can also contain a Vendor-Specific attribute called
Cisco-Avpair. This field is a freeform text field that most Cisco Cisco-Avpair. This field is a freeform text field that most Cisco
devices understand to contain configuration instructions for the session. In devices understand to contain configuration instructions for the session. In
the case of l2tpns it is expected to be of the form the case of l2tpns it is expected to be of the form
@ -758,7 +798,7 @@ supplied structure:
<TABLE CELLSPACING=1 CELLPADDING=3> <TABLE CELLSPACING=1 CELLPADDING=3>
<TR BGCOLOR=LIGHTGREEN><TH><B>Event</B></TH><TH><B>Description</B></TH><TH><B>Parameters</B></TH></TR> <TR BGCOLOR=LIGHTGREEN><TH><B>Event</B></TH><TH><B>Description</B></TH><TH><B>Parameters</B></TH></TR>
<TR VALIGN=TOP BGCOLOR=WHITE><TD><B>pre_auth</B></TD> <TR VALIGN=TOP BGCOLOR=WHITE><TD><B>pre_auth</B></TD>
<TD>This is called after a radius response has been <TD>This is called after a RADIUS response has been
received, but before it has been processed by the received, but before it has been processed by the
code. This will allow you to modify the response in code. This will allow you to modify the response in
some way. some way.
@ -775,7 +815,7 @@ supplied structure:
</TD> </TD>
</TR> </TR>
<TR VALIGN=TOP BGCOLOR=WHITE><TD><B>post_auth</B></TD> <TR VALIGN=TOP BGCOLOR=WHITE><TD><B>post_auth</B></TD>
<TD>This is called after a radius response has been <TD>This is called after a RADIUS response has been
received, and the basic checks have been performed. This received, and the basic checks have been performed. This
is what the garden module uses to force authentication is what the garden module uses to force authentication
to be accepted. to be accepted.
@ -855,7 +895,7 @@ supplied structure:
</TD> </TD>
</TR> </TR>
<TR VALIGN=TOP BGCOLOR=WHITE><TD><B>radius_response</B></TD> <TR VALIGN=TOP BGCOLOR=WHITE><TD><B>radius_response</B></TD>
<TD>This is called whenever a radius response includes a <TD>This is called whenever a RADIUS response includes a
Cisco-Avpair value. The value is split up into Cisco-Avpair value. The value is split up into
<EM>key=value</EM> pairs, and each is processed through all <EM>key=value</EM> pairs, and each is processed through all
modules. modules.
@ -901,7 +941,7 @@ Walled Garden is implemented so that you can provide perhaps limited service
to sessions that incorrectly authenticate.<P> to sessions that incorrectly authenticate.<P>
Whenever a session provides incorrect authentication, and the Whenever a session provides incorrect authentication, and the
radius server responds with Auth-Reject, the walled garden module RADIUS server responds with Auth-Reject, the walled garden module
(if loaded) will force authentication to succeed, but set the flag (if loaded) will force authentication to succeed, but set the flag
<EM>garden</EM> in the session structure, and adds an iptables rule to <EM>garden</EM> in the session structure, and adds an iptables rule to
the <B>garden_users</B> chain to force all packets for the session's IP the <B>garden_users</B> chain to force all packets for the session's IP
@ -926,6 +966,14 @@ command:
iptables -t nat -L garden -nvx iptables -t nat -L garden -nvx
</PRE> </PRE>
<H2 ID="Filtering">Filtering</H2>
Sessions may be filtered by specifying <B>Filter-Id</B> attributes in
the RADIUS reply. <I>filter</I>.<B>in</B> specifies that the named
access-list <I>filter</I> should be applied to traffic from the
customer, <I>filter</I>.<B>out</B> specifies a list for traffic to the
customer.
<H2 ID="Clustering">Clustering</H2> <H2 ID="Clustering">Clustering</H2>
An l2tpns cluster consists of of one* or more servers configured with An l2tpns cluster consists of of one* or more servers configured with

View file

@ -2,7 +2,7 @@
.de Id .de Id
.ds Dt \\$4 \\$5 .ds Dt \\$4 \\$5
.. ..
.Id $Id: startup-config.5,v 1.1 2004/11/17 15:08:19 bodea Exp $ .Id $Id: startup-config.5,v 1.2 2004/11/27 05:19:54 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
@ -199,5 +199,111 @@ is the remote AS number and
.IR keepalive , .IR keepalive ,
.I hold .I hold
are the timer values in seconds. are the timer values in seconds.
.SS NAMED ACCESS LISTS
Named access lists may be defined with either of
.IP
.BI "ip access\-list standard " name
.br
.BI "ip access\-list extended " name
.PP
Subsequent lines starting with
.B permit
or
.B deny
define the body of the access\-list.
.PP
.B Standard Access Lists
.RS 4n
Standard access lists are defined with:
.IP
.RB { permit | deny }
.IR source " [" dest ]
.PP
Where
.I source
and
.I dest
specify IP matches using one of:
.IP
.I address
.I wildard
.br
.B host
.I address
.br
.B any
.PP
.I address
and
.I wildard
are in dotted-quad notation, bits in the
.I wildard
indicate which address bits in
.I address
are relevant to the match (0 = exact match; 1 = don't care).
.PP
The shorthand
.RB ' host
.IR address '
is equivalent to
.RI ' address
.BR 0.0.0.0 ';
.RB ' any '
to
.RB ' 0.0.0.0
.BR 255.255.255.255 '.
.RE
.PP
.B Extended Access Lists
.RS 4n
Extended access lists are defined with:
.IP
.RB { permit | deny }
.I proto
.IR source " [" ports "] " dest " [" ports "] [" flags ]
.PP
Where
.I proto
is one of
.BR ip ,
.B tcp
or
.BR udp ,
and
.I source
and
.I dest
are as described above for standard lists.
.PP
For
.B tcp
and
.B udp
matches, source and destination may be optionally followed by a
.I ports
specification:
.IP
.RB { eq | neq | gt | lt }
.I port
.br
.B
range
.I from to
.PP
.B tcp
matches may also specify
.I flags
to match against tcp header flags:
.IP
.RB { match\-any | match\-all }
.RB { + | - }{ fin | syn | rst | psh | ack | urg }
\&...
.br
.B established
.PP
.RB ' established '
is shorthand for
.RB ' "match-any +ack +rst -syn" '.
.RE
.SH SEE ALSO .SH SEE ALSO
.BR l2tpns (8) .BR l2tpns (8)

615
cli.c
View file

@ -2,7 +2,7 @@
// vim: sw=8 ts=8 // vim: sw=8 ts=8
char const *cvs_name = "$Name: $"; char const *cvs_name = "$Name: $";
char const *cvs_id_cli = "$Id: cli.c,v 1.28 2004/11/16 07:54:32 bodea Exp $"; char const *cvs_id_cli = "$Id: cli.c,v 1.29 2004/11/27 05:19:53 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
@ -38,14 +38,15 @@ extern radiust *radius;
extern ippoolt *ip_address_pool; extern ippoolt *ip_address_pool;
extern struct Tstats *_statistics; extern struct Tstats *_statistics;
static struct cli_def *cli = NULL; static struct cli_def *cli = NULL;
extern struct configt *config; extern configt *config;
extern struct config_descriptt config_values[]; extern config_descriptt config_values[];
#ifdef RINGBUFFER #ifdef RINGBUFFER
extern struct Tringbuffer *ringbuffer; extern struct Tringbuffer *ringbuffer;
#endif #endif
extern struct cli_session_actions *cli_session_actions; extern struct cli_session_actions *cli_session_actions;
extern struct cli_tunnel_actions *cli_tunnel_actions; extern struct cli_tunnel_actions *cli_tunnel_actions;
extern tbft *filter_list; extern tbft *filter_list;
extern ip_filtert *ip_filters;
static char *debug_levels[] = { static char *debug_levels[] = {
"CRIT", "CRIT",
@ -110,6 +111,14 @@ static int cmd_no_suspend_bgp(struct cli_def *cli, char *command, char **argv, i
static int cmd_restart_bgp(struct cli_def *cli, char *command, char **argv, int argc); static int cmd_restart_bgp(struct cli_def *cli, char *command, char **argv, int argc);
#endif /* BGP */ #endif /* BGP */
#define MODE_CONFIG_NACL 9
static int cmd_ip_access_list(struct cli_def *cli, char *command, char **argv, int argc);
static int cmd_no_ip_access_list(struct cli_def *cli, char *command, char **argv, int argc);
static int cmd_ip_access_list_rule(struct cli_def *cli, char *command, char **argv, int argc);
/* match if b is a substr of a */
#define MATCH(a,b) (!strncmp((a), (b), strlen(b)))
void init_cli(char *hostname) void init_cli(char *hostname)
{ {
FILE *f; FILE *f;
@ -203,6 +212,16 @@ void init_cli(char *hostname)
cli_register_command(cli, NULL, "set", cmd_set, PRIVILEGE_PRIVILEGED, MODE_CONFIG, "Set a configuration variable"); cli_register_command(cli, NULL, "set", cmd_set, PRIVILEGE_PRIVILEGED, MODE_CONFIG, "Set a configuration variable");
c = cli_register_command(cli, NULL, "ip", NULL, PRIVILEGE_PRIVILEGED, MODE_CONFIG, NULL);
cli_register_command(cli, c, "access-list", cmd_ip_access_list, PRIVILEGE_PRIVILEGED, MODE_CONFIG, "Add named access-list");
cli_register_command(cli, NULL, "permit", cmd_ip_access_list_rule, PRIVILEGE_PRIVILEGED, MODE_CONFIG_NACL, "Permit rule");
cli_register_command(cli, NULL, "deny", cmd_ip_access_list_rule, PRIVILEGE_PRIVILEGED, MODE_CONFIG_NACL, "Deny rule");
c = cli_register_command(cli, NULL, "no", NULL, PRIVILEGE_UNPRIVILEGED, MODE_CONFIG, NULL);
c2 = cli_register_command(cli, c, "ip", NULL, PRIVILEGE_PRIVILEGED, MODE_CONFIG, NULL);
cli_register_command(cli, c2, "access-list", cmd_no_ip_access_list, PRIVILEGE_PRIVILEGED, MODE_CONFIG, "Remove named access-list");
// Enable regular processing // Enable regular processing
cli_regular(cli, regular_stuff); cli_regular(cli, regular_stuff);
@ -852,6 +871,8 @@ static int cmd_write_memory(struct cli_def *cli, char *command, char **argv, int
return CLI_OK; return CLI_OK;
} }
static char const *show_access_list_rule(int extended, ip_filter_rulet *rule);
static int cmd_show_run(struct cli_def *cli, char *command, char **argv, int argc) static int cmd_show_run(struct cli_def *cli, char *command, char **argv, int argc)
{ {
int i; int i;
@ -929,6 +950,22 @@ static int cmd_show_run(struct cli_def *cli, char *command, char **argv, int arg
} }
#endif #endif
cli_print(cli, "# Filters");
for (i = 0; i < MAXFILTER; i++)
{
ip_filter_rulet *rules;
if (!*ip_filters[i].name)
continue;
cli_print(cli, "ip access-list %s %s",
ip_filters[i].extended ? "extended" : "standard",
ip_filters[i].name);
rules = ip_filters[i].rules;
while (rules->action)
cli_print(cli, "%s", show_access_list_rule(ip_filters[i].extended, rules++));
}
cli_print(cli, "# end"); cli_print(cli, "# end");
return CLI_OK; return CLI_OK;
} }
@ -1877,7 +1914,7 @@ static int cmd_router_bgp(struct cli_def *cli, char *command, char **argv, int a
return CLI_OK; return CLI_OK;
} }
static int find_bgp_neighbour(char *name) static int find_bgp_neighbour(char const *name)
{ {
int i; int i;
int new = -1; int new = -1;
@ -1940,10 +1977,10 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a
NULL); NULL);
default: default:
if (!strncmp("remote-as", argv[1], strlen(argv[1]))) if (MATCH("remote-as", argv[1]))
return cli_arg_help(cli, argv[2][1], "<1-65535>", "Autonomous system number", NULL); return cli_arg_help(cli, argv[2][1], "<1-65535>", "Autonomous system number", NULL);
if (!strncmp("timers", argv[1], strlen(argv[1]))) if (MATCH("timers", argv[1]))
{ {
if (argc == 3) if (argc == 3)
return cli_arg_help(cli, 0, "<1-65535>", "Keepalive time", NULL); return cli_arg_help(cli, 0, "<1-65535>", "Keepalive time", NULL);
@ -1977,7 +2014,7 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a
return CLI_OK; return CLI_OK;
} }
if (!strncmp("remote-as", argv[1], strlen(argv[1]))) if (MATCH("remote-as", argv[1]))
{ {
int as = atoi(argv[2]); int as = atoi(argv[2]);
if (as < 0 || as > 65535) if (as < 0 || as > 65535)
@ -1997,7 +2034,7 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a
return CLI_OK; return CLI_OK;
} }
if (argc != 4 || strncmp("timers", argv[1], strlen(argv[1]))) if (argc != 4 || !MATCH("timers", argv[1]))
{ {
cli_print(cli, "Invalid arguments"); cli_print(cli, "Invalid arguments");
return CLI_OK; return CLI_OK;
@ -2222,6 +2259,568 @@ static int cmd_restart_bgp(struct cli_def *cli, char *command, char **argv, int
} }
#endif /* BGP*/ #endif /* BGP*/
static int filt;
static int find_access_list(char const *name)
{
int i;
for (i = 0; i < MAXFILTER; i++)
if (!(*ip_filters[i].name && strcmp(ip_filters[i].name, name)))
return i;
return -1;
}
static int access_list(struct cli_def *cli, char **argv, int argc, int add)
{
int extended;
if (CLI_HELP_REQUESTED)
{
switch (argc)
{
case 1:
return cli_arg_help(cli, 0,
"standard", "Standard syntax",
"extended", "Extended syntax",
NULL);
case 2:
return cli_arg_help(cli, argv[1][1],
"NAME", "Access-list name",
NULL);
default:
if (argc == 3 && !argv[2][1])
return cli_arg_help(cli, 1, NULL);
return CLI_OK;
}
}
if (argc != 2)
{
cli_print(cli, "Specify access-list type and name");
return CLI_OK;
}
if (MATCH("standard", argv[0]))
extended = 0;
else if (MATCH("extended", argv[0]))
extended = 1;
else
{
cli_print(cli, "Invalid access-list type");
return CLI_OK;
}
if (strlen(argv[1]) > sizeof(ip_filters[0].name) - 1 ||
strspn(argv[1], "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_") != strlen(argv[1]))
{
cli_print(cli, "Invalid access-list name");
return CLI_OK;
}
filt = find_access_list(argv[1]);
if (add)
{
if (filt < 0)
{
cli_print(cli, "Too many access-lists");
return CLI_OK;
}
// racy
if (!*ip_filters[filt].name)
{
memset(&ip_filters[filt], 0, sizeof(ip_filters[filt]));
strcpy(ip_filters[filt].name, argv[1]);
ip_filters[filt].extended = extended;
}
else if (ip_filters[filt].extended != extended)
{
cli_print(cli, "Access-list is %s",
ip_filters[filt].extended ? "extended" : "standard");
return CLI_OK;
}
cli_set_configmode(cli, MODE_CONFIG_NACL, extended ? "ext-nacl" : "std-nacl");
return CLI_OK;
}
if (filt < 0 || !*ip_filters[filt].name)
{
cli_print(cli, "Access-list not defined");
return CLI_OK;
}
// racy
if (ip_filters[filt].used)
{
cli_print(cli, "Access-list in use");
return CLI_OK;
}
memset(&ip_filters[filt], 0, sizeof(ip_filters[filt]));
return CLI_OK;
}
static int cmd_ip_access_list(struct cli_def *cli, char *command, char **argv, int argc)
{
return access_list(cli, argv, argc, 1);
}
static int cmd_no_ip_access_list(struct cli_def *cli, char *command, char **argv, int argc)
{
return access_list(cli, argv, argc, 0);
}
static int show_ip_wild(char *buf, ipt ip, ipt wild)
{
int i;
if (ip == INADDR_ANY && wild == INADDR_BROADCAST)
return sprintf(buf, " any");
if (wild == INADDR_ANY)
return sprintf(buf, " host %s", inet_toa(ip));
i = sprintf(buf, " %s", inet_toa(ip));
return i + sprintf(buf + i, " %s", inet_toa(wild));
}
static int show_ports(char *buf, ip_filter_portt *ports)
{
switch (ports->op)
{
case FILTER_PORT_OP_EQ: return sprintf(buf, " eq %u", ports->port);
case FILTER_PORT_OP_NEQ: return sprintf(buf, " neq %u", ports->port);
case FILTER_PORT_OP_GT: return sprintf(buf, " gt %u", ports->port);
case FILTER_PORT_OP_LT: return sprintf(buf, " lt %u", ports->port);
case FILTER_PORT_OP_RANGE: return sprintf(buf, " range %u %u", ports->port, ports->port2);
}
return 0;
}
static char const *show_access_list_rule(int extended, ip_filter_rulet *rule)
{
static char buf[256];
char *p = buf;
p += sprintf(p, " %s", rule->action == FILTER_ACTION_PERMIT ? "permit" : "deny");
if (extended)
{
struct protoent *proto = getprotobynumber(rule->proto);
p += sprintf(p, " %s", proto ? proto->p_name : "ERR");
}
p += show_ip_wild(p, rule->src_ip, rule->src_wild);
if (!extended)
return buf;
if (rule->proto == IPPROTO_TCP || rule->proto == IPPROTO_UDP)
p += show_ports(p, &rule->src_ports);
p += show_ip_wild(p, rule->dst_ip, rule->dst_wild);
if (rule->proto == IPPROTO_TCP || rule->proto == IPPROTO_UDP)
p += show_ports(p, &rule->dst_ports);
if (rule->proto == IPPROTO_TCP && (rule->tcp_sflags || rule->tcp_cflags))
{
if (rule->tcp_flag_op == FILTER_FLAG_OP_ANY &&
rule->tcp_sflags == (TCP_FLAG_ACK|TCP_FLAG_FIN) &&
rule->tcp_cflags == TCP_FLAG_SYN)
{
p += sprintf(p, " established");
}
else
{
p += sprintf(p, " match-%s", rule->tcp_flag_op == FILTER_FLAG_OP_ALL ? "all" : "any");
if (rule->tcp_sflags & TCP_FLAG_FIN) p += sprintf(p, " +fin");
if (rule->tcp_cflags & TCP_FLAG_FIN) p += sprintf(p, " -fin");
if (rule->tcp_sflags & TCP_FLAG_SYN) p += sprintf(p, " +syn");
if (rule->tcp_cflags & TCP_FLAG_SYN) p += sprintf(p, " -syn");
if (rule->tcp_sflags & TCP_FLAG_RST) p += sprintf(p, " +rst");
if (rule->tcp_cflags & TCP_FLAG_RST) p += sprintf(p, " -rst");
if (rule->tcp_sflags & TCP_FLAG_PSH) p += sprintf(p, " +psh");
if (rule->tcp_cflags & TCP_FLAG_PSH) p += sprintf(p, " -psh");
if (rule->tcp_sflags & TCP_FLAG_ACK) p += sprintf(p, " +ack");
if (rule->tcp_cflags & TCP_FLAG_ACK) p += sprintf(p, " -ack");
if (rule->tcp_sflags & TCP_FLAG_URG) p += sprintf(p, " +urg");
if (rule->tcp_cflags & TCP_FLAG_URG) p += sprintf(p, " -urg");
}
}
return buf;
}
ip_filter_rulet *access_list_rule_ext(struct cli_def *cli, char *command, char **argv, int argc)
{
static ip_filter_rulet rule;
struct in_addr addr;
int i;
int a;
if (CLI_HELP_REQUESTED)
{
if (argc == 1)
{
cli_arg_help(cli, 0,
"ip", "Match IP packets",
"tcp", "Match TCP packets",
"udp", "Match UDP packets",
NULL);
return NULL;
}
// *sigh*, too darned complex
cli_arg_help(cli, 0, "RULE", "SOURCE [PORTS] DEST [PORTS] FLAGS", NULL);
return NULL;
}
if (argc < 3)
{
cli_print(cli, "Specify rule details");
return NULL;
}
memset(&rule, 0, sizeof(rule));
rule.action = (command[0] == 'p')
? FILTER_ACTION_PERMIT
: FILTER_ACTION_DENY;
if (MATCH("ip", argv[0]))
rule.proto = IPPROTO_IP;
else if (MATCH("udp", argv[0]))
rule.proto = IPPROTO_UDP;
else if (MATCH("tcp", argv[0]))
rule.proto = IPPROTO_TCP;
else
{
cli_print(cli, "Invalid protocol \"%s\"", argv[0]);
return NULL;
}
for (a = 1, i = 0; i < 2; i++)
{
ipt *ip;
ipt *wild;
ip_filter_portt *port;
if (i == 0)
{
ip = &rule.src_ip;
wild = &rule.src_wild;
port = &rule.src_ports;
}
else
{
ip = &rule.dst_ip;
wild = &rule.dst_wild;
port = &rule.dst_ports;
if (a >= argc)
{
cli_print(cli, "Specify destination");
return NULL;
}
}
if (MATCH("any", argv[a]))
{
*ip = INADDR_ANY;
*wild = INADDR_BROADCAST;
a++;
}
else if (MATCH("host", argv[a]))
{
if (++a >= argc)
{
cli_print(cli, "Specify host ip address");
return NULL;
}
if (!inet_aton(argv[a], &addr))
{
cli_print(cli, "Cannot parse IP \"%s\"", argv[a]);
return NULL;
}
*ip = addr.s_addr;
*wild = INADDR_ANY;
a++;
}
else
{
if (++a >= argc)
{
cli_print(cli, "Specify %s ip address and wildcard", i ? "destination" : "source");
return NULL;
}
if (!inet_aton(argv[a], &addr))
{
cli_print(cli, "Cannot parse IP \"%s\"", argv[a]);
return NULL;
}
*ip = addr.s_addr;
if (!inet_aton(argv[++a], &addr))
{
cli_print(cli, "Cannot parse IP \"%s\"", argv[a]);
return NULL;
}
*wild = addr.s_addr;
}
if (rule.proto == IPPROTO_IP || a >= argc)
continue;
port->op = 0;
if (MATCH("eq", argv[a]))
port->op = FILTER_PORT_OP_EQ;
else if (MATCH("neq", argv[a]))
port->op = FILTER_PORT_OP_NEQ;
else if (MATCH("gt", argv[a]))
port->op = FILTER_PORT_OP_GT;
else if (MATCH("lt", argv[a]))
port->op = FILTER_PORT_OP_LT;
else if (MATCH("range", argv[a]))
port->op = FILTER_PORT_OP_RANGE;
if (!port->op)
continue;
if (++a >= argc)
{
cli_print(cli, "Specify port");
return NULL;
}
if (!(port->port = atoi(argv[a])))
{
cli_print(cli, "Invalid port \"%s\"", argv[a]);
return NULL;
}
a++;
if (port->op != FILTER_PORT_OP_RANGE)
continue;
if (a >= argc)
{
cli_print(cli, "Specify port");
return NULL;
}
if (!(port->port2 = atoi(argv[a])) || port->port2 < port->port)
{
cli_print(cli, "Invalid port \"%s\"", argv[a]);
return NULL;
}
a++;
}
if (rule.proto == IPPROTO_TCP && a < argc)
{
if (MATCH("established", argv[a]))
{
rule.tcp_flag_op = FILTER_FLAG_OP_ANY;
rule.tcp_sflags = (TCP_FLAG_ACK|TCP_FLAG_FIN);
rule.tcp_cflags = TCP_FLAG_SYN;
a++;
}
else if (!strcmp(argv[a], "match-any") || !strcmp(argv[a], "match-an") ||
!strcmp(argv[a], "match-all") || !strcmp(argv[a], "match-al"))
{
rule.tcp_flag_op = argv[a][7] == 'n'
? FILTER_FLAG_OP_ANY
: FILTER_FLAG_OP_ALL;
if (++a >= argc)
{
cli_print(cli, "Specify tcp flags");
return NULL;
}
while (a < argc && (argv[a][0] == '+' || argv[a][0] == '-'))
{
u8 *f;
f = (argv[a][0] == '+') ? &rule.tcp_sflags : &rule.tcp_cflags;
if (MATCH("fin", &argv[a][1])) *f |= TCP_FLAG_FIN;
else if (MATCH("syn", &argv[a][1])) *f |= TCP_FLAG_SYN;
else if (MATCH("rst", &argv[a][1])) *f |= TCP_FLAG_RST;
else if (MATCH("psh", &argv[a][1])) *f |= TCP_FLAG_PSH;
else if (MATCH("ack", &argv[a][1])) *f |= TCP_FLAG_ACK;
else if (MATCH("urg", &argv[a][1])) *f |= TCP_FLAG_URG;
else
{
cli_print(cli, "Invalid tcp flag \"%s\"", argv[a]);
return NULL;
}
a++;
}
}
}
if (a < argc)
{
cli_print(cli, "Invalid flag \"%s\"", argv[a]);
return NULL;
}
return &rule;
}
ip_filter_rulet *access_list_rule_std(struct cli_def *cli, char *command, char **argv, int argc)
{
static ip_filter_rulet rule;
struct in_addr addr;
if (CLI_HELP_REQUESTED)
{
if (argc == 1)
{
cli_arg_help(cli, argv[0][1],
"A.B.C.D", "Source address",
"any", "Any source address",
"host", "Source host",
NULL);
return NULL;
}
if (MATCH("any", argv[0]))
{
if (argc == 2 && !argv[1][1])
cli_arg_help(cli, 1, NULL);
}
else if (MATCH("host", argv[0]))
{
if (argc == 2)
{
cli_arg_help(cli, argv[1][1],
"A.B.C.D", "Host address",
NULL);
}
else if (argc == 3 && !argv[2][1])
cli_arg_help(cli, 1, NULL);
}
else
{
if (argc == 2)
{
cli_arg_help(cli, 1,
"A.B.C.D", "Wildcard bits",
NULL);
}
else if (argc == 3 && !argv[2][1])
cli_arg_help(cli, 1, NULL);
}
return NULL;
}
if (argc < 1)
{
cli_print(cli, "Specify rule details");
return NULL;
}
memset(&rule, 0, sizeof(rule));
rule.action = (command[0] == 'p')
? FILTER_ACTION_PERMIT
: FILTER_ACTION_DENY;
rule.proto = IPPROTO_IP;
if (MATCH("any", argv[0]))
{
rule.src_ip = INADDR_ANY;
rule.src_wild = INADDR_BROADCAST;
}
else if (MATCH("host", argv[0]))
{
if (argc != 2)
{
cli_print(cli, "Specify host ip address");
return NULL;
}
if (!inet_aton(argv[1], &addr))
{
cli_print(cli, "Cannot parse IP \"%s\"", argv[1]);
return NULL;
}
rule.src_ip = addr.s_addr;
rule.src_wild = INADDR_ANY;
}
else
{
if (argc > 2)
{
cli_print(cli, "Specify source ip address and wildcard");
return NULL;
}
if (!inet_aton(argv[0], &addr))
{
cli_print(cli, "Cannot parse IP \"%s\"", argv[0]);
return NULL;
}
rule.src_ip = addr.s_addr;
if (argc > 1)
{
if (!inet_aton(argv[1], &addr))
{
cli_print(cli, "Cannot parse IP \"%s\"", argv[1]);
return NULL;
}
rule.src_wild = addr.s_addr;
}
else
rule.src_wild = INADDR_ANY;
}
return &rule;
}
static int cmd_ip_access_list_rule(struct cli_def *cli, char *command, char **argv, int argc)
{
int i;
ip_filter_rulet *rule = ip_filters[filt].extended
? access_list_rule_ext(cli, command, argv, argc)
: access_list_rule_std(cli, command, argv, argc);
if (!rule)
return CLI_OK;
for (i = 0; i < MAXFILTER_RULES - 1; i++) // -1: list always terminated by empty rule
{
if (!ip_filters[filt].rules[i].action)
{
memcpy(&ip_filters[filt].rules[i], rule, sizeof(*rule));
return CLI_OK;
}
if (!memcmp(&ip_filters[filt].rules[i], rule, sizeof(*rule)))
return CLI_OK;
}
cli_print(cli, "Too many rules");
return CLI_OK;
}
// Convert a string in the form of abcd.ef12.3456 into char[6] // Convert a string in the form of abcd.ef12.3456 into char[6]
void parsemac(char *string, char mac[6]) void parsemac(char *string, char mac[6])
{ {

View file

@ -4,7 +4,7 @@
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
// vim: sw=8 ts=8 // vim: sw=8 ts=8
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.56 2004/11/25 02:49:18 bodea Exp $"; char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.57 2004/11/27 05:19:53 bodea Exp $";
#include <arpa/inet.h> #include <arpa/inet.h>
#include <assert.h> #include <assert.h>
@ -54,7 +54,7 @@ char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.56 2004/11/25 02:49:18 bodea Exp
#endif /* BGP */ #endif /* BGP */
// Globals // Globals
struct configt *config = NULL; // all configuration configt *config = NULL; // all configuration
int tunfd = -1; // tun interface file handle. (network device) int tunfd = -1; // tun interface file handle. (network device)
int udpfd = -1; // UDP file handle int udpfd = -1; // UDP file handle
int controlfd = -1; // Control signal handle int controlfd = -1; // Control signal handle
@ -88,9 +88,9 @@ linked_list *loaded_plugins;
linked_list *plugins[MAX_PLUGIN_TYPES]; linked_list *plugins[MAX_PLUGIN_TYPES];
#define membersize(STRUCT, MEMBER) sizeof(((STRUCT *)0)->MEMBER) #define membersize(STRUCT, MEMBER) sizeof(((STRUCT *)0)->MEMBER)
#define CONFIG(NAME, MEMBER, TYPE) { NAME, offsetof(struct configt, MEMBER), membersize(struct configt, MEMBER), TYPE } #define CONFIG(NAME, MEMBER, TYPE) { NAME, offsetof(configt, MEMBER), membersize(configt, MEMBER), TYPE }
struct config_descriptt config_values[] = { config_descriptt config_values[] = {
CONFIG("debug", debug, INT), CONFIG("debug", debug, INT),
CONFIG("log_file", log_filename, STRING), CONFIG("log_file", log_filename, STRING),
CONFIG("pid_file", pid_file, STRING), CONFIG("pid_file", pid_file, STRING),
@ -146,6 +146,7 @@ sessiont *session = NULL; // Array of session structures.
sessioncountt *sess_count = NULL; // Array of partial per-session traffic counters. sessioncountt *sess_count = NULL; // Array of partial per-session traffic counters.
radiust *radius = NULL; // Array of radius structures. radiust *radius = NULL; // Array of radius structures.
ippoolt *ip_address_pool = NULL; // Array of dynamic IP addresses. ippoolt *ip_address_pool = NULL; // Array of dynamic IP addresses.
ip_filtert *ip_filters = NULL; // Array of named filters.
static controlt *controlfree = 0; static controlt *controlfree = 0;
struct Tstats *_statistics = NULL; struct Tstats *_statistics = NULL;
#ifdef RINGBUFFER #ifdef RINGBUFFER
@ -942,8 +943,10 @@ static void controladd(controlt * c, tunnelidt t, sessionidt s)
tunnel[t].controle->next = c; tunnel[t].controle->next = c;
else else
tunnel[t].controls = c; tunnel[t].controls = c;
tunnel[t].controle = c; tunnel[t].controle = c;
tunnel[t].controlc++; tunnel[t].controlc++;
// send now if space in window // send now if space in window
if (tunnel[t].controlc <= tunnel[t].window) if (tunnel[t].controlc <= tunnel[t].window)
{ {
@ -1306,10 +1309,9 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
return; return;
} }
LOG(3, ntohl(addr->sin_addr.s_addr), s, t, "Control message (%d bytes): (unacked %d) l-ns %d l-nr %d r-ns %d r-nr %d\n",
l, tunnel[t].controlc, tunnel[t].ns, tunnel[t].nr, ns, nr); // check for duplicate tunnel open message
// if no tunnel specified, assign one if (!t && ns == 0)
if (!t)
{ {
int i; int i;
@ -1323,10 +1325,15 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
tunnel[i].port != ntohs(addr->sin_port) ) tunnel[i].port != ntohs(addr->sin_port) )
continue; continue;
t = i; t = i;
LOG(3, ntohl(addr->sin_addr.s_addr), s, t, "Duplicate SCCRQ?\n");
break; break;
} }
} }
LOG(3, ntohl(addr->sin_addr.s_addr), s, t, "Control message (%d bytes): (unacked %d) l-ns %d l-nr %d r-ns %d r-nr %d\n",
l, tunnel[t].controlc, tunnel[t].ns, tunnel[t].nr, ns, nr);
// if no tunnel specified, assign one
if (!t) if (!t)
{ {
if (!(t = new_tunnel())) if (!(t = new_tunnel()))
@ -1339,26 +1346,10 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
tunnel[t].ip = ntohl(*(ipt *) & addr->sin_addr); tunnel[t].ip = ntohl(*(ipt *) & addr->sin_addr);
tunnel[t].port = ntohs(addr->sin_port); tunnel[t].port = ntohs(addr->sin_port);
tunnel[t].window = 4; // default window tunnel[t].window = 4; // default window
LOG(1, ntohl(addr->sin_addr.s_addr), 0, t, " New tunnel from %u.%u.%u.%u/%u ID %d\n", tunnel[t].ip >> 24, tunnel[t].ip >> 16 & 255, tunnel[t].ip >> 8 & 255, tunnel[t].ip & 255, tunnel[t].port, t);
STAT(tunnel_created); STAT(tunnel_created);
} LOG(1, ntohl(addr->sin_addr.s_addr), 0, t, " New tunnel from %u.%u.%u.%u/%u ID %d\n",
tunnel[t].ip >> 24, tunnel[t].ip >> 16 & 255,
// This is used to time out old tunnels tunnel[t].ip >> 8 & 255, tunnel[t].ip & 255, tunnel[t].port, t);
tunnel[t].lastrec = time_now;
// check sequence of this message
{
int skip = tunnel[t].window; // track how many in-window packets are still in queue
// some to clear maybe?
while (tunnel[t].controlc && (((tunnel[t].ns - tunnel[t].controlc) - nr) & 0x8000))
{
controlt *c = tunnel[t].controls;
tunnel[t].controls = c->next;
tunnel[t].controlc--;
c->next = controlfree;
controlfree = c;
skip--;
tunnel[t].try = 0; // we have progress
} }
// If the 'ns' just received is not the 'nr' we're // If the 'ns' just received is not the 'nr' we're
@ -1370,13 +1361,33 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
if (ns != tunnel[t].nr) if (ns != tunnel[t].nr)
{ {
// is this the sequence we were expecting? // is this the sequence we were expecting?
LOG(1, ntohl(addr->sin_addr.s_addr), 0, t, " Out of sequence tunnel %d, (%d is not the expected %d)\n", t, ns, tunnel[t].nr);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
LOG(1, ntohl(addr->sin_addr.s_addr), 0, t, " Out of sequence tunnel %d, (%d is not the expected %d)\n",
t, ns, tunnel[t].nr);
if (l) // Is this not a ZLB? if (l) // Is this not a ZLB?
controlnull(t); controlnull(t);
return; return;
} }
// This is used to time out old tunnels
tunnel[t].lastrec = time_now;
// check sequence of this message
{
int skip = tunnel[t].window; // track how many in-window packets are still in queue
// some to clear maybe?
while (tunnel[t].controlc > 0 && (((tunnel[t].ns - tunnel[t].controlc) - nr) & 0x8000))
{
controlt *c = tunnel[t].controls;
tunnel[t].controls = c->next;
tunnel[t].controlc--;
c->next = controlfree;
controlfree = c;
skip--;
tunnel[t].try = 0; // we have progress
}
// receiver advance (do here so quoted correctly in any sends below) // receiver advance (do here so quoted correctly in any sends below)
if (l) tunnel[t].nr = (ns + 1); if (l) tunnel[t].nr = (ns + 1);
if (skip < 0) skip = 0; if (skip < 0) skip = 0;
@ -2480,12 +2491,12 @@ static void initdata(int optdebug, char *optconfig)
LOG(0, 0, 0, 0, "Error doing malloc for _statistics: %s\n", strerror(errno)); LOG(0, 0, 0, 0, "Error doing malloc for _statistics: %s\n", strerror(errno));
exit(1); exit(1);
} }
if (!(config = shared_malloc(sizeof(struct configt)))) if (!(config = shared_malloc(sizeof(configt))))
{ {
LOG(0, 0, 0, 0, "Error doing malloc for configuration: %s\n", strerror(errno)); LOG(0, 0, 0, 0, "Error doing malloc for configuration: %s\n", strerror(errno));
exit(1); exit(1);
} }
memset(config, 0, sizeof(struct configt)); memset(config, 0, sizeof(configt));
time(&config->start_time); time(&config->start_time);
strncpy(config->config_file, optconfig, strlen(optconfig)); strncpy(config->config_file, optconfig, strlen(optconfig));
config->debug = optdebug; config->debug = optdebug;
@ -2521,6 +2532,13 @@ static void initdata(int optdebug, char *optconfig)
exit(1); exit(1);
} }
if (!(ip_filters = shared_malloc(sizeof(ip_filtert) * MAXFILTER)))
{
LOG(0, 0, 0, 0, "Error doing malloc for ip_filters: %s\n", strerror(errno));
exit(1);
}
memset(ip_filters, 0, sizeof(ip_filtert) * MAXFILTER);
#ifdef RINGBUFFER #ifdef RINGBUFFER
if (!(ringbuffer = shared_malloc(sizeof(struct Tringbuffer)))) if (!(ringbuffer = shared_malloc(sizeof(struct Tringbuffer))))
{ {

View file

@ -1,5 +1,5 @@
// L2TPNS Global Stuff // L2TPNS Global Stuff
// $Id: l2tpns.h,v 1.37 2004/11/25 12:41:35 bodea Exp $ // $Id: l2tpns.h,v 1.38 2004/11/27 05:19:53 bodea Exp $
#ifndef __L2TPNS_H__ #ifndef __L2TPNS_H__
#define __L2TPNS_H__ #define __L2TPNS_H__
@ -142,7 +142,7 @@ struct cli_tunnel_actions {
#define DUMP_MAGIC "L2TPNS#" VERSION "#" #define DUMP_MAGIC "L2TPNS#" VERSION "#"
// structures // structures
typedef struct routes // route typedef struct // route
{ {
ipt ip; ipt ip;
ipt mask; ipt mask;
@ -157,7 +157,7 @@ typedef struct controls // control message
} }
controlt; controlt;
typedef struct sessions typedef struct
{ {
sessionidt next; // next session in linked list sessionidt next; // next session in linked list
sessionidt far; // far end session ID sessionidt far; // far end session ID
@ -199,7 +199,9 @@ typedef struct sessions
ipt snoop_ip; // Interception destination IP ipt snoop_ip; // Interception destination IP
u16 snoop_port; // Interception destination port u16 snoop_port; // Interception destination port
u16 sid; // near end session id. u16 sid; // near end session id.
char reserved[20]; // Space to expand structure without changing HB_VERSION u8 filter_in; // input filter index (to ip_filters[N-1]; 0 if none)
u8 filter_out; // output filter index
char reserved[18]; // Space to expand structure without changing HB_VERSION
} }
sessiont; sessiont;
@ -207,7 +209,8 @@ sessiont;
#define SF_LCP_ACKED 2 // LCP negotiated #define SF_LCP_ACKED 2 // LCP negotiated
#define SF_CCP_ACKED 4 // CCP negotiated #define SF_CCP_ACKED 4 // CCP negotiated
typedef struct { typedef struct
{
u32 cin; u32 cin;
u32 cout; u32 cout;
} sessioncountt; } sessioncountt;
@ -216,7 +219,7 @@ typedef struct {
#define SESSIONACFC 2 // ACFC negotiated flags #define SESSIONACFC 2 // ACFC negotiated flags
// 168 bytes per tunnel // 168 bytes per tunnel
typedef struct tunnels typedef struct
{ {
tunnelidt far; // far end tunnel ID tunnelidt far; // far end tunnel ID
ipt ip; // Ip for far end ipt ip; // Ip for far end
@ -239,7 +242,7 @@ typedef struct tunnels
tunnelt; tunnelt;
// 180 bytes per radius session // 180 bytes per radius session
typedef struct radiuss // outstanding RADIUS requests typedef struct // outstanding RADIUS requests
{ {
sessionidt session; // which session this applies to sessionidt session; // which session this applies to
hasht auth; // request authenticator hasht auth; // request authenticator
@ -393,7 +396,7 @@ struct Tstats
#define SET_STAT(x, y) #define SET_STAT(x, y)
#endif #endif
struct configt typedef struct
{ {
int debug; // debugging level int debug; // debugging level
time_t start_time; // time when l2tpns was started time_t start_time; // time when l2tpns was started
@ -470,16 +473,65 @@ struct configt
int hold; int hold;
} neighbour[BGP_NUM_PEERS]; } neighbour[BGP_NUM_PEERS];
#endif #endif
}; } configt;
enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IP, MAC }; enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IP, MAC };
struct config_descriptt typedef struct
{ {
char *key; char *key;
int offset; int offset;
int size; int size;
enum config_typet type; enum config_typet type;
}; } config_descriptt;
typedef struct
{
u8 op; // operation
#define FILTER_PORT_OP_NONE 0 // all ports match
#define FILTER_PORT_OP_EQ 1
#define FILTER_PORT_OP_NEQ 2
#define FILTER_PORT_OP_GT 3
#define FILTER_PORT_OP_LT 4
#define FILTER_PORT_OP_RANGE 5
portt port;
portt port2; // for range
} ip_filter_portt;
typedef struct
{
int action; // permit/deny
#define FILTER_ACTION_DENY 1
#define FILTER_ACTION_PERMIT 2
int proto; // protocol: IPPROTO_* (netinet/in.h)
ipt src_ip; // source ip
ipt src_wild;
ip_filter_portt src_ports;
ipt dst_ip; // dest ip
ipt dst_wild;
ip_filter_portt dst_ports;
u8 tcp_flag_op; // match type: any, all
#define FILTER_FLAG_OP_ANY 0
#define FILTER_FLAG_OP_ALL 1
u8 tcp_sflags; // flags set
u8 tcp_cflags; // flags clear
} ip_filter_rulet;
#define TCP_FLAG_FIN 0x01
#define TCP_FLAG_SYN 0x02
#define TCP_FLAG_RST 0x04
#define TCP_FLAG_PSH 0x08
#define TCP_FLAG_ACK 0x10
#define TCP_FLAG_URG 0x20
#define MAXFILTER 32
#define MAXFILTER_RULES 32
typedef struct
{
char name[32]; // ACL name
int extended; // type: 0 = standard, 1 = extended
ip_filter_rulet rules[MAXFILTER_RULES];
int used; // session ref count
} ip_filtert;
// arp.c // arp.c
void sendarp(int ifr_idx, const unsigned char* mac, ipt ip); void sendarp(int ifr_idx, const unsigned char* mac, ipt ip);
@ -570,7 +622,7 @@ if (count++ < max) { \
} }
extern struct configt *config; extern configt *config;
extern time_t basetime; // Time when this process started. extern time_t basetime; // Time when this process started.
extern time_t time_now; // Seconds since EPOCH. extern time_t time_now; // Seconds since EPOCH.
extern u32 last_id; extern u32 last_id;

View file

@ -43,5 +43,5 @@ rm -rf %{buildroot}
%attr(644,root,root) /usr/share/man/man[58]/* %attr(644,root,root) /usr/share/man/man[58]/*
%changelog %changelog
* Thu Nov 25 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.9-1 * Sat Nov 27 2004 Brendan O'Dea <bod@optusnet.com.au> 2.0.9-1
- 2.0.9 release, see /usr/share/doc/l2tpns-2.0.9/Changes - 2.0.9 release, see /usr/share/doc/l2tpns-2.0.9/Changes

4
ppp.c
View file

@ -1,6 +1,6 @@
// L2TPNS PPP Stuff // L2TPNS PPP Stuff
char const *cvs_id_ppp = "$Id: ppp.c,v 1.30 2004/11/25 12:46:48 bodea Exp $"; char const *cvs_id_ppp = "$Id: ppp.c,v 1.31 2004/11/27 05:19:53 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -21,7 +21,7 @@ extern int tunfd;
extern char hostname[]; extern char hostname[];
extern u32 eth_tx; extern u32 eth_tx;
extern time_t time_now; extern time_t time_now;
extern struct configt *config; extern configt *config;
static void initccp(tunnelidt t, sessionidt s); static void initccp(tunnelidt t, sessionidt s);

View file

@ -1,6 +1,6 @@
// L2TPNS Radius Stuff // L2TPNS Radius Stuff
char const *cvs_id_radius = "$Id: radius.c,v 1.13 2004/11/25 02:45:27 bodea Exp $"; char const *cvs_id_radius = "$Id: radius.c,v 1.14 2004/11/27 05:19:53 bodea Exp $";
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
@ -22,7 +22,7 @@ extern radiust *radius;
extern sessiont *session; extern sessiont *session;
extern tunnelt *tunnel; extern tunnelt *tunnel;
extern u32 sessionid; extern u32 sessionid;
extern struct configt *config; extern configt *config;
extern int *radfds; extern int *radfds;
static const char *radius_state(int state) static const char *radius_state(int state)