// 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.51 2004/11/17 08:23:34 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.56 2004/11/25 02:49:18 bodea Exp $";
#include <arpa/inet.h>
#include <assert.h>
STAT(tunnel_tx_errors);
return;
}
+
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
*(u32 *) & addr.sin_addr = htonl(tunnel[t].ip);
// Add on L2TP header
{
u8 *p = makeppp(b, sizeof(b), buf, len, t, s, PPPIP);
- if (!p)
- {
- LOG(3, session[s].ip, s, t, "failed to send packet in processipout.\n");
- return;
- }
+ if (!p) return;
tunnelsend(b, len + (p-b), t); // send it...
}
// Add on L2TP header
{
u8 *p = makeppp(b, sizeof(b), buf, len, t, s, PPPIP);
- if (!p)
- {
- LOG(3, session[s].ip, s, t, "failed to send packet in send_ipout.\n");
- return;
- }
+ if (!p) return;
tunnelsend(b, len + (p-b), t); // send it...
}
if (session[s].ip)
{ // IP allocated, clear and unroute
int r;
+ int routed = 0;
for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
{
+ if ((session[s].ip & session[s].route[r].mask) ==
+ (session[s].route[r].ip & session[s].route[r].mask))
+ routed++;
+
routeset(s, session[s].route[r].ip, session[s].route[r].mask, 0, 0);
session[s].route[r].ip = 0;
}
if (session[s].ip_pool_index == -1) // static ip
{
- routeset(s, session[s].ip, 0, 0, 0); // Delete route.
+ if (!routed) routeset(s, session[s].ip, 0, 0, 0);
session[s].ip = 0;
}
else
}
q = makeppp(buf,sizeof(buf), 0, 0, t, s, PPPIPCP);
- if (!q)
- {
- LOG(3, session[s].ip, s, t, "failed to send packet in sendipcp.\n");
- return;
- }
+ if (!q) return;
*q = ConfigReq;
q[1] = r << RADIUS_SHIFT; // ID, dont care, we only send one type of request
u8 b[MAXCONTROL] = {0};
u8 *q = makeppp(b, sizeof(b), 0, 0, session[s].tunnel, s, PPPLCP);
- if (!q)
- {
- LOG(3, session[s].ip, s, t, "failed to send ECHO packet.\n");
- continue;
- }
+ if (!q) continue;
*q = EchoReq;
*(u8 *)(q + 1) = (time_now % 255); // ID
}
}
+ {
+ int routed = 0;
+
// Add the route for this session.
- //
- // Static IPs need to be routed. Anything else
- // is part of the IP address pool and is already routed,
- // it just needs to be added to the IP cache.
- if (session[s].ip_pool_index == -1) // static ip
- routeset(s, session[s].ip, 0, 0, 1);
- else
- cache_ipmap(session[s].ip, s);
+ for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
+ {
+ if ((session[s].ip & session[s].route[r].mask) ==
+ (session[s].route[r].ip & session[s].route[r].mask))
+ routed++;
- for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++)
- routeset(s, session[s].route[r].ip, session[s].route[r].mask, 0, 1);
+ routeset(s, session[s].route[r].ip, session[s].route[r].mask, 0, 1);
+ }
+
+ // Static IPs need to be routed if not already
+ // convered by a Framed-Route. Anything else is part
+ // of the IP address pool and is already routed, it
+ // just needs to be added to the IP cache.
+ if (session[s].ip_pool_index == -1) // static ip
+ {
+ if (!routed) routeset(s, session[s].ip, 0, 0, 1);
+ }
+ else
+ cache_ipmap(session[s].ip, s);
+ }
if (!session[s].unique_id)
{
int load_session(sessionidt s, sessiont *new)
{
int i;
+ int newip = 0;
// Sanity checks.
if (new->ip_pool_index >= MAXIPPOOL ||
session[s].tunnel = new->tunnel; // For logging in cache_ipmap
+ // See if routes/ip cache need updating
+ if (new->ip != session[s].ip)
+ newip++;
- if (new->ip != session[s].ip) // Changed ip. fix up hash tables.
+ for (i = 0; !newip && i < MAXROUTE && (session[s].route[i].ip || new->route[i].ip); i++)
+ if (new->route[i].ip != session[s].route[i].ip ||
+ new->route[i].mask != session[s].route[i].mask)
+ newip++;
+
+ // needs update
+ if (newip)
{
- if (session[s].ip) // If there's an old one, remove it.
+ int routed = 0;
+
+ // remove old routes...
+ for (i = 0; i < MAXROUTE && session[s].route[i].ip; i++)
{
- // Remove any routes if the IP has changed
- for (i = 0; i < MAXROUTE && session[s].route[i].ip; i++)
- {
- routeset(s, session[s].route[i].ip, session[s].route[i].mask, 0, 0);
- session[s].route[i].ip = 0;
- }
+ if ((session[s].ip & session[s].route[i].mask) ==
+ (session[s].route[i].ip & session[s].route[i].mask))
+ routed++;
+ routeset(s, session[s].route[i].ip, session[s].route[i].mask, 0, 0);
+ }
+
+ // ...ip
+ if (session[s].ip)
+ {
if (session[s].ip_pool_index == -1) // static IP
- routeset(s, session[s].ip, 0, 0, 0);
+ {
+ if (!routed) routeset(s, session[s].ip, 0, 0, 0);
+ }
else // It's part of the IP pool, remove it manually.
uncache_ipmap(session[s].ip);
}
+ routed = 0;
+
+ // add new routes...
+ for (i = 0; i < MAXROUTE && new->route[i].ip; i++)
+ {
+ if ((new->ip & new->route[i].mask) ==
+ (new->route[i].ip & new->route[i].mask))
+ routed++;
+
+ routeset(s, new->route[i].ip, new->route[i].mask, 0, 1);
+ }
+
+ // ...ip
if (new->ip)
{
// If there's a new one, add it.
if (new->ip_pool_index == -1)
- routeset(s, new->ip, 0, 0, 1);
+ {
+ if (!routed) routeset(s, new->ip, 0, 0, 1);
+ }
else
cache_ipmap(new->ip, s);
}
}
- // Update routed networks
- for (i = 0; i < MAXROUTE && (session[s].route[i].ip || new->route[i].ip); i++)
- {
- if (new->route[i].ip == session[s].route[i].ip &&
- new->route[i].mask == session[s].route[i].mask)
- continue;
-
- if (session[s].route[i].ip) // Remove the old one if it exists.
- routeset(s, session[s].route[i].ip, session[s].route[i].mask, 0, 0);
-
- if (new->route[i].ip) // Add the new one if it exists.
- routeset(s, new->route[i].ip, new->route[i].mask, 0, 1);
- }
-
if (new->tunnel && s > config->cluster_highest_sessionid) // Maintain this in the slave. It's used
// for walking the sessions to forward byte counts to the master.
config->cluster_highest_sessionid = s;
sessionbyuser,
sessiontbysessionidt,
sessionidtbysessiont,
- sessionkill,
radiusnew,
radiussend,
getconfig,
+ sessionkill,
+ throttle_session,
+ cluster_send_session,
};
void *p = open_plugin(plugin_name, 1);
int run_plugins(int plugin_type, void *data)
{
int (*func)(void *data);
- if (!plugins[plugin_type] || plugin_type > max_plugin_functions) return 1;
+
+ if (!plugins[plugin_type] || plugin_type > max_plugin_functions)
+ return PLUGIN_RET_ERROR;
ll_reset(plugins[plugin_type]);
while ((func = ll_next(plugins[plugin_type])))
{
- int rc;
- rc = func(data);
- if (rc == PLUGIN_RET_STOP) return 1;
- if (rc == PLUGIN_RET_ERROR) return 0;
+ int r = func(data);
+
+ if (r != PLUGIN_RET_OK)
+ return r; // stop here
}
- return 1;
+
+ return PLUGIN_RET_OK;
}
static void plugins_done()
case NSCTL_REQ_CONTROL:
{
- struct param_control param = { request.argc, request.argv, 0, NULL };
- if (!run_plugins(PLUGIN_CONTROL, ¶m))
+ struct param_control param = {
+ config->cluster_iam_master,
+ request.argc,
+ request.argv,
+ 0,
+ NULL,
+ };
+
+ int r = run_plugins(PLUGIN_CONTROL, ¶m);
+
+ if (r == PLUGIN_RET_ERROR)
{
response.type = NSCTL_RES_ERR;
response.argc = 1;
? param.additional
: "error returned by plugin";
}
+ else if (r == PLUGIN_RET_NOTMASTER)
+ {
+ static char msg[] = "must be run on master: 000.000.000.000";
+
+ response.type = NSCTL_RES_ERR;
+ response.argc = 1;
+ if (config->cluster_master_address)
+ {
+ strcpy(msg + 23, inet_toa(config->cluster_master_address));
+ response.argv[0] = msg;
+ }
+ else
+ {
+ response.argv[0] = "must be run on master: none elected";
+ }
+ }
else if (!(param.response & NSCTL_RESPONSE))
{
response.type = NSCTL_RES_ERR;