- Replace flags used for LCP/IPCP with state machine.

- Use openssl MD5, fix DAE vector (Alex Kiernan).
This commit is contained in:
bodea 2005-07-31 10:04:09 +00:00
parent 17b2ce31a6
commit afc8f4c6c0
27 changed files with 1399 additions and 1120 deletions

View file

@ -1,10 +1,10 @@
* Wed Jun 29 2005 Brendan O'Dea <bod@c47.org> 2.1.2 * Sun Jul 31 2005 Brendan O'Dea <bod@> 2.1.2
- Don't resend IPCP while still in progress.
- Ignore duplicate ACKs for IPCP.
- Clear RADIUSIPCP for walled garden sessions on ACK.
- Clear cluster_master on election so that slaves will accept a new master. - Clear cluster_master on election so that slaves will accept a new master.
- Provide more comments/defaults in etc/startup-config.default. - Provide more comments/defaults in etc/startup-config.default.
- Add DAE support (PoD/CoA) from Vladislav Bjelic. - Add DAE support (PoD/CoA) from Vladislav Bjelic.
- Clean up new warnings from gcc 4.0.
- Replace flags used for LCP/IPCP with state machine.
- Use openssl MD5, fix DAE vector (Alex Kiernan).
* Tue Jun 14 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.1 * Tue Jun 14 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.1
- Add missing newline to backtrace macro. - Add missing newline to backtrace macro.

View file

@ -185,6 +185,13 @@ the same as the LAC, or authentication will fail. Only actually be
used if the LAC requests authentication. used if the LAC requests authentication.
</LI> </LI>
<LI><B>ppp_restart_time</B> (int)<BR>
<B>ppp_max_configure</B> (int)<BR>
<B>ppp_max_failure</B> (int)<BR>
PPP counters and timers values, as described in &sect;4.1 of
<a href="ftp://ftp.rfc-editor.org/in-notes/rfc1661.txt">RFC1661</a>.
</LI>
<LI><B>primary_dns</B> (ip address) <LI><B>primary_dns</B> (ip address)
<LI><B>secondary_dns</B> (ip address)<BR> <LI><B>secondary_dns</B> (ip address)<BR>
Whenever a PPP connection is established, DNS servers will be sent to the Whenever a PPP connection is established, DNS servers will be sent to the

View file

@ -2,7 +2,7 @@
.de Id .de Id
.ds Dt \\$4 \\$5 .ds Dt \\$4 \\$5
.. ..
.Id $Id: startup-config.5,v 1.11 2005/06/28 14:48:31 bodea Exp $ .Id $Id: startup-config.5,v 1.12 2005/07/31 10:04:14 bodea Exp $
.TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions" .TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions"
.SH NAME .SH NAME
startup\-config \- configuration file for l2tpns startup\-config \- configuration file for l2tpns
@ -63,6 +63,16 @@ for authenticating tunnel request. Must be the same as the LAC, or
authentication will fail. Only actually be used if the LAC requests authentication will fail. Only actually be used if the LAC requests
authentication. authentication.
.TP .TP
.B ppp_restart_time
Restart timer for PPP protocol negotiation in seconds (default: 3).
.TP
.B ppp_max_configure
Number of configure requests to send before giving up (default: 10).
.TP
.B ppp_max_failure
Number of Configure-Nak requests to send before sending a
Configure-Reject (default: 5).
.TP
.BR primary_dns , " secondary_dns" .BR primary_dns , " secondary_dns"
Whenever a PPP connection is established, DNS servers will be sent to the Whenever a PPP connection is established, DNS servers will be sent to the
user, both a primary and a secondary. If either is set to 0.0.0.0, then that user, both a primary and a secondary. If either is set to 0.0.0.0, then that

View file

@ -23,10 +23,10 @@ LDFLAGS =
LDLIBS = LDLIBS =
INSTALL = install -c -D -o root -g root INSTALL = install -c -D -o root -g root
l2tpns.LIBS = -lm -lcli -ldl l2tpns.LIBS = -lcrypto -lm -lcli -ldl
OBJS = arp.o cli.o cluster.o constants.o control.o icmp.o l2tpns.o \ OBJS = arp.o cli.o cluster.o constants.o control.o icmp.o l2tpns.o \
ll.o md5.o ppp.o radius.o tbf.o util.o ll.o ppp.o radius.o tbf.o util.o
PROGRAMS = l2tpns nsctl PROGRAMS = l2tpns nsctl
PLUGINS = autosnoop.so autothrottle.so garden.so sessionctl.so \ PLUGINS = autosnoop.so autothrottle.so garden.so sessionctl.so \
@ -109,20 +109,19 @@ install: all
## Dependencies: (autogenerated) ## ## Dependencies: (autogenerated) ##
arp.o: arp.c l2tpns.h arp.o: arp.c l2tpns.h
cli.o: cli.c l2tpns.h util.h cluster.h tbf.h ll.h bgp.h cli.o: cli.c l2tpns.h constants.h util.h cluster.h tbf.h ll.h bgp.h
cluster.o: cluster.c l2tpns.h cluster.h util.h tbf.h bgp.h cluster.o: cluster.c l2tpns.h cluster.h util.h tbf.h bgp.h
constants.o: constants.c constants.h constants.o: constants.c constants.h
control.o: control.c l2tpns.h control.h control.o: control.c l2tpns.h control.h
icmp.o: icmp.c l2tpns.h icmp.o: icmp.c l2tpns.h
l2tpns.o: l2tpns.c md5.h l2tpns.h cluster.h plugin.h ll.h constants.h \ l2tpns.o: l2tpns.c l2tpns.h cluster.h plugin.h ll.h constants.h control.h \
control.h util.h tbf.h bgp.h util.h tbf.h bgp.h fake_epoll.h
ll.o: ll.c ll.h ll.o: ll.c ll.h
md5.o: md5.c md5.h
ppp.o: ppp.c l2tpns.h constants.h plugin.h util.h tbf.h cluster.h ppp.o: ppp.c l2tpns.h constants.h plugin.h util.h tbf.h cluster.h
radius.o: radius.c md5.h constants.h l2tpns.h plugin.h util.h radius.o: radius.c constants.h l2tpns.h plugin.h util.h cluster.h
tbf.o: tbf.c l2tpns.h util.h tbf.h tbf.o: tbf.c l2tpns.h util.h tbf.h
util.o: util.c l2tpns.h bgp.h util.o: util.c l2tpns.h bgp.h
bgp.o: bgp.c l2tpns.h bgp.h util.h bgp.o: bgp.c l2tpns.h bgp.h util.h fake_epoll.h
autosnoop.so: autosnoop.c l2tpns.h plugin.h autosnoop.so: autosnoop.c l2tpns.h plugin.h
autothrottle.so: autothrottle.c l2tpns.h plugin.h autothrottle.so: autothrottle.c l2tpns.h plugin.h
garden.so: garden.c l2tpns.h plugin.h control.h garden.so: garden.c l2tpns.h plugin.h control.h

1
THANKS
View file

@ -16,3 +16,4 @@ Bj
Roberto Chostakovis <rchostakovis@users.sourceforge.net> Roberto Chostakovis <rchostakovis@users.sourceforge.net>
Jordan Hrycaj <jordan@mjh.teddy-net.com> Jordan Hrycaj <jordan@mjh.teddy-net.com>
Vladislav Bjelic <vladislav@gmail.com> Vladislav Bjelic <vladislav@gmail.com>
Alex Kiernan <alex.kiernan@gmail.com>

4
arp.c
View file

@ -1,6 +1,6 @@
// L2TPNS: arp // L2TPNS: arp
char const *cvs_id_arp = "$Id: arp.c,v 1.6 2005/01/07 07:14:14 bodea Exp $"; char const *cvs_id_arp = "$Id: arp.c,v 1.7 2005/07/31 10:04:09 bodea Exp $";
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -55,7 +55,7 @@ void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip)
memset(&sll, 0, sizeof(sll)); memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET; sll.sll_family = AF_PACKET;
strncpy(sll.sll_addr, mac, sizeof(sll.sll_addr) - 1); memcpy(sll.sll_addr, mac, sizeof(sll.sll_addr) - 1);
sll.sll_halen = ETH_ALEN; sll.sll_halen = ETH_ALEN;
sll.sll_ifindex = ifr_idx; sll.sll_ifindex = ifr_idx;

4
bgp.c
View file

@ -10,7 +10,7 @@
* nor RFC2385 (which requires a kernel patch on 2.4 kernels). * nor RFC2385 (which requires a kernel patch on 2.4 kernels).
*/ */
char const *cvs_id_bgp = "$Id: bgp.c,v 1.10 2005/06/04 15:42:35 bodea Exp $"; char const *cvs_id_bgp = "$Id: bgp.c,v 1.11 2005/07/31 10:04:09 bodea Exp $";
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -767,7 +767,7 @@ static int bgp_connect(struct bgp_peer *peer)
static int bgp_handle_connect(struct bgp_peer *peer) static int bgp_handle_connect(struct bgp_peer *peer)
{ {
int err = 0; int err = 0;
int len = sizeof(int); socklen_t len = sizeof(int);
getsockopt(peer->sock, SOL_SOCKET, SO_ERROR, &err, &len); getsockopt(peer->sock, SOL_SOCKET, SO_ERROR, &err, &len);
if (err) if (err)
{ {

23
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.63 2005/06/28 14:48:17 bodea Exp $"; char const *cvs_id_cli = "$Id: cli.c,v 1.64 2005/07/31 10:04:09 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
@ -25,6 +25,7 @@ char const *cvs_id_cli = "$Id: cli.c,v 1.63 2005/06/28 14:48:17 bodea Exp $";
#include <libcli.h> #include <libcli.h>
#include "l2tpns.h" #include "l2tpns.h"
#include "constants.h"
#include "util.h" #include "util.h"
#include "cluster.h" #include "cluster.h"
#include "tbf.h" #include "tbf.h"
@ -289,10 +290,10 @@ void cli_do(int sockfd)
{ {
int require_auth = 1; int require_auth = 1;
struct sockaddr_in addr; struct sockaddr_in addr;
int l = sizeof(addr); socklen_t l = sizeof(addr);
if (fork_and_close()) return; if (fork_and_close()) return;
if (getpeername(sockfd, (struct sockaddr *)&addr, &l) == 0) if (getpeername(sockfd, (struct sockaddr *) &addr, &l) == 0)
{ {
require_auth = addr.sin_addr.s_addr != inet_addr("127.0.0.1"); require_auth = addr.sin_addr.s_addr != inet_addr("127.0.0.1");
LOG(require_auth ? 3 : 4, 0, 0, "Accepted connection to CLI from %s\n", LOG(require_auth ? 3 : 4, 0, 0, "Accepted connection to CLI from %s\n",
@ -407,6 +408,19 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
cli_print(cli, "\tCalling Num:\t%s", session[s].calling); cli_print(cli, "\tCalling Num:\t%s", session[s].calling);
cli_print(cli, "\tCalled Num:\t%s", session[s].called); cli_print(cli, "\tCalled Num:\t%s", session[s].called);
cli_print(cli, "\tTunnel ID:\t%d", session[s].tunnel); cli_print(cli, "\tTunnel ID:\t%d", session[s].tunnel);
cli_print(cli, "\tPPP Phase:\t%s", ppp_phase(session[s].ppp.phase));
switch (session[s].ppp.phase)
{
case Establish:
cli_print(cli, "\tLCP state:\t%s", ppp_state(session[s].ppp.lcp));
break;
case Authenticate:
case Network:
cli_print(cli, "\t IPCP state:\t%s", ppp_state(session[s].ppp.ipcp));
cli_print(cli, "\t IPV6CP state:\t%s", ppp_state(session[s].ppp.ipv6cp));
cli_print(cli, "\t CCP state:\t%s", ppp_state(session[s].ppp.ccp));
}
cli_print(cli, "\tIP address:\t%s", fmtaddr(htonl(session[s].ip), 0)); cli_print(cli, "\tIP address:\t%s", fmtaddr(htonl(session[s].ip), 0));
cli_print(cli, "\tUnique SID:\t%u", session[s].unique_id); cli_print(cli, "\tUnique SID:\t%u", session[s].unique_id);
cli_print(cli, "\tOpened:\t\t%u seconds", session[s].opened ? abs(time_now - session[s].opened) : 0); cli_print(cli, "\tOpened:\t\t%u seconds", session[s].opened ? abs(time_now - session[s].opened) : 0);
@ -507,7 +521,7 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
(session[i].snoop_ip && session[i].snoop_port) ? "Y" : "N", (session[i].snoop_ip && session[i].snoop_port) ? "Y" : "N",
(session[i].throttle_in || session[i].throttle_out) ? "Y" : "N", (session[i].throttle_in || session[i].throttle_out) ? "Y" : "N",
(session[i].walled_garden) ? "Y" : "N", (session[i].walled_garden) ? "Y" : "N",
(session[i].flags & SF_IPV6CP_ACKED) ? "Y" : "N", (session[i].ppp.ipv6cp == Opened) ? "Y" : "N",
abs(time_now - (unsigned long)session[i].opened), abs(time_now - (unsigned long)session[i].opened),
(unsigned long)session[i].cout, (unsigned long)session[i].cout,
(unsigned long)session[i].cin, (unsigned long)session[i].cin,
@ -816,7 +830,6 @@ static int cmd_show_version(struct cli_def *cli, char *command, char **argv, int
cli_print(cli, " %s", cvs_id_icmp); cli_print(cli, " %s", cvs_id_icmp);
cli_print(cli, " %s", cvs_id_l2tpns); cli_print(cli, " %s", cvs_id_l2tpns);
cli_print(cli, " %s", cvs_id_ll); cli_print(cli, " %s", cvs_id_ll);
cli_print(cli, " %s", cvs_id_md5);
cli_print(cli, " %s", cvs_id_ppp); cli_print(cli, " %s", cvs_id_ppp);
cli_print(cli, " %s", cvs_id_radius); cli_print(cli, " %s", cvs_id_radius);
cli_print(cli, " %s", cvs_id_tbf); cli_print(cli, " %s", cvs_id_tbf);

View file

@ -1,6 +1,6 @@
// L2TPNS Clustering Stuff // L2TPNS Clustering Stuff
char const *cvs_id_cluster = "$Id: cluster.c,v 1.44 2005/06/28 14:48:19 bodea Exp $"; char const *cvs_id_cluster = "$Id: cluster.c,v 1.45 2005/07/31 10:04:09 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -56,7 +56,7 @@ static struct {
static struct { static struct {
int seq; int seq;
int size; int size;
char data[MAX_HEART_SIZE]; uint8_t data[MAX_HEART_SIZE];
} past_hearts[HB_HISTORY_SIZE]; // Ring buffer of heartbeats that we've recently sent out. Needed so } past_hearts[HB_HISTORY_SIZE]; // Ring buffer of heartbeats that we've recently sent out. Needed so
// we can re-transmit if needed. // we can re-transmit if needed.
@ -178,7 +178,7 @@ static int cluster_send_data(void *data, int datalen)
// Maintains the format. Assumes that the caller // Maintains the format. Assumes that the caller
// has passed in a big enough buffer! // has passed in a big enough buffer!
// //
static void add_type(char **p, int type, int more, char *data, int size) static void add_type(uint8_t **p, int type, int more, uint8_t *data, int size)
{ {
*((uint32_t *) (*p)) = type; *((uint32_t *) (*p)) = type;
*p += sizeof(uint32_t); *p += sizeof(uint32_t);
@ -231,7 +231,7 @@ static void cluster_uptodate(void)
// Send a unicast UDP packet to a peer with 'data' as the // Send a unicast UDP packet to a peer with 'data' as the
// contents. // contents.
// //
static int peer_send_data(in_addr_t peer, char *data, int size) static int peer_send_data(in_addr_t peer, uint8_t *data, int size)
{ {
struct sockaddr_in addr = {0}; struct sockaddr_in addr = {0};
@ -259,10 +259,10 @@ static int peer_send_data(in_addr_t peer, char *data, int size)
// //
// Send a structured message to a peer with a single element of type 'type'. // Send a structured message to a peer with a single element of type 'type'.
// //
static int peer_send_message(in_addr_t peer, int type, int more, char *data, int size) static int peer_send_message(in_addr_t peer, int type, int more, uint8_t *data, int size)
{ {
char buf[65536]; // Vast overkill. uint8_t buf[65536]; // Vast overkill.
char *p = buf; uint8_t *p = buf;
LOG(4, 0, 0, "Sending message to peer (type %d, more %d, size %d)\n", type, more, size); LOG(4, 0, 0, "Sending message to peer (type %d, more %d, size %d)\n", type, more, size);
add_type(&p, type, more, data, size); add_type(&p, type, more, data, size);
@ -271,10 +271,10 @@ static int peer_send_message(in_addr_t peer, int type, int more, char *data, int
} }
// send a packet to the master // send a packet to the master
static int _forward_packet(char *data, int size, in_addr_t addr, int port, int type) static int _forward_packet(uint8_t *data, int size, in_addr_t addr, int port, int type)
{ {
char buf[65536]; // Vast overkill. uint8_t buf[65536]; // Vast overkill.
char *p = buf; uint8_t *p = buf;
if (!config->cluster_master_address) // No election has been held yet. Just skip it. if (!config->cluster_master_address) // No election has been held yet. Just skip it.
return -1; return -1;
@ -282,7 +282,7 @@ static int _forward_packet(char *data, int size, in_addr_t addr, int port, int t
LOG(4, 0, 0, "Forwarding packet from %s to master (size %d)\n", fmtaddr(addr, 0), size); LOG(4, 0, 0, "Forwarding packet from %s to master (size %d)\n", fmtaddr(addr, 0), size);
STAT(c_forwarded); STAT(c_forwarded);
add_type(&p, type, addr, (char *) &port, sizeof(port)); // ick. should be uint16_t add_type(&p, type, addr, (uint8_t *) &port, sizeof(port)); // ick. should be uint16_t
memcpy(p, data, size); memcpy(p, data, size);
p += size; p += size;
@ -295,13 +295,13 @@ static int _forward_packet(char *data, int size, in_addr_t addr, int port, int t
// The master just processes the payload as if it had // The master just processes the payload as if it had
// received it off the tun device. // received it off the tun device.
// //
int master_forward_packet(char *data, int size, in_addr_t addr, int port) int master_forward_packet(uint8_t *data, int size, in_addr_t addr, int port)
{ {
return _forward_packet(data, size, addr, port, C_FORWARD); return _forward_packet(data, size, addr, port, C_FORWARD);
} }
// Forward a DAE RADIUS packet to the master. // Forward a DAE RADIUS packet to the master.
int master_forward_dae_packet(char *data, int size, in_addr_t addr, int port) int master_forward_dae_packet(uint8_t *data, int size, in_addr_t addr, int port)
{ {
return _forward_packet(data, size, addr, port, C_FORWARD_DAE); return _forward_packet(data, size, addr, port, C_FORWARD_DAE);
} }
@ -313,10 +313,10 @@ int master_forward_dae_packet(char *data, int size, in_addr_t addr, int port)
// token bucket queue, and lets normal processing take care // token bucket queue, and lets normal processing take care
// of it. // of it.
// //
int master_throttle_packet(int tbfid, char *data, int size) int master_throttle_packet(int tbfid, uint8_t *data, int size)
{ {
char buf[65536]; // Vast overkill. uint8_t buf[65536]; // Vast overkill.
char *p = buf; uint8_t *p = buf;
if (!config->cluster_master_address) // No election has been held yet. Just skip it. if (!config->cluster_master_address) // No election has been held yet. Just skip it.
return -1; return -1;
@ -338,10 +338,10 @@ int master_throttle_packet(int tbfid, char *data, int size)
// //
// (Note that this must be called with the tun header // (Note that this must be called with the tun header
// as the start of the data). // as the start of the data).
int master_garden_packet(sessionidt s, char *data, int size) int master_garden_packet(sessionidt s, uint8_t *data, int size)
{ {
char buf[65536]; // Vast overkill. uint8_t buf[65536]; // Vast overkill.
char *p = buf; uint8_t *p = buf;
if (!config->cluster_master_address) // No election has been held yet. Just skip it. if (!config->cluster_master_address) // No election has been held yet. Just skip it.
return -1; return -1;
@ -358,7 +358,7 @@ int master_garden_packet(sessionidt s, char *data, int size)
// Send a chunk of data as a heartbeat.. // Send a chunk of data as a heartbeat..
// We save it in the history buffer as we do so. // We save it in the history buffer as we do so.
// //
static void send_heartbeat(int seq, char *data, int size) static void send_heartbeat(int seq, uint8_t *data, int size)
{ {
int i; int i;
@ -380,8 +380,8 @@ static void send_heartbeat(int seq, char *data, int size)
// //
void cluster_send_ping(time_t basetime) void cluster_send_ping(time_t basetime)
{ {
char buff[100 + sizeof(pingt)]; uint8_t buff[100 + sizeof(pingt)];
char *p = buff; uint8_t *p = buff;
pingt x; pingt x;
if (config->cluster_iam_master && basetime) // We're heartbeating so no need to ping. if (config->cluster_iam_master && basetime) // We're heartbeating so no need to ping.
@ -394,7 +394,7 @@ void cluster_send_ping(time_t basetime)
x.undef = config->cluster_undefined_sessions + config->cluster_undefined_tunnels; x.undef = config->cluster_undefined_sessions + config->cluster_undefined_tunnels;
x.basetime = basetime; x.basetime = basetime;
add_type(&p, C_PING, basetime, (char *) &x, sizeof(x)); add_type(&p, C_PING, basetime, (uint8_t *) &x, sizeof(x));
cluster_send_data(buff, (p-buff) ); cluster_send_data(buff, (p-buff) );
} }
@ -456,7 +456,7 @@ void master_update_counts(void)
// Forward the data to the master. // Forward the data to the master.
LOG(4, 0, 0, "Sending byte counters to master (%d elements)\n", c); LOG(4, 0, 0, "Sending byte counters to master (%d elements)\n", c);
peer_send_message(config->cluster_master_address, C_BYTES, c, (char *) &b, sizeof(b[0]) * c); peer_send_message(config->cluster_master_address, C_BYTES, c, (uint8_t *) &b, sizeof(b[0]) * c);
return; return;
} }
@ -738,7 +738,7 @@ static void cluster_check_sessions(int highsession, int freesession_ptr, int hig
cluster_uptodate(); cluster_uptodate();
} }
static int hb_add_type(char **p, int type, int id) static int hb_add_type(uint8_t **p, int type, int id)
{ {
switch (type) { switch (type) {
case C_CSESSION: { // Compressed C_SESSION. case C_CSESSION: { // Compressed C_SESSION.
@ -752,13 +752,13 @@ static int hb_add_type(char **p, int type, int id)
// Did we compress the full structure, and is the size actually // Did we compress the full structure, and is the size actually
// reduced?? // reduced??
if ( (d - orig) == sizeof(sessiont) && size < sizeof(sessiont) ) { if ( (d - orig) == sizeof(sessiont) && size < sizeof(sessiont) ) {
add_type(p, C_CSESSION, id, (char *) c, size); add_type(p, C_CSESSION, id, c, size);
break; break;
} }
// Failed to compress : Fall through. // Failed to compress : Fall through.
} }
case C_SESSION: add_type(p, C_SESSION, id, case C_SESSION:
(char *) &session[id], sizeof(sessiont)); add_type(p, C_SESSION, id, (uint8_t *) &session[id], sizeof(sessiont));
break; break;
case C_CTUNNEL: { // Compressed C_TUNNEL case C_CTUNNEL: { // Compressed C_TUNNEL
@ -777,8 +777,8 @@ static int hb_add_type(char **p, int type, int id)
} }
// Failed to compress : Fall through. // Failed to compress : Fall through.
} }
case C_TUNNEL: add_type(p, C_TUNNEL, id, case C_TUNNEL:
(char *) &tunnel[id], sizeof(tunnelt)); add_type(p, C_TUNNEL, id, (uint8_t *) &tunnel[id], sizeof(tunnelt));
break; break;
default: default:
LOG(0, 0, 0, "Found an invalid type in heart queue! (%d)\n", type); LOG(0, 0, 0, "Found an invalid type in heart queue! (%d)\n", type);
@ -794,9 +794,9 @@ static int hb_add_type(char **p, int type, int id)
void cluster_heartbeat() void cluster_heartbeat()
{ {
int i, count = 0, tcount = 0; int i, count = 0, tcount = 0;
char buff[MAX_HEART_SIZE + sizeof(heartt) + sizeof(int) ]; uint8_t buff[MAX_HEART_SIZE + sizeof(heartt) + sizeof(int) ];
heartt h; heartt h;
char *p = buff; uint8_t *p = buff;
if (!config->cluster_iam_master) // Only the master does this. if (!config->cluster_iam_master) // Only the master does this.
return; return;
@ -820,7 +820,7 @@ void cluster_heartbeat()
h.timeout = config->cluster_hb_timeout; h.timeout = config->cluster_hb_timeout;
h.table_version = config->cluster_table_version; h.table_version = config->cluster_table_version;
add_type(&p, C_HEARTBEAT, HB_VERSION, (char *) &h, sizeof(h)); add_type(&p, C_HEARTBEAT, HB_VERSION, (uint8_t *) &h, sizeof(h));
for (i = 0; i < config->cluster_num_changes; ++i) { for (i = 0; i < config->cluster_num_changes; ++i) {
hb_add_type(&p, cluster_changes[i].type, cluster_changes[i].id); hb_add_type(&p, cluster_changes[i].type, cluster_changes[i].id);
@ -1099,7 +1099,7 @@ static int cluster_set_master(in_addr_t peer, in_addr_t master)
// Note that we don't mark the session as dirty; We rely on // Note that we don't mark the session as dirty; We rely on
// the slow table walk to propogate this back out to the slaves. // the slow table walk to propogate this back out to the slaves.
// //
static int cluster_handle_bytes(char *data, int size) static int cluster_handle_bytes(uint8_t *data, int size)
{ {
bytest *b; bytest *b;
@ -1238,6 +1238,9 @@ struct oldsession {
uint32_t tx_connect_speed; uint32_t tx_connect_speed;
uint32_t rx_connect_speed; uint32_t rx_connect_speed;
uint32_t flags; uint32_t flags;
#define SF_IPCP_ACKED 1 // Has this session seen an IPCP Ack?
#define SF_LCP_ACKED 2 // LCP negotiated
#define SF_CCP_ACKED 4 // CCP negotiated
in_addr_t snoop_ip; in_addr_t snoop_ip;
uint16_t snoop_port; uint16_t snoop_port;
uint16_t sid; uint16_t sid;
@ -1257,7 +1260,6 @@ static uint8_t *convert_session(struct oldsession *old)
new.far = old->far; new.far = old->far;
new.tunnel = old->tunnel; new.tunnel = old->tunnel;
new.l2tp_flags = old->l2tp_flags; new.l2tp_flags = old->l2tp_flags;
new.flags = old->flags;
new.ip = old->ip; new.ip = old->ip;
new.ip_pool_index = old->ip_pool_index; new.ip_pool_index = old->ip_pool_index;
new.unique_id = old->unique_id; new.unique_id = old->unique_id;
@ -1297,6 +1299,21 @@ static uint8_t *convert_session(struct oldsession *old)
for (i = 0; i < MAXROUTE; i++) for (i = 0; i < MAXROUTE; i++)
memcpy(&new.route[i], &old->route[i], sizeof(new.route[i])); memcpy(&new.route[i], &old->route[i], sizeof(new.route[i]));
if (new.opened)
{
new.ppp.phase = Establish;
if (old->flags & (SF_IPCP_ACKED|SF_LCP_ACKED))
{
new.ppp.phase = Network;
new.ppp.lcp = Opened;
new.ppp.ipcp = (old->flags & SF_IPCP_ACKED) ? Opened : Starting;
new.ppp.ccp = (old->flags & SF_CCP_ACKED) ? Opened : Stopped;
}
// no PPPv6 in old session
new.ppp.ipv6cp = Stopped;
}
return (uint8_t *) &new; return (uint8_t *) &new;
} }
@ -1572,10 +1589,10 @@ shortpacket:
// We got a packet on the cluster port! // We got a packet on the cluster port!
// Handle pings, lastseens, and heartbeats! // Handle pings, lastseens, and heartbeats!
// //
int processcluster(char *data, int size, in_addr_t addr) int processcluster(uint8_t *data, int size, in_addr_t addr)
{ {
int type, more; int type, more;
char *p = data; uint8_t *p = data;
int s = size; int s = size;
if (addr == my_address) if (addr == my_address)
@ -1814,7 +1831,7 @@ static int rle_decompress(uint8_t **src_p, int ssize, uint8_t *dst, int dsize)
{ {
int count; int count;
int orig_dsize = dsize; int orig_dsize = dsize;
char *src = *src_p; uint8_t *src = *src_p;
while (ssize >0 && dsize > 0) { // While there's more to decompress, and there's room in the decompress buffer... while (ssize >0 && dsize > 0) { // While there's more to decompress, and there's room in the decompress buffer...
count = *src++; --ssize; // get the count byte from the source. count = *src++; --ssize; // get the count byte from the source.

View file

@ -1,5 +1,5 @@
// L2TPNS Clustering Stuff // L2TPNS Clustering Stuff
// $Id: cluster.h,v 1.13 2005/06/28 14:48:19 bodea Exp $ // $Id: cluster.h,v 1.14 2005/07/31 10:04:10 bodea Exp $
#ifndef __CLUSTER_H__ #ifndef __CLUSTER_H__
#define __CLUSTER_H__ #define __CLUSTER_H__
@ -72,13 +72,13 @@ typedef struct {
} pingt; } pingt;
int cluster_init(void); int cluster_init(void);
int processcluster(char *buf, int size, in_addr_t addr); int processcluster(uint8_t *buf, int size, in_addr_t addr);
int cluster_send_session(int sid); int cluster_send_session(int sid);
int cluster_send_tunnel(int tid); int cluster_send_tunnel(int tid);
int master_forward_packet(char *data, int size, in_addr_t addr, int port); int master_forward_packet(uint8_t *data, int size, in_addr_t addr, int port);
int master_forward_dae_packet(char *data, int size, in_addr_t addr, int port); int master_forward_dae_packet(uint8_t *data, int size, in_addr_t addr, int port);
int master_throttle_packet(int tid, char *data, int size); int master_throttle_packet(int tid, uint8_t *data, int size);
int master_garden_packet(sessionidt s, char *data, int size); int master_garden_packet(sessionidt s, uint8_t *data, int size);
void master_update_counts(void); void master_update_counts(void);
void cluster_send_ping(time_t basetime); void cluster_send_ping(time_t basetime);
void cluster_heartbeat(void); void cluster_heartbeat(void);

View file

@ -1,6 +1,6 @@
// L2TPNS: constants // L2TPNS: constants
char const *cvs_id_constants = "$Id: constants.c,v 1.6 2005/06/28 14:48:20 bodea Exp $"; char const *cvs_id_constants = "$Id: constants.c,v 1.7 2005/07/31 10:04:10 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include "constants.h" #include "constants.h"
@ -19,19 +19,27 @@ char const *cvs_id_constants = "$Id: constants.c,v 1.6 2005/06/28 14:48:20 bodea
return n; \ return n; \
} }
CONSTANT(lcp_type, CONSTANT(l2tp_code,
0, // 0 0, // 0
"Maximum-Receive-Unit", // 1 "SCCRQ", // 1
"Async-Control-Map", // 2 "SCCRP", // 2
"Authentication-Protocol", // 3 "SCCCN", // 3
"Quality-Protocol", // 4 "StopCCN", // 4
"Magic-Number", // 5 0, // 5
0, // 6 "HELLO", // 6
"Protocol-Field-Compression", // 7 "OCRQ", // 7
"Address-and-Control-Field-Compression" // 8 "OCRP", // 8
"OCCN", // 9
"ICRQ", // 10
"ICRP", // 11
"ICCN", // 12
0, // 13
"CDN", // 14
"WEN", // 15
"SLI" // 16
) )
CONSTANT(avp_name, CONSTANT(l2tp_avp_name,
"Message Type", // 0 "Message Type", // 0
"Result Code", // 1 "Result Code", // 1
"Protocol Version", // 2 "Protocol Version", // 2
@ -74,7 +82,7 @@ CONSTANT(avp_name,
"Sequencing Required" // 39 "Sequencing Required" // 39
) )
CONSTANT(stopccn_result_code, CONSTANT(l2tp_stopccn_result_code,
0, // 0 0, // 0
"General request to clear control connection", // 1 "General request to clear control connection", // 1
"General error--Error Code indicates the problem", // 2 "General error--Error Code indicates the problem", // 2
@ -87,7 +95,7 @@ CONSTANT(stopccn_result_code,
"Finite State Machine error" // 7 "Finite State Machine error" // 7
) )
CONSTANT(cdn_result_code, CONSTANT(l2tp_cdn_result_code,
0, // 0 0, // 0
"Call disconnected due to loss of carrier", // 1 "Call disconnected due to loss of carrier", // 1
"Call disconnected for the reason indicated in" "Call disconnected for the reason indicated in"
@ -107,7 +115,7 @@ CONSTANT(cdn_result_code,
" detected" // 11 " detected" // 11
) )
CONSTANT(error_code, CONSTANT(l2tp_error_code,
"No general error", // 0 "No general error", // 0
"No control connection exists yet for this LAC-LNS" "No control connection exists yet for this LAC-LNS"
" pair", // 1 " pair", // 1
@ -124,7 +132,28 @@ CONSTANT(error_code,
" an unknown AVP with the M-bit set" // 8 " an unknown AVP with the M-bit set" // 8
) )
CONSTANT(auth_type, CONSTANT(ppp_phase,
"Dead", // 0
"Establish", // 1
"Authenticate", // 2
"Network", // 3
"Terminate", // 4
)
CONSTANT(ppp_state,
"Initial", // 0
"Starting", // 1
"Closed", // 2
"Stopped", // 3
"Closing", // 4
"Stopping", // 5
"Request-Sent", // 6
"Ack-Received", // 7
"Ack-Sent", // 8
"Opened" // 9
)
CONSTANT(ppp_auth_type,
0, // 0 0, // 0
"Textual username/password exchange", // 1 "Textual username/password exchange", // 1
"PPP CHAP", // 2 "PPP CHAP", // 2
@ -133,7 +162,7 @@ CONSTANT(auth_type,
"Microsoft CHAP Version 1 (MSCHAPv1)" // 5 "Microsoft CHAP Version 1 (MSCHAPv1)" // 5
) )
CONSTANT(ppp_lcp_type, CONSTANT(ppp_code,
0, // 0 0, // 0
"ConfigReq", // 1 "ConfigReq", // 1
"ConfigAck", // 2 "ConfigAck", // 2
@ -149,15 +178,26 @@ CONSTANT(ppp_lcp_type,
"IdentRequest" // 12 "IdentRequest" // 12
) )
CONSTANT(ppp_lcp_option,
0, // 0
"Maximum-Receive-Unit", // 1
"Async-Control-Map", // 2
"Authentication-Protocol", // 3
"Quality-Protocol", // 4
"Magic-Number", // 5
0, // 6
"Protocol-Field-Compression", // 7
"Address-and-Control-Field-Compression" // 8
)
CONSTANT(radius_state, CONSTANT(radius_state,
"RADIUSNULL", // 0 "RADIUSNULL", // 0
"RADIUSCHAP", // 1 "RADIUSCHAP", // 1
"RADIUSAUTH", // 2 "RADIUSAUTH", // 2
"RADIUSIPCP", // 3 "RADIUSSTART", // 3
"RADIUSSTART", // 4 "RADIUSSTOP", // 4
"RADIUSSTOP", // 5 "RADIUSINTERIM", // 5
"RADIUSINTERIM", // 6 "RADIUSWAIT" // 6
"RADIUSWAIT" // 7
) )
CONSTANT(radius_code, CONSTANT(radius_code,
@ -185,23 +225,3 @@ CONSTANT(radius_code,
"CoA-ACK", // 44 "CoA-ACK", // 44
"CoA-NAK" // 45 "CoA-NAK" // 45
) )
CONSTANT(l2tp_message_type,
0, // 0
"SCCRQ", // 1
"SCCRP", // 2
"SCCCN", // 3
"StopCCN", // 4
0, // 5
"HELLO", // 6
"OCRQ", // 7
"OCRP", // 8
"OCCN", // 9
"ICRQ", // 10
"ICRP", // 11
"ICCN", // 12
0, // 13
"CDN", // 14
"WEN", // 15
"SLI" // 16
)

View file

@ -1,15 +1,17 @@
#ifndef __CONSTANTS_H__ #ifndef __CONSTANTS_H__
#define __CONSTANTS_H__ #define __CONSTANTS_H__
char const *lcp_type(int type); char const *l2tp_code(int type);
char const *avp_name(int avp); char const *l2tp_avp_name(int avp);
char const *stopccn_result_code(int code); char const *l2tp_stopccn_result_code(int code);
char const *cdn_result_code(int code); char const *l2tp_cdn_result_code(int code);
char const *error_code(int code); char const *l2tp_error_code(int code);
char const *auth_type(int type); char const *ppp_phase(int code);
char const *ppp_lcp_type(int type); char const *ppp_state(int code);
char const *ppp_auth_type(int type);
char const *ppp_code(int type);
char const *ppp_lcp_option(int type);
char const *radius_state(int state); char const *radius_state(int state);
char const *radius_code(int code); char const *radius_code(int code);
char const *l2tp_message_type(int type);
#endif /* __CONSTANTS_H__ */ #endif /* __CONSTANTS_H__ */

View file

@ -1,12 +1,12 @@
// L2TPNS: control // L2TPNS: control
char const *cvs_id_control = "$Id: control.c,v 1.4 2004/12/16 08:49:53 bodea Exp $"; char const *cvs_id_control = "$Id: control.c,v 1.5 2005/07/31 10:04:10 bodea Exp $";
#include <string.h> #include <string.h>
#include "l2tpns.h" #include "l2tpns.h"
#include "control.h" #include "control.h"
int pack_control(char *data, int len, uint8_t type, int argc, char *argv[]) int pack_control(uint8_t *data, int len, uint8_t type, int argc, char *argv[])
{ {
struct nsctl_packet pkt; struct nsctl_packet pkt;
struct nsctl_args arg; struct nsctl_args arg;
@ -62,7 +62,7 @@ int pack_control(char *data, int len, uint8_t type, int argc, char *argv[])
return sz; return sz;
} }
int unpack_control(struct nsctl *control, char *data, int len) int unpack_control(struct nsctl *control, uint8_t *data, int len)
{ {
struct nsctl_packet pkt; struct nsctl_packet pkt;
char *p = pkt.argv; char *p = pkt.argv;

View file

@ -47,8 +47,8 @@ struct nsctl {
char *argv[0xff]; char *argv[0xff];
}; };
int pack_control(char *data, int len, uint8_t type, int argc, char *argv[]); int pack_control(uint8_t *data, int len, uint8_t type, int argc, char *argv[]);
int unpack_control(struct nsctl *packet, char *data, int len); int unpack_control(struct nsctl *packet, uint8_t *data, int len);
void dump_control(struct nsctl *control, FILE *stream); void dump_control(struct nsctl *control, FILE *stream);
#endif /* __CONTROL_H__ */ #endif /* __CONTROL_H__ */

14
icmp.c
View file

@ -1,6 +1,6 @@
// L2TPNS: icmp // L2TPNS: icmp
char const *cvs_id_icmp = "$Id: icmp.c,v 1.8 2005/06/04 15:42:06 bodea Exp $"; char const *cvs_id_icmp = "$Id: icmp.c,v 1.9 2005/07/31 10:04:10 bodea Exp $";
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
@ -18,7 +18,7 @@ char const *cvs_id_icmp = "$Id: icmp.c,v 1.8 2005/06/04 15:42:06 bodea Exp $";
#include "l2tpns.h" #include "l2tpns.h"
static uint16_t _checksum(unsigned char *addr, int count); static uint16_t _checksum(uint8_t *addr, int count);
struct ipv6_pseudo_hdr { struct ipv6_pseudo_hdr {
struct in6_addr src; struct in6_addr src;
@ -28,7 +28,7 @@ struct ipv6_pseudo_hdr {
uint32_t nexthdr : 8; uint32_t nexthdr : 8;
}; };
void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, char *packet, int packet_len) void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, uint8_t *packet, int packet_len)
{ {
char buf[128] = {0}; char buf[128] = {0};
struct iphdr *iph; struct iphdr *iph;
@ -72,15 +72,15 @@ void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, char
icmp->type = ICMP_DEST_UNREACH; icmp->type = ICMP_DEST_UNREACH;
icmp->code = ICMP_HOST_UNREACH; icmp->code = ICMP_HOST_UNREACH;
icmp->checksum = _checksum((char *) icmp, sizeof(struct icmphdr) + packet_len); icmp->checksum = _checksum((uint8_t *) icmp, sizeof(struct icmphdr) + packet_len);
iph->check = _checksum((char *) iph, sizeof(struct iphdr)); iph->check = _checksum((uint8_t *) iph, sizeof(struct iphdr));
sendto(icmp_socket, (char *)buf, len, 0, (struct sockaddr *)&whereto, sizeof(struct sockaddr)); sendto(icmp_socket, buf, len, 0, (struct sockaddr *)&whereto, sizeof(struct sockaddr));
close(icmp_socket); close(icmp_socket);
} }
static uint16_t _checksum(unsigned char *addr, int count) static uint16_t _checksum(uint8_t *addr, int count)
{ {
register long sum = 0; register long sum = 0;

389
l2tpns.c
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.114 2005/07/04 05:49:46 bodea Exp $"; char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.115 2005/07/31 10:04:10 bodea Exp $";
#include <arpa/inet.h> #include <arpa/inet.h>
#include <assert.h> #include <assert.h>
@ -38,9 +38,9 @@ char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.114 2005/07/04 05:49:46 bodea Exp
#include <unistd.h> #include <unistd.h>
#include <sched.h> #include <sched.h>
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#include <openssl/md5.h>
#include <libcli.h> #include <libcli.h>
#include "md5.h"
#include "l2tpns.h" #include "l2tpns.h"
#include "cluster.h" #include "cluster.h"
#include "plugin.h" #include "plugin.h"
@ -105,6 +105,9 @@ config_descriptt config_values[] = {
CONFIG("pid_file", pid_file, STRING), CONFIG("pid_file", pid_file, STRING),
CONFIG("random_device", random_device, STRING), CONFIG("random_device", random_device, STRING),
CONFIG("l2tp_secret", l2tpsecret, STRING), CONFIG("l2tp_secret", l2tpsecret, STRING),
CONFIG("ppp_restart_time", ppp_restart_time, INT),
CONFIG("ppp_max_configure", ppp_max_configure, INT),
CONFIG("ppp_max_failure", ppp_max_failure, INT),
CONFIG("primary_dns", default_dns1, IPv4), CONFIG("primary_dns", default_dns1, IPv4),
CONFIG("secondary_dns", default_dns2, IPv4), CONFIG("secondary_dns", default_dns2, IPv4),
CONFIG("primary_radius", radiusserver[0], IPv4), CONFIG("primary_radius", radiusserver[0], IPv4),
@ -182,7 +185,7 @@ static void sighup_handler(int sig);
static void sigalrm_handler(int sig); static void sigalrm_handler(int sig);
static void shutdown_handler(int sig); static void shutdown_handler(int sig);
static void sigchild_handler(int sig); static void sigchild_handler(int sig);
static void build_chap_response(char *challenge, uint8_t id, uint16_t challenge_length, char **challenge_response); static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challenge_length, uint8_t **challenge_response);
static void update_config(void); static void update_config(void);
static void read_config_file(void); static void read_config_file(void);
static void initplugins(void); static void initplugins(void);
@ -258,10 +261,10 @@ void _log(int level, sessionidt s, tunnelidt t, const char *format, ...)
va_end(ap); va_end(ap);
} }
void _log_hex(int level, const char *title, const char *data, int maxsize) void _log_hex(int level, const char *title, const uint8_t *data, int maxsize)
{ {
int i, j; int i, j;
const uint8_t *d = (const uint8_t *) data; const uint8_t *d = data;
if (config->debug < level) return; if (config->debug < level) return;
@ -551,7 +554,7 @@ static void inittun(void)
tunidx = ifr.ifr_ifindex; tunidx = ifr.ifr_ifindex;
// Only setup IPv6 on the tun device if we have a configured prefix // Only setup IPv6 on the tun device if we have a configured prefix
if (config->ipv6_prefix.s6_addr[0] > 0) { if (config->ipv6_prefix.s6_addr[0]) {
ifr6fd = socket(PF_INET6, SOCK_DGRAM, 0); ifr6fd = socket(PF_INET6, SOCK_DGRAM, 0);
// Link local address is FE80::1 // Link local address is FE80::1
@ -702,8 +705,11 @@ sessionidt sessionbyipv6(struct in6_addr ip)
CSTAT(sessionbyipv6); CSTAT(sessionbyipv6);
if (!memcmp(&config->ipv6_prefix, &ip, 8) || if (!memcmp(&config->ipv6_prefix, &ip, 8) ||
(ip.s6_addr[0] == 0xFE && ip.s6_addr[1] == 0x80 && (ip.s6_addr[0] == 0xFE &&
(ip.s6_addr16[1] == ip.s6_addr16[2] == ip.s6_addr16[3] == 0))) { ip.s6_addr[1] == 0x80 &&
ip.s6_addr16[1] == 0 &&
ip.s6_addr16[2] == 0 &&
ip.s6_addr16[3] == 0)) {
s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]); s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]);
} else { } else {
s = lookup_ipv6map(ip); s = lookup_ipv6map(ip);
@ -973,14 +979,14 @@ int tun_write(uint8_t * data, int size)
// process outgoing (to tunnel) IP // process outgoing (to tunnel) IP
// //
static void processipout(uint8_t * buf, int len) static void processipout(uint8_t *buf, int len)
{ {
sessionidt s; sessionidt s;
sessiont *sp; sessiont *sp;
tunnelidt t; tunnelidt t;
in_addr_t ip; in_addr_t ip;
char *data = buf; // Keep a copy of the originals. uint8_t *data = buf; // Keep a copy of the originals.
int size = len; int size = len;
uint8_t b[MAXETHER + 20]; uint8_t b[MAXETHER + 20];
@ -1126,7 +1132,7 @@ static void processipv6out(uint8_t * buf, int len)
in_addr_t ip; in_addr_t ip;
struct in6_addr ip6; struct in6_addr ip6;
char *data = buf; // Keep a copy of the originals. uint8_t *data = buf; // Keep a copy of the originals.
int size = len; int size = len;
uint8_t b[MAXETHER + 20]; uint8_t b[MAXETHER + 20];
@ -1313,7 +1319,7 @@ static void controls(controlt * c, uint16_t avp, char *val, uint8_t m)
} }
// add a binary AVP // add a binary AVP
static void controlb(controlt * c, uint16_t avp, char *val, unsigned int len, uint8_t m) static void controlb(controlt * c, uint16_t avp, uint8_t *val, unsigned int len, uint8_t m)
{ {
uint16_t l = ((m ? 0x8000 : 0) + len + 6); uint16_t l = ((m ? 0x8000 : 0) + len + 6);
*(uint16_t *) (c->buf + c->length + 0) = htons(l); *(uint16_t *) (c->buf + c->length + 0) = htons(l);
@ -1493,10 +1499,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
if (session[s].ip && !walled_garden && !session[s].die) if (session[s].ip && !walled_garden && !session[s].die)
{ {
// RADIUS Stop message // RADIUS Stop message
uint16_t r = sess_local[s].radius; uint16_t r = radiusnew(s);
if (!r)
r = radiusnew(s);
if (r) if (r)
{ {
// stop, if not already trying // stop, if not already trying
@ -1534,7 +1537,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
free_ip_address(s); free_ip_address(s);
// unroute IPv6, if setup // unroute IPv6, if setup
if (session[s].flags & SF_IPV6_ROUTED) if (session[s].ppp.ipv6cp == Opened && session[s].ipv6prefixlen)
route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0); route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0);
} }
@ -1546,7 +1549,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
controlt *c = controlnew(14); // sending CDN controlt *c = controlnew(14); // sending CDN
if (error) if (error)
{ {
char buf[4]; uint8_t buf[4];
*(uint16_t *) buf = htons(result); *(uint16_t *) buf = htons(result);
*(uint16_t *) (buf+2) = htons(error); *(uint16_t *) (buf+2) = htons(error);
controlb(c, 1, buf, 4, 1); controlb(c, 1, buf, 4, 1);
@ -1565,78 +1568,66 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
if (session[s].filter_in) ip_filters[session[s].filter_in - 1].used--; if (session[s].filter_in) ip_filters[session[s].filter_in - 1].used--;
if (session[s].filter_out) ip_filters[session[s].filter_out - 1].used--; if (session[s].filter_out) ip_filters[session[s].filter_out - 1].used--;
// clear PPP state
memset(&session[s].ppp, 0, sizeof(session[s].ppp));
sess_local[s].lcp.restart = 0;
sess_local[s].ipcp.restart = 0;
sess_local[s].ipv6cp.restart = 0;
sess_local[s].ccp.restart = 0;
cluster_send_session(s); cluster_send_session(s);
} }
void sendipcp(tunnelidt t, sessionidt s) void sendipcp(tunnelidt t, sessionidt s)
{ {
uint8_t buf[MAXCONTROL]; uint8_t buf[MAXCONTROL];
uint16_t r = sess_local[s].radius;
uint8_t *q; uint8_t *q;
CSTAT(sendipcp); CSTAT(sendipcp);
if (!r) if (!session[s].unique_id)
r = radiusnew(s);
if (!r)
{ {
sessionshutdown(s, "No free RADIUS sessions for IPCP", 3, 0); if (!++last_id) ++last_id; // skip zero
return; session[s].unique_id = last_id;
}
if (radius[r].state != RADIUSIPCP)
{
radius[r].state = RADIUSIPCP;
radius[r].try = 0;
}
radius[r].retry = backoff(radius[r].try++);
if (radius[r].try > 10)
{
radiusclear(r, s); // Clear radius session.
sessionshutdown(s, "No reply to IPCP.", 3, 0);
return;
} }
q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPCP); q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPCP);
if (!q) return; if (!q) return;
*q = ConfigReq; *q = ConfigReq;
q[1] = r >> RADIUS_SHIFT; // ID, dont care, we only send one type of request q[1] = session[s].unique_id & 0xf; // ID, dont care, we only send one type of request
*(uint16_t *) (q + 2) = htons(10); *(uint16_t *) (q + 2) = htons(10); // packet length
q[4] = 3; q[4] = 3; // ip address option
q[5] = 6; q[5] = 6; // option length
*(in_addr_t *) (q + 6) = config->peer_address ? config->peer_address : *(in_addr_t *) (q + 6) = config->peer_address ? config->peer_address :
config->bind_address ? config->bind_address : config->bind_address ? config->bind_address :
my_address; // send my IP my_address; // send my IP
tunnelsend(buf, 10 + (q - buf), t); // send it tunnelsend(buf, 10 + (q - buf), t); // send it
session[s].flags &= ~SF_IPCP_ACKED; // Clear flag. }
// If we have an IPv6 prefix length configured, assume we should void sendipv6cp(tunnelidt t, sessionidt s)
// try to negotiate an IPv6 session as well. Unless we've had a {
// (N)ACK for IPV6CP. uint8_t buf[MAXCONTROL];
if (config->ipv6_prefix.s6_addr[0] > 0 && uint8_t *q;
!(session[s].flags & SF_IPV6CP_ACKED) &&
!(session[s].flags & SF_IPV6_NACKED))
{
q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPV6CP);
if (!q) return;
*q = ConfigReq; CSTAT(sendipv6cp);
q[1] = r >> RADIUS_SHIFT; // ID, don't care, we
// only send one type
// of request
*(uint16_t *) (q + 2) = htons(14);
q[4] = 1;
q[5] = 10;
*(uint32_t *) (q + 6) = 0; // We'll be prefix::1
*(uint32_t *) (q + 10) = 0;
q[13] = 1;
tunnelsend(buf, 14 + (q - buf), t); // send it q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPV6CP);
} if (!q) return;
*q = ConfigReq;
q[1] = session[s].unique_id & 0xf; // ID, don't care, we
// only send one type
// of request
*(uint16_t *) (q + 2) = htons(14);
q[4] = 1; // interface identifier option
q[5] = 10; // option length
*(uint32_t *) (q + 6) = 0; // We'll be prefix::1
*(uint32_t *) (q + 10) = 0;
q[13] = 1;
tunnelsend(buf, 14 + (q - buf), t); // send it
} }
static void sessionclear(sessionidt s) static void sessionclear(sessionidt s)
@ -1742,7 +1733,7 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha
controlt *c = controlnew(4); // sending StopCCN controlt *c = controlnew(4); // sending StopCCN
if (error) if (error)
{ {
char buf[64]; uint8_t buf[64];
int l = 4; int l = 4;
*(uint16_t *) buf = htons(result); *(uint16_t *) buf = htons(result);
*(uint16_t *) (buf+2) = htons(error); *(uint16_t *) (buf+2) = htons(error);
@ -1767,9 +1758,9 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha
} }
// read and process packet on tunnel (UDP) // read and process packet on tunnel (UDP)
void processudp(uint8_t * buf, int len, struct sockaddr_in *addr) void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
{ {
char *chapresponse = NULL; uint8_t *chapresponse = NULL;
uint16_t l = len, t = 0, s = 0, ns = 0, nr = 0; uint16_t l = len, t = 0, s = 0, ns = 0, nr = 0;
uint8_t *p = buf + 2; uint8_t *p = buf + 2;
@ -2061,7 +2052,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
n = orig_len; n = orig_len;
} }
LOG(4, s, t, " AVP %d (%s) len %d%s%s\n", mtype, avp_name(mtype), n, LOG(4, s, t, " AVP %d (%s) len %d%s%s\n", mtype, l2tp_avp_name(mtype), n,
flags & 0x40 ? ", hidden" : "", flags & 0x80 ? ", mandatory" : ""); flags & 0x40 ? ", hidden" : "", flags & 0x80 ? ", mandatory" : "");
switch (mtype) switch (mtype)
@ -2069,7 +2060,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
case 0: // message type case 0: // message type
message = ntohs(*(uint16_t *) b); message = ntohs(*(uint16_t *) b);
mandatory = flags & 0x80; mandatory = flags & 0x80;
LOG(4, s, t, " Message type = %d (%s)\n", *b, l2tp_message_type(message)); LOG(4, s, t, " Message type = %d (%s)\n", *b, l2tp_code(message));
break; break;
case 1: // result code case 1: // result code
{ {
@ -2077,18 +2068,18 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
const char* resdesc = "(unknown)"; const char* resdesc = "(unknown)";
if (message == 4) if (message == 4)
{ /* StopCCN */ { /* StopCCN */
resdesc = stopccn_result_code(rescode); resdesc = l2tp_stopccn_result_code(rescode);
} }
else if (message == 14) else if (message == 14)
{ /* CDN */ { /* CDN */
resdesc = cdn_result_code(rescode); resdesc = l2tp_cdn_result_code(rescode);
} }
LOG(4, s, t, " Result Code %d: %s\n", rescode, resdesc); LOG(4, s, t, " Result Code %d: %s\n", rescode, resdesc);
if (n >= 4) if (n >= 4)
{ {
uint16_t errcode = ntohs(*(uint16_t *)(b + 2)); uint16_t errcode = ntohs(*(uint16_t *)(b + 2));
LOG(4, s, t, " Error Code %d: %s\n", errcode, error_code(errcode)); LOG(4, s, t, " Error Code %d: %s\n", errcode, l2tp_error_code(errcode));
} }
if (n > 4) if (n > 4)
LOG(4, s, t, " Error String: %.*s\n", n-4, b+4); LOG(4, s, t, " Error String: %.*s\n", n-4, b+4);
@ -2222,7 +2213,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
case 29: // Proxy Authentication Type case 29: // Proxy Authentication Type
{ {
uint16_t atype = ntohs(*(uint16_t *)b); uint16_t atype = ntohs(*(uint16_t *)b);
LOG(4, s, t, " Proxy Auth Type %d (%s)\n", atype, auth_type(atype)); LOG(4, s, t, " Proxy Auth Type %d (%s)\n", atype, ppp_auth_type(atype));
if (atype == 2) if (atype == 2)
authtype = AUTHCHAP; authtype = AUTHCHAP;
else if (atype == 3) else if (atype == 3)
@ -2351,7 +2342,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
case 10: // ICRQ case 10: // ICRQ
if (sessionfree && main_quit != QUIT_SHUTDOWN) if (sessionfree && main_quit != QUIT_SHUTDOWN)
{ {
uint16_t r; controlt *c = controlnew(11); // ICRP
s = sessionfree; s = sessionfree;
sessionfree = session[s].next; sessionfree = session[s].next;
@ -2360,41 +2351,34 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
if (s > config->cluster_highest_sessionid) if (s > config->cluster_highest_sessionid)
config->cluster_highest_sessionid = s; config->cluster_highest_sessionid = s;
// make a RADIUS session session[s].opened = time_now;
if ((r = radiusnew(s))) session[s].tunnel = t;
{ session[s].far = asession;
controlt *c = controlnew(11); // sending ICRP session[s].last_packet = time_now;
session[s].opened = time_now; LOG(3, s, t, "New session (%d/%d)\n", tunnel[t].far, session[s].far);
session[s].tunnel = t; control16(c, 14, s, 1); // assigned session
session[s].far = asession; controladd(c, t, asession); // send the reply
session[s].last_packet = time_now;
LOG(3, s, t, "New session (%d/%d)\n", tunnel[t].far, session[s].far);
control16(c, 14, s, 1); // assigned session
controladd(c, t, asession); // send the reply
strncpy(radius[r].calling, calling, sizeof(radius[r].calling) - 1); strncpy(session[s].called, called, sizeof(session[s].called) - 1);
strncpy(session[s].called, called, sizeof(session[s].called) - 1); strncpy(session[s].calling, calling, sizeof(session[s].calling) - 1);
strncpy(session[s].calling, calling, sizeof(session[s].calling) - 1);
STAT(session_created);
break;
}
session[s].ppp.phase = Establish;
session[s].ppp.lcp = Starting;
LOG(1, s, t, "No free RADIUS sessions for ICRQ\n"); STAT(session_created);
sessionclear(s); break;
}
else
{
STAT(session_overflow);
LOG(1, 0, t, "No free sessions\n");
} }
{ {
controlt *c = controlnew(14); // CDN controlt *c = controlnew(14); // CDN
if (main_quit == QUIT_SHUTDOWN) if (!sessionfree)
control16(c, 1, 2, 7); // try another {
else STAT(session_overflow);
LOG(1, 0, t, "No free sessions\n");
control16(c, 1, 4, 0); // temporary lack of resources control16(c, 1, 4, 0); // temporary lack of resources
}
else
control16(c, 1, 2, 7); // shutting down, try another
controladd(c, t, asession); // send the message controladd(c, t, asession); // send the message
} }
@ -2408,12 +2392,19 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
session[s].l2tp_flags = aflags; // set flags received session[s].l2tp_flags = aflags; // set flags received
LOG(3, s, t, "Magic %X Flags %X\n", amagic, aflags); LOG(3, s, t, "Magic %X Flags %X\n", amagic, aflags);
controlnull(t); // ack controlnull(t); // ack
// proxy authentication type is not supported // proxy authentication type is not supported
if (!(config->radius_authtypes & authtype)) if (!(config->radius_authtypes & authtype))
authtype = config->radius_authprefer; authtype = config->radius_authprefer;
// start LCP // start LCP
sendlcp(t, s, authtype); sendlcp(t, s, authtype);
sess_local[s].lcp.restart = time_now + config->ppp_restart_time;
sess_local[s].lcp.conf_sent = 1;
sess_local[s].lcp.nak_sent = 0;
sess_local[s].lcp_authtype = authtype;
session[s].ppp.lcp = RequestSent;
break; break;
case 14: // CDN case 14: // CDN
controlnull(t); // ack controlnull(t); // ack
@ -2507,16 +2498,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
} }
else if (prot == PPPIPV6CP) else if (prot == PPPIPV6CP)
{ {
if (config->ipv6_prefix.s6_addr[0] > 0) session[s].last_packet = time_now;
{ if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; }
session[s].last_packet = time_now; processipv6cp(t, s, p, l);
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port); return; }
processipv6cp(t, s, p, l);
}
else
{
LOG(1, s, t, "IPv6 not configured; ignoring IPv6CP\n");
}
} }
else if (prot == PPPCCP) else if (prot == PPPCCP)
{ {
@ -2543,7 +2527,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
} }
else if (prot == PPPIPV6) else if (prot == PPPIPV6)
{ {
if (!config->ipv6_prefix.s6_addr[0] > 0) if (!config->ipv6_prefix.s6_addr[0])
{ {
LOG(1, s, t, "IPv6 not configured; yet received IPv6 packet. Ignoring.\n"); LOG(1, s, t, "IPv6 not configured; yet received IPv6 packet. Ignoring.\n");
return; return;
@ -2592,7 +2576,7 @@ static void processtun(uint8_t * buf, int len)
if (*(uint16_t *) (buf + 2) == htons(PKTIP)) // IPv4 if (*(uint16_t *) (buf + 2) == htons(PKTIP)) // IPv4
processipout(buf, len); processipout(buf, len);
else if (*(uint16_t *) (buf + 2) == htons(PKTIPV6) // IPV6 else if (*(uint16_t *) (buf + 2) == htons(PKTIPV6) // IPV6
&& config->ipv6_prefix.s6_addr[0] > 0) && config->ipv6_prefix.s6_addr[0])
processipv6out(buf, len); processipv6out(buf, len);
// Else discard. // Else discard.
@ -2734,13 +2718,123 @@ static void regular_cleanups(double period)
continue; continue;
} }
if (session[s].ip && !(session[s].flags & SF_IPCP_ACKED) // PPP timeouts
&& !(sess_local[s].radius && radius[sess_local[s].radius].state == RADIUSIPCP)) if (sess_local[s].lcp.restart >= time_now)
{ {
// IPCP has not completed yet. Resend int next_state = session[s].ppp.lcp;
LOG(3, s, session[s].tunnel, "No ACK for initial IPCP ConfigReq... resending\n"); switch (session[s].ppp.lcp)
sendipcp(session[s].tunnel, s); {
s_actions++; case RequestSent:
case AckReceived:
next_state = RequestSent;
case AckSent:
if (sess_local[s].lcp.conf_sent < config->ppp_max_configure)
{
LOG(3, s, session[s].tunnel, "No ACK for LCP ConfigReq... resending\n");
sess_local[s].lcp.restart = time_now + config->ppp_restart_time;
sess_local[s].lcp.conf_sent++;
sendlcp(t, s, sess_local[s].lcp_authtype);
change_state(s, lcp, next_state);
}
else
{
sessionshutdown(s, "No response to LCP ConfigReq.", 3, 0);
STAT(session_timeout);
}
s_actions++;
}
if (session[s].die)
continue;
}
if (sess_local[s].ipcp.restart >= time_now)
{
int next_state = session[s].ppp.ipcp;
switch (session[s].ppp.ipcp)
{
case RequestSent:
case AckReceived:
next_state = RequestSent;
case AckSent:
if (sess_local[s].ipcp.conf_sent < config->ppp_max_configure)
{
LOG(3, s, session[s].tunnel, "No ACK for IPCP ConfigReq... resending\n");
sess_local[s].ipcp.restart = time_now + config->ppp_restart_time;
sess_local[s].ipcp.conf_sent++;
sendipcp(t, s);
change_state(s, ipcp, next_state);
}
else
{
sessionshutdown(s, "No response to IPCP ConfigReq.", 3, 0);
STAT(session_timeout);
}
s_actions++;
}
if (session[s].die)
continue;
}
if (sess_local[s].ipv6cp.restart >= time_now)
{
int next_state = session[s].ppp.ipv6cp;
switch (session[s].ppp.ipv6cp)
{
case RequestSent:
case AckReceived:
next_state = RequestSent;
case AckSent:
if (sess_local[s].ipv6cp.conf_sent < config->ppp_max_configure)
{
LOG(3, s, session[s].tunnel, "No ACK for IPV6CP ConfigReq... resending\n");
sess_local[s].ipv6cp.restart = time_now + config->ppp_restart_time;
sess_local[s].ipv6cp.conf_sent++;
sendipv6cp(t, s);
change_state(s, ipv6cp, next_state);
}
else
{
LOG(3, s, session[s].tunnel, "No ACK for IPV6CP ConfigReq\n");
change_state(s, ipv6cp, Stopped);
}
s_actions++;
}
}
if (sess_local[s].ccp.restart >= time_now)
{
int next_state = session[s].ppp.ccp;
switch (session[s].ppp.ccp)
{
case RequestSent:
case AckReceived:
next_state = RequestSent;
case AckSent:
if (sess_local[s].ccp.conf_sent < config->ppp_max_configure)
{
LOG(3, s, session[s].tunnel, "No ACK for CCP ConfigReq... resending\n");
sess_local[s].ccp.restart = time_now + config->ppp_restart_time;
sess_local[s].ccp.conf_sent++;
sendccp(t, s);
change_state(s, ccp, next_state);
}
else
{
LOG(3, s, session[s].tunnel, "No ACK for CCP ConfigReq\n");
change_state(s, ccp, Stopped);
}
s_actions++;
}
} }
// Drop sessions who have not responded within IDLE_TIMEOUT seconds // Drop sessions who have not responded within IDLE_TIMEOUT seconds
@ -2753,7 +2847,7 @@ static void regular_cleanups(double period)
} }
// No data in ECHO_TIMEOUT seconds, send LCP ECHO // No data in ECHO_TIMEOUT seconds, send LCP ECHO
if (session[s].user[0] && (time_now - session[s].last_packet >= ECHO_TIMEOUT)) if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= ECHO_TIMEOUT))
{ {
uint8_t b[MAXCONTROL] = {0}; uint8_t b[MAXCONTROL] = {0};
@ -3084,7 +3178,8 @@ static void mainloop(void)
if (n) if (n)
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
int alen, c, s; socklen_t alen;
int c, s;
int udp_ready = 0; int udp_ready = 0;
int tun_ready = 0; int tun_ready = 0;
int cluster_ready = 0; int cluster_ready = 0;
@ -3391,6 +3486,9 @@ static void initdata(int optdebug, char *optconfig)
config->num_tbfs = MAXTBFS; config->num_tbfs = MAXTBFS;
config->rl_rate = 28; // 28kbps config->rl_rate = 28; // 28kbps
config->cluster_master_min_adv = 1; config->cluster_master_min_adv = 1;
config->ppp_restart_time = 3;
config->ppp_max_configure = 10;
config->ppp_max_failure = 5;
strcpy(config->random_device, RANDOMDEVICE); strcpy(config->random_device, RANDOMDEVICE);
log_stream = stderr; log_stream = stderr;
@ -3758,7 +3856,7 @@ static void initippool()
LOG(1, 0, 0, "IP address pool is %d addresses\n", ip_pool_size - 1); LOG(1, 0, 0, "IP address pool is %d addresses\n", ip_pool_size - 1);
} }
void snoop_send_packet(char *packet, uint16_t size, in_addr_t destination, uint16_t port) void snoop_send_packet(uint8_t *packet, uint16_t size, in_addr_t destination, uint16_t port)
{ {
struct sockaddr_in snoop_addr = {0}; struct sockaddr_in snoop_addr = {0};
if (!destination || !port || snoopfd <= 0 || size <= 0 || !packet) if (!destination || !port || snoopfd <= 0 || size <= 0 || !packet)
@ -4055,7 +4153,7 @@ static void sigchild_handler(int sig)
; ;
} }
static void build_chap_response(char *challenge, uint8_t id, uint16_t challenge_length, char **challenge_response) static void build_chap_response(uint8_t *challenge, uint8_t id, uint16_t challenge_length, uint8_t **challenge_response)
{ {
MD5_CTX ctx; MD5_CTX ctx;
*challenge_response = NULL; *challenge_response = NULL;
@ -4068,13 +4166,13 @@ static void build_chap_response(char *challenge, uint8_t id, uint16_t challenge_
LOG(4, 0, 0, " Building challenge response for CHAP request\n"); LOG(4, 0, 0, " Building challenge response for CHAP request\n");
*challenge_response = (char *)calloc(17, 1); *challenge_response = calloc(17, 1);
MD5Init(&ctx); MD5_Init(&ctx);
MD5Update(&ctx, &id, 1); MD5_Update(&ctx, &id, 1);
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret)); MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5Update(&ctx, challenge, challenge_length); MD5_Update(&ctx, challenge, challenge_length);
MD5Final(*challenge_response, &ctx); MD5_Final(*challenge_response, &ctx);
return; return;
} }
@ -4384,13 +4482,8 @@ int sessionsetup(tunnelidt t, sessionidt s)
cache_ipmap(session[s].ip, s); cache_ipmap(session[s].ip, s);
} }
if (!session[s].unique_id) sess_local[s].lcp_authtype = 0; // RADIUS authentication complete
{ lcp_open(t, s); // transition to Network phase and send initial IPCP
// did this session just finish radius?
LOG(3, s, t, "Sending initial IPCP to client\n");
sendipcp(t, s);
session[s].unique_id = ++last_id;
}
// Run the plugin's against this new session. // Run the plugin's against this new session.
{ {
@ -4499,7 +4592,7 @@ int load_session(sessionidt s, sessiont *new)
} }
// check v6 routing // check v6 routing
if (new->flags & SF_IPV6_ROUTED && !(session[s].flags & SF_IPV6_ROUTED)) if (new->ipv6prefixlen && new->ppp.ipv6cp == Opened && session[s].ppp.ipv6cp != Opened)
route6set(s, new->ipv6route, new->ipv6prefixlen, 1); route6set(s, new->ipv6route, new->ipv6prefixlen, 1);
// check filters // check filters
@ -4716,7 +4809,7 @@ static void plugins_done()
run_plugin_done(p); run_plugin_done(p);
} }
static void processcontrol(uint8_t * buf, int len, struct sockaddr_in *addr, int alen) static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
{ {
struct nsctl request; struct nsctl request;
struct nsctl response; struct nsctl response;
@ -5040,11 +5133,11 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec
uint16_t m = htons(type); uint16_t m = htons(type);
// Compute initial pad // Compute initial pad
MD5Init(&ctx); MD5_Init(&ctx);
MD5Update(&ctx, (unsigned char *) &m, 2); MD5_Update(&ctx, (unsigned char *) &m, 2);
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret)); MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5Update(&ctx, vector, vec_len); MD5_Update(&ctx, vector, vec_len);
MD5Final(digest, &ctx); MD5_Final(digest, &ctx);
// pointer to last decoded 16 octets // pointer to last decoded 16 octets
last = value; last = value;
@ -5054,10 +5147,10 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec
// calculate a new pad based on the last decoded block // calculate a new pad based on the last decoded block
if (d >= sizeof(digest)) if (d >= sizeof(digest))
{ {
MD5Init(&ctx); MD5_Init(&ctx);
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret)); MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5Update(&ctx, last, sizeof(digest)); MD5_Update(&ctx, last, sizeof(digest));
MD5Final(digest, &ctx); MD5_Final(digest, &ctx);
d = 0; d = 0;
last = value; last = value;

112
l2tpns.h
View file

@ -1,5 +1,5 @@
// L2TPNS Global Stuff // L2TPNS Global Stuff
// $Id: l2tpns.h,v 1.80 2005/06/28 14:48:27 bodea Exp $ // $Id: l2tpns.h,v 1.81 2005/07/31 10:04:10 bodea Exp $
#ifndef __L2TPNS_H__ #ifndef __L2TPNS_H__
#define __L2TPNS_H__ #define __L2TPNS_H__
@ -72,14 +72,14 @@
#define CONFIGFILE FLASHDIR "/startup-config" // Configuration file #define CONFIGFILE FLASHDIR "/startup-config" // Configuration file
#define CLIUSERS FLASHDIR "/users" // CLI Users file #define CLIUSERS FLASHDIR "/users" // CLI Users file
#define IPPOOLFILE FLASHDIR "/ip_pool" // Address pool configuration #define IPPOOLFILE FLASHDIR "/ip_pool" // Address pool configuration
#define ACCT_TIME 3000 // 5 minute accounting interval #define ACCT_TIME 3000 // 5 minute accounting interval
#define ACCT_SHUT_TIME 600 // 1 minute for counters of shutdown sessions #define ACCT_SHUT_TIME 600 // 1 minute for counters of shutdown sessions
#define L2TPPORT 1701 // L2TP port #define L2TPPORT 1701 // L2TP port
#define RADPORT 1645 // old radius port... #define RADPORT 1645 // old radius port...
#define DAEPORT 3799 // DAE port #define DAEPORT 3799 // DAE port
#define PKTARP 0x0806 // ARP packet type #define PKTARP 0x0806 // ARP packet type
#define PKTIP 0x0800 // IPv4 packet type #define PKTIP 0x0800 // IPv4 packet type
#define PKTIPV6 0x86DD // IPv6 packet type #define PKTIPV6 0x86DD // IPv6 packet type
#define PPPPAP 0xC023 #define PPPPAP 0xC023
#define PPPCHAP 0xC223 #define PPPCHAP 0xC223
#define PPPLCP 0xC021 #define PPPLCP 0xC021
@ -121,6 +121,52 @@ enum {
CoANAK CoANAK
}; };
// PPP phases
enum {
Dead,
Establish,
Authenticate,
Network,
Terminate
};
// PPP states
enum {
Initial,
Starting,
Closed,
Stopped,
Closing,
Stopping,
RequestSent,
AckReceived,
AckSent,
Opened
};
// reset state machine counters
#define initialise_restart_count(_s, _fsm) \
sess_local[_s]._fsm.conf_sent = sess_local[_s]._fsm.nak_sent
// stop timer on change to state where timer does not run
#define change_state(_s, _fsm, _new) ({ \
if (_new != session[_s].ppp._fsm) \
{ \
switch (_new) \
{ \
case Initial: \
case Starting: \
case Closed: \
case Stopped: \
case Opened: \
sess_local[_s]._fsm.restart = 0; \
initialise_restart_count(_s, _fsm); \
} \
session[_s].ppp._fsm = _new; \
cluster_send_session(_s); \
} \
})
// Types // Types
typedef uint16_t sessionidt; typedef uint16_t sessionidt;
typedef uint16_t tunnelidt; typedef uint16_t tunnelidt;
@ -174,7 +220,14 @@ typedef struct
sessionidt far; // far end session ID sessionidt far; // far end session ID
tunnelidt tunnel; // near end tunnel ID tunnelidt tunnel; // near end tunnel ID
uint8_t l2tp_flags; // various bit flags from the ICCN on the l2tp tunnel. uint8_t l2tp_flags; // various bit flags from the ICCN on the l2tp tunnel.
uint8_t flags; // Various session flags. struct {
uint8_t phase; // PPP phase
uint8_t lcp:4; // LCP state
uint8_t ipcp:4; // IPCP state
uint8_t ipv6cp:4; // IPV6CP state
uint8_t ccp:4; // CCP state
uint8_t pad; // unused
} ppp;
in_addr_t ip; // IP of session set by RADIUS response (host byte order). in_addr_t ip; // IP of session set by RADIUS response (host byte order).
int ip_pool_index; // index to IP pool int ip_pool_index; // index to IP pool
uint32_t unique_id; // unique session id uint32_t unique_id; // unique session id
@ -198,7 +251,7 @@ typedef struct
uint16_t tbf_in; // filter bucket for throttling in from the user. uint16_t tbf_in; // filter bucket for throttling in from the user.
uint16_t tbf_out; // filter bucket for throttling out to the user. uint16_t tbf_out; // filter bucket for throttling out to the user.
int random_vector_length; int random_vector_length;
char random_vector[MAXTEL]; uint8_t random_vector[MAXTEL];
char user[MAXUSER]; // user (needed in seesion for radius stop messages) char user[MAXUSER]; // user (needed in seesion for radius stop messages)
char called[MAXTEL]; // called number char called[MAXTEL]; // called number
char calling[MAXTEL]; // calling number char calling[MAXTEL]; // calling number
@ -209,17 +262,10 @@ typedef struct
uint8_t walled_garden; // is this session gardened? uint8_t walled_garden; // is this session gardened?
uint8_t ipv6prefixlen; // IPv6 route prefix length uint8_t ipv6prefixlen; // IPv6 route prefix length
struct in6_addr ipv6route; // Static IPv6 route struct in6_addr ipv6route; // Static IPv6 route
char reserved[16]; // Space to expand structure without changing HB_VERSION char reserved[11]; // Space to expand structure without changing HB_VERSION
} }
sessiont; sessiont;
#define SF_IPCP_ACKED 1 // Has this session seen an IPCP Ack?
#define SF_LCP_ACKED 2 // LCP negotiated
#define SF_CCP_ACKED 4 // CCP negotiated
#define SF_IPV6CP_ACKED 8 // IPv6 negotiated
#define SF_IPV6_NACKED 16 // IPv6 rejected
#define SF_IPV6_ROUTED 32 // advertised v6 route
#define AUTHPAP 1 // allow PAP #define AUTHPAP 1 // allow PAP
#define AUTHCHAP 2 // allow CHAP #define AUTHCHAP 2 // allow CHAP
@ -233,6 +279,16 @@ typedef struct
uint32_t cin; uint32_t cin;
uint32_t cout; uint32_t cout;
// PPP restart timer/counters
struct {
time_t restart;
int conf_sent;
int nak_sent;
} lcp, ipcp, ipv6cp, ccp;
// authentication to use
int lcp_authtype;
// DoS prevention // DoS prevention
clockt last_packet_out; clockt last_packet_out;
uint32_t packets_out; uint32_t packets_out;
@ -271,13 +327,12 @@ typedef struct
} }
tunnelt; tunnelt;
// 180 bytes per radius session // 160 bytes per radius session
typedef struct // 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
clockt retry; // when to try next clockt retry; // when to try next
char calling[MAXTEL]; // calling number
char pass[129]; // password char pass[129]; // password
uint8_t id; // ID for PPP response uint8_t id; // ID for PPP response
uint8_t try; // which try we are on uint8_t try; // which try we are on
@ -328,7 +383,6 @@ enum
RADIUSNULL, // Not in use RADIUSNULL, // Not in use
RADIUSCHAP, // sending CHAP down PPP RADIUSCHAP, // sending CHAP down PPP
RADIUSAUTH, // sending auth to RADIUS server RADIUSAUTH, // sending auth to RADIUS server
RADIUSIPCP, // sending IPCP to end user
RADIUSSTART, // sending start accounting to RADIUS server RADIUSSTART, // sending start accounting to RADIUS server
RADIUSSTOP, // sending stop accounting to RADIUS server RADIUSSTOP, // sending stop accounting to RADIUS server
RADIUSINTERIM, // sending interim accounting to RADIUS server RADIUSINTERIM, // sending interim accounting to RADIUS server
@ -391,6 +445,7 @@ struct Tstats
uint32_t call_sessionbyuser; uint32_t call_sessionbyuser;
uint32_t call_sendarp; uint32_t call_sendarp;
uint32_t call_sendipcp; uint32_t call_sendipcp;
uint32_t call_sendipv6cp;
uint32_t call_processipv6cp; uint32_t call_processipv6cp;
uint32_t call_tunnelsend; uint32_t call_tunnelsend;
uint32_t call_sessionkill; uint32_t call_sessionkill;
@ -457,6 +512,10 @@ typedef struct
char random_device[256]; // random device path, defaults to RANDOMDEVICE char random_device[256]; // random device path, defaults to RANDOMDEVICE
int ppp_restart_time; // timeout for PPP restart
int ppp_max_configure; // max lcp configure requests to send
int ppp_max_failure; // max lcp configure naks to send
char radiussecret[64]; char radiussecret[64];
int radius_accounting; int radius_accounting;
int radius_interim; int radius_interim;
@ -601,6 +660,7 @@ void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip);
// ppp.c // ppp.c
void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l); void processpap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
void processchap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l); void processchap(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
void lcp_open(tunnelidt t, sessionidt s);
void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l); void processlcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
void processipcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l); void processipcp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
void processipv6cp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l); void processipv6cp(tunnelidt t, sessionidt s, uint8_t *p, uint16_t l);
@ -611,6 +671,7 @@ void sendchap(tunnelidt t, sessionidt s);
uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, tunnelidt t, sessionidt s, uint16_t mtype); uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, tunnelidt t, sessionidt s, uint16_t mtype);
void sendlcp(tunnelidt t, sessionidt s, int authtype); void sendlcp(tunnelidt t, sessionidt s, int authtype);
void send_ipin(sessionidt s, uint8_t *buf, int len); void send_ipin(sessionidt s, uint8_t *buf, int len);
void sendccp(tunnelidt t, sessionidt s);
// radius.c // radius.c
@ -638,8 +699,9 @@ void filter_session(sessionidt s, int filter_in, int filter_out);
void send_garp(in_addr_t ip); void send_garp(in_addr_t ip);
void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t); void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
void sendipcp(tunnelidt t, sessionidt s); void sendipcp(tunnelidt t, sessionidt s);
void sendipv6cp(tunnelidt t, sessionidt s);
void processudp(uint8_t *buf, int len, struct sockaddr_in *addr); void processudp(uint8_t *buf, int len, struct sockaddr_in *addr);
void snoop_send_packet(char *packet, uint16_t size, in_addr_t destination, uint16_t port); void snoop_send_packet(uint8_t *packet, uint16_t size, in_addr_t destination, uint16_t port);
int find_filter(char const *name, size_t len); int find_filter(char const *name, size_t len);
int ip_filter(uint8_t *buf, int len, uint8_t filter); int ip_filter(uint8_t *buf, int len, uint8_t filter);
int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc); int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc);
@ -652,7 +714,7 @@ int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc
#define LOG_HEX(D, t, d, s) ({ if (D <= config->debug) _log_hex(D, t, d, s); }) #define LOG_HEX(D, t, d, s) ({ if (D <= config->debug) _log_hex(D, t, d, s); })
void _log(int level, sessionidt s, tunnelidt t, const char *format, ...) __attribute__((format (printf, 4, 5))); void _log(int level, sessionidt s, tunnelidt t, const char *format, ...) __attribute__((format (printf, 4, 5)));
void _log_hex(int level, const char *title, const char *data, int maxsize); void _log_hex(int level, const char *title, const uint8_t *data, int maxsize);
int sessionsetup(tunnelidt t, sessionidt s); int sessionsetup(tunnelidt t, sessionidt s);
int run_plugins(int plugin_type, void *data); int run_plugins(int plugin_type, void *data);
@ -670,7 +732,7 @@ int cli_arg_help(struct cli_def *cli, int cr_ok, char *entry, ...);
// icmp.c // icmp.c
void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, char *packet, int packet_len); void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, uint8_t *packet, int packet_len);
extern tunnelt *tunnel; extern tunnelt *tunnel;

View file

@ -8,8 +8,8 @@ Source: http://optusnet.dl.sourceforge.net/sourceforge/l2tpns/l2tpns-%{version}.
URL: http://sourceforge.net/projects/l2tpns URL: http://sourceforge.net/projects/l2tpns
BuildRoot: %{_tmppath}/%{name}-%{version}-root BuildRoot: %{_tmppath}/%{name}-%{version}-root
Prereq: /sbin/chkconfig Prereq: /sbin/chkconfig
BuildRequires: libcli >= 1.8.5 BuildRequires: libcli >= 1.8.5, openssl-devel
Requires: libcli >= 1.8.5 Requires: libcli >= 1.8.5, openssl
%description %description
l2tpns is a layer 2 tunneling protocol network server (LNS). It l2tpns is a layer 2 tunneling protocol network server (LNS). It
@ -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
* Wed Jun 29 2005 Brendan O'Dea <bod@c47.org> 2.1.2-1 * Sun Jul 31 2005 Brendan O'Dea <bod@> 2.1.2-1
- 2.1.2 release, see /usr/share/doc/l2tpns-2.1.2/Changes - 2.1.2 release, see /usr/share/doc/l2tpns-2.1.2/Changes

296
md5.c
View file

@ -1,296 +0,0 @@
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
char const *cvs_id_md5 = "$Id: md5.c,v 1.3 2004/08/13 00:02:50 fred_nerk Exp $";
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include <string.h>
#include "md5.h"
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform PROTO_LIST((UINT4[4], unsigned char[64]));
static void Encode PROTO_LIST((unsigned char *, UINT4 *, unsigned int));
static void Decode PROTO_LIST((UINT4 *, unsigned char *, unsigned int));
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void MD5Init(MD5_CTX *context)
{
context->count[0] = context->count[1] = 0;
// Load magic initialization constants.
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputLen)
{
unsigned int i,
index,
partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4) inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen)
{
memcpy(&context->buffer[index], input, partLen);
MD5Transform(context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform(context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
memcpy(&context->buffer[index], &input[i], inputLen - i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void MD5Final(unsigned char digest[16], MD5_CTX *context)
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode(bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update(context, PADDING, padLen);
/* Append length (before padding) */
MD5Update(context, bits, 8);
/* Store state in digest */
Encode(digest, context->state, 16);
/* Zeroize sensitive information.
*/
memset(context, 0, sizeof(*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform(UINT4 state[4], unsigned char block[64])
{
UINT4 a = state[0],
b = state[1],
c = state[2],
d = state[3],
x[16];
Decode(x, block, 64);
/* Round 1 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
// Zeroize sensitive information.
memset(x, 0, sizeof(x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode(unsigned char *output, UINT4 *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (unsigned char) (input[i] & 0xff);
output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode(UINT4 *output, unsigned char *input, unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
}

74
md5.h
View file

@ -1,74 +0,0 @@
/* RSAREF types and constants
*/
#ifndef __MD5_H__
#define __MD5_H__
/* PROTOTYPES should be set to one if and only if the compiler supports
function argument prototyping.
The following makes PROTOTYPES default to 0 if it has not already
been defined with C compiler flags.
*/
#ifndef PROTOTYPES
#define PROTOTYPES 0
#endif
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
returns an empty list.
*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init PROTO_LIST ((MD5_CTX *));
void MD5Update PROTO_LIST
((MD5_CTX *, unsigned char *, unsigned int));
void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
#endif /* __MD5_H__ */

View file

@ -141,7 +141,7 @@ static struct nsctl *request(char *host, int port, int type, int argc, char *arg
socklen_t len = sizeof(peer); socklen_t len = sizeof(peer);
struct hostent *h = gethostbyname(host); struct hostent *h = gethostbyname(host);
int fd; int fd;
char buf[NSCTL_MAX_PKT_SZ]; uint8_t buf[NSCTL_MAX_PKT_SZ];
int sz; int sz;
char *err; char *err;

View file

@ -28,7 +28,7 @@ enum
struct pluginfuncs struct pluginfuncs
{ {
void (*log)(int level, sessionidt s, tunnelidt t, const char *format, ...); void (*log)(int level, sessionidt s, tunnelidt t, const char *format, ...);
void (*log_hex)(int level, const char *title, const char *data, int maxsize); void (*log_hex)(int level, const char *title, const uint8_t *data, int maxsize);
char *(*fmtaddr)(in_addr_t addr, int n); char *(*fmtaddr)(in_addr_t addr, int n);
sessionidt (*get_session_by_username)(char *username); sessionidt (*get_session_by_username)(char *username);
sessiont *(*get_session_by_id)(sessionidt s); sessiont *(*get_session_by_id)(sessionidt s);

1185
ppp.c

File diff suppressed because it is too large Load diff

106
radius.c
View file

@ -1,6 +1,6 @@
// L2TPNS Radius Stuff // L2TPNS Radius Stuff
char const *cvs_id_radius = "$Id: radius.c,v 1.36 2005/06/30 14:31:26 bodea Exp $"; char const *cvs_id_radius = "$Id: radius.c,v 1.37 2005/07/31 10:04:10 bodea Exp $";
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
@ -13,7 +13,7 @@ char const *cvs_id_radius = "$Id: radius.c,v 1.36 2005/06/30 14:31:26 bodea Exp
#include <ctype.h> #include <ctype.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <errno.h> #include <errno.h>
#include "md5.h" #include <openssl/md5.h>
#include "constants.h" #include "constants.h"
#include "l2tpns.h" #include "l2tpns.h"
#include "plugin.h" #include "plugin.h"
@ -182,7 +182,7 @@ void radiussend(uint16_t r, uint8_t state)
{ {
*p = 1; // user name *p = 1; // user name
p[1] = strlen(session[s].user) + 2; p[1] = strlen(session[s].user) + 2;
strcpy(p + 2, session[s].user); strcpy((char *) p + 2, session[s].user);
p += p[1]; p += p[1];
} }
if (state == RADIUSAUTH) if (state == RADIUSAUTH)
@ -212,13 +212,13 @@ void radiussend(uint16_t r, uint8_t state)
while (p < pl) while (p < pl)
{ {
MD5_CTX ctx; MD5_CTX ctx;
MD5Init(&ctx); MD5_Init(&ctx);
MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret)); MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret));
if (p) if (p)
MD5Update(&ctx, pass + p - 16, 16); MD5_Update(&ctx, pass + p - 16, 16);
else else
MD5Update(&ctx, radius[r].auth, 16); MD5_Update(&ctx, radius[r].auth, 16);
MD5Final(hash, &ctx); MD5_Final(hash, &ctx);
do do
{ {
pass[p] ^= hash[p & 15]; pass[p] ^= hash[p & 15];
@ -244,7 +244,7 @@ void radiussend(uint16_t r, uint8_t state)
{ {
*p = 44; // session ID *p = 44; // session ID
p[1] = 18; p[1] = 18;
sprintf(p + 2, "%08X%08X", session[s].unique_id, session[s].opened); sprintf((char *) p + 2, "%08X%08X", session[s].unique_id, session[s].opened);
p += p[1]; p += p[1];
if (state == RADIUSSTART) if (state == RADIUSSTART)
{ // start { // start
@ -299,7 +299,7 @@ void radiussend(uint16_t r, uint8_t state)
*p = 26; // vendor-specific *p = 26; // vendor-specific
*(uint32_t *) (p + 2) = htonl(9); // Cisco *(uint32_t *) (p + 2) = htonl(9); // Cisco
p[6] = 1; // Cisco-AVPair p[6] = 1; // Cisco-AVPair
p[7] = 2 + sprintf(p + 8, "intercept=%s:%d", p[7] = 2 + sprintf((char *) p + 8, "intercept=%s:%d",
fmtaddr(session[s].snoop_ip, 0), session[s].snoop_port); fmtaddr(session[s].snoop_ip, 0), session[s].snoop_port);
p[1] = p[7] + 6; p[1] = p[7] + 6;
@ -325,21 +325,14 @@ void radiussend(uint16_t r, uint8_t state)
{ {
*p = 30; // called *p = 30; // called
p[1] = strlen(session[s].called) + 2; p[1] = strlen(session[s].called) + 2;
strcpy(p + 2, session[s].called); strcpy((char *) p + 2, session[s].called);
p += p[1];
}
if (*radius[r].calling)
{
*p = 31; // calling
p[1] = strlen(radius[r].calling) + 2;
strcpy(p + 2, radius[r].calling);
p += p[1]; p += p[1];
} }
else if (*session[s].calling) else if (*session[s].calling)
{ {
*p = 31; // calling *p = 31; // calling
p[1] = strlen(session[s].calling) + 2; p[1] = strlen(session[s].calling) + 2;
strcpy(p + 2, session[s].calling); strcpy((char *) p + 2, session[s].calling);
p += p[1]; p += p[1];
} }
// NAS-IP-Address // NAS-IP-Address
@ -353,15 +346,15 @@ void radiussend(uint16_t r, uint8_t state)
if (state != RADIUSAUTH) if (state != RADIUSAUTH)
{ {
// Build auth for accounting packet // Build auth for accounting packet
char z[16] = {0}; uint8_t z[16] = {0};
char hash[16] = {0}; uint8_t hash[16] = {0};
MD5_CTX ctx; MD5_CTX ctx;
MD5Init(&ctx); MD5_Init(&ctx);
MD5Update(&ctx, b, 4); MD5_Update(&ctx, b, 4);
MD5Update(&ctx, z, 16); MD5_Update(&ctx, z, 16);
MD5Update(&ctx, b + 20, (p - b) - 20); MD5_Update(&ctx, b + 20, (p - b) - 20);
MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret)); MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret));
MD5Final(hash, &ctx); MD5_Final(hash, &ctx);
memcpy(b + 4, hash, 16); memcpy(b + 4, hash, 16);
memcpy(radius[r].auth, hash, 16); memcpy(radius[r].auth, hash, 16);
} }
@ -381,9 +374,9 @@ void radiussend(uint16_t r, uint8_t state)
static void handle_avpair(sessionidt s, uint8_t *avp, int len) static void handle_avpair(sessionidt s, uint8_t *avp, int len)
{ {
char *key = avp; uint8_t *key = avp;
char *value = memchr(avp, '=', len); uint8_t *value = memchr(avp, '=', len);
char tmp[2048] = ""; uint8_t tmp[2048] = "";
if (value) if (value)
{ {
@ -415,7 +408,7 @@ static void handle_avpair(sessionidt s, uint8_t *avp, int len)
// Run hooks // Run hooks
{ {
struct param_radius_response p = { &tunnel[session[s].tunnel], &session[s], key, value }; struct param_radius_response p = { &tunnel[session[s].tunnel], &session[s], (char *) key, (char *) value };
run_plugins(PLUGIN_RADIUS_RESPONSE, &p); run_plugins(PLUGIN_RADIUS_RESPONSE, &p);
} }
} }
@ -463,12 +456,12 @@ void processrad(uint8_t *buf, int len, char socket_index)
return; return;
} }
t = session[s].tunnel; t = session[s].tunnel;
MD5Init(&ctx); MD5_Init(&ctx);
MD5Update(&ctx, buf, 4); MD5_Update(&ctx, buf, 4);
MD5Update(&ctx, radius[r].auth, 16); MD5_Update(&ctx, radius[r].auth, 16);
MD5Update(&ctx, buf + 20, len - 20); MD5_Update(&ctx, buf + 20, len - 20);
MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret)); MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret));
MD5Final(hash, &ctx); MD5_Final(hash, &ctx);
do { do {
if (memcmp(hash, buf + 4, 16)) if (memcmp(hash, buf + 4, 16))
{ {
@ -617,7 +610,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
else if (*p == 11) else if (*p == 11)
{ {
// Filter-Id // Filter-Id
char *filter = p + 2; char *filter = (char *) p + 2;
int l = p[1] - 2; int l = p[1] - 2;
char *suffix; char *suffix;
int f; int f;
@ -680,10 +673,10 @@ void processrad(uint8_t *buf, int len, char socket_index)
int prefixlen; int prefixlen;
uint8_t *n = p + 2; uint8_t *n = p + 2;
uint8_t *e = p + p[1]; uint8_t *e = p + p[1];
uint8_t *m = strchr(n, '/'); uint8_t *m = memchr(n, '/', e - p);
*m++ = 0; *m++ = 0;
inet_pton(AF_INET6, n, &r6); inet_pton(AF_INET6, (char *) n, &r6);
prefixlen = 0; prefixlen = 0;
while (m < e && isdigit(*m)) { while (m < e && isdigit(*m)) {
@ -710,12 +703,12 @@ void processrad(uint8_t *buf, int len, char socket_index)
if (!session[s].dns1 && config->default_dns1) if (!session[s].dns1 && config->default_dns1)
{ {
session[s].dns1 = htonl(config->default_dns1); session[s].dns1 = ntohl(config->default_dns1);
LOG(3, s, t, " Sending dns1 = %s\n", fmtaddr(config->default_dns1, 0)); LOG(3, s, t, " Sending dns1 = %s\n", fmtaddr(config->default_dns1, 0));
} }
if (!session[s].dns2 && config->default_dns2) if (!session[s].dns2 && config->default_dns2)
{ {
session[s].dns2 = htonl(config->default_dns2); session[s].dns2 = ntohl(config->default_dns2);
LOG(3, s, t, " Sending dns2 = %s\n", fmtaddr(config->default_dns2, 0)); LOG(3, s, t, " Sending dns2 = %s\n", fmtaddr(config->default_dns2, 0));
} }
@ -750,20 +743,11 @@ void radiusretry(uint16_t r)
case RADIUSCHAP: // sending CHAP down PPP case RADIUSCHAP: // sending CHAP down PPP
sendchap(t, s); sendchap(t, s);
break; break;
case RADIUSIPCP:
sendipcp(t, s); // send IPCP
break;
case RADIUSAUTH: // sending auth to RADIUS server case RADIUSAUTH: // sending auth to RADIUS server
radiussend(r, RADIUSAUTH);
break;
case RADIUSSTART: // sending start accounting to RADIUS server case RADIUSSTART: // sending start accounting to RADIUS server
radiussend(r, RADIUSSTART);
break;
case RADIUSSTOP: // sending stop accounting to RADIUS server case RADIUSSTOP: // sending stop accounting to RADIUS server
radiussend(r, RADIUSSTOP);
break;
case RADIUSINTERIM: // sending interim accounting to RADIUS server case RADIUSINTERIM: // sending interim accounting to RADIUS server
radiussend(r, RADIUSINTERIM); radiussend(r, radius[r].state);
break; break;
default: default:
case RADIUSNULL: // Not in use case RADIUSNULL: // Not in use
@ -832,10 +816,10 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
i = strlen(config->radiussecret); i = strlen(config->radiussecret);
if (i > 16) i = 16; if (i > 16) i = 16;
MD5Init(&ctx); MD5_Init(&ctx);
MD5Update(&ctx, buf, len); MD5_Update(&ctx, buf, len);
MD5Update(&ctx, buf, config->radiussecret, i); MD5_Update(&ctx, config->radiussecret, i);
MD5Final(hash, &ctx); MD5_Final(hash, &ctx);
if (memcmp(hash, vector, 16) != 0) if (memcmp(hash, vector, 16) != 0)
{ {
LOG(1, 0, 0, "Incorrect vector in DAE request (wrong secret in radius config?)\n"); LOG(1, 0, 0, "Incorrect vector in DAE request (wrong secret in radius config?)\n");
@ -903,7 +887,7 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
} }
len = p - packet; len = p - packet;
i = find_filter(packet, len); i = find_filter((char *) packet, len);
if (i < 0 || !*ip_filters[i].name) if (i < 0 || !*ip_filters[i].name)
{ {
error = 404; error = 404;
@ -1063,10 +1047,10 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
i = strlen(config->radiussecret); i = strlen(config->radiussecret);
if (i > 16) i = 16; if (i > 16) i = 16;
MD5Init(&ctx); MD5_Init(&ctx);
MD5Update(&ctx, buf, len); MD5_Update(&ctx, buf, len);
MD5Update(&ctx, config->radiussecret, i); MD5_Update(&ctx, config->radiussecret, i);
MD5Final(hash, &ctx); MD5_Final(hash, &ctx);
memcpy(buf + 4, hash, 16); memcpy(buf + 4, hash, 16);
LOG(3, 0, 0, "Sending DAE %s, id=%d\n", radius_code(r_code), r_id); LOG(3, 0, 0, "Sending DAE %s, id=%d\n", radius_code(r_code), r_id);

6
tbf.c
View file

@ -1,6 +1,6 @@
// L2TPNS: token bucket filters // L2TPNS: token bucket filters
char const *cvs_id_tbf = "$Id: tbf.c,v 1.12 2005/05/02 09:55:04 bodea Exp $"; char const *cvs_id_tbf = "$Id: tbf.c,v 1.13 2005/07/31 10:04:10 bodea Exp $";
#include <string.h> #include <string.h>
#include "l2tpns.h" #include "l2tpns.h"
@ -159,10 +159,10 @@ void fsck_tbfs(void)
// If we can send it right away, we do. Else we // If we can send it right away, we do. Else we
// try and queue it to send later. Else we drop it. // try and queue it to send later. Else we drop it.
// //
int tbf_queue_packet(int tbf_id, char * data, int size) int tbf_queue_packet(int tbf_id, uint8_t *data, int size)
{ {
int i; int i;
tbft * f; tbft *f;
if (!filter_list) if (!filter_list)
return -1; return -1;

4
tbf.h
View file

@ -30,12 +30,12 @@ typedef struct {
uint32_t p_delayed; // Total packets not sent immediately. uint32_t p_delayed; // Total packets not sent immediately.
int sizes[TBF_MAX_QUEUE]; int sizes[TBF_MAX_QUEUE];
char packets[TBF_MAX_QUEUE][TBF_MAX_SIZE]; uint8_t packets[TBF_MAX_QUEUE][TBF_MAX_SIZE];
} tbft; } tbft;
void init_tbf(int num_tbfs); void init_tbf(int num_tbfs);
int tbf_run_timer(void); int tbf_run_timer(void);
int tbf_queue_packet(int tbf_id, char * data, int size); int tbf_queue_packet(int tbf_id, uint8_t * data, int size);
int new_tbf(int sid, int max_credit, int rate, void (*f)(sessionidt, uint8_t *, int)); int new_tbf(int sid, int max_credit, int rate, void (*f)(sessionidt, uint8_t *, int));
int free_tbf(int tid); int free_tbf(int tid);
void fsck_tbfs(void); void fsck_tbfs(void);

View file

@ -19,7 +19,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/select.h> #include <sys/select.h>
#include <signal.h> #include <signal.h>
#include "../md5.h" #include <openssl/md5.h>
extern char *optarg; extern char *optarg;
extern int optind; extern int optind;
@ -394,16 +394,16 @@ int main(int argc, char *argv[])
for (int j = 0; j < pw_len; j += 16) for (int j = 0; j < pw_len; j += 16)
{ {
MD5_CTX ctx; MD5_CTX ctx;
MD5Init(&ctx); MD5_Init(&ctx);
MD5Update(&ctx, secret, strlen(secret)); MD5_Update(&ctx, secret, strlen(secret));
if (j) if (j)
MD5Update(&ctx, pass + j - 16, 16); MD5_Update(&ctx, pass + j - 16, 16);
else else
/* authenticator */ /* authenticator */
MD5Update(&ctx, u->request + 4, 16); MD5_Update(&ctx, u->request + 4, 16);
char digest[16]; uint8_t digest[16];
MD5Final(digest, &ctx); MD5_Final(digest, &ctx);
for (int k = 0; k < 16; k++) for (int k = 0; k < 16; k++)
pass[j + k] ^= digest[k]; pass[j + k] ^= digest[k];