/*
+ * Fernando ALVES 2013
* Add functionality "LAC" to l2tpns.
* Used to forward a ppp session to another "LNS".
+ * GPL licenced
*/
+
#include <errno.h>
#include <string.h>
+#include <sys/socket.h>
+#include <linux/rtnetlink.h>
#include "md5.h"
#include "l2tpns.h"
#include "util.h"
+#include "cluster.h"
#include "l2tplac.h"
+#include "pppoe.h"
/* sequence diagram: Client <--> LAC <--> LNS1 <--> LNS2
*
if (nbtagfound > 0)
{
// random between 0 and nbtagfound-1
- idtag = (nbtagfound*rand()/(RAND_MAX+1.0));
+ idtag = (rand() % nbtagfound);
+
if (idtag >= nbtagfound)
idtag = 0; //Sanity checks.
LOG(1, s, session[s].tunnel, "Error, Bad IP tunnel server endpoint \n");
else if (strlen(ptunnelrlns[idtag].tunnel_assignment_id) <= 0)
LOG(1, s, session[s].tunnel, "Error, No tunnel_assignment_id \n");
+ else if (ptunnelrlns[idtag].tunnel_server_endpoint == ntohl(config->bind_address))
+ LOG(0, s, session[s].tunnel, "Error, IP Remote LNS == IP local bind address (%s) !!!\n", fmtaddr(config->bind_address, 0));
else
+ {
for (idrlns = 1; idrlns < MAXRLNSTUNNEL; ++idrlns)
{
if (pconfigrlns[idrlns].state == CONFRLNSFREE)
{
pconfigrlns[idrlns].ip = ptunnelrlns[idtag].tunnel_server_endpoint;
- pconfigrlns[idrlns].port = L2TPPORT; //Default L2TP poart
+ pconfigrlns[idrlns].port = L2TPPORT; //Default L2TP port
strcpy(pconfigrlns[idrlns].l2tp_secret, ptunnelrlns[idtag].tunnel_password);
strcpy(pconfigrlns[idrlns].tunnel_assignment_id, ptunnelrlns[idtag].tunnel_assignment_id);
if ( (pconfigrlns[idrlns].ip == ptunnelrlns[idtag].tunnel_server_endpoint) &&
(strcmp(pconfigrlns[idrlns].tunnel_assignment_id, ptunnelrlns[idtag].tunnel_assignment_id) == 0) )
{
- LOG(3, s, session[s].tunnel, "Tunnel IP %s already defined\n", fmtaddr(htonl(pconfigrlns[idrlns].ip), 0));
// l2tp_secret may be changed
strcpy(pconfigrlns[idrlns].l2tp_secret, ptunnelrlns[idtag].tunnel_password);
pconfigrlns[idrlns].port = L2TPPORT; //Default L2TP poart
}
}
- if (idrlns >= MAXRLNSTUNNEL)
- {
- LOG(0, s, session[s].tunnel, "No more Remote LNS Conf Free\n");
- return;
+ if (idrlns >= MAXRLNSTUNNEL)
+ {
+ LOG(0, s, session[s].tunnel, "No more Remote LNS Conf Free\n");
+ return;
+ }
}
}
}
tunnel[t].port = pconfigrlns[i_conf].port;
tunnel[t].window = 4; // default window
tunnel[t].isremotelns = i_conf;
+ tunnel[t].indexudp = config->indexlacudpfd;
STAT(tunnel_created);
random_data(pconfigrlns[i_conf].auth, sizeof(pconfigrlns[i_conf].auth));
}
// Forward session to LAC or Remote LNS
-int lac_session_forward(uint8_t *buf, int len, sessionidt sess, uint16_t proto)
+int lac_session_forward(uint8_t *buf, int len, sessionidt sess, uint16_t proto, in_addr_t s_addr, int sin_port, uint16_t indexudpfd)
{
uint16_t t = 0, s = 0;
uint8_t *p = buf + 2; // First word L2TP options
if ((!tunnel[t].isremotelns) && (!tunnel[session[sess].tunnel].isremotelns))
{
- LOG(0, sess, session[sess].tunnel, "Link Tunnel Session (%u) broken\n", s);
+ LOG(0, sess, session[sess].tunnel, "Link Tunnel Session (%u/%u) broken\n", s, t);
return 0;
}
+ if (!config->cluster_iam_master)
+ {
+ if ( (proto == PPPIPCP) || (proto == PPPLCP) ||
+ (proto == PPPPAP) || (proto == PPPCHAP) ||
+ (proto == PPPIPV6CP && config->ipv6_prefix.s6_addr[0]) ||
+ (proto == PPPCCP) )
+ {
+ session[sess].last_packet = time_now;
+ master_forward_packet(buf, len, s_addr, sin_port, indexudpfd);
+ return 1;
+ }
+ }
+
+ if (t == TUNNEL_ID_PPPOE)
+ {
+ pppoe_forwardto_session_pppoe(buf, len, sess, proto);
+ return 1;
+ }
+
if (*buf & 0x40)
{ // length
p += 2;
if (idrlns == 0)
// Show Summary
- sprintf(strout, "%15s %-32s %-32s %11s %7s %10s",
+ sprintf(strout, "%15s %3s %-32s %-32s %11s %7s %10s",
"IP Remote LNS",
+ "TID",
"l2tp secret",
"assignment Id",
"File/Radius",
"Count Sess");
else
{
- tunnelidt t;
+ tunnelidt t, tfound = 0;
sessionidt s;
int countsess = 0;
char state[20];
strcpy(state, "Close");
for (t = 0; t <= config->cluster_highest_tunnelid ; ++t)
{
- if ((tunnel[t].isremotelns) &&
+ if ((tunnel[t].isremotelns == idrlns) &&
(tunnel[t].ip == pconfigrlns[idrlns].ip) &&
(tunnel[t].port == pconfigrlns[idrlns].port) &&
(tunnel[t].state != TUNNELDIE))
{
- if (tunnel[t].isremotelns)
- {
- if (tunnel[t].state == TUNNELOPENING)
- strcpy(state, "Opening");
- else if (tunnel[t].state == TUNNELOPEN)
- strcpy(state, "Open");
-
- for (s = 1; s <= config->cluster_highest_sessionid ; ++s)
- if (session[s].tunnel == t)
- countsess++;
-
- break;
- }
+ if (tunnel[t].state == TUNNELOPENING)
+ strcpy(state, "Opening");
+ else if (tunnel[t].state == TUNNELOPEN)
+ strcpy(state, "Open");
+
+ for (s = 1; s <= config->cluster_highest_sessionid ; ++s)
+ if (session[s].tunnel == t)
+ countsess++;
+ tfound = t;
+ break;
}
}
- sprintf(strout, "%15s %-32s %-32s %11s %7s %10u",
+ sprintf(strout, "%15s %3u %-32s %-32s %11s %7s %10u",
fmtaddr(htonl(pconfigrlns[idrlns].ip), 0),
+ tfound,
pconfigrlns[idrlns].l2tp_secret,
pconfigrlns[idrlns].tunnel_assignment_id,
(pconfigrlns[idrlns].state == CONFRLNSSET?"File":(pconfigrlns[idrlns].state == CONFRLNSSETBYRADIUS?"Radius":"Free")),