- 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:
parent
c5134c0536
commit
3057f5e655
9 changed files with 920 additions and 94 deletions
5
Changes
5
Changes
|
|
@ -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.
|
||||
- Don't copy the old buffer into Config{Nak,Rej} LCP responses (oops);
|
||||
add length checks when appending.
|
||||
- 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
|
||||
- Ignore gateway address in Framed-Route (from Jonathan McDowell).
|
||||
|
|
|
|||
100
Docs/manual.html
100
Docs/manual.html
|
|
@ -52,7 +52,8 @@ H3 {
|
|||
<LI><A HREF="#Interception">Interception</A></LI>
|
||||
<LI><A HREF="#Authentication">Authentication</A></LI>
|
||||
<LI><A HREF="#Plugins">Plugins</A></LI>
|
||||
<LI><A HREF="#Walled Garden">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="#Routing">Routing</A></LI>
|
||||
<LI><A HREF="#Performance">Performance</A></LI>
|
||||
|
|
@ -200,29 +201,34 @@ software upgrade.
|
|||
|
||||
<LI><B>primary_radius</B> (ip address)
|
||||
<LI><B>secondary_radius</B> (ip address)<BR>
|
||||
Sets the radius servers used for both authentication and accounting.
|
||||
If the primary server does not respond, then the secondary radius
|
||||
server will be tried.
|
||||
Sets the RADIUS servers used for both authentication and accounting.
|
||||
If the primary server does not respond, then the secondary RADIUS
|
||||
server will be tried.<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><B>primary_radius_port</B> (short)
|
||||
<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
|
||||
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.
|
||||
</LI>
|
||||
|
||||
<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
|
||||
successfully authenticated, and a Stop record will be sent when the
|
||||
session is closed.
|
||||
</LI>
|
||||
|
||||
<LI><B>radius_secret</B> (string)<BR>
|
||||
This secret will be used in all radius queries. If this is not set then
|
||||
radius queries will fail.
|
||||
This secret will be used in all RADIUS queries. If this is not set then
|
||||
RADIUS queries will fail.
|
||||
</LI>
|
||||
|
||||
<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>,
|
||||
<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>
|
||||
|
||||
Usernames and passwords for the command-line interface are stored in
|
||||
|
|
@ -500,19 +540,19 @@ IP Address Used Session User
|
|||
</LI>
|
||||
|
||||
<LI><B>show radius</B><BR>
|
||||
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
|
||||
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
|
||||
columns listed are:
|
||||
<TABLE>
|
||||
<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>
|
||||
<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>
|
||||
<TR><TD><B>State</B></TD><TD>The state of the request - WAIT, CHAP,
|
||||
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>
|
||||
<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>
|
||||
<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>
|
||||
</TABLE>
|
||||
<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
|
||||
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>.
|
||||
<P>
|
||||
</LI>
|
||||
|
|
@ -564,7 +604,7 @@ session. Specify <EM>no throttle username</EM> to disable throttling
|
|||
for the current session.<P>
|
||||
|
||||
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>
|
||||
</LI>
|
||||
|
||||
|
|
@ -660,7 +700,7 @@ desire. You must first enable the global setting <EM>throttle_speed</EM>
|
|||
before this will be activated.<P>
|
||||
|
||||
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>
|
||||
|
||||
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>
|
||||
|
||||
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,
|
||||
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
|
||||
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>
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
devices understand to contain configuration instructions for the session. In
|
||||
the case of l2tpns it is expected to be of the form
|
||||
|
|
@ -758,7 +798,7 @@ supplied structure:
|
|||
<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 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
|
||||
code. This will allow you to modify the response in
|
||||
some way.
|
||||
|
|
@ -775,7 +815,7 @@ supplied structure:
|
|||
</TD>
|
||||
</TR>
|
||||
<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
|
||||
is what the garden module uses to force authentication
|
||||
to be accepted.
|
||||
|
|
@ -855,7 +895,7 @@ supplied structure:
|
|||
</TD>
|
||||
</TR>
|
||||
<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
|
||||
<EM>key=value</EM> pairs, and each is processed through all
|
||||
modules.
|
||||
|
|
@ -901,7 +941,7 @@ Walled Garden is implemented so that you can provide perhaps limited service
|
|||
to sessions that incorrectly authenticate.<P>
|
||||
|
||||
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
|
||||
<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
|
||||
|
|
@ -926,6 +966,14 @@ command:
|
|||
iptables -t nat -L garden -nvx
|
||||
</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>
|
||||
|
||||
An l2tpns cluster consists of of one* or more servers configured with
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
.de Id
|
||||
.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"
|
||||
.SH NAME
|
||||
startup\-config \- configuration file for l2tpns
|
||||
|
|
@ -199,5 +199,111 @@ is the remote AS number and
|
|||
.IR keepalive ,
|
||||
.I hold
|
||||
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
|
||||
.BR l2tpns (8)
|
||||
|
|
|
|||
615
cli.c
615
cli.c
|
|
@ -2,7 +2,7 @@
|
|||
// vim: sw=8 ts=8
|
||||
|
||||
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 <stdarg.h>
|
||||
|
|
@ -38,14 +38,15 @@ extern radiust *radius;
|
|||
extern ippoolt *ip_address_pool;
|
||||
extern struct Tstats *_statistics;
|
||||
static struct cli_def *cli = NULL;
|
||||
extern struct configt *config;
|
||||
extern struct config_descriptt config_values[];
|
||||
extern configt *config;
|
||||
extern config_descriptt config_values[];
|
||||
#ifdef RINGBUFFER
|
||||
extern struct Tringbuffer *ringbuffer;
|
||||
#endif
|
||||
extern struct cli_session_actions *cli_session_actions;
|
||||
extern struct cli_tunnel_actions *cli_tunnel_actions;
|
||||
extern tbft *filter_list;
|
||||
extern ip_filtert *ip_filters;
|
||||
|
||||
static char *debug_levels[] = {
|
||||
"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);
|
||||
#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)
|
||||
{
|
||||
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");
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -929,6 +950,22 @@ static int cmd_show_run(struct cli_def *cli, char *command, char **argv, int arg
|
|||
}
|
||||
#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");
|
||||
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;
|
||||
}
|
||||
|
||||
static int find_bgp_neighbour(char *name)
|
||||
static int find_bgp_neighbour(char const *name)
|
||||
{
|
||||
int i;
|
||||
int new = -1;
|
||||
|
|
@ -1940,10 +1977,10 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a
|
|||
NULL);
|
||||
|
||||
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);
|
||||
|
||||
if (!strncmp("timers", argv[1], strlen(argv[1])))
|
||||
if (MATCH("timers", argv[1]))
|
||||
{
|
||||
if (argc == 3)
|
||||
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;
|
||||
}
|
||||
|
||||
if (!strncmp("remote-as", argv[1], strlen(argv[1])))
|
||||
if (MATCH("remote-as", argv[1]))
|
||||
{
|
||||
int as = atoi(argv[2]);
|
||||
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;
|
||||
}
|
||||
|
||||
if (argc != 4 || strncmp("timers", argv[1], strlen(argv[1])))
|
||||
if (argc != 4 || !MATCH("timers", argv[1]))
|
||||
{
|
||||
cli_print(cli, "Invalid arguments");
|
||||
return CLI_OK;
|
||||
|
|
@ -2222,6 +2259,568 @@ static int cmd_restart_bgp(struct cli_def *cli, char *command, char **argv, int
|
|||
}
|
||||
#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]
|
||||
void parsemac(char *string, char mac[6])
|
||||
{
|
||||
|
|
|
|||
78
l2tpns.c
78
l2tpns.c
|
|
@ -4,7 +4,7 @@
|
|||
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
|
||||
// vim: sw=8 ts=8
|
||||
|
||||
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.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 <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 */
|
||||
|
||||
// Globals
|
||||
struct configt *config = NULL; // all configuration
|
||||
configt *config = NULL; // all configuration
|
||||
int tunfd = -1; // tun interface file handle. (network device)
|
||||
int udpfd = -1; // UDP file handle
|
||||
int controlfd = -1; // Control signal handle
|
||||
|
|
@ -88,9 +88,9 @@ linked_list *loaded_plugins;
|
|||
linked_list *plugins[MAX_PLUGIN_TYPES];
|
||||
|
||||
#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("log_file", log_filename, 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.
|
||||
radiust *radius = NULL; // Array of radius structures.
|
||||
ippoolt *ip_address_pool = NULL; // Array of dynamic IP addresses.
|
||||
ip_filtert *ip_filters = NULL; // Array of named filters.
|
||||
static controlt *controlfree = 0;
|
||||
struct Tstats *_statistics = NULL;
|
||||
#ifdef RINGBUFFER
|
||||
|
|
@ -942,8 +943,10 @@ static void controladd(controlt * c, tunnelidt t, sessionidt s)
|
|||
tunnel[t].controle->next = c;
|
||||
else
|
||||
tunnel[t].controls = c;
|
||||
|
||||
tunnel[t].controle = c;
|
||||
tunnel[t].controlc++;
|
||||
|
||||
// send now if space in 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);
|
||||
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);
|
||||
// if no tunnel specified, assign one
|
||||
if (!t)
|
||||
|
||||
// check for duplicate tunnel open message
|
||||
if (!t && ns == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -1323,10 +1325,15 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
|
|||
tunnel[i].port != ntohs(addr->sin_port) )
|
||||
continue;
|
||||
t = i;
|
||||
LOG(3, ntohl(addr->sin_addr.s_addr), s, t, "Duplicate SCCRQ?\n");
|
||||
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 = 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].port = ntohs(addr->sin_port);
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 && (((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
|
||||
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);
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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);
|
||||
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?
|
||||
controlnull(t);
|
||||
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)
|
||||
if (l) tunnel[t].nr = (ns + 1);
|
||||
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));
|
||||
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));
|
||||
exit(1);
|
||||
}
|
||||
memset(config, 0, sizeof(struct configt));
|
||||
memset(config, 0, sizeof(configt));
|
||||
time(&config->start_time);
|
||||
strncpy(config->config_file, optconfig, strlen(optconfig));
|
||||
config->debug = optdebug;
|
||||
|
|
@ -2521,6 +2532,13 @@ static void initdata(int optdebug, char *optconfig)
|
|||
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
|
||||
if (!(ringbuffer = shared_malloc(sizeof(struct Tringbuffer))))
|
||||
{
|
||||
|
|
|
|||
76
l2tpns.h
76
l2tpns.h
|
|
@ -1,5 +1,5 @@
|
|||
// 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__
|
||||
#define __L2TPNS_H__
|
||||
|
|
@ -142,7 +142,7 @@ struct cli_tunnel_actions {
|
|||
#define DUMP_MAGIC "L2TPNS#" VERSION "#"
|
||||
|
||||
// structures
|
||||
typedef struct routes // route
|
||||
typedef struct // route
|
||||
{
|
||||
ipt ip;
|
||||
ipt mask;
|
||||
|
|
@ -157,7 +157,7 @@ typedef struct controls // control message
|
|||
}
|
||||
controlt;
|
||||
|
||||
typedef struct sessions
|
||||
typedef struct
|
||||
{
|
||||
sessionidt next; // next session in linked list
|
||||
sessionidt far; // far end session ID
|
||||
|
|
@ -199,7 +199,9 @@ typedef struct sessions
|
|||
ipt snoop_ip; // Interception destination IP
|
||||
u16 snoop_port; // Interception destination port
|
||||
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;
|
||||
|
||||
|
|
@ -207,7 +209,8 @@ sessiont;
|
|||
#define SF_LCP_ACKED 2 // LCP negotiated
|
||||
#define SF_CCP_ACKED 4 // CCP negotiated
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
u32 cin;
|
||||
u32 cout;
|
||||
} sessioncountt;
|
||||
|
|
@ -216,7 +219,7 @@ typedef struct {
|
|||
#define SESSIONACFC 2 // ACFC negotiated flags
|
||||
|
||||
// 168 bytes per tunnel
|
||||
typedef struct tunnels
|
||||
typedef struct
|
||||
{
|
||||
tunnelidt far; // far end tunnel ID
|
||||
ipt ip; // Ip for far end
|
||||
|
|
@ -239,7 +242,7 @@ typedef struct tunnels
|
|||
tunnelt;
|
||||
|
||||
// 180 bytes per radius session
|
||||
typedef struct radiuss // outstanding RADIUS requests
|
||||
typedef struct // outstanding RADIUS requests
|
||||
{
|
||||
sessionidt session; // which session this applies to
|
||||
hasht auth; // request authenticator
|
||||
|
|
@ -393,7 +396,7 @@ struct Tstats
|
|||
#define SET_STAT(x, y)
|
||||
#endif
|
||||
|
||||
struct configt
|
||||
typedef struct
|
||||
{
|
||||
int debug; // debugging level
|
||||
time_t start_time; // time when l2tpns was started
|
||||
|
|
@ -470,16 +473,65 @@ struct configt
|
|||
int hold;
|
||||
} neighbour[BGP_NUM_PEERS];
|
||||
#endif
|
||||
};
|
||||
} configt;
|
||||
|
||||
enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IP, MAC };
|
||||
struct config_descriptt
|
||||
typedef struct
|
||||
{
|
||||
char *key;
|
||||
int offset;
|
||||
int size;
|
||||
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
|
||||
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 time_now; // Seconds since EPOCH.
|
||||
extern u32 last_id;
|
||||
|
|
|
|||
|
|
@ -43,5 +43,5 @@ rm -rf %{buildroot}
|
|||
%attr(644,root,root) /usr/share/man/man[58]/*
|
||||
|
||||
%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
|
||||
|
|
|
|||
4
ppp.c
4
ppp.c
|
|
@ -1,6 +1,6 @@
|
|||
// 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 <string.h>
|
||||
|
|
@ -21,7 +21,7 @@ extern int tunfd;
|
|||
extern char hostname[];
|
||||
extern u32 eth_tx;
|
||||
extern time_t time_now;
|
||||
extern struct configt *config;
|
||||
extern configt *config;
|
||||
|
||||
static void initccp(tunnelidt t, sessionidt s);
|
||||
|
||||
|
|
|
|||
4
radius.c
4
radius.c
|
|
@ -1,6 +1,6 @@
|
|||
// 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 <stdio.h>
|
||||
|
|
@ -22,7 +22,7 @@ extern radiust *radius;
|
|||
extern sessiont *session;
|
||||
extern tunnelt *tunnel;
|
||||
extern u32 sessionid;
|
||||
extern struct configt *config;
|
||||
extern configt *config;
|
||||
extern int *radfds;
|
||||
|
||||
static const char *radius_state(int state)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue