- Use multiple radius sockets to allow more concurrent authentication requests
- Add gcc __attribute__ to logging functions - Fix warnings shown by __attribute__ - Make sure regular cleanup happens regularly under high load - Add variable cleanup_interval for changing cleanup interval - Add support for reading more than one packet per fd in each processing loop - This is configurable with the multi_read_count variable - Remove segv handler so core dumps can happen - Use nonblocking sockets - Increase tun queue length - Fix minimum length of IP packets - Remove per-packet plugin hooks (they are slow) - Don't drop session if no free RADIUS - Don't expire more than 1000 sessions per cleanup interval - Remove -a and -c command-line options. They don't work anyway - Don't require file: in log_filename
This commit is contained in:
parent
fa7f80895b
commit
8512f6d924
1 changed files with 185 additions and 153 deletions
300
l2tpns.c
300
l2tpns.c
|
|
@ -49,7 +49,7 @@ int tapfd = -1; // tap interface file handle
|
||||||
int udpfd = -1; // UDP file handle
|
int udpfd = -1; // UDP file handle
|
||||||
int controlfd = -1; // Control signal handle
|
int controlfd = -1; // Control signal handle
|
||||||
int snoopfd = -1; // UDP file handle for sending out intercept data
|
int snoopfd = -1; // UDP file handle for sending out intercept data
|
||||||
int radfd = -1; // RADIUS requests file handle
|
int *radfds = NULL; // RADIUS requests file handles
|
||||||
int ifrfd = -1; // File descriptor for routing, etc
|
int ifrfd = -1; // File descriptor for routing, etc
|
||||||
time_t basetime = 0; // base clock
|
time_t basetime = 0; // base clock
|
||||||
char hostname[1000] = ""; // us.
|
char hostname[1000] = ""; // us.
|
||||||
|
|
@ -62,7 +62,6 @@ FILE *log_stream = NULL;
|
||||||
struct sockaddr_in snoop_addr = {0};
|
struct sockaddr_in snoop_addr = {0};
|
||||||
extern int cluster_sockfd;
|
extern int cluster_sockfd;
|
||||||
unsigned long last_sid = 0;
|
unsigned long last_sid = 0;
|
||||||
int handle_interface = 0;
|
|
||||||
int clifd = 0;
|
int clifd = 0;
|
||||||
sessionidt *cli_session_kill = NULL;
|
sessionidt *cli_session_kill = NULL;
|
||||||
tunnelidt *cli_tunnel_kill = NULL;
|
tunnelidt *cli_tunnel_kill = NULL;
|
||||||
|
|
@ -99,6 +98,8 @@ struct config_descriptt config_values[] = {
|
||||||
CONFIG("accounting_dir", accounting_dir, STRING),
|
CONFIG("accounting_dir", accounting_dir, STRING),
|
||||||
CONFIG("setuid", target_uid, INT),
|
CONFIG("setuid", target_uid, INT),
|
||||||
CONFIG("dump_speed", dump_speed, BOOL),
|
CONFIG("dump_speed", dump_speed, BOOL),
|
||||||
|
CONFIG("cleanup_interval", cleanup_interval, INT),
|
||||||
|
CONFIG("multi_read_count", multi_read_count, INT),
|
||||||
{ NULL, 0, 0, 0 },
|
{ NULL, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -132,7 +133,6 @@ void sighup_handler(int);
|
||||||
void sigterm_handler(int);
|
void sigterm_handler(int);
|
||||||
void sigquit_handler(int);
|
void sigquit_handler(int);
|
||||||
void sigchild_handler(int);
|
void sigchild_handler(int);
|
||||||
void sigsegv_handler(int);
|
|
||||||
void read_config_file();
|
void read_config_file();
|
||||||
void read_state();
|
void read_state();
|
||||||
void dump_state();
|
void dump_state();
|
||||||
|
|
@ -285,6 +285,10 @@ void inittap(void)
|
||||||
log(0, 0, 0, 0, "Can't open %s: %s\n", TAPDEVICE, strerror(errno));
|
log(0, 0, 0, 0, "Can't open %s: %s\n", TAPDEVICE, strerror(errno));
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
int flags = fcntl(tapfd, F_GETFL, 0);
|
||||||
|
fcntl(tapfd, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
}
|
||||||
if (ioctl(tapfd, TUNSETIFF, (void *) &ifr) < 0)
|
if (ioctl(tapfd, TUNSETIFF, (void *) &ifr) < 0)
|
||||||
{
|
{
|
||||||
log(0, 0, 0, 0, "Can't set tap interface: %s\n", strerror(errno));
|
log(0, 0, 0, 0, "Can't set tap interface: %s\n", strerror(errno));
|
||||||
|
|
@ -295,7 +299,7 @@ void inittap(void)
|
||||||
ifrfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
ifrfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||||
|
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
sin.sin_addr.s_addr = handle_interface ? config->bind_address : 0x01010101; // 1.1.1.1
|
sin.sin_addr.s_addr = config->bind_address ? config->bind_address : 0x01010101; // 1.1.1.1
|
||||||
memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));
|
memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));
|
||||||
|
|
||||||
if (ioctl(ifrfd, SIOCSIFADDR, (void *) &ifr) < 0)
|
if (ioctl(ifrfd, SIOCSIFADDR, (void *) &ifr) < 0)
|
||||||
|
|
@ -303,6 +307,13 @@ void inittap(void)
|
||||||
perror("set tap addr");
|
perror("set tap addr");
|
||||||
exit( -1);
|
exit( -1);
|
||||||
}
|
}
|
||||||
|
/* Bump up the qlen to deal with bursts from the network */
|
||||||
|
ifr.ifr_qlen = 1000;
|
||||||
|
if (ioctl(ifrfd, SIOCSIFTXQLEN, (void *) &ifr) < 0)
|
||||||
|
{
|
||||||
|
perror("set tap qlen");
|
||||||
|
exit( -1);
|
||||||
|
}
|
||||||
ifr.ifr_flags = IFF_UP;
|
ifr.ifr_flags = IFF_UP;
|
||||||
if (ioctl(ifrfd, SIOCSIFFLAGS, (void *) &ifr) < 0)
|
if (ioctl(ifrfd, SIOCSIFFLAGS, (void *) &ifr) < 0)
|
||||||
{
|
{
|
||||||
|
|
@ -336,6 +347,10 @@ void initudp(void)
|
||||||
addr.sin_addr.s_addr = config->bind_address;
|
addr.sin_addr.s_addr = config->bind_address;
|
||||||
udpfd = socket(AF_INET, SOCK_DGRAM, UDP);
|
udpfd = socket(AF_INET, SOCK_DGRAM, UDP);
|
||||||
setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||||
|
{
|
||||||
|
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, (void *) &addr, sizeof(addr)) < 0)
|
||||||
{
|
{
|
||||||
perror("udp bind");
|
perror("udp bind");
|
||||||
|
|
@ -361,6 +376,7 @@ sessionidt sessionbyip(ipt ip)
|
||||||
{
|
{
|
||||||
unsigned char *a = (unsigned char *)&ip;
|
unsigned char *a = (unsigned char *)&ip;
|
||||||
char **d = (char **) ip_hash;
|
char **d = (char **) ip_hash;
|
||||||
|
sessionidt s;
|
||||||
|
|
||||||
#ifdef STAT_CALLS
|
#ifdef STAT_CALLS
|
||||||
STAT(call_sessionbyip);
|
STAT(call_sessionbyip);
|
||||||
|
|
@ -370,7 +386,10 @@ sessionidt sessionbyip(ipt ip)
|
||||||
if (!(d = (char **) d[(size_t) *a++])) return 0;
|
if (!(d = (char **) d[(size_t) *a++])) return 0;
|
||||||
if (!(d = (char **) d[(size_t) *a++])) return 0;
|
if (!(d = (char **) d[(size_t) *a++])) return 0;
|
||||||
|
|
||||||
return (ipt) d[(size_t) *a];
|
s = (ipt) d[(size_t) *a];
|
||||||
|
if (s && session[s].tunnel)
|
||||||
|
return s;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cache_sessionid(ipt ip, sessionidt s)
|
void cache_sessionid(ipt ip, sessionidt s)
|
||||||
|
|
@ -432,21 +451,23 @@ void send_garp(ipt ip)
|
||||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
if (s < 0)
|
if (s < 0)
|
||||||
{
|
{
|
||||||
perror("socket");
|
log(0, 0, 0, 0, "Error creating socket for GARP: %s\n", strerror(errno));
|
||||||
exit(-1);
|
return;
|
||||||
}
|
}
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
|
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
|
||||||
if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0)
|
if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0)
|
||||||
{
|
{
|
||||||
perror("get eth0 hwaddr");
|
log(0, 0, 0, 0, "Error getting eth0 hardware address for GARP: %s\n", strerror(errno));
|
||||||
exit(-1);
|
close(s);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
memcpy(mac, &ifr.ifr_hwaddr.sa_data, 6*sizeof(char));
|
memcpy(mac, &ifr.ifr_hwaddr.sa_data, 6*sizeof(char));
|
||||||
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0)
|
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0)
|
||||||
{
|
{
|
||||||
perror("get eth0 ifindex");
|
log(0, 0, 0, 0, "Error getting eth0 interface index for GARP: %s\n", strerror(errno));
|
||||||
exit(-1);
|
close(s);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
close(s);
|
close(s);
|
||||||
sendarp(ifr.ifr_ifindex, mac, ip);
|
sendarp(ifr.ifr_ifindex, mac, ip);
|
||||||
|
|
@ -537,7 +558,7 @@ void processarp(u8 * buf, int len)
|
||||||
s = sessionbyip(htonl(ip));
|
s = sessionbyip(htonl(ip));
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
log(3, ip, s, session[s].tunnel, "ARP reply for %u.%u.%u.%u\n", ip >> 24, ip >> 16 & 255, ip >> 8 & 255, ip & 255, session[s].tunnel, s);
|
log(3, ip, s, session[s].tunnel, "ARP reply for %u.%u.%u.%u\n", ip >> 24, ip >> 16 & 255, ip >> 8 & 255, ip & 255);
|
||||||
memcpy(buf + 4, buf + 10, 6); // set destination as source
|
memcpy(buf + 4, buf + 10, 6); // set destination as source
|
||||||
*(u16 *) (buf + 10) = htons(tapmac[0]); // set soucre address
|
*(u16 *) (buf + 10) = htons(tapmac[0]); // set soucre address
|
||||||
*(u16 *) (buf + 12) = htons(tapmac[1]);
|
*(u16 *) (buf + 12) = htons(tapmac[1]);
|
||||||
|
|
@ -565,9 +586,20 @@ void tunnelsend(u8 * buf, u16 l, tunnelidt t)
|
||||||
#ifdef STAT_CALLS
|
#ifdef STAT_CALLS
|
||||||
STAT(call_tunnelsend);
|
STAT(call_tunnelsend);
|
||||||
#endif
|
#endif
|
||||||
|
if (!t)
|
||||||
|
{
|
||||||
|
static int backtrace_count = 0;
|
||||||
|
log(0, 0, 0, t, "tunnelsend called with 0 as tunnel id\n");
|
||||||
|
STAT(tunnel_tx_errors);
|
||||||
|
log_backtrace(backtrace_count, 5)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!tunnel[t].ip)
|
if (!tunnel[t].ip)
|
||||||
{
|
{
|
||||||
|
static int backtrace_count = 0;
|
||||||
log(1, 0, 0, t, "Error sending data out tunnel: no remote endpoint (tunnel not set up)\n");
|
log(1, 0, 0, t, "Error sending data out tunnel: no remote endpoint (tunnel not set up)\n");
|
||||||
|
log_backtrace(backtrace_count, 5)
|
||||||
STAT(tunnel_tx_errors);
|
STAT(tunnel_tx_errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -615,7 +647,7 @@ void processipout(u8 * buf, int len)
|
||||||
#ifdef STAT_CALLS
|
#ifdef STAT_CALLS
|
||||||
STAT(call_processipout);
|
STAT(call_processipout);
|
||||||
#endif
|
#endif
|
||||||
if (len < 38)
|
if (len < MIN_IP_SIZE)
|
||||||
{
|
{
|
||||||
log(1, 0, 0, 0, "Short IP, %d bytes\n", len);
|
log(1, 0, 0, 0, "Short IP, %d bytes\n", len);
|
||||||
STAT(tunnel_tx_errors);
|
STAT(tunnel_tx_errors);
|
||||||
|
|
@ -648,12 +680,6 @@ void processipout(u8 * buf, int len)
|
||||||
|
|
||||||
log(5, session[s].ip, s, t, "Ethernet -> Tunnel (%d bytes)\n", len);
|
log(5, session[s].ip, s, t, "Ethernet -> Tunnel (%d bytes)\n", len);
|
||||||
|
|
||||||
// Plugin hook
|
|
||||||
{
|
|
||||||
struct param_packet_rx packet = { &tunnel[t], &session[s], buf, len };
|
|
||||||
run_plugins(PLUGIN_PACKET_RX, &packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add on L2TP header
|
// Add on L2TP header
|
||||||
{
|
{
|
||||||
u8 *p = makeppp(b, buf, len, t, s, PPPIP);
|
u8 *p = makeppp(b, buf, len, t, s, PPPIP);
|
||||||
|
|
@ -776,7 +802,10 @@ void sessionshutdown(sessionidt s, char *reason)
|
||||||
STAT(call_sessionshutdown);
|
STAT(call_sessionshutdown);
|
||||||
#endif
|
#endif
|
||||||
if (!session[s].tunnel)
|
if (!session[s].tunnel)
|
||||||
|
{
|
||||||
|
log(3, session[s].ip, s, session[s].tunnel, "Called sessionshutdown on a session with no tunnel.\n");
|
||||||
return; // not a live session
|
return; // not a live session
|
||||||
|
}
|
||||||
|
|
||||||
if (!session[s].die)
|
if (!session[s].die)
|
||||||
log(2, 0, s, session[s].tunnel, "Shutting down session %d: %s\n", s, reason);
|
log(2, 0, s, session[s].tunnel, "Shutting down session %d: %s\n", s, reason);
|
||||||
|
|
@ -790,7 +819,7 @@ void sessionshutdown(sessionidt s, char *reason)
|
||||||
|
|
||||||
// RADIUS Stop message
|
// RADIUS Stop message
|
||||||
if (session[s].opened && !walled_garden && !dead) {
|
if (session[s].opened && !walled_garden && !dead) {
|
||||||
u8 r = session[s].radius;
|
u16 r = session[s].radius;
|
||||||
if (!r)
|
if (!r)
|
||||||
{
|
{
|
||||||
if (!(r = radiusnew(s)))
|
if (!(r = radiusnew(s)))
|
||||||
|
|
@ -811,7 +840,7 @@ void sessionshutdown(sessionidt s, char *reason)
|
||||||
|
|
||||||
if (session[s].ip)
|
if (session[s].ip)
|
||||||
{ // IP allocated, clear and unroute
|
{ // IP allocated, clear and unroute
|
||||||
u8 r;
|
u16 r;
|
||||||
if (session[s].route[0].ip)
|
if (session[s].route[0].ip)
|
||||||
{
|
{
|
||||||
routeset(session[s].ip, 0, 0, 0);
|
routeset(session[s].ip, 0, 0, 0);
|
||||||
|
|
@ -839,7 +868,7 @@ void sessionshutdown(sessionidt s, char *reason)
|
||||||
void sendipcp(tunnelidt t, sessionidt s)
|
void sendipcp(tunnelidt t, sessionidt s)
|
||||||
{
|
{
|
||||||
u8 buf[MAXCONTROL];
|
u8 buf[MAXCONTROL];
|
||||||
u8 r = session[s].radius;
|
u16 r = session[s].radius;
|
||||||
u8 *q;
|
u8 *q;
|
||||||
#ifdef STAT_CALLS
|
#ifdef STAT_CALLS
|
||||||
STAT(call_sendipcp);
|
STAT(call_sendipcp);
|
||||||
|
|
@ -859,7 +888,7 @@ void sendipcp(tunnelidt t, sessionidt s)
|
||||||
}
|
}
|
||||||
q = makeppp(buf, 0, 0, t, s, PPPIPCP);
|
q = makeppp(buf, 0, 0, t, s, PPPIPCP);
|
||||||
*q = ConfigReq;
|
*q = ConfigReq;
|
||||||
q[1] = r; // ID, dont care, we only send one type of request
|
q[1] = r << RADIUS_SHIFT; // ID, dont care, we only send one type of request
|
||||||
*(u16 *) (q + 2) = htons(10);
|
*(u16 *) (q + 2) = htons(10);
|
||||||
q[4] = 3;
|
q[4] = 3;
|
||||||
q[5] = 6;
|
q[5] = 6;
|
||||||
|
|
@ -876,10 +905,10 @@ void sessionkill(sessionidt s, char *reason)
|
||||||
sessionshutdown(s, reason); // close radius/routes, etc.
|
sessionshutdown(s, reason); // close radius/routes, etc.
|
||||||
if (session[s].radius)
|
if (session[s].radius)
|
||||||
radiusclear(session[s].radius, 0); // cant send clean accounting data, session is killed
|
radiusclear(session[s].radius, 0); // cant send clean accounting data, session is killed
|
||||||
|
log(2, 0, s, session[s].tunnel, "Kill session %d: %s\n", s, reason);
|
||||||
memset(&session[s], 0, sizeof(session[s]));
|
memset(&session[s], 0, sizeof(session[s]));
|
||||||
session[s].next = sessionfree;
|
session[s].next = sessionfree;
|
||||||
sessionfree = s;
|
sessionfree = s;
|
||||||
log(2, 0, s, session[s].tunnel, "Kill session %d: %s\n", s, reason);
|
|
||||||
cluster_send_session(s);
|
cluster_send_session(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1143,7 +1172,7 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log(1, ntohl(addr->sin_addr.s_addr), s, t, "Hidden AVP\n");
|
log(4, ntohl(addr->sin_addr.s_addr), s, t, "Hidden AVP\n");
|
||||||
}
|
}
|
||||||
if (*b & 0x3C)
|
if (*b & 0x3C)
|
||||||
{
|
{
|
||||||
|
|
@ -1294,7 +1323,7 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
|
||||||
memcpy(tmp, b, (n >= 30) ? 30 : n);
|
memcpy(tmp, b, (n >= 30) ? 30 : n);
|
||||||
session[s].tx_connect_speed = atol(tmp);
|
session[s].tx_connect_speed = atol(tmp);
|
||||||
}
|
}
|
||||||
log(4, ntohl(addr->sin_addr.s_addr), s, t, " TX connect speed <%d>\n",
|
log(4, ntohl(addr->sin_addr.s_addr), s, t, " TX connect speed <%lu>\n",
|
||||||
session[s].tx_connect_speed);
|
session[s].tx_connect_speed);
|
||||||
break;
|
break;
|
||||||
case 38: // rx connect speed
|
case 38: // rx connect speed
|
||||||
|
|
@ -1309,7 +1338,7 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
|
||||||
memcpy(tmp, b, (n >= 30) ? 30 : n);
|
memcpy(tmp, b, (n >= 30) ? 30 : n);
|
||||||
session[s].rx_connect_speed = atol(tmp);
|
session[s].rx_connect_speed = atol(tmp);
|
||||||
}
|
}
|
||||||
log(4, ntohl(addr->sin_addr.s_addr), s, t, " RX connect speed <%d>\n",
|
log(4, ntohl(addr->sin_addr.s_addr), s, t, " RX connect speed <%lu>\n",
|
||||||
session[s].rx_connect_speed);
|
session[s].rx_connect_speed);
|
||||||
break;
|
break;
|
||||||
case 25: // Physical Channel ID
|
case 25: // Physical Channel ID
|
||||||
|
|
@ -1337,7 +1366,7 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
|
||||||
case 31: // Proxy Authentication Challenge
|
case 31: // Proxy Authentication Challenge
|
||||||
{
|
{
|
||||||
memcpy(radius[session[s].radius].auth, b, 16);
|
memcpy(radius[session[s].radius].auth, b, 16);
|
||||||
log(4, ntohl(addr->sin_addr.s_addr), s, t, " Proxy Auth Challenge (%X)\n", radius[session[s].radius].auth);
|
log(4, ntohl(addr->sin_addr.s_addr), s, t, " Proxy Auth Challenge\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 32: // Proxy Authentication ID
|
case 32: // Proxy Authentication ID
|
||||||
|
|
@ -1457,7 +1486,7 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u8 r;
|
u16 r;
|
||||||
controlt *c;
|
controlt *c;
|
||||||
|
|
||||||
s = sessionfree;
|
s = sessionfree;
|
||||||
|
|
@ -1468,7 +1497,6 @@ void processudp(u8 * buf, int len, struct sockaddr_in *addr)
|
||||||
if (!(r = radiusnew(s)))
|
if (!(r = radiusnew(s)))
|
||||||
{
|
{
|
||||||
log(1, ntohl(addr->sin_addr.s_addr), s, t, "No free RADIUS sessions for ICRQ\n");
|
log(1, ntohl(addr->sin_addr.s_addr), s, t, "No free RADIUS sessions for ICRQ\n");
|
||||||
sessionkill(s, "no free RADIUS sesions");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1617,42 +1645,45 @@ void processtap(u8 * buf, int len)
|
||||||
}
|
}
|
||||||
if (*(u16 *) (buf + 2) == htons(PKTARP)) // ARP
|
if (*(u16 *) (buf + 2) == htons(PKTARP)) // ARP
|
||||||
processarp(buf, len);
|
processarp(buf, len);
|
||||||
else if (*(u16 *) (buf + 2) == htons(PKTIP)) // ARP
|
else if (*(u16 *) (buf + 2) == htons(PKTIP)) // IP
|
||||||
processipout(buf, len);
|
processipout(buf, len);
|
||||||
else
|
|
||||||
{
|
|
||||||
log(1, 0, 0, 0, "Unexpected tap packet %04X, %d bytes\n", ntohs(*(u16 *) (buf + 2)), len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// main loop - gets packets on tap or udp and processes them
|
// main loop - gets packets on tap or udp and processes them
|
||||||
void mainloop(void)
|
void mainloop(void)
|
||||||
{
|
{
|
||||||
fd_set cr;
|
fd_set cr;
|
||||||
int cn;
|
int cn, i;
|
||||||
u8 buf[65536];
|
u8 buf[65536];
|
||||||
struct timeval to;
|
struct timeval to;
|
||||||
|
|
||||||
clockt slow = now(); // occasional functions like session/tunnel expiry, tunnel hello, etc
|
clockt slow = now(); // occasional functions like session/tunnel expiry, tunnel hello, etc
|
||||||
clockt next_acct = slow + ACCT_TIME;
|
clockt next_acct = slow + ACCT_TIME;
|
||||||
clockt next_cluster_ping = slow + 50;
|
clockt next_cluster_ping = slow + 50;
|
||||||
|
clockt next_clean = time_now + config->cleanup_interval;
|
||||||
to.tv_sec = 1;
|
to.tv_sec = 1;
|
||||||
to.tv_usec = 0;
|
to.tv_usec = 0;
|
||||||
log(4, 0, 0, 0, "Beginning of main loop. udpfd=%d, tapfd=%d, radfd=%d, cluster_sockfd=%d, controlfd=%d\n",
|
log(4, 0, 0, 0, "Beginning of main loop. udpfd=%d, tapfd=%d, cluster_sockfd=%d, controlfd=%d\n",
|
||||||
udpfd, tapfd, radfd, cluster_sockfd, controlfd);
|
udpfd, tapfd, cluster_sockfd, controlfd);
|
||||||
|
|
||||||
FD_ZERO(&cr);
|
FD_ZERO(&cr);
|
||||||
FD_SET(udpfd, &cr);
|
FD_SET(udpfd, &cr);
|
||||||
FD_SET(tapfd, &cr);
|
FD_SET(tapfd, &cr);
|
||||||
FD_SET(radfd, &cr);
|
|
||||||
FD_SET(controlfd, &cr);
|
FD_SET(controlfd, &cr);
|
||||||
FD_SET(clifd, &cr);
|
FD_SET(clifd, &cr);
|
||||||
if (cluster_sockfd) FD_SET(cluster_sockfd, &cr);
|
if (cluster_sockfd) FD_SET(cluster_sockfd, &cr);
|
||||||
cn = udpfd;
|
cn = udpfd;
|
||||||
if (cn < radfd) cn = radfd;
|
|
||||||
if (cn < tapfd) cn = tapfd;
|
if (cn < tapfd) cn = tapfd;
|
||||||
if (cn < controlfd) cn = controlfd;
|
if (cn < controlfd) cn = controlfd;
|
||||||
if (cn < clifd) cn = clifd;
|
if (cn < clifd) cn = clifd;
|
||||||
if (cn < cluster_sockfd) cn = cluster_sockfd;
|
if (cn < cluster_sockfd) cn = cluster_sockfd;
|
||||||
|
for (i = 0; i < config->num_radfds; i++)
|
||||||
|
{
|
||||||
|
if (!radfds[i]) continue;
|
||||||
|
FD_SET(radfds[i], &cr);
|
||||||
|
if (radfds[i] > cn)
|
||||||
|
cn = radfds[i];
|
||||||
|
}
|
||||||
|
|
||||||
while (!main_quit)
|
while (!main_quit)
|
||||||
{
|
{
|
||||||
|
|
@ -1680,16 +1711,35 @@ void mainloop(void)
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int alen = sizeof(addr);
|
int alen = sizeof(addr);
|
||||||
if (FD_ISSET(udpfd, &r))
|
if (FD_ISSET(udpfd, &r))
|
||||||
processudp(buf, recvfrom(udpfd, buf, sizeof(buf), 0, (void *) &addr, &alen), &addr);
|
{
|
||||||
else if (FD_ISSET(tapfd, &r))
|
int c, n;
|
||||||
processtap(buf, read(tapfd, buf, sizeof(buf)));
|
for (c = 0; c < config->multi_read_count; c++)
|
||||||
else if (FD_ISSET(radfd, &r))
|
{
|
||||||
processrad(buf, recv(radfd, buf, sizeof(buf), 0));
|
if ((n = recvfrom(udpfd, buf, sizeof(buf), 0, (void *) &addr, &alen)) > 0)
|
||||||
else if (FD_ISSET(cluster_sockfd, &r))
|
processudp(buf, n, &addr);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FD_ISSET(tapfd, &r))
|
||||||
|
{
|
||||||
|
int c, n;
|
||||||
|
for (c = 0; c < config->multi_read_count; c++)
|
||||||
|
{
|
||||||
|
if ((n = read(tapfd, buf, sizeof(buf))) > 0)
|
||||||
|
processtap(buf, n);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < config->num_radfds; i++)
|
||||||
|
if (FD_ISSET(radfds[i], &r))
|
||||||
|
processrad(buf, recv(radfds[i], buf, sizeof(buf), 0), i);
|
||||||
|
if (FD_ISSET(cluster_sockfd, &r))
|
||||||
processcluster(buf, recvfrom(cluster_sockfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen));
|
processcluster(buf, recvfrom(cluster_sockfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen));
|
||||||
else if (FD_ISSET(controlfd, &r))
|
if (FD_ISSET(controlfd, &r))
|
||||||
processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr);
|
processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr);
|
||||||
else if (FD_ISSET(clifd, &r))
|
if (FD_ISSET(clifd, &r))
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int sockfd;
|
int sockfd;
|
||||||
|
|
@ -1706,20 +1756,22 @@ void mainloop(void)
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
log(1, 0, 0, 0, "Main select() loop returned %d, but no fds have data waiting\n", n);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (n == 0) { // handle timeouts
|
/* Handle timeouts. Make sure that this gets run anyway, even if there was
|
||||||
|
* something to read, else under load this will never actually run....
|
||||||
|
*/
|
||||||
|
if (n == 0 || next_clean <= time_now) {
|
||||||
clockt when = now();
|
clockt when = now();
|
||||||
clockt best = when + 100; // default timeout
|
clockt best = when + 100; // default timeout
|
||||||
sessionidt s;
|
sessionidt s;
|
||||||
tunnelidt t;
|
tunnelidt t;
|
||||||
u8 r;
|
int count;
|
||||||
|
u16 r;
|
||||||
|
|
||||||
|
log(3, 0, 0, 0, "Begin regular cleanup\n");
|
||||||
for (r = 1; r < MAXRADIUS; r++)
|
for (r = 1; r < MAXRADIUS; r++)
|
||||||
|
{
|
||||||
if (radius[r].state && radius[r].retry)
|
if (radius[r].state && radius[r].retry)
|
||||||
{
|
{
|
||||||
if (radius[r].retry <= when)
|
if (radius[r].retry <= when)
|
||||||
|
|
@ -1727,6 +1779,9 @@ void mainloop(void)
|
||||||
if (radius[r].retry && radius[r].retry < best)
|
if (radius[r].retry && radius[r].retry < best)
|
||||||
best = radius[r].retry;
|
best = radius[r].retry;
|
||||||
}
|
}
|
||||||
|
else if (radius[r].state && !radius[r].retry)
|
||||||
|
radius[r].retry = backoff(radius[r].try+1);
|
||||||
|
}
|
||||||
for (t = 1; t < MAXTUNNEL; t++)
|
for (t = 1; t < MAXTUNNEL; t++)
|
||||||
{
|
{
|
||||||
// check for expired tunnels
|
// check for expired tunnels
|
||||||
|
|
@ -1770,7 +1825,7 @@ void mainloop(void)
|
||||||
if (cli_session_kill[0])
|
if (cli_session_kill[0])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 1; i < MAXSESSION && cli_session_kill[i]; i++)
|
for (i = 0; i < MAXSESSION && cli_session_kill[i]; i++)
|
||||||
{
|
{
|
||||||
log(2, 0, cli_session_kill[i], 0, "Dropping session by CLI\n");
|
log(2, 0, cli_session_kill[i], 0, "Dropping session by CLI\n");
|
||||||
sessionshutdown(cli_session_kill[i], "Requested by administrator");
|
sessionshutdown(cli_session_kill[i], "Requested by administrator");
|
||||||
|
|
@ -1789,12 +1844,14 @@ void mainloop(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count = 0;
|
||||||
for (s = 1; s < MAXSESSION; s++)
|
for (s = 1; s < MAXSESSION; s++)
|
||||||
{
|
{
|
||||||
// check for expired sessions
|
// check for expired sessions
|
||||||
if (session[s].die && session[s].die <= when)
|
if (session[s].die && session[s].die <= when)
|
||||||
{
|
{
|
||||||
sessionkill(s, "Expired");
|
sessionkill(s, "Expired");
|
||||||
|
if (++count >= 1000) break;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1803,6 +1860,7 @@ void mainloop(void)
|
||||||
{
|
{
|
||||||
sessionkill(s, "No response to LCP ECHO requests");
|
sessionkill(s, "No response to LCP ECHO requests");
|
||||||
STAT(session_timeout);
|
STAT(session_timeout);
|
||||||
|
if (++count >= 1000) break;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1818,8 +1876,9 @@ void mainloop(void)
|
||||||
*(u32 *)(q + 4) = 0; // Magic Number (not supported)
|
*(u32 *)(q + 4) = 0; // Magic Number (not supported)
|
||||||
|
|
||||||
log(4, session[s].ip, s, session[s].tunnel, "No data in %d seconds, sending LCP ECHO\n",
|
log(4, session[s].ip, s, session[s].tunnel, "No data in %d seconds, sending LCP ECHO\n",
|
||||||
time_now - session[s].last_packet);
|
(int)(time_now - session[s].last_packet));
|
||||||
tunnelsend(b, 24, session[s].tunnel); // send it
|
tunnelsend(b, 24, session[s].tunnel); // send it
|
||||||
|
if (++count >= 1000) break;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1837,11 +1896,12 @@ void mainloop(void)
|
||||||
cluster_send_message(config->cluster_address, config->bind_address, C_PING, hostname, strlen(hostname));
|
cluster_send_message(config->cluster_address, config->bind_address, C_PING, hostname, strlen(hostname));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best <= when)
|
if (best < when + config->cleanup_interval)
|
||||||
best = when + 1; // should not really happen
|
best = when + config->cleanup_interval; // Throttle to at most once per 10 seconds
|
||||||
to.tv_sec = (best - when) / 10;
|
next_clean = time_now + config->cleanup_interval;
|
||||||
to.tv_usec = 100000 * ((best - when) % 10);
|
to.tv_sec = config->cleanup_interval;
|
||||||
log(5, 0, 0, 0, "Next time check in %d.%d seconds\n", (best - when) / 10, ((best - when) % 10));
|
to.tv_usec = 0;
|
||||||
|
log(3, 0, 0, 0, "End regular cleanup, next in %d seconds\n", config->cleanup_interval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1995,6 +2055,7 @@ int assign_ip_address(sessionidt s)
|
||||||
session[s].ip_pool_index = best;
|
session[s].ip_pool_index = best;
|
||||||
ip_address_pool[best].assigned = 1;
|
ip_address_pool[best].assigned = 1;
|
||||||
ip_address_pool[best].last = time_now;
|
ip_address_pool[best].last = time_now;
|
||||||
|
ip_address_pool[best].session = s;
|
||||||
if (session[s].walled_garden)
|
if (session[s].walled_garden)
|
||||||
/* Don't track addresses of users in walled garden (note: this
|
/* Don't track addresses of users in walled garden (note: this
|
||||||
means that their address isn't "sticky" even if they get
|
means that their address isn't "sticky" even if they get
|
||||||
|
|
@ -2005,7 +2066,7 @@ int assign_ip_address(sessionidt s)
|
||||||
|
|
||||||
STAT(ip_allocated);
|
STAT(ip_allocated);
|
||||||
log(4, ip_address_pool[best].address, s, session[s].tunnel,
|
log(4, ip_address_pool[best].address, s, session[s].tunnel,
|
||||||
"assign_ip_address(): %s ip address %lu from pool\n", reuse ? "Reusing" : "Allocating", best);
|
"assign_ip_address(): %s ip address %d from pool\n", reuse ? "Reusing" : "Allocating", best);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -2025,6 +2086,7 @@ void free_ip_address(sessionidt s)
|
||||||
uncache_sessionid(session[s].ip);
|
uncache_sessionid(session[s].ip);
|
||||||
session[s].ip = 0;
|
session[s].ip = 0;
|
||||||
ip_address_pool[i].assigned = 0;
|
ip_address_pool[i].assigned = 0;
|
||||||
|
ip_address_pool[i].session = 0;
|
||||||
ip_address_pool[i].last = time_now;
|
ip_address_pool[i].last = time_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2077,7 +2139,7 @@ void initippool()
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
if (!*p || !(numbits = atoi(p)))
|
if (!*p || !(numbits = atoi(p)))
|
||||||
{
|
{
|
||||||
log(0, 0, 0, 0, "Invalid pool range %s/\n", buf, p);
|
log(0, 0, 0, 0, "Invalid pool range %s\n", buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
start = end = ntohl(inet_addr(pool));
|
start = end = ntohl(inet_addr(pool));
|
||||||
|
|
@ -2092,7 +2154,7 @@ void initippool()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a static route for this pool
|
// Add a static route for this pool
|
||||||
log(5, 0, 0, 0, "Adding route for address pool %s/%d\n", inet_toa(htonl(start)), 32+mask);
|
log(5, 0, 0, 0, "Adding route for address pool %s/%lu\n", inet_toa(htonl(start)), 32 + mask);
|
||||||
memset(&r, 0, sizeof(r));
|
memset(&r, 0, sizeof(r));
|
||||||
r.rt_dev = config->tapdevice;
|
r.rt_dev = config->tapdevice;
|
||||||
r.rt_dst.sa_family = AF_INET;
|
r.rt_dst.sa_family = AF_INET;
|
||||||
|
|
@ -2102,7 +2164,8 @@ void initippool()
|
||||||
r.rt_flags = (RTF_UP | RTF_STATIC);
|
r.rt_flags = (RTF_UP | RTF_STATIC);
|
||||||
if (ioctl(ifrfd, SIOCADDRT, (void *) &r) < 0)
|
if (ioctl(ifrfd, SIOCADDRT, (void *) &r) < 0)
|
||||||
{
|
{
|
||||||
log(0, 0, 0, 0, "Error adding ip address pool route %s/%d: %s\n", inet_toa(start), mask, strerror(errno));
|
log(0, 0, 0, 0, "Error adding ip address pool route %s/%lu: %s\n",
|
||||||
|
inet_toa(start), mask, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2145,7 +2208,7 @@ void dump_acct_info()
|
||||||
|
|
||||||
for (i = 0; i < MAXSESSION; i++)
|
for (i = 0; i < MAXSESSION; i++)
|
||||||
{
|
{
|
||||||
if (!session[i].opened || !session[i].cin || !session[i].cout || !*session[i].user || session[i].walled_garden)
|
if (!session[i].opened || !session[i].ip || !session[i].cin || !session[i].cout || !*session[i].user || session[i].walled_garden)
|
||||||
continue;
|
continue;
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
|
|
@ -2188,20 +2251,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
_program_name = strdup(argv[0]);
|
_program_name = strdup(argv[0]);
|
||||||
|
|
||||||
{
|
|
||||||
struct rlimit rlim;
|
|
||||||
rlim.rlim_cur = RLIM_INFINITY;
|
|
||||||
rlim.rlim_max = RLIM_INFINITY;
|
|
||||||
// Remove the maximum core size
|
|
||||||
setrlimit(RLIMIT_CORE, &rlim);
|
|
||||||
// Make core dumps go to /tmp
|
|
||||||
chdir("/tmp");
|
|
||||||
}
|
|
||||||
|
|
||||||
time(&basetime); // start clock
|
time(&basetime); // start clock
|
||||||
initdata();
|
|
||||||
|
|
||||||
// scan args
|
// scan args
|
||||||
|
|
||||||
while ((o = getopt(argc, argv, "vc:h:a:")) >= 0)
|
while ((o = getopt(argc, argv, "vc:h:a:")) >= 0)
|
||||||
{
|
{
|
||||||
switch (o)
|
switch (o)
|
||||||
|
|
@ -2209,21 +2261,9 @@ int main(int argc, char *argv[])
|
||||||
case 'v':
|
case 'v':
|
||||||
config->debug++;
|
config->debug++;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
|
||||||
strncpy(config->config_file, optarg, sizeof(config->config_file) - 1);
|
|
||||||
break;
|
|
||||||
case 'h':
|
case 'h':
|
||||||
strncpy(hostname, optarg, 999);
|
strncpy(hostname, optarg, 999);
|
||||||
break;
|
break;
|
||||||
case 'a':
|
|
||||||
myip = inet_addr(optarg);
|
|
||||||
if (myip == INADDR_NONE) {
|
|
||||||
log(0, 0, 0, 0, "Invalid ip %s\n", optarg);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
config->bind_address = myip;
|
|
||||||
handle_interface = 1;
|
|
||||||
break;
|
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
printf("Args are:\n\t-c <file>\tConfig file\n\t-h <hostname>\tForce hostname\n\t-a <address>\tUse specific address\n\t-v\t\tDebug\n");
|
printf("Args are:\n\t-c <file>\tConfig file\n\t-h <hostname>\tForce hostname\n\t-a <address>\tUse specific address\n\t-v\t\tDebug\n");
|
||||||
|
|
@ -2235,13 +2275,25 @@ int main(int argc, char *argv[])
|
||||||
// Start the timer routine off
|
// Start the timer routine off
|
||||||
time(&time_now);
|
time(&time_now);
|
||||||
strftime(time_now_string, 64, "%Y-%m-%d %H:%M:%S", localtime(&time_now));
|
strftime(time_now_string, 64, "%Y-%m-%d %H:%M:%S", localtime(&time_now));
|
||||||
|
signal(SIGALRM, sigalrm_handler);
|
||||||
|
siginterrupt(SIGALRM, 0);
|
||||||
|
|
||||||
initiptables();
|
initiptables();
|
||||||
initplugins();
|
initplugins();
|
||||||
|
initdata();
|
||||||
init_cli();
|
init_cli();
|
||||||
read_config_file();
|
read_config_file();
|
||||||
log(1, 0, 0, 0, "L2TPNS Version 1.1.0 - http://l2tpns.sourceforge.net/\n");
|
log(0, 0, 0, 0, "$Id: l2tpns.c,v 1.6 2004/05/24 04:20:28 fred_nerk Exp $\n(c) Copyright 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced\n");
|
||||||
log(1, 0, 0, 0, "Licensed under the GPL\n");
|
{
|
||||||
|
struct rlimit rlim;
|
||||||
|
rlim.rlim_cur = RLIM_INFINITY;
|
||||||
|
rlim.rlim_max = RLIM_INFINITY;
|
||||||
|
// Remove the maximum core size
|
||||||
|
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
|
||||||
|
log(0, 0, 0, 0, "Can't set ulimit: %s\n", strerror(errno));
|
||||||
|
// Make core dumps go to /tmp
|
||||||
|
chdir("/tmp");
|
||||||
|
}
|
||||||
|
|
||||||
/* Start up the cluster first, so that we don't have two machines with
|
/* Start up the cluster first, so that we don't have two machines with
|
||||||
* the same IP at once.
|
* the same IP at once.
|
||||||
|
|
@ -2257,9 +2309,8 @@ int main(int argc, char *argv[])
|
||||||
initrad();
|
initrad();
|
||||||
initippool();
|
initippool();
|
||||||
init_rl();
|
init_rl();
|
||||||
if (handle_interface) {
|
if (config->bind_address)
|
||||||
send_garp(config->bind_address);
|
send_garp(config->bind_address);
|
||||||
}
|
|
||||||
|
|
||||||
// If NOSTATEFILE exists, we will ignore any updates from the cluster master for this execution
|
// If NOSTATEFILE exists, we will ignore any updates from the cluster master for this execution
|
||||||
if (!unlink(NOSTATEFILE))
|
if (!unlink(NOSTATEFILE))
|
||||||
|
|
@ -2267,13 +2318,11 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
read_state();
|
read_state();
|
||||||
|
|
||||||
signal(SIGALRM, sigalrm_handler);
|
|
||||||
signal(SIGHUP, sighup_handler);
|
signal(SIGHUP, sighup_handler);
|
||||||
signal(SIGTERM, sigterm_handler);
|
signal(SIGTERM, sigterm_handler);
|
||||||
signal(SIGINT, sigterm_handler);
|
signal(SIGINT, sigterm_handler);
|
||||||
signal(SIGQUIT, sigquit_handler);
|
signal(SIGQUIT, sigquit_handler);
|
||||||
signal(SIGCHLD, sigchild_handler);
|
signal(SIGCHLD, sigchild_handler);
|
||||||
signal(SIGSEGV, sigsegv_handler);
|
|
||||||
|
|
||||||
alarm(1);
|
alarm(1);
|
||||||
|
|
||||||
|
|
@ -2369,14 +2418,6 @@ void sigchild_handler(int signal)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sigsegv_handler(int signal)
|
|
||||||
{
|
|
||||||
log(0, 0, 0, 0, "----------------------------------------------\n");
|
|
||||||
log(0, 0, 0, 0, "- SEGFAULT! -\n");
|
|
||||||
log(0, 0, 0, 0, "----------------------------------------------\n");
|
|
||||||
_exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_state()
|
void read_state()
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
@ -2490,7 +2531,6 @@ void read_state()
|
||||||
for (i = 0; i < MAXSESSION; i++)
|
for (i = 0; i < MAXSESSION; i++)
|
||||||
{
|
{
|
||||||
session[i].tbf = 0;
|
session[i].tbf = 0;
|
||||||
session[i].throttle = 0;
|
|
||||||
if (session[i].opened)
|
if (session[i].opened)
|
||||||
{
|
{
|
||||||
log(2, 0, i, 0, "Loaded active session for user %s\n", session[i].user);
|
log(2, 0, i, 0, "Loaded active session for user %s\n", session[i].user);
|
||||||
|
|
@ -2597,9 +2637,18 @@ void update_config()
|
||||||
}
|
}
|
||||||
if (*config->log_filename)
|
if (*config->log_filename)
|
||||||
{
|
{
|
||||||
if (strstr(config->log_filename, "file:") == config->log_filename)
|
if (strstr(config->log_filename, "syslog:") == config->log_filename)
|
||||||
{
|
{
|
||||||
if ((log_stream = fopen((char *)(config->log_filename + 5), "a")))
|
char *p = config->log_filename + 7;
|
||||||
|
if (*p)
|
||||||
|
{
|
||||||
|
openlog("l2tpns", LOG_PID, facility_value(p));
|
||||||
|
syslog_log = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strchr(config->log_filename, '/') == config->log_filename)
|
||||||
|
{
|
||||||
|
if ((log_stream = fopen((char *)(config->log_filename), "a")))
|
||||||
{
|
{
|
||||||
fseek(log_stream, 0, SEEK_END);
|
fseek(log_stream, 0, SEEK_END);
|
||||||
setbuf(log_stream, NULL);
|
setbuf(log_stream, NULL);
|
||||||
|
|
@ -2610,15 +2659,6 @@ void update_config()
|
||||||
setbuf(log_stream, NULL);
|
setbuf(log_stream, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strstr(config->log_filename, "syslog:") == config->log_filename)
|
|
||||||
{
|
|
||||||
char *p = config->log_filename + 7;
|
|
||||||
if (*p)
|
|
||||||
{
|
|
||||||
openlog("l2tpns", LOG_PID, facility_value(p));
|
|
||||||
syslog_log = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2637,6 +2677,8 @@ void update_config()
|
||||||
log(0, 0, 0, 0, "No RADIUS servers defined!\n");
|
log(0, 0, 0, 0, "No RADIUS servers defined!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config->num_radfds = 2 << RADIUS_SHIFT;
|
||||||
|
|
||||||
// Update plugins
|
// Update plugins
|
||||||
for (i = 0; i < MAXPLUGINS; i++)
|
for (i = 0; i < MAXPLUGINS; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -2654,6 +2696,8 @@ void update_config()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy(config->old_plugins, config->plugins, sizeof(config->plugins));
|
memcpy(config->old_plugins, config->plugins, sizeof(config->plugins));
|
||||||
|
if (!config->cleanup_interval) config->cleanup_interval = 10;
|
||||||
|
if (!config->multi_read_count) config->multi_read_count = 1;
|
||||||
config->reload_config = 0;
|
config->reload_config = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2672,7 +2716,6 @@ void read_config_file()
|
||||||
log(3, 0, 0, 0, "Done reading config file\n");
|
log(3, 0, 0, 0, "Done reading config file\n");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
update_config();
|
update_config();
|
||||||
log_stream = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sessionsetup(tunnelidt t, sessionidt s, u8 routes)
|
int sessionsetup(tunnelidt t, sessionidt s, u8 routes)
|
||||||
|
|
@ -2693,7 +2736,7 @@ int sessionsetup(tunnelidt t, sessionidt s, u8 routes)
|
||||||
// Make sure this is right
|
// Make sure this is right
|
||||||
session[s].tunnel = t;
|
session[s].tunnel = t;
|
||||||
// zap old sessions with same IP and/or username
|
// zap old sessions with same IP and/or username
|
||||||
// Don't kill walled garden sessions - doing so leads to a DoS
|
// Don't kill gardened sessions - doing so leads to a DoS
|
||||||
// from someone who doesn't need to know the password
|
// from someone who doesn't need to know the password
|
||||||
ip = session[s].ip;
|
ip = session[s].ip;
|
||||||
user = session[s].user;
|
user = session[s].user;
|
||||||
|
|
@ -2723,7 +2766,7 @@ int sessionsetup(tunnelidt t, sessionidt s, u8 routes)
|
||||||
// Force throttling on or off
|
// Force throttling on or off
|
||||||
// This has the advantage of cleaning up after another throttled user who may have left
|
// This has the advantage of cleaning up after another throttled user who may have left
|
||||||
// firewall rules lying around
|
// firewall rules lying around
|
||||||
throttle_session(s, session[s].throttle);
|
session[s].throttle = throttle_session(s, session[s].throttle);
|
||||||
|
|
||||||
{
|
{
|
||||||
struct param_new_session data = { &tunnel[t], &session[s] };
|
struct param_new_session data = { &tunnel[t], &session[s] };
|
||||||
|
|
@ -2813,7 +2856,7 @@ void add_plugin(char *plugin_name)
|
||||||
int *v = dlsym(p, "__plugin_api_version");
|
int *v = dlsym(p, "__plugin_api_version");
|
||||||
if (!v || *v != PLUGIN_API_VERSION)
|
if (!v || *v != PLUGIN_API_VERSION)
|
||||||
{
|
{
|
||||||
log(1, 0, 0, 0, " Plugin load failed: API version mismatch\n", dlerror());
|
log(1, 0, 0, 0, " Plugin load failed: API version mismatch: %s\n", dlerror());
|
||||||
dlclose(p);
|
dlclose(p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2822,14 +2865,14 @@ void add_plugin(char *plugin_name)
|
||||||
initfunc = dlsym(p, "plugin_init");
|
initfunc = dlsym(p, "plugin_init");
|
||||||
if (!initfunc)
|
if (!initfunc)
|
||||||
{
|
{
|
||||||
log(1, 0, 0, 0, " Plugin load failed: function plugin_init() does not exist.\n", dlerror());
|
log(1, 0, 0, 0, " Plugin load failed: function plugin_init() does not exist: %s\n", dlerror());
|
||||||
dlclose(p);
|
dlclose(p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!initfunc(&funcs))
|
if (!initfunc(&funcs))
|
||||||
{
|
{
|
||||||
log(1, 0, 0, 0, " Plugin load failed: plugin_init() returned FALSE.\n", dlerror());
|
log(1, 0, 0, 0, " Plugin load failed: plugin_init() returned FALSE: %s\n", dlerror());
|
||||||
dlclose(p);
|
dlclose(p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2918,18 +2961,7 @@ void processcontrol(u8 * buf, int len, struct sockaddr_in *addr)
|
||||||
param.response = resp;
|
param.response = resp;
|
||||||
param.response_length = l;
|
param.response_length = l;
|
||||||
|
|
||||||
if (param.type == PKT_LOAD_PLUGIN && param.data_length)
|
|
||||||
{
|
|
||||||
add_plugin(param.data);
|
|
||||||
}
|
|
||||||
else if (param.type == PKT_UNLOAD_PLUGIN && param.data_length)
|
|
||||||
{
|
|
||||||
remove_plugin(param.data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
run_plugins(PLUGIN_CONTROL, ¶m);
|
run_plugins(PLUGIN_CONTROL, ¶m);
|
||||||
}
|
|
||||||
|
|
||||||
if (param.send_response)
|
if (param.send_response)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue