// 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.168 2006/06/22 15:30:29 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.171 2006/08/02 13:35:39 bodea Exp $";
#include <arpa/inet.h>
#include <assert.h>
struct cli_session_actions *cli_session_actions = NULL; // Pending session changes requested by CLI
struct cli_tunnel_actions *cli_tunnel_actions = NULL; // Pending tunnel changes required by CLI
-static void *ip_hash[256]; // Mapping from IP address to session structures.
+union iphash {
+ sessionidt sess;
+ union iphash *idx;
+} ip_hash[256]; // Mapping from IP address to session structures.
+
struct ipv6radix {
- int sess;
+ sessionidt sess;
struct ipv6radix *branch;
} ipv6_hash[256]; // Mapping from IPv6 address to session structures.
CONFIG("radius_secret", radiussecret, STRING),
CONFIG("radius_authtypes", radius_authtypes_s, STRING),
CONFIG("radius_dae_port", radius_dae_port, SHORT),
+ CONFIG("radius_bind_min", radius_bind_min, SHORT),
+ CONFIG("radius_bind_max", radius_bind_max, SHORT),
CONFIG("allow_duplicate_users", allow_duplicate_users, BOOL),
CONFIG("guest_account", guest_user, STRING),
CONFIG("bind_address", bind_address, IPv4),
struct Tringbuffer *ringbuffer = NULL;
#endif
-static void cache_ipmap(in_addr_t ip, int s);
+static void cache_ipmap(in_addr_t ip, sessionidt s);
static void uncache_ipmap(in_addr_t ip);
-static void cache_ipv6map(struct in6_addr ip, int prefixlen, int s);
+static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s);
static void free_ip_address(sessionidt s);
static void dump_acct_info(int all);
static void sighup_handler(int sig);
int flags = fcntl(udpfd, F_GETFL, 0);
fcntl(udpfd, F_SETFL, flags | O_NONBLOCK);
}
- if (bind(udpfd, (void *) &addr, sizeof(addr)) < 0)
+ if (bind(udpfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
LOG(0, 0, 0, "Error in UDP bind: %s\n", strerror(errno));
exit(1);
controlfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt(controlfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
setsockopt(controlfd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); // recvfromto
- if (bind(controlfd, (void *) &addr, sizeof(addr)) < 0)
+ if (bind(controlfd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
LOG(0, 0, 0, "Error in control bind: %s\n", strerror(errno));
exit(1);
daefd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt(daefd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
setsockopt(daefd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); // recvfromto
- if (bind(daefd, (void *) &addr, sizeof(addr)) < 0)
+ if (bind(daefd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
{
LOG(0, 0, 0, "Error in DAE bind: %s\n", strerror(errno));
exit(1);
// IP address.
//
-static int lookup_ipmap(in_addr_t ip)
+static sessionidt lookup_ipmap(in_addr_t ip)
{
uint8_t *a = (uint8_t *) &ip;
- uint8_t **d = (uint8_t **) ip_hash;
+ union iphash *h = ip_hash;
- if (!(d = (uint8_t **) d[(size_t) *a++])) return 0;
- if (!(d = (uint8_t **) d[(size_t) *a++])) return 0;
- if (!(d = (uint8_t **) d[(size_t) *a++])) return 0;
+ if (!(h = h[*a++].idx)) return 0;
+ if (!(h = h[*a++].idx)) return 0;
+ if (!(h = h[*a++].idx)) return 0;
- return (int) (intptr_t) d[(size_t) *a];
+ return h[*a].sess;
}
-static int lookup_ipv6map(struct in6_addr ip)
+static sessionidt lookup_ipv6map(struct in6_addr ip)
{
struct ipv6radix *curnode;
int i;
sessionidt sessionbyip(in_addr_t ip)
{
- int s = lookup_ipmap(ip);
+ sessionidt s = lookup_ipmap(ip);
CSTAT(sessionbyip);
if (s > 0 && s < MAXSESSION && session[s].opened)
- return (sessionidt) s;
+ return s;
return 0;
}
sessionidt sessionbyipv6(struct in6_addr ip)
{
- int s;
+ sessionidt s;
CSTAT(sessionbyipv6);
if (!memcmp(&config->ipv6_prefix, &ip, 8) ||
//
// (It's actually cached in network order)
//
-static void cache_ipmap(in_addr_t ip, int s)
+static void cache_ipmap(in_addr_t ip, sessionidt s)
{
in_addr_t nip = htonl(ip); // MUST be in network order. I.e. MSB must in be ((char *) (&ip))[0]
uint8_t *a = (uint8_t *) &nip;
- uint8_t **d = (uint8_t **) ip_hash;
+ union iphash *h = ip_hash;
int i;
for (i = 0; i < 3; i++)
{
- if (!d[(size_t) a[i]])
- {
- if (!(d[(size_t) a[i]] = calloc(256, sizeof(void *))))
- return;
- }
+ if (!(h[a[i]].idx || (h[a[i]].idx = calloc(256, sizeof(union iphash)))))
+ return;
- d = (uint8_t **) d[(size_t) a[i]];
+ h = h[a[i]].idx;
}
- d[(size_t) a[3]] = (uint8_t *) (intptr_t) s;
+ h[a[3]].sess = s;
if (s > 0)
LOG(4, s, session[s].tunnel, "Caching ip address %s\n", fmtaddr(nip, 0));
cache_ipmap(ip, 0); // Assign it to the NULL session.
}
-static void cache_ipv6map(struct in6_addr ip, int prefixlen, int s)
+static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s)
{
int i;
int bytes;
//
int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc)
{
- char **d = (char **) ip_hash, **e, **f, **g;
+ union iphash *d = ip_hash, *e, *f, *g;
int i, j, k, l;
int count = 0;
for (i = 0; i < 256; ++i)
{
- if (!d[i])
+ if (!d[i].idx)
continue;
- e = (char **) d[i];
+
+ e = d[i].idx;
for (j = 0; j < 256; ++j)
{
- if (!e[j])
+ if (!e[j].idx)
continue;
- f = (char **) e[j];
+
+ f = e[j].idx;
for (k = 0; k < 256; ++k)
{
- if (!f[k])
+ if (!f[k].idx)
continue;
- g = (char **)f[k];
+
+ g = f[k].idx;
for (l = 0; l < 256; ++l)
{
- if (!g[l])
+ if (!g[l].sess)
continue;
- cli_print(cli, "%7d %d.%d.%d.%d", (int) (intptr_t) g[l], i, j, k, l);
+
+ cli_print(cli, "%7d %d.%d.%d.%d", g[l].sess, i, j, k, l);
++count;
}
}
continue;
}
- // check for timed out sessions
- if (session[s].timeout)
- {
- bundleidt bid = session[s].bundle;
- if (bid)
- {
- clockt curr_time = time_now;
- if (curr_time - bundle[bid].last_check >= 1)
- {
- bundle[bid].online_time += (curr_time-bundle[bid].last_check)*bundle[bid].num_of_links;
- bundle[bid].last_check = curr_time;
- if (bundle[bid].online_time >= session[s].timeout)
- {
- int ses;
- for (ses = bundle[bid].num_of_links - 1; ses >= 0; ses--)
- {
- sessionshutdown(bundle[bid].members[ses], "Session timeout", CDN_ADMIN_DISC, TERM_SESSION_TIMEOUT);
- s_actions++;
- continue;
- }
- }
- }
- }
- else if (session[s].timeout <= time_now - session[s].opened)
- {
- sessionshutdown(s, "Session timeout", CDN_ADMIN_DISC, TERM_SESSION_TIMEOUT);
- s_actions++;
- continue;
- }
- }
-
// PPP timeouts
if (sess_local[s].lcp.restart <= time_now)
{
}
// Drop sessions who have reached session_timeout seconds
- if (session[s].session_timeout && (time_now - session[s].opened >= session[s].session_timeout))
+ if (session[s].session_timeout)
{
- sessionshutdown(s, "Session Timeout Reached", CDN_ADMIN_DISC, TERM_SESSION_TIMEOUT);
- STAT(session_timeout);
- s_actions++;
- continue;
+ bundleidt bid = session[s].bundle;
+ if (bid)
+ {
+ if (time_now - bundle[bid].last_check >= 1)
+ {
+ bundle[bid].online_time += (time_now - bundle[bid].last_check) * bundle[bid].num_of_links;
+ bundle[bid].last_check = time_now;
+ if (bundle[bid].online_time >= session[s].session_timeout)
+ {
+ int ses;
+ for (ses = bundle[bid].num_of_links - 1; ses >= 0; ses--)
+ {
+ sessionshutdown(bundle[bid].members[ses], "Session timeout", CDN_ADMIN_DISC, TERM_SESSION_TIMEOUT);
+ s_actions++;
+ continue;
+ }
+ }
+ }
+ }
+ else if (time_now - session[s].opened >= session[s].session_timeout)
+ {
+ sessionshutdown(s, "Session timeout", CDN_ADMIN_DISC, TERM_SESSION_TIMEOUT);
+ s_actions++;
+ continue;
+ }
}
// Drop sessions who have reached idle_timeout seconds