- 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
- Don't resend IPCP while still in progress.
- Ignore duplicate ACKs for IPCP.
- Clear RADIUSIPCP for walled garden sessions on ACK.
* Sun Jul 31 2005 Brendan O'Dea <bod@> 2.1.2
- Clear cluster_master on election so that slaves will accept a new master.
- Provide more comments/defaults in etc/startup-config.default.
- 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
- 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.
</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>secondary_dns</B> (ip address)<BR>
Whenever a PPP connection is established, DNS servers will be sent to the

View file

@ -2,7 +2,7 @@
.de Id
.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"
.SH NAME
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.
.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"
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

View file

@ -23,10 +23,10 @@ LDFLAGS =
LDLIBS =
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 \
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
PLUGINS = autosnoop.so autothrottle.so garden.so sessionctl.so \
@ -109,20 +109,19 @@ install: all
## Dependencies: (autogenerated) ##
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
constants.o: constants.c constants.h
control.o: control.c l2tpns.h control.h
icmp.o: icmp.c l2tpns.h
l2tpns.o: l2tpns.c md5.h l2tpns.h cluster.h plugin.h ll.h constants.h \
control.h util.h tbf.h bgp.h
l2tpns.o: l2tpns.c l2tpns.h cluster.h plugin.h ll.h constants.h control.h \
util.h tbf.h bgp.h fake_epoll.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
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
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
autothrottle.so: autothrottle.c l2tpns.h plugin.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>
Jordan Hrycaj <jordan@mjh.teddy-net.com>
Vladislav Bjelic <vladislav@gmail.com>
Alex Kiernan <alex.kiernan@gmail.com>

4
arp.c
View file

@ -1,6 +1,6 @@
// 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 <unistd.h>
@ -55,7 +55,7 @@ void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip)
memset(&sll, 0, sizeof(sll));
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_ifindex = ifr_idx;

4
bgp.c
View file

@ -10,7 +10,7 @@
* 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 <unistd.h>
@ -767,7 +767,7 @@ static int bgp_connect(struct bgp_peer *peer)
static int bgp_handle_connect(struct bgp_peer *peer)
{
int err = 0;
int len = sizeof(int);
socklen_t len = sizeof(int);
getsockopt(peer->sock, SOL_SOCKET, SO_ERROR, &err, &len);
if (err)
{

23
cli.c
View file

@ -2,7 +2,7 @@
// vim: sw=8 ts=8
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 <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 "l2tpns.h"
#include "constants.h"
#include "util.h"
#include "cluster.h"
#include "tbf.h"
@ -289,10 +290,10 @@ void cli_do(int sockfd)
{
int require_auth = 1;
struct sockaddr_in addr;
int l = sizeof(addr);
socklen_t l = sizeof(addr);
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");
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, "\tCalled Num:\t%s", session[s].called);
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, "\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);
@ -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].throttle_in || session[i].throttle_out) ? "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),
(unsigned long)session[i].cout,
(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_l2tpns);
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_radius);
cli_print(cli, " %s", cvs_id_tbf);

View file

@ -1,6 +1,6 @@
// 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 <stdlib.h>
@ -56,7 +56,7 @@ static struct {
static struct {
int seq;
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
// 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
// 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;
*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
// 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};
@ -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'.
//
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.
char *p = buf;
uint8_t buf[65536]; // Vast overkill.
uint8_t *p = buf;
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);
@ -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
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.
char *p = buf;
uint8_t buf[65536]; // Vast overkill.
uint8_t *p = buf;
if (!config->cluster_master_address) // No election has been held yet. Just skip it.
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);
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);
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
// 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);
}
// 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);
}
@ -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
// 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.
char *p = buf;
uint8_t buf[65536]; // Vast overkill.
uint8_t *p = buf;
if (!config->cluster_master_address) // No election has been held yet. Just skip it.
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
// 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.
char *p = buf;
uint8_t buf[65536]; // Vast overkill.
uint8_t *p = buf;
if (!config->cluster_master_address) // No election has been held yet. Just skip it.
return -1;
@ -358,7 +358,7 @@ int master_garden_packet(sessionidt s, char *data, int size)
// Send a chunk of data as a heartbeat..
// 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;
@ -380,8 +380,8 @@ static void send_heartbeat(int seq, char *data, int size)
//
void cluster_send_ping(time_t basetime)
{
char buff[100 + sizeof(pingt)];
char *p = buff;
uint8_t buff[100 + sizeof(pingt)];
uint8_t *p = buff;
pingt x;
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.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) );
}
@ -456,7 +456,7 @@ void master_update_counts(void)
// Forward the data to the master.
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;
}
@ -738,7 +738,7 @@ static void cluster_check_sessions(int highsession, int freesession_ptr, int hig
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) {
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
// reduced??
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;
}
// Failed to compress : Fall through.
}
case C_SESSION: add_type(p, C_SESSION, id,
(char *) &session[id], sizeof(sessiont));
case C_SESSION:
add_type(p, C_SESSION, id, (uint8_t *) &session[id], sizeof(sessiont));
break;
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.
}
case C_TUNNEL: add_type(p, C_TUNNEL, id,
(char *) &tunnel[id], sizeof(tunnelt));
case C_TUNNEL:
add_type(p, C_TUNNEL, id, (uint8_t *) &tunnel[id], sizeof(tunnelt));
break;
default:
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()
{
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;
char *p = buff;
uint8_t *p = buff;
if (!config->cluster_iam_master) // Only the master does this.
return;
@ -820,7 +820,7 @@ void cluster_heartbeat()
h.timeout = config->cluster_hb_timeout;
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) {
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
// 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;
@ -1238,6 +1238,9 @@ struct oldsession {
uint32_t tx_connect_speed;
uint32_t rx_connect_speed;
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;
uint16_t snoop_port;
uint16_t sid;
@ -1257,7 +1260,6 @@ static uint8_t *convert_session(struct oldsession *old)
new.far = old->far;
new.tunnel = old->tunnel;
new.l2tp_flags = old->l2tp_flags;
new.flags = old->flags;
new.ip = old->ip;
new.ip_pool_index = old->ip_pool_index;
new.unique_id = old->unique_id;
@ -1297,6 +1299,21 @@ static uint8_t *convert_session(struct oldsession *old)
for (i = 0; i < MAXROUTE; 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;
}
@ -1572,10 +1589,10 @@ shortpacket:
// We got a packet on the cluster port!
// 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;
char *p = data;
uint8_t *p = data;
int s = size;
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 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...
count = *src++; --ssize; // get the count byte from the source.

View file

@ -1,5 +1,5 @@
// 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__
#define __CLUSTER_H__
@ -72,13 +72,13 @@ typedef struct {
} pingt;
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_tunnel(int tid);
int master_forward_packet(char *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_throttle_packet(int tid, char *data, int size);
int master_garden_packet(sessionidt s, char *data, int size);
int master_forward_packet(uint8_t *data, int size, in_addr_t addr, int port);
int master_forward_dae_packet(uint8_t *data, int size, in_addr_t addr, int port);
int master_throttle_packet(int tid, uint8_t *data, int size);
int master_garden_packet(sessionidt s, uint8_t *data, int size);
void master_update_counts(void);
void cluster_send_ping(time_t basetime);
void cluster_heartbeat(void);

View file

@ -1,6 +1,6 @@
// 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 "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; \
}
CONSTANT(lcp_type,
CONSTANT(l2tp_code,
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
"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
)
CONSTANT(avp_name,
CONSTANT(l2tp_avp_name,
"Message Type", // 0
"Result Code", // 1
"Protocol Version", // 2
@ -74,7 +82,7 @@ CONSTANT(avp_name,
"Sequencing Required" // 39
)
CONSTANT(stopccn_result_code,
CONSTANT(l2tp_stopccn_result_code,
0, // 0
"General request to clear control connection", // 1
"General error--Error Code indicates the problem", // 2
@ -87,7 +95,7 @@ CONSTANT(stopccn_result_code,
"Finite State Machine error" // 7
)
CONSTANT(cdn_result_code,
CONSTANT(l2tp_cdn_result_code,
0, // 0
"Call disconnected due to loss of carrier", // 1
"Call disconnected for the reason indicated in"
@ -107,7 +115,7 @@ CONSTANT(cdn_result_code,
" detected" // 11
)
CONSTANT(error_code,
CONSTANT(l2tp_error_code,
"No general error", // 0
"No control connection exists yet for this LAC-LNS"
" pair", // 1
@ -124,7 +132,28 @@ CONSTANT(error_code,
" 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
"Textual username/password exchange", // 1
"PPP CHAP", // 2
@ -133,7 +162,7 @@ CONSTANT(auth_type,
"Microsoft CHAP Version 1 (MSCHAPv1)" // 5
)
CONSTANT(ppp_lcp_type,
CONSTANT(ppp_code,
0, // 0
"ConfigReq", // 1
"ConfigAck", // 2
@ -149,15 +178,26 @@ CONSTANT(ppp_lcp_type,
"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,
"RADIUSNULL", // 0
"RADIUSCHAP", // 1
"RADIUSAUTH", // 2
"RADIUSIPCP", // 3
"RADIUSSTART", // 4
"RADIUSSTOP", // 5
"RADIUSINTERIM", // 6
"RADIUSWAIT" // 7
"RADIUSSTART", // 3
"RADIUSSTOP", // 4
"RADIUSINTERIM", // 5
"RADIUSWAIT" // 6
)
CONSTANT(radius_code,
@ -185,23 +225,3 @@ CONSTANT(radius_code,
"CoA-ACK", // 44
"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__
#define __CONSTANTS_H__
char const *lcp_type(int type);
char const *avp_name(int avp);
char const *stopccn_result_code(int code);
char const *cdn_result_code(int code);
char const *error_code(int code);
char const *auth_type(int type);
char const *ppp_lcp_type(int type);
char const *l2tp_code(int type);
char const *l2tp_avp_name(int avp);
char const *l2tp_stopccn_result_code(int code);
char const *l2tp_cdn_result_code(int code);
char const *l2tp_error_code(int code);
char const *ppp_phase(int code);
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_code(int code);
char const *l2tp_message_type(int type);
#endif /* __CONSTANTS_H__ */

View file

@ -1,12 +1,12 @@
// 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 "l2tpns.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_args arg;
@ -62,7 +62,7 @@ int pack_control(char *data, int len, uint8_t type, int argc, char *argv[])
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;
char *p = pkt.argv;

View file

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

14
icmp.c
View file

@ -1,6 +1,6 @@
// 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 <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"
static uint16_t _checksum(unsigned char *addr, int count);
static uint16_t _checksum(uint8_t *addr, int count);
struct ipv6_pseudo_hdr {
struct in6_addr src;
@ -28,7 +28,7 @@ struct ipv6_pseudo_hdr {
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};
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->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);
}
static uint16_t _checksum(unsigned char *addr, int count)
static uint16_t _checksum(uint8_t *addr, int count)
{
register long sum = 0;

389
l2tpns.c
View file

@ -4,7 +4,7 @@
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
// vim: sw=8 ts=8
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.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 <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 <sched.h>
#include <sys/sysinfo.h>
#include <openssl/md5.h>
#include <libcli.h>
#include "md5.h"
#include "l2tpns.h"
#include "cluster.h"
#include "plugin.h"
@ -105,6 +105,9 @@ config_descriptt config_values[] = {
CONFIG("pid_file", pid_file, STRING),
CONFIG("random_device", random_device, 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("secondary_dns", default_dns2, 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 shutdown_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 read_config_file(void);
static void initplugins(void);
@ -258,10 +261,10 @@ void _log(int level, sessionidt s, tunnelidt t, const char *format, ...)
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;
const uint8_t *d = (const uint8_t *) data;
const uint8_t *d = data;
if (config->debug < level) return;
@ -551,7 +554,7 @@ static void inittun(void)
tunidx = ifr.ifr_ifindex;
// 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);
// Link local address is FE80::1
@ -702,8 +705,11 @@ sessionidt sessionbyipv6(struct in6_addr ip)
CSTAT(sessionbyipv6);
if (!memcmp(&config->ipv6_prefix, &ip, 8) ||
(ip.s6_addr[0] == 0xFE && ip.s6_addr[1] == 0x80 &&
(ip.s6_addr16[1] == ip.s6_addr16[2] == ip.s6_addr16[3] == 0))) {
(ip.s6_addr[0] == 0xFE &&
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]);
} else {
s = lookup_ipv6map(ip);
@ -973,14 +979,14 @@ int tun_write(uint8_t * data, int size)
// process outgoing (to tunnel) IP
//
static void processipout(uint8_t * buf, int len)
static void processipout(uint8_t *buf, int len)
{
sessionidt s;
sessiont *sp;
tunnelidt t;
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;
uint8_t b[MAXETHER + 20];
@ -1126,7 +1132,7 @@ static void processipv6out(uint8_t * buf, int len)
in_addr_t ip;
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;
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
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 *) (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)
{
// RADIUS Stop message
uint16_t r = sess_local[s].radius;
if (!r)
r = radiusnew(s);
uint16_t r = radiusnew(s);
if (r)
{
// stop, if not already trying
@ -1534,7 +1537,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
free_ip_address(s);
// 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);
}
@ -1546,7 +1549,7 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
controlt *c = controlnew(14); // sending CDN
if (error)
{
char buf[4];
uint8_t buf[4];
*(uint16_t *) buf = htons(result);
*(uint16_t *) (buf+2) = htons(error);
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_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);
}
void sendipcp(tunnelidt t, sessionidt s)
{
uint8_t buf[MAXCONTROL];
uint16_t r = sess_local[s].radius;
uint8_t *q;
CSTAT(sendipcp);
if (!r)
r = radiusnew(s);
if (!r)
if (!session[s].unique_id)
{
sessionshutdown(s, "No free RADIUS sessions for IPCP", 3, 0);
return;
}
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;
if (!++last_id) ++last_id; // skip zero
session[s].unique_id = last_id;
}
q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPCP);
if (!q) return;
*q = ConfigReq;
q[1] = r >> RADIUS_SHIFT; // ID, dont care, we only send one type of request
*(uint16_t *) (q + 2) = htons(10);
q[4] = 3;
q[5] = 6;
q[1] = session[s].unique_id & 0xf; // ID, dont care, we only send one type of request
*(uint16_t *) (q + 2) = htons(10); // packet length
q[4] = 3; // ip address option
q[5] = 6; // option length
*(in_addr_t *) (q + 6) = config->peer_address ? config->peer_address :
config->bind_address ? config->bind_address :
my_address; // send my IP
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
// try to negotiate an IPv6 session as well. Unless we've had a
// (N)ACK for IPV6CP.
if (config->ipv6_prefix.s6_addr[0] > 0 &&
!(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;
void sendipv6cp(tunnelidt t, sessionidt s)
{
uint8_t buf[MAXCONTROL];
uint8_t *q;
*q = ConfigReq;
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;
CSTAT(sendipv6cp);
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)
@ -1742,7 +1733,7 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha
controlt *c = controlnew(4); // sending StopCCN
if (error)
{
char buf[64];
uint8_t buf[64];
int l = 4;
*(uint16_t *) buf = htons(result);
*(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)
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;
uint8_t *p = buf + 2;
@ -2061,7 +2052,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
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" : "");
switch (mtype)
@ -2069,7 +2060,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
case 0: // message type
message = ntohs(*(uint16_t *) b);
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;
case 1: // result code
{
@ -2077,18 +2068,18 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
const char* resdesc = "(unknown)";
if (message == 4)
{ /* StopCCN */
resdesc = stopccn_result_code(rescode);
resdesc = l2tp_stopccn_result_code(rescode);
}
else if (message == 14)
{ /* CDN */
resdesc = cdn_result_code(rescode);
resdesc = l2tp_cdn_result_code(rescode);
}
LOG(4, s, t, " Result Code %d: %s\n", rescode, resdesc);
if (n >= 4)
{
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)
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
{
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)
authtype = AUTHCHAP;
else if (atype == 3)
@ -2351,7 +2342,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
case 10: // ICRQ
if (sessionfree && main_quit != QUIT_SHUTDOWN)
{
uint16_t r;
controlt *c = controlnew(11); // ICRP
s = sessionfree;
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)
config->cluster_highest_sessionid = s;
// make a RADIUS session
if ((r = radiusnew(s)))
{
controlt *c = controlnew(11); // sending ICRP
session[s].opened = time_now;
session[s].tunnel = t;
session[s].far = asession;
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
session[s].opened = time_now;
session[s].tunnel = t;
session[s].far = asession;
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].calling, calling, sizeof(session[s].calling) - 1);
STAT(session_created);
break;
}
strncpy(session[s].called, called, sizeof(session[s].called) - 1);
strncpy(session[s].calling, calling, sizeof(session[s].calling) - 1);
session[s].ppp.phase = Establish;
session[s].ppp.lcp = Starting;
LOG(1, s, t, "No free RADIUS sessions for ICRQ\n");
sessionclear(s);
}
else
{
STAT(session_overflow);
LOG(1, 0, t, "No free sessions\n");
STAT(session_created);
break;
}
{
controlt *c = controlnew(14); // CDN
if (main_quit == QUIT_SHUTDOWN)
control16(c, 1, 2, 7); // try another
else
if (!sessionfree)
{
STAT(session_overflow);
LOG(1, 0, t, "No free sessions\n");
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
}
@ -2408,12 +2392,19 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
session[s].l2tp_flags = aflags; // set flags received
LOG(3, s, t, "Magic %X Flags %X\n", amagic, aflags);
controlnull(t); // ack
// proxy authentication type is not supported
if (!(config->radius_authtypes & authtype))
authtype = config->radius_authprefer;
// start LCP
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;
case 14: // CDN
controlnull(t); // ack
@ -2507,16 +2498,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
}
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; }
processipv6cp(t, s, p, l);
}
else
{
LOG(1, s, t, "IPv6 not configured; ignoring IPv6CP\n");
}
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; }
processipv6cp(t, s, p, l);
}
else if (prot == PPPCCP)
{
@ -2543,7 +2527,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
}
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");
return;
@ -2592,7 +2576,7 @@ static void processtun(uint8_t * buf, int len)
if (*(uint16_t *) (buf + 2) == htons(PKTIP)) // IPv4
processipout(buf, len);
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);
// Else discard.
@ -2734,13 +2718,123 @@ static void regular_cleanups(double period)
continue;
}
if (session[s].ip && !(session[s].flags & SF_IPCP_ACKED)
&& !(sess_local[s].radius && radius[sess_local[s].radius].state == RADIUSIPCP))
// PPP timeouts
if (sess_local[s].lcp.restart >= time_now)
{
// IPCP has not completed yet. Resend
LOG(3, s, session[s].tunnel, "No ACK for initial IPCP ConfigReq... resending\n");
sendipcp(session[s].tunnel, s);
s_actions++;
int next_state = session[s].ppp.lcp;
switch (session[s].ppp.lcp)
{
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
@ -2753,7 +2847,7 @@ static void regular_cleanups(double period)
}
// 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};
@ -3084,7 +3178,8 @@ static void mainloop(void)
if (n)
{
struct sockaddr_in addr;
int alen, c, s;
socklen_t alen;
int c, s;
int udp_ready = 0;
int tun_ready = 0;
int cluster_ready = 0;
@ -3391,6 +3486,9 @@ static void initdata(int optdebug, char *optconfig)
config->num_tbfs = MAXTBFS;
config->rl_rate = 28; // 28kbps
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);
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);
}
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};
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;
*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");
*challenge_response = (char *)calloc(17, 1);
*challenge_response = calloc(17, 1);
MD5Init(&ctx);
MD5Update(&ctx, &id, 1);
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5Update(&ctx, challenge, challenge_length);
MD5Final(*challenge_response, &ctx);
MD5_Init(&ctx);
MD5_Update(&ctx, &id, 1);
MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5_Update(&ctx, challenge, challenge_length);
MD5_Final(*challenge_response, &ctx);
return;
}
@ -4384,13 +4482,8 @@ int sessionsetup(tunnelidt t, sessionidt s)
cache_ipmap(session[s].ip, s);
}
if (!session[s].unique_id)
{
// 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;
}
sess_local[s].lcp_authtype = 0; // RADIUS authentication complete
lcp_open(t, s); // transition to Network phase and send initial IPCP
// Run the plugin's against this new session.
{
@ -4499,7 +4592,7 @@ int load_session(sessionidt s, sessiont *new)
}
// 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);
// check filters
@ -4716,7 +4809,7 @@ static void plugins_done()
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 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);
// Compute initial pad
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char *) &m, 2);
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5Update(&ctx, vector, vec_len);
MD5Final(digest, &ctx);
MD5_Init(&ctx);
MD5_Update(&ctx, (unsigned char *) &m, 2);
MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5_Update(&ctx, vector, vec_len);
MD5_Final(digest, &ctx);
// pointer to last decoded 16 octets
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
if (d >= sizeof(digest))
{
MD5Init(&ctx);
MD5Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5Update(&ctx, last, sizeof(digest));
MD5Final(digest, &ctx);
MD5_Init(&ctx);
MD5_Update(&ctx, config->l2tpsecret, strlen(config->l2tpsecret));
MD5_Update(&ctx, last, sizeof(digest));
MD5_Final(digest, &ctx);
d = 0;
last = value;

112
l2tpns.h
View file

@ -1,5 +1,5 @@
// 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__
#define __L2TPNS_H__
@ -72,14 +72,14 @@
#define CONFIGFILE FLASHDIR "/startup-config" // Configuration file
#define CLIUSERS FLASHDIR "/users" // CLI Users file
#define IPPOOLFILE FLASHDIR "/ip_pool" // Address pool configuration
#define ACCT_TIME 3000 // 5 minute accounting interval
#define ACCT_SHUT_TIME 600 // 1 minute for counters of shutdown sessions
#define L2TPPORT 1701 // L2TP port
#define RADPORT 1645 // old radius port...
#define DAEPORT 3799 // DAE port
#define PKTARP 0x0806 // ARP packet type
#define PKTIP 0x0800 // IPv4 packet type
#define PKTIPV6 0x86DD // IPv6 packet type
#define ACCT_TIME 3000 // 5 minute accounting interval
#define ACCT_SHUT_TIME 600 // 1 minute for counters of shutdown sessions
#define L2TPPORT 1701 // L2TP port
#define RADPORT 1645 // old radius port...
#define DAEPORT 3799 // DAE port
#define PKTARP 0x0806 // ARP packet type
#define PKTIP 0x0800 // IPv4 packet type
#define PKTIPV6 0x86DD // IPv6 packet type
#define PPPPAP 0xC023
#define PPPCHAP 0xC223
#define PPPLCP 0xC021
@ -121,6 +121,52 @@ enum {
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
typedef uint16_t sessionidt;
typedef uint16_t tunnelidt;
@ -174,7 +220,14 @@ typedef struct
sessionidt far; // far end session ID
tunnelidt tunnel; // near end tunnel ID
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).
int ip_pool_index; // index to IP pool
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_out; // filter bucket for throttling out to the user.
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 called[MAXTEL]; // called number
char calling[MAXTEL]; // calling number
@ -209,17 +262,10 @@ typedef struct
uint8_t walled_garden; // is this session gardened?
uint8_t ipv6prefixlen; // IPv6 route prefix length
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;
#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 AUTHCHAP 2 // allow CHAP
@ -233,6 +279,16 @@ typedef struct
uint32_t cin;
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
clockt last_packet_out;
uint32_t packets_out;
@ -271,13 +327,12 @@ typedef struct
}
tunnelt;
// 180 bytes per radius session
// 160 bytes per radius session
typedef struct // outstanding RADIUS requests
{
sessionidt session; // which session this applies to
hasht auth; // request authenticator
clockt retry; // when to try next
char calling[MAXTEL]; // calling number
char pass[129]; // password
uint8_t id; // ID for PPP response
uint8_t try; // which try we are on
@ -328,7 +383,6 @@ enum
RADIUSNULL, // Not in use
RADIUSCHAP, // sending CHAP down PPP
RADIUSAUTH, // sending auth to RADIUS server
RADIUSIPCP, // sending IPCP to end user
RADIUSSTART, // sending start accounting to RADIUS server
RADIUSSTOP, // sending stop accounting to RADIUS server
RADIUSINTERIM, // sending interim accounting to RADIUS server
@ -391,6 +445,7 @@ struct Tstats
uint32_t call_sessionbyuser;
uint32_t call_sendarp;
uint32_t call_sendipcp;
uint32_t call_sendipv6cp;
uint32_t call_processipv6cp;
uint32_t call_tunnelsend;
uint32_t call_sessionkill;
@ -457,6 +512,10 @@ typedef struct
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];
int radius_accounting;
int radius_interim;
@ -601,6 +660,7 @@ void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip);
// ppp.c
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 lcp_open(tunnelidt t, sessionidt s);
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 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);
void sendlcp(tunnelidt t, sessionidt s, int authtype);
void send_ipin(sessionidt s, uint8_t *buf, int len);
void sendccp(tunnelidt t, sessionidt s);
// 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 tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
void sendipcp(tunnelidt t, sessionidt s);
void sendipv6cp(tunnelidt t, sessionidt s);
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 ip_filter(uint8_t *buf, int len, uint8_t filter);
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); })
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 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
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;

View file

@ -8,8 +8,8 @@ Source: http://optusnet.dl.sourceforge.net/sourceforge/l2tpns/l2tpns-%{version}.
URL: http://sourceforge.net/projects/l2tpns
BuildRoot: %{_tmppath}/%{name}-%{version}-root
Prereq: /sbin/chkconfig
BuildRequires: libcli >= 1.8.5
Requires: libcli >= 1.8.5
BuildRequires: libcli >= 1.8.5, openssl-devel
Requires: libcli >= 1.8.5, openssl
%description
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]/*
%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

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);
struct hostent *h = gethostbyname(host);
int fd;
char buf[NSCTL_MAX_PKT_SZ];
uint8_t buf[NSCTL_MAX_PKT_SZ];
int sz;
char *err;

View file

@ -28,7 +28,7 @@ enum
struct pluginfuncs
{
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);
sessionidt (*get_session_by_username)(char *username);
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
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 <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 <netinet/in.h>
#include <errno.h>
#include "md5.h"
#include <openssl/md5.h>
#include "constants.h"
#include "l2tpns.h"
#include "plugin.h"
@ -182,7 +182,7 @@ void radiussend(uint16_t r, uint8_t state)
{
*p = 1; // user name
p[1] = strlen(session[s].user) + 2;
strcpy(p + 2, session[s].user);
strcpy((char *) p + 2, session[s].user);
p += p[1];
}
if (state == RADIUSAUTH)
@ -212,13 +212,13 @@ void radiussend(uint16_t r, uint8_t state)
while (p < pl)
{
MD5_CTX ctx;
MD5Init(&ctx);
MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret));
MD5_Init(&ctx);
MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret));
if (p)
MD5Update(&ctx, pass + p - 16, 16);
MD5_Update(&ctx, pass + p - 16, 16);
else
MD5Update(&ctx, radius[r].auth, 16);
MD5Final(hash, &ctx);
MD5_Update(&ctx, radius[r].auth, 16);
MD5_Final(hash, &ctx);
do
{
pass[p] ^= hash[p & 15];
@ -244,7 +244,7 @@ void radiussend(uint16_t r, uint8_t state)
{
*p = 44; // session ID
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];
if (state == RADIUSSTART)
{ // start
@ -299,7 +299,7 @@ void radiussend(uint16_t r, uint8_t state)
*p = 26; // vendor-specific
*(uint32_t *) (p + 2) = htonl(9); // Cisco
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);
p[1] = p[7] + 6;
@ -325,21 +325,14 @@ void radiussend(uint16_t r, uint8_t state)
{
*p = 30; // called
p[1] = strlen(session[s].called) + 2;
strcpy(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);
strcpy((char *) p + 2, session[s].called);
p += p[1];
}
else if (*session[s].calling)
{
*p = 31; // calling
p[1] = strlen(session[s].calling) + 2;
strcpy(p + 2, session[s].calling);
strcpy((char *) p + 2, session[s].calling);
p += p[1];
}
// NAS-IP-Address
@ -353,15 +346,15 @@ void radiussend(uint16_t r, uint8_t state)
if (state != RADIUSAUTH)
{
// Build auth for accounting packet
char z[16] = {0};
char hash[16] = {0};
uint8_t z[16] = {0};
uint8_t hash[16] = {0};
MD5_CTX ctx;
MD5Init(&ctx);
MD5Update(&ctx, b, 4);
MD5Update(&ctx, z, 16);
MD5Update(&ctx, b + 20, (p - b) - 20);
MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret));
MD5Final(hash, &ctx);
MD5_Init(&ctx);
MD5_Update(&ctx, b, 4);
MD5_Update(&ctx, z, 16);
MD5_Update(&ctx, b + 20, (p - b) - 20);
MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret));
MD5_Final(hash, &ctx);
memcpy(b + 4, 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)
{
char *key = avp;
char *value = memchr(avp, '=', len);
char tmp[2048] = "";
uint8_t *key = avp;
uint8_t *value = memchr(avp, '=', len);
uint8_t tmp[2048] = "";
if (value)
{
@ -415,7 +408,7 @@ static void handle_avpair(sessionidt s, uint8_t *avp, int len)
// 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);
}
}
@ -463,12 +456,12 @@ void processrad(uint8_t *buf, int len, char socket_index)
return;
}
t = session[s].tunnel;
MD5Init(&ctx);
MD5Update(&ctx, buf, 4);
MD5Update(&ctx, radius[r].auth, 16);
MD5Update(&ctx, buf + 20, len - 20);
MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret));
MD5Final(hash, &ctx);
MD5_Init(&ctx);
MD5_Update(&ctx, buf, 4);
MD5_Update(&ctx, radius[r].auth, 16);
MD5_Update(&ctx, buf + 20, len - 20);
MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret));
MD5_Final(hash, &ctx);
do {
if (memcmp(hash, buf + 4, 16))
{
@ -617,7 +610,7 @@ void processrad(uint8_t *buf, int len, char socket_index)
else if (*p == 11)
{
// Filter-Id
char *filter = p + 2;
char *filter = (char *) p + 2;
int l = p[1] - 2;
char *suffix;
int f;
@ -680,10 +673,10 @@ void processrad(uint8_t *buf, int len, char socket_index)
int prefixlen;
uint8_t *n = p + 2;
uint8_t *e = p + p[1];
uint8_t *m = strchr(n, '/');
uint8_t *m = memchr(n, '/', e - p);
*m++ = 0;
inet_pton(AF_INET6, n, &r6);
inet_pton(AF_INET6, (char *) n, &r6);
prefixlen = 0;
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)
{
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));
}
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));
}
@ -750,20 +743,11 @@ void radiusretry(uint16_t r)
case RADIUSCHAP: // sending CHAP down PPP
sendchap(t, s);
break;
case RADIUSIPCP:
sendipcp(t, s); // send IPCP
break;
case RADIUSAUTH: // sending auth to RADIUS server
radiussend(r, RADIUSAUTH);
break;
case RADIUSSTART: // sending start accounting to RADIUS server
radiussend(r, RADIUSSTART);
break;
case RADIUSSTOP: // sending stop accounting to RADIUS server
radiussend(r, RADIUSSTOP);
break;
case RADIUSINTERIM: // sending interim accounting to RADIUS server
radiussend(r, RADIUSINTERIM);
radiussend(r, radius[r].state);
break;
default:
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);
if (i > 16) i = 16;
MD5Init(&ctx);
MD5Update(&ctx, buf, len);
MD5Update(&ctx, buf, config->radiussecret, i);
MD5Final(hash, &ctx);
MD5_Init(&ctx);
MD5_Update(&ctx, buf, len);
MD5_Update(&ctx, config->radiussecret, i);
MD5_Final(hash, &ctx);
if (memcmp(hash, vector, 16) != 0)
{
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;
i = find_filter(packet, len);
i = find_filter((char *) packet, len);
if (i < 0 || !*ip_filters[i].name)
{
error = 404;
@ -1063,10 +1047,10 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
i = strlen(config->radiussecret);
if (i > 16) i = 16;
MD5Init(&ctx);
MD5Update(&ctx, buf, len);
MD5Update(&ctx, config->radiussecret, i);
MD5Final(hash, &ctx);
MD5_Init(&ctx);
MD5_Update(&ctx, buf, len);
MD5_Update(&ctx, config->radiussecret, i);
MD5_Final(hash, &ctx);
memcpy(buf + 4, hash, 16);
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
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 "l2tpns.h"
@ -159,10 +159,10 @@ void fsck_tbfs(void)
// If we can send it right away, we do. Else we
// 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;
tbft * f;
tbft *f;
if (!filter_list)
return -1;

4
tbf.h
View file

@ -30,12 +30,12 @@ typedef struct {
uint32_t p_delayed; // Total packets not sent immediately.
int sizes[TBF_MAX_QUEUE];
char packets[TBF_MAX_QUEUE][TBF_MAX_SIZE];
uint8_t packets[TBF_MAX_QUEUE][TBF_MAX_SIZE];
} tbft;
void init_tbf(int num_tbfs);
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 free_tbf(int tid);
void fsck_tbfs(void);

View file

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