add DAE support (PoD/CoA) from Vladislav Bjelic

This commit is contained in:
bodea 2005-06-28 14:48:17 +00:00
parent 659ed315c2
commit 4f253feef0
16 changed files with 604 additions and 158 deletions

View file

@ -1,9 +1,10 @@
* Mon Jun 27 2005 Brendan O'Dea <bod@optus.net> 2.1.2 * Wed Jun 29 2005 Brendan O'Dea <bod@c47.org> 2.1.2
- Don't resend IPCP while still in progress. - Don't resend IPCP while still in progress.
- Ignore duplicate ACKs for IPCP. - Ignore duplicate ACKs for IPCP.
- Clear RADIUSIPCP for walled garden sessions on ACK. - Clear RADIUSIPCP for walled garden sessions on ACK.
- Clear cluster_master on election so that slaves will accept a new master. - Clear cluster_master on election so that slaves will accept a new master.
- Provide more comments/defaults in etc/startup-config.default. - Provide more comments/defaults in etc/startup-config.default.
- Add DAE support (PoD/CoA) from Vladislav Bjelic.
* Tue Jun 14 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.1 * Tue Jun 14 2005 Brendan O'Dea <bod@optusnet.com.au> 2.1.1
- Add missing newline to backtrace macro. - Add missing newline to backtrace macro.

View file

@ -229,6 +229,11 @@ A comma separated list of supported RADIUS authentication methods
(<B>pap</B> or <B>chap</B>), in order of preference (default <B>pap</B>). (<B>pap</B> or <B>chap</B>), in order of preference (default <B>pap</B>).
</LI> </LI>
<LI><B>radius_dae_port</B> (short)<BR>
Port for DAE RADIUS (Packet of Death/Disconnect, Change of Authorization)
requests (default: <B>3799</B>).
</LI>
<LI><B>allow_duplicate_users</B> (boolean)</BR> <LI><B>allow_duplicate_users</B> (boolean)</BR>
Allow multiple logins with the same username. If false (the default), Allow multiple logins with the same username. If false (the default),
any prior session with the same username will be dropped when a new any prior session with the same username will be dropped when a new

View file

@ -2,7 +2,7 @@
.de Id .de Id
.ds Dt \\$4 \\$5 .ds Dt \\$4 \\$5
.. ..
.Id $Id: startup-config.5,v 1.10 2005/06/02 11:32:33 bodea Exp $ .Id $Id: startup-config.5,v 1.11 2005/06/28 14:48:31 bodea Exp $
.TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions" .TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions"
.SH NAME .SH NAME
startup\-config \- configuration file for l2tpns startup\-config \- configuration file for l2tpns
@ -100,6 +100,10 @@ Secret to be used in RADIUS packets.
A comma separated list of supported RADIUS authentication methods A comma separated list of supported RADIUS authentication methods
("pap" or "chap"), in order of preference (default "pap"). ("pap" or "chap"), in order of preference (default "pap").
.TP .TP
.B radius_dae_port
Port for DAE RADIUS (Packet of Death/Disconnect, Change of Authorization)
requests (default: 3799).
.TP
.B allow_duplicate_users .B allow_duplicate_users
Allow multiple logins with the same username. If false (the default), Allow multiple logins with the same username. If false (the default),
any prior session with the same username will be dropped when a new any prior session with the same username will be dropped when a new

19
cli.c
View file

@ -2,7 +2,7 @@
// vim: sw=8 ts=8 // vim: sw=8 ts=8
char const *cvs_name = "$Name: $"; char const *cvs_name = "$Name: $";
char const *cvs_id_cli = "$Id: cli.c,v 1.62 2005/06/07 05:31:43 bodea Exp $"; char const *cvs_id_cli = "$Id: cli.c,v 1.63 2005/06/28 14:48:17 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
@ -2316,17 +2316,6 @@ static int cmd_restart_bgp(struct cli_def *cli, char *command, char **argv, int
#endif /* BGP*/ #endif /* BGP*/
static int filt; static int filt;
static int find_access_list(char const *name)
{
int i;
for (i = 0; i < MAXFILTER; i++)
if (!(*ip_filters[i].name && strcmp(ip_filters[i].name, name)))
return i;
return -1;
}
static int access_list(struct cli_def *cli, char **argv, int argc, int add) static int access_list(struct cli_def *cli, char **argv, int argc, int add)
{ {
int extended; int extended;
@ -2377,7 +2366,7 @@ static int access_list(struct cli_def *cli, char **argv, int argc, int add)
return CLI_OK; return CLI_OK;
} }
filt = find_access_list(argv[1]); filt = find_filter(argv[1], strlen(argv[1]));
if (add) if (add)
{ {
if (filt < 0) if (filt < 0)
@ -2970,7 +2959,7 @@ static int cmd_filter(struct cli_def *cli, char *command, char **argv, int argc)
return CLI_OK; return CLI_OK;
} }
v = find_access_list(argv[i+1]); v = find_filter(argv[i+1], strlen(argv[i+1]));
if (v < 0 || !*ip_filters[v].name) if (v < 0 || !*ip_filters[v].name)
{ {
cli_error(cli, "Access-list %s not defined", argv[i+1]); cli_error(cli, "Access-list %s not defined", argv[i+1]);
@ -3046,7 +3035,7 @@ static int cmd_show_access_list(struct cli_def *cli, char *command, char **argv,
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
int f = find_access_list(argv[i]); int f = find_filter(argv[i], strlen(argv[i]));
ip_filter_rulet *rules; ip_filter_rulet *rules;
if (f < 0 || !*ip_filters[f].name) if (f < 0 || !*ip_filters[f].name)

View file

@ -1,6 +1,6 @@
// L2TPNS Clustering Stuff // L2TPNS Clustering Stuff
char const *cvs_id_cluster = "$Id: cluster.c,v 1.43 2005/06/27 04:52:54 bodea Exp $"; char const *cvs_id_cluster = "$Id: cluster.c,v 1.44 2005/06/28 14:48:19 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -270,13 +270,8 @@ static int peer_send_message(in_addr_t peer, int type, int more, char *data, int
return peer_send_data(peer, buf, (p-buf) ); return peer_send_data(peer, buf, (p-buf) );
} }
// // send a packet to the master
// Forward a state changing packet to the master. static int _forward_packet(char *data, int size, in_addr_t addr, int port, int type)
//
// 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)
{ {
char buf[65536]; // Vast overkill. char buf[65536]; // Vast overkill.
char *p = buf; char *p = buf;
@ -287,13 +282,30 @@ int master_forward_packet(char *data, int size, in_addr_t addr, int port)
LOG(4, 0, 0, "Forwarding packet from %s to master (size %d)\n", fmtaddr(addr, 0), size); LOG(4, 0, 0, "Forwarding packet from %s to master (size %d)\n", fmtaddr(addr, 0), size);
STAT(c_forwarded); STAT(c_forwarded);
add_type(&p, C_FORWARD, addr, (char *) &port, sizeof(port)); // ick. should be uint16_t add_type(&p, type, addr, (char *) &port, sizeof(port)); // ick. should be uint16_t
memcpy(p, data, size); memcpy(p, data, size);
p += size; p += size;
return peer_send_data(config->cluster_master_address, buf, (p - buf)); return peer_send_data(config->cluster_master_address, buf, (p - buf));
} }
//
// Forward a state changing packet to the master.
//
// 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)
{
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)
{
return _forward_packet(data, size, addr, port, C_FORWARD_DAE);
}
// //
// Forward a throttled packet to the master for handling. // Forward a throttled packet to the master for handling.
// //
@ -1585,7 +1597,8 @@ int processcluster(char *data, int size, in_addr_t addr)
p += sizeof(uint32_t); p += sizeof(uint32_t);
s -= sizeof(uint32_t); s -= sizeof(uint32_t);
switch (type) { switch (type)
{
case C_PING: // Update the peers table. case C_PING: // Update the peers table.
return cluster_add_peer(addr, more, (pingt *) p, s); return cluster_add_peer(addr, more, (pingt *) p, s);
@ -1595,7 +1608,17 @@ int processcluster(char *data, int size, in_addr_t addr)
case C_LASTSEEN: // Catch up a slave (slave missed a packet). case C_LASTSEEN: // Catch up a slave (slave missed a packet).
return cluster_catchup_slave(more, addr); return cluster_catchup_slave(more, addr);
case C_FORWARD: { // Forwarded control packet. pass off to processudp. case C_FORWARD: // Forwarded control packet. pass off to processudp.
case C_FORWARD_DAE: // Forwarded DAE packet. pass off to processdae.
if (!config->cluster_iam_master)
{
LOG(0, 0, 0, "I'm not the master, but I got a C_FORWARD_%s from %s?\n",
type == C_FORWARD_DAE ? "_DAE" : "", fmtaddr(addr, 0));
return -1;
}
else
{
struct sockaddr_in a; struct sockaddr_in a;
a.sin_addr.s_addr = more; a.sin_addr.s_addr = more;
@ -1603,16 +1626,18 @@ int processcluster(char *data, int size, in_addr_t addr)
s -= sizeof(int); s -= sizeof(int);
p += sizeof(int); p += sizeof(int);
if (!config->cluster_iam_master) { // huh? LOG(4, 0, 0, "Got a forwarded %spacket... (%s:%d)\n",
LOG(0, 0, 0, "I'm not the master, but I got a C_FORWARD from %s?\n", fmtaddr(addr, 0)); type == C_FORWARD_DAE ? "DAE " : "", fmtaddr(more, 0), a.sin_port);
return -1;
}
LOG(4, 0, 0, "Got a forwarded packet... (%s:%d)\n", fmtaddr(more, 0), a.sin_port);
STAT(recv_forward); STAT(recv_forward);
if (type == C_FORWARD_DAE)
processdae(p, s, &a, sizeof(a));
else
processudp(p, s, &a); processudp(p, s, &a);
return 0; return 0;
} }
case C_THROTTLE: { // Receive a forwarded packet from a slave. case C_THROTTLE: { // Receive a forwarded packet from a slave.
if (!config->cluster_iam_master) { if (!config->cluster_iam_master) {
LOG(0, 0, 0, "I'm not the master, but I got a C_THROTTLE from %s?\n", fmtaddr(addr, 0)); LOG(0, 0, 0, "I'm not the master, but I got a C_THROTTLE from %s?\n", fmtaddr(addr, 0));

View file

@ -1,5 +1,5 @@
// L2TPNS Clustering Stuff // L2TPNS Clustering Stuff
// $Id: cluster.h,v 1.12 2005/06/02 11:32:30 bodea Exp $ // $Id: cluster.h,v 1.13 2005/06/28 14:48:19 bodea Exp $
#ifndef __CLUSTER_H__ #ifndef __CLUSTER_H__
#define __CLUSTER_H__ #define __CLUSTER_H__
@ -20,6 +20,7 @@
#define C_CTUNNEL 13 // Compressed tunnel structure. #define C_CTUNNEL 13 // Compressed tunnel structure.
#define C_GARDEN 14 // Gardened packet #define C_GARDEN 14 // Gardened packet
#define C_MASTER 15 // Tell a slave the address of the master. #define C_MASTER 15 // Tell a slave the address of the master.
#define C_FORWARD_DAE 16 // A DAE packet for the master to handle
#define HB_VERSION 5 // Protocol version number.. #define HB_VERSION 5 // Protocol version number..
#define HB_MAX_SEQ (1<<30) // Maximum sequence number. (MUST BE A POWER OF 2!) #define HB_MAX_SEQ (1<<30) // Maximum sequence number. (MUST BE A POWER OF 2!)
@ -75,6 +76,7 @@ int processcluster(char *buf, int size, in_addr_t addr);
int cluster_send_session(int sid); int cluster_send_session(int sid);
int cluster_send_tunnel(int tid); int cluster_send_tunnel(int tid);
int master_forward_packet(char *data, int size, in_addr_t addr, int port); 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_throttle_packet(int tid, char *data, int size);
int master_garden_packet(sessionidt s, char *data, int size); int master_garden_packet(sessionidt s, char *data, int size);
void master_update_counts(void); void master_update_counts(void);

View file

@ -1,6 +1,6 @@
// L2TPNS: constants // L2TPNS: constants
char const *cvs_id_constants = "$Id: constants.c,v 1.5 2005/05/05 10:02:07 bodea Exp $"; char const *cvs_id_constants = "$Id: constants.c,v 1.6 2005/06/28 14:48:20 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include "constants.h" #include "constants.h"
@ -173,8 +173,17 @@ CONSTANT(radius_code,
0, // 9 0, // 9
0, // 10 0, // 10
"Access-Challenge", // 11 "Access-Challenge", // 11
"Status-Server (experimental)", // 12 "Status-Server", // 12
"Status-Client (experimental)" // 13 "Status-Client", // 13
0, 0, 0, 0, 0, 0, // 14-19
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20-29
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30-39
"Disconnect-Request", // 40
"Disconnect-ACK", // 41
"Disconnect-NAK", // 42
"CoA-Request", // 43
"CoA-ACK", // 44
"CoA-NAK" // 45
) )
CONSTANT(l2tp_message_type, CONSTANT(l2tp_message_type,

103
l2tpns.c
View file

@ -4,7 +4,7 @@
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
// vim: sw=8 ts=8 // vim: sw=8 ts=8
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.112 2005/06/24 07:05:04 bodea Exp $"; char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.113 2005/06/28 14:48:20 bodea Exp $";
#include <arpa/inet.h> #include <arpa/inet.h>
#include <assert.h> #include <assert.h>
@ -60,6 +60,7 @@ int tunfd = -1; // tun interface file handle. (network device)
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 clifd = -1; // Socket listening for CLI connections. int clifd = -1; // Socket listening for CLI connections.
int daefd = -1; // Socket listening for DAE connections.
int snoopfd = -1; // UDP file handle for sending out intercept data int snoopfd = -1; // UDP file handle for sending out intercept data
int *radfds = NULL; // RADIUS requests file handles int *radfds = NULL; // RADIUS requests file handles
int ifrfd = -1; // File descriptor for routing, etc int ifrfd = -1; // File descriptor for routing, etc
@ -114,6 +115,7 @@ config_descriptt config_values[] = {
CONFIG("radius_interim", radius_interim, INT), CONFIG("radius_interim", radius_interim, INT),
CONFIG("radius_secret", radiussecret, STRING), CONFIG("radius_secret", radiussecret, STRING),
CONFIG("radius_authtypes", radius_authtypes_s, STRING), CONFIG("radius_authtypes", radius_authtypes_s, STRING),
CONFIG("radius_dae_port", radius_dae_port, SHORT),
CONFIG("allow_duplicate_users", allow_duplicate_users, BOOL), CONFIG("allow_duplicate_users", allow_duplicate_users, BOOL),
CONFIG("bind_address", bind_address, IPv4), CONFIG("bind_address", bind_address, IPv4),
CONFIG("peer_address", peer_address, IPv4), CONFIG("peer_address", peer_address, IPv4),
@ -148,6 +150,7 @@ static char *plugin_functions[] = {
"plugin_kill_session", "plugin_kill_session",
"plugin_control", "plugin_control",
"plugin_radius_response", "plugin_radius_response",
"plugin_radius_reset",
"plugin_become_master", "plugin_become_master",
"plugin_new_session_master", "plugin_new_session_master",
}; };
@ -578,7 +581,7 @@ static void inittun(void)
} }
} }
// set up UDP port // set up UDP ports
static void initudp(void) static void initudp(void)
{ {
int on = 1; int on = 1;
@ -600,7 +603,6 @@ static void initudp(void)
LOG(0, 0, 0, "Error in UDP bind: %s\n", strerror(errno)); LOG(0, 0, 0, "Error in UDP bind: %s\n", strerror(errno));
exit(1); exit(1);
} }
snoopfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// Control // Control
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
@ -613,6 +615,21 @@ static void initudp(void)
LOG(0, 0, 0, "Error in control bind: %s\n", strerror(errno)); LOG(0, 0, 0, "Error in control bind: %s\n", strerror(errno));
exit(1); exit(1);
} }
// Dynamic Authorization Extensions to RADIUS
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(config->radius_dae_port);
daefd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt(daefd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(daefd, (void *) &addr, sizeof(addr)) < 0)
{
LOG(0, 0, 0, "Error in DAE bind: %s\n", strerror(errno));
exit(1);
}
// Intercept
snoopfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
} }
// //
@ -1415,7 +1432,7 @@ void throttle_session(sessionidt s, int rate_in, int rate_out)
} }
// add/remove filters from session (-1 = no change) // add/remove filters from session (-1 = no change)
static void filter_session(sessionidt s, int filter_in, int filter_out) void filter_session(sessionidt s, int filter_in, int filter_out)
{ {
if (!session[s].opened) if (!session[s].opened)
return; // No-one home. return; // No-one home.
@ -2959,8 +2976,8 @@ static int still_busy(void)
# include "fake_epoll.h" # include "fake_epoll.h"
#endif #endif
// the base set of fds polled: control, cli, udp, tun, cluster // the base set of fds polled: cli, cluster, tun, udp, control, dae
#define BASE_FDS 5 #define BASE_FDS 6
// additional polled fds // additional polled fds
#ifdef BGP #ifdef BGP
@ -2984,8 +3001,8 @@ static void mainloop(void)
exit(1); exit(1);
} }
LOG(4, 0, 0, "Beginning of main loop. udpfd=%d, tunfd=%d, cluster_sockfd=%d, controlfd=%d\n", LOG(4, 0, 0, "Beginning of main loop. clifd=%d, cluster_sockfd=%d, tunfd=%d, udpfd=%d, controlfd=%d, daefd=%d\n",
udpfd, tunfd, cluster_sockfd, controlfd); clifd, cluster_sockfd, tunfd, udpfd, controlfd, daefd);
/* setup our fds to poll for input */ /* setup our fds to poll for input */
{ {
@ -2995,25 +3012,29 @@ static void mainloop(void)
e.events = EPOLLIN; e.events = EPOLLIN;
i = 0; i = 0;
d[i].type = FD_TYPE_CONTROL;
e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, controlfd, &e);
d[i].type = FD_TYPE_CLI; d[i].type = FD_TYPE_CLI;
e.data.ptr = &d[i++]; e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, clifd, &e); epoll_ctl(epollfd, EPOLL_CTL_ADD, clifd, &e);
d[i].type = FD_TYPE_UDP; d[i].type = FD_TYPE_CLUSTER;
e.data.ptr = &d[i++]; e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, udpfd, &e); epoll_ctl(epollfd, EPOLL_CTL_ADD, cluster_sockfd, &e);
d[i].type = FD_TYPE_TUN; d[i].type = FD_TYPE_TUN;
e.data.ptr = &d[i++]; e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, tunfd, &e); epoll_ctl(epollfd, EPOLL_CTL_ADD, tunfd, &e);
d[i].type = FD_TYPE_CLUSTER; d[i].type = FD_TYPE_UDP;
e.data.ptr = &d[i++]; e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, cluster_sockfd, &e); epoll_ctl(epollfd, EPOLL_CTL_ADD, udpfd, &e);
d[i].type = FD_TYPE_CONTROL;
e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, controlfd, &e);
d[i].type = FD_TYPE_DAE;
e.data.ptr = &d[i++];
epoll_ctl(epollfd, EPOLL_CTL_ADD, daefd, &e);
} }
#ifdef BGP #ifdef BGP
@ -3080,12 +3101,6 @@ static void mainloop(void)
struct event_data *d = events[i].data.ptr; struct event_data *d = events[i].data.ptr;
switch (d->type) switch (d->type)
{ {
case FD_TYPE_CONTROL: // nsctl commands
alen = sizeof(addr);
processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen);
n--;
break;
case FD_TYPE_CLI: // CLI connections case FD_TYPE_CLI: // CLI connections
{ {
int cli; int cli;
@ -3104,9 +3119,21 @@ static void mainloop(void)
} }
// these are handled below, with multiple interleaved reads // these are handled below, with multiple interleaved reads
case FD_TYPE_UDP: udp_ready++; break;
case FD_TYPE_TUN: tun_ready++; break;
case FD_TYPE_CLUSTER: cluster_ready++; break; case FD_TYPE_CLUSTER: cluster_ready++; break;
case FD_TYPE_TUN: tun_ready++; break;
case FD_TYPE_UDP: udp_ready++; break;
case FD_TYPE_CONTROL: // nsctl commands
alen = sizeof(addr);
processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen);
n--;
break;
case FD_TYPE_DAE: // DAE requests
alen = sizeof(addr);
processdae(buf, recvfrom(daefd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen);
n--;
break;
case FD_TYPE_RADIUS: // RADIUS response case FD_TYPE_RADIUS: // RADIUS response
s = recv(radfds[d->index], buf, sizeof(buf), 0); s = recv(radfds[d->index], buf, sizeof(buf), 0);
@ -4186,6 +4213,9 @@ static void update_config()
strcat(config->radius_authtypes_s, ", pap"); strcat(config->radius_authtypes_s, ", pap");
} }
if (!config->radius_dae_port)
config->radius_dae_port = DAEPORT;
// re-initialise the random number source // re-initialise the random number source
initrandom(config->random_device); initrandom(config->random_device);
@ -5044,6 +5074,31 @@ static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vec
} }
} }
int find_filter(char const *name, size_t len)
{
int free = -1;
int i;
for (i = 0; i < MAXFILTER; i++)
{
if (!*ip_filters[i].name)
{
if (free < 0)
free = i;
continue;
}
if (strlen(ip_filters[i].name) != len)
continue;
if (!strncmp(ip_filters[i].name, name, len))
return i;
}
return free;
}
static int ip_filter_port(ip_filter_portt *p, uint16_t port) static int ip_filter_port(ip_filter_portt *p, uint16_t port)
{ {
switch (p->op) switch (p->op)

View file

@ -1,5 +1,5 @@
// L2TPNS Global Stuff // L2TPNS Global Stuff
// $Id: l2tpns.h,v 1.79 2005/06/24 07:05:04 bodea Exp $ // $Id: l2tpns.h,v 1.80 2005/06/28 14:48:27 bodea Exp $
#ifndef __L2TPNS_H__ #ifndef __L2TPNS_H__
#define __L2TPNS_H__ #define __L2TPNS_H__
@ -76,6 +76,7 @@
#define ACCT_SHUT_TIME 600 // 1 minute for counters of shutdown sessions #define ACCT_SHUT_TIME 600 // 1 minute for counters of shutdown sessions
#define L2TPPORT 1701 // L2TP port #define L2TPPORT 1701 // L2TP port
#define RADPORT 1645 // old radius port... #define RADPORT 1645 // old radius port...
#define DAEPORT 3799 // DAE port
#define PKTARP 0x0806 // ARP packet type #define PKTARP 0x0806 // ARP packet type
#define PKTIP 0x0800 // IPv4 packet type #define PKTIP 0x0800 // IPv4 packet type
#define PKTIPV6 0x86DD // IPv6 packet type #define PKTIPV6 0x86DD // IPv6 packet type
@ -111,7 +112,13 @@ enum {
AccessReject, AccessReject,
AccountingRequest, AccountingRequest,
AccountingResponse, AccountingResponse,
AccessChallenge = 11 AccessChallenge = 11,
DisconnectRequest = 40,
DisconnectACK,
DisconnectNAK,
CoARequest,
CoAACK,
CoANAK
}; };
// Types // Types
@ -457,6 +464,8 @@ typedef struct
uint16_t radiusport[MAXRADSERVER]; // radius base ports uint16_t radiusport[MAXRADSERVER]; // radius base ports
uint8_t numradiusservers; // radius server count uint8_t numradiusservers; // radius server count
uint16_t radius_dae_port; // local port for radius dae
char radius_authtypes_s[32]; // list of valid authentication types (chap, pap) in order of preference char radius_authtypes_s[32]; // list of valid authentication types (chap, pap) in order of preference
int radius_authtypes; int radius_authtypes;
int radius_authprefer; int radius_authprefer;
@ -611,6 +620,7 @@ void processrad(uint8_t *buf, int len, char socket_index);
void radiusretry(uint16_t r); void radiusretry(uint16_t r);
uint16_t radiusnew(sessionidt s); uint16_t radiusnew(sessionidt s);
void radiusclear(uint16_t r, sessionidt s); void radiusclear(uint16_t r, sessionidt s);
void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen);
// l2tpns.c // l2tpns.c
@ -624,11 +634,13 @@ void increment_counter(uint32_t *counter, uint32_t *wrap, uint32_t delta);
void random_data(uint8_t *buf, int len); void random_data(uint8_t *buf, int len);
void sessionkill(sessionidt s, char *reason); void sessionkill(sessionidt s, char *reason);
void sessionshutdown(sessionidt s, char *reason, int result, int error); void sessionshutdown(sessionidt s, char *reason, int result, int error);
void filter_session(sessionidt s, int filter_in, int filter_out);
void send_garp(in_addr_t ip); void send_garp(in_addr_t ip);
void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t); void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
void sendipcp(tunnelidt t, sessionidt s); void sendipcp(tunnelidt t, sessionidt s);
void processudp(uint8_t *buf, int len, struct sockaddr_in *addr); 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(char *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 ip_filter(uint8_t *buf, int len, uint8_t filter);
int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc); int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc);
int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc); int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc);
@ -696,11 +708,12 @@ extern int epollfd;
struct event_data { struct event_data {
enum { enum {
FD_TYPE_CONTROL,
FD_TYPE_CLI, FD_TYPE_CLI,
FD_TYPE_UDP,
FD_TYPE_TUN,
FD_TYPE_CLUSTER, FD_TYPE_CLUSTER,
FD_TYPE_TUN,
FD_TYPE_UDP,
FD_TYPE_CONTROL,
FD_TYPE_DAE,
FD_TYPE_RADIUS, FD_TYPE_RADIUS,
FD_TYPE_BGP, FD_TYPE_BGP,
} type; } type;

View file

@ -43,5 +43,5 @@ rm -rf %{buildroot}
%attr(644,root,root) /usr/share/man/man[58]/* %attr(644,root,root) /usr/share/man/man[58]/*
%changelog %changelog
* Mon Jun 27 2005 Brendan O'Dea <bod@optus.net> 2.1.2-1 * Wed Jun 29 2005 Brendan O'Dea <bod@c47.org> 2.1.2-1
- 2.1.2 release, see /usr/share/doc/l2tpns-2.1.2/Changes - 2.1.2 release, see /usr/share/doc/l2tpns-2.1.2/Changes

View file

@ -1,7 +1,7 @@
#ifndef __PLUGIN_H__ #ifndef __PLUGIN_H__
#define __PLUGIN_H__ #define __PLUGIN_H__
#define PLUGIN_API_VERSION 5 #define PLUGIN_API_VERSION 6
#define MAX_PLUGIN_TYPES 30 #define MAX_PLUGIN_TYPES 30
enum enum
@ -15,6 +15,7 @@ enum
PLUGIN_KILL_SESSION, PLUGIN_KILL_SESSION,
PLUGIN_CONTROL, PLUGIN_CONTROL,
PLUGIN_RADIUS_RESPONSE, PLUGIN_RADIUS_RESPONSE,
PLUGIN_RADIUS_RESET,
PLUGIN_BECOME_MASTER, PLUGIN_BECOME_MASTER,
PLUGIN_NEW_SESSION_MASTER, PLUGIN_NEW_SESSION_MASTER,
}; };
@ -111,4 +112,10 @@ struct param_radius_response
char *value; char *value;
}; };
struct param_radius_reset
{
tunnelt *t;
sessiont *s;
};
#endif /* __PLUGIN_H__ */ #endif /* __PLUGIN_H__ */

424
radius.c
View file

@ -1,6 +1,6 @@
// L2TPNS Radius Stuff // L2TPNS Radius Stuff
char const *cvs_id_radius = "$Id: radius.c,v 1.33 2005/06/04 15:42:36 bodea Exp $"; char const *cvs_id_radius = "$Id: radius.c,v 1.34 2005/06/28 14:48:28 bodea Exp $";
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
@ -12,11 +12,13 @@ char const *cvs_id_radius = "$Id: radius.c,v 1.33 2005/06/04 15:42:36 bodea Exp
#include <arpa/inet.h> #include <arpa/inet.h>
#include <ctype.h> #include <ctype.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <errno.h>
#include "md5.h" #include "md5.h"
#include "constants.h" #include "constants.h"
#include "l2tpns.h" #include "l2tpns.h"
#include "plugin.h" #include "plugin.h"
#include "util.h" #include "util.h"
#include "cluster.h"
extern radiust *radius; extern radiust *radius;
extern sessiont *session; extern sessiont *session;
@ -51,7 +53,7 @@ static uint16_t get_free_radius()
int count; int count;
static uint32_t next_radius_id = 0; static uint32_t next_radius_id = 0;
for (count = MAXRADIUS; count > 0 ; --count) for (count = MAXRADIUS; count > 0; --count)
{ {
++next_radius_id; // Find the next ID to check. ++next_radius_id; // Find the next ID to check.
if (next_radius_id >= MAXRADIUS) if (next_radius_id >= MAXRADIUS)
@ -296,7 +298,7 @@ void radiussend(uint16_t r, uint8_t state)
{ {
*p = 26; // vendor-specific *p = 26; // vendor-specific
*(uint32_t *) (p + 2) = htonl(9); // Cisco *(uint32_t *) (p + 2) = htonl(9); // Cisco
p[6] = 1; // Cisco-Avpair p[6] = 1; // Cisco-AVPair
p[7] = 2 + sprintf(p + 8, "intercept=%s:%d", p[7] = 2 + sprintf(p + 8, "intercept=%s:%d",
fmtaddr(session[s].snoop_ip, 0), session[s].snoop_port); fmtaddr(session[s].snoop_ip, 0), session[s].snoop_port);
@ -377,6 +379,47 @@ void radiussend(uint16_t r, uint8_t state)
sendto(radfds[r & RADIUS_MASK], b, p - b, 0, (void *) &addr, sizeof(addr)); sendto(radfds[r & RADIUS_MASK], b, p - b, 0, (void *) &addr, sizeof(addr));
} }
static void handle_avpair(sessionidt s, uint8_t *avp, int len)
{
char *key = avp;
char *value = memchr(avp, '=', len);
char tmp[2048] = "";
if (value)
{
*value++ = 0;
len -= value - key;
}
else
{
value = tmp;
len = 0;
}
// strip quotes
if (len > 2 && (*value == '"' || *value == '\'') && value[len - 1] == *value)
{
value++;
len--;
value[len - 1] = 0;
}
// copy and null terminate
else if (len < sizeof(tmp) - 1)
{
memcpy(tmp, value, len);
tmp[len] = 0;
value = tmp;
}
else
return;
// Run hooks
{
struct param_radius_response p = { &tunnel[session[s].tunnel], &session[s], key, value };
run_plugins(PLUGIN_RADIUS_RESPONSE, &p);
}
}
// process RADIUS response // process RADIUS response
void processrad(uint8_t *buf, int len, char socket_index) void processrad(uint8_t *buf, int len, char socket_index)
{ {
@ -577,37 +620,36 @@ void processrad(uint8_t *buf, int len, char socket_index)
char *filter = p + 2; char *filter = p + 2;
int l = p[1] - 2; int l = p[1] - 2;
char *suffix; char *suffix;
uint8_t *f = 0; int f;
int i; uint8_t *fp = 0;
LOG(3, s, session[s].tunnel, " Radius reply contains Filter-Id \"%.*s\"\n", l, filter); LOG(3, s, session[s].tunnel, " Radius reply contains Filter-Id \"%.*s\"\n", l, filter);
if ((suffix = memchr(filter, '.', l))) if ((suffix = memchr(filter, '.', l)))
{ {
int b = suffix - filter; int b = suffix - filter;
if (l - b == 3 && !memcmp("in", suffix+1, 2)) if (l - b == 3 && !memcmp("in", suffix+1, 2))
f = &session[s].filter_in; fp = &session[s].filter_in;
else if (l - b == 4 && !memcmp("out", suffix+1, 3)) else if (l - b == 4 && !memcmp("out", suffix+1, 3))
f = &session[s].filter_out; fp = &session[s].filter_out;
l = b; l = b;
} }
if (!f) if (!fp)
{ {
LOG(3, s, session[s].tunnel, " Invalid filter\n"); LOG(3, s, session[s].tunnel, " Invalid filter\n");
continue; continue;
} }
for (*f = 0, i = 0; !*f && i < MAXFILTER; i++) if ((f = find_filter(filter, l)) < 0 || !*ip_filters[f].name)
if (strlen(ip_filters[i].name) == l && {
!strncmp(ip_filters[i].name, filter, l))
*f = i + 1;
if (*f)
ip_filters[*f - 1].used++;
else
LOG(3, s, session[s].tunnel, " Unknown filter\n"); LOG(3, s, session[s].tunnel, " Unknown filter\n");
}
else
{
*fp = f + 1;
ip_filters[f].used++;
}
} }
else if (*p == 26 && p[1] >= 7) else if (*p == 26 && p[1] >= 7)
{ {
@ -615,7 +657,6 @@ void processrad(uint8_t *buf, int len, char socket_index)
int vendor = ntohl(*(int *)(p + 2)); int vendor = ntohl(*(int *)(p + 2));
char attrib = *(p + 6); char attrib = *(p + 6);
int attrib_length = *(p + 7) - 2; int attrib_length = *(p + 7) - 2;
char *avpair, *value, *key, *newp;
LOG(3, s, session[s].tunnel, " Radius reply contains Vendor-Specific. Vendor=%d Attrib=%d Length=%d\n", vendor, attrib, attrib_length); LOG(3, s, session[s].tunnel, " Radius reply contains Vendor-Specific. Vendor=%d Attrib=%d Length=%d\n", vendor, attrib, attrib_length);
if (vendor != 9 || attrib != 1) if (vendor != 9 || attrib != 1)
@ -624,36 +665,13 @@ void processrad(uint8_t *buf, int len, char socket_index)
continue; continue;
} }
if (attrib_length < 0) continue; if (attrib_length > 0)
avpair = key = calloc(attrib_length + 1, 1);
memcpy(avpair, p + 8, attrib_length);
LOG(3, s, session[s].tunnel, " Cisco-Avpair value: %s\n", avpair);
do {
value = strchr(key, '=');
if (!value) break;
*value++ = 0;
// Trim quotes off reply string
if (*value == '\'' || *value == '\"')
{ {
char *x; LOG(3, s, session[s].tunnel, " Cisco-AVPair value: %.*s\n",
value++; attrib_length, p + 8);
x = value + strlen(value) - 1;
if (*x == '\'' || *x == '\"')
*x = 0;
}
// Run hooks handle_avpair(s, p + 8, attrib_length);
newp = strchr(value, ',');
if (newp) *newp++ = 0;
{
struct param_radius_response p = { &tunnel[session[s].tunnel], &session[s], key, value };
run_plugins(PLUGIN_RADIUS_RESPONSE, &p);
} }
key = newp;
} while (newp);
free(avpair);
} }
else if (*p == 99) else if (*p == 99)
{ {
@ -756,3 +774,319 @@ void radiusretry(uint16_t r)
break; break;
} }
} }
extern int daefd;
void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen)
{
int i, r_code, r_id, length, attribute_length;
uint8_t vector[16], hash[16], *packet, attribute;
MD5_CTX ctx;
char username[MAXUSER] = "";
in_addr_t nas = 0;
in_addr_t ip = 0;
uint32_t port = 0;
uint32_t error = 0;
sessionidt s = 0;
tunnelidt t;
int fin = -1;
int fout = -1;
uint8_t *avpair[64];
int avpair_len[sizeof(avpair)/sizeof(*avpair)];
int avp = 0;
int auth_only = 0;
uint8_t *p;
LOG(3, 0, 0, "DAE request from %s\n", fmtaddr(addr->sin_addr.s_addr, 0));
// check if DAE is from RADIUS server
for (i = 0; i < config->numradiusservers; i++)
if (config->radiusserver[i] == addr -> sin_addr.s_addr)
break;
if (i >= config->numradiusservers)
{
LOG(1, 0, 0, "Unknown DAE client %s\n", fmtaddr(addr->sin_addr.s_addr, 0));
return;
}
LOG_HEX(5, "DAE Request", buf, len);
if (len < 20 || len < ntohs(*(uint16_t *) (buf + 2)))
{
LOG(1, 0, 0, "Duff DAE request length %d\n", len);
return;
}
r_code = buf[0]; // request type
r_id = buf[1]; // radius indentifier.
if (r_code != DisconnectRequest && r_code != CoARequest)
{
LOG(1, 0, 0, "Unrecognised DAE request %s\n", radius_code(r_code));
return;
}
if (!config->cluster_iam_master)
{
master_forward_dae_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port);
return;
}
len = ntohs(*(uint16_t *) (buf + 2));
LOG(3, 0, 0, "Received DAE %s, id %d\n", radius_code(r_code), r_id);
// check authenticator
memcpy(vector, buf + 4, 16);
memset(buf + 4, 0, 16);
i = strlen(config->radiussecret);
if (i > 16) i = 16;
MD5Init(&ctx);
MD5Update(&ctx, buf, len);
MD5Update(&ctx, buf, config->radiussecret, i);
MD5Final(hash, &ctx);
if (memcmp(hash, vector, 16) != 0)
{
LOG(1, 0, 0, "Incorrect vector in DAE request (wrong secret in radius config?)\n");
return;
}
// unpack attributes
packet = buf + 20;
length = len - 20;
while (length > 0)
{
attribute = *packet++;
attribute_length = *packet++;
if (attribute_length < 2)
break;
length -= attribute_length;
attribute_length -= 2;
switch (attribute)
{
case 1: /* username */
len = attribute_length < MAXUSER ? attribute_length : MAXUSER - 1;
memcpy(username, packet, len);
username[len] = 0;
LOG(4, 0, 0, " Received DAE User-Name: %s\n", username);
break;
case 4: /* nas ip address */
nas = *(uint32_t *) packet; // net order
if (nas != config->bind_address)
error = 403; // NAS identification mismatch
LOG(4, 0, 0, " Received DAE NAS-IP-Address: %s\n", fmtaddr(nas, 0));
break;
case 5: /* nas port */
port = ntohl(*(uint32_t *) packet);
if (port < 1 || port > MAXSESSION)
error = 404;
LOG(4, 0, 0, " Received DAE NAS-Port: %u\n", port);
break;
case 6: /* service type */
{
uint32_t service_type = ntohl(*(uint32_t *) packet);
auth_only = service_type == 8; // Authenticate only
LOG(4, 0, 0, " Received DAE Service-Type: %u\n", service_type);
}
break;
case 8: /* ip address */
ip = *(uint32_t *) packet; // net order
LOG(4, 0, 0, " Received DAE Framed-IP-Address: %s\n", fmtaddr(ip, 0));
break;
case 11: /* filter id */
LOG(4, 0, 0, " Received DAE Filter-Id: %.*s\n", attribute_length, packet);
if (!(p = memchr(packet, '.', attribute_length)))
{
error = 404; // invalid request
break;
}
len = p - packet;
i = find_filter(packet, len);
if (i < 0 || !*ip_filters[i].name)
{
error = 404;
break;
}
if (!memcmp(p, ".in", attribute_length - len))
fin = i + 1;
else if (!memcmp(p, ".out", attribute_length - len))
fout = i + 1;
else
error = 404;
break;
case 26: /* vendor specific */
if (attribute_length >= 6
&& ntohl(*(uint32_t *) packet) == 9 // Cisco
&& *(packet + 4) == 1 // Cisco-AVPair
&& *(packet + 5) >= 2) // length
{
int len = *(packet + 5) - 2;
uint8_t *a = packet + 6;
LOG(4, 0, 0, " Received DAE Cisco-AVPair: %.*s\n", len, a);
if (avp < sizeof(avpair)/sizeof(*avpair) - 1)
{
avpair[avp] = a;
avpair_len[avp++] = len;
}
}
break;
}
packet += attribute_length;
}
if (!error && auth_only)
{
if (fin != -1 || fout != -1 || avp)
error = 401; // unsupported attribute
else
error = 405; // unsupported service
}
if (!error && !(port || ip || *username))
error = 402; // missing attribute
// exact match for SID if given
if (!error && port)
{
s = port;
if (!session[s].opened)
error = 503; // not found
}
if (!error && ip)
{
// find/check session by IP
i = sessionbyip(ip);
if (!i || (s && s != i)) // not found or mismatching port
error = 503;
else
s = i;
}
if (!error && *username)
{
if (s)
{
if (strcmp(session[s].user, username))
error = 503;
}
else if (!(s = sessionbyuser(username)))
error = 503;
}
t = session[s].tunnel;
switch (r_code)
{
case DisconnectRequest: // Packet of Disconnect/Death
if (error)
{
r_code = DisconnectNAK;
break;
}
LOG(3, s, t, " DAE Disconnect %d (%s)\n", s, session[s].user);
r_code = DisconnectACK;
sessionshutdown(s, "Requested by PoD", 3, 0); // disconnect session
break;
case CoARequest: // Change of Authorization
if (error)
{
r_code = CoANAK;
break;
}
LOG(3, s, t, " DAE Change %d (%s)\n", s, session[s].user);
r_code = CoAACK;
// reset
{
struct param_radius_reset p = { &tunnel[session[s].tunnel], &session[s] };
run_plugins(PLUGIN_RADIUS_RESET, &p);
}
// apply filters
if (fin != -1 || fout != -1)
{
if (fin == -1)
fin = 0;
else
LOG(3, s, t, " Filter in %d (%s)\n", fin, ip_filters[fin - 1].name);
if (fout == -1)
fout = 0;
else
LOG(3, s, t, " Filter out %d (%s)\n", fout, ip_filters[fout - 1].name);
filter_session(s, fin, fout);
}
// process cisco av-pair(s)
for (i = 0; i < avp; i++)
{
LOG(3, s, t, " Cisco-AVPair: %.*s\n", avpair_len[i], avpair[i]);
handle_avpair(s, avpair[i], avpair_len[i]);
}
cluster_send_session(s);
break;
}
// send response
packet = buf;
*packet++ = r_code;
*packet++ = r_id;
packet += 2;
memset(packet, 0, 16);
packet += 16;
len = 20;
// add attributes
if (error)
{
// add error cause
*packet++ = 101;
*packet++ = 6;
*(uint32_t *) packet = htonl(error);
len += 6;
}
*((uint16_t *)(buf + 2)) = htons(len);
// make vector
i = strlen(config->radiussecret);
if (i > 16) i = 16;
MD5Init(&ctx);
MD5Update(&ctx, buf, len);
MD5Update(&ctx, config->radiussecret, i);
MD5Final(hash, &ctx);
memcpy(buf + 4, hash, 16);
LOG(3, 0, 0, "Sending DAE %s, id=%d\n", radius_code(r_code), r_id);
// send DAE response
if (sendto(daefd, buf, len, MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *) addr, alen) < 0)
LOG(0, 0, 0, "Error sending DAE response packet: %s\n", strerror(errno));
}

View file

@ -5,7 +5,7 @@
/* session control */ /* session control */
char const *cvs_id = "$Id: sessionctl.c,v 1.2 2005/05/10 06:48:16 bodea Exp $"; char const *cvs_id = "$Id: sessionctl.c,v 1.3 2005/06/28 14:48:28 bodea Exp $";
int plugin_api_version = PLUGIN_API_VERSION; int plugin_api_version = PLUGIN_API_VERSION;
static struct pluginfuncs *p = 0; static struct pluginfuncs *p = 0;
@ -16,15 +16,6 @@ char *plugin_control_help[] = {
0 0
}; };
int plugin_init(struct pluginfuncs *funcs)
{
if (!funcs)
return 0;
p = funcs;
return 1;
}
int plugin_control(struct param_control *data) int plugin_control(struct param_control *data)
{ {
sessionidt session; sessionidt session;
@ -76,3 +67,8 @@ int plugin_control(struct param_control *data)
return PLUGIN_RET_STOP; return PLUGIN_RET_STOP;
} }
int plugin_init(struct pluginfuncs *funcs)
{
return ((p = funcs)) ? 1 : 0;
}

View file

@ -5,7 +5,7 @@
/* snoop control */ /* snoop control */
char const *cvs_id = "$Id: snoopctl.c,v 1.4 2004/12/16 08:49:53 bodea Exp $"; char const *cvs_id = "$Id: snoopctl.c,v 1.5 2005/06/28 14:48:28 bodea Exp $";
int plugin_api_version = PLUGIN_API_VERSION; int plugin_api_version = PLUGIN_API_VERSION;
static struct pluginfuncs *p = 0; static struct pluginfuncs *p = 0;
@ -16,15 +16,6 @@ char *plugin_control_help[] = {
0 0
}; };
int plugin_init(struct pluginfuncs *funcs)
{
if (!funcs)
return 0;
p = funcs;
return 1;
}
int plugin_control(struct param_control *data) int plugin_control(struct param_control *data)
{ {
sessionidt session; sessionidt session;
@ -124,3 +115,15 @@ int plugin_control(struct param_control *data)
return PLUGIN_RET_STOP; return PLUGIN_RET_STOP;
} }
int plugin_radius_reset(struct param_radius_reset *data)
{
data->s->snoop_ip = 0;
data->s->snoop_port = 0;
return PLUGIN_RET_OK;
}
int plugin_init(struct pluginfuncs *funcs)
{
return ((p = funcs)) ? 1 : 0;
}

View file

@ -5,7 +5,7 @@
/* throttle control */ /* throttle control */
char const *cvs_id = "$Id: throttlectl.c,v 1.6 2004/12/01 04:44:29 bodea Exp $"; char const *cvs_id = "$Id: throttlectl.c,v 1.7 2005/06/28 14:48:28 bodea Exp $";
int plugin_api_version = PLUGIN_API_VERSION; int plugin_api_version = PLUGIN_API_VERSION;
static struct pluginfuncs *p = 0; static struct pluginfuncs *p = 0;
@ -16,15 +16,6 @@ char *plugin_control_help[] = {
0 0
}; };
int plugin_init(struct pluginfuncs *funcs)
{
if (!funcs)
return 0;
p = funcs;
return 1;
}
int plugin_control(struct param_control *data) int plugin_control(struct param_control *data)
{ {
sessionidt session; sessionidt session;
@ -137,3 +128,14 @@ int plugin_control(struct param_control *data)
return PLUGIN_RET_STOP; return PLUGIN_RET_STOP;
} }
int plugin_radius_reset(struct param_radius_reset *data)
{
p->throttle(p->get_id_by_session(data->s), 0, 0);
return PLUGIN_RET_OK;
}
int plugin_init(struct pluginfuncs *funcs)
{
return ((p = funcs)) ? 1 : 0;
}

9
util.c
View file

@ -1,6 +1,6 @@
/* Misc util functions */ /* Misc util functions */
char const *cvs_id_util = "$Id: util.c,v 1.11 2005/06/04 15:42:36 bodea Exp $"; char const *cvs_id_util = "$Id: util.c,v 1.12 2005/06/28 14:48:28 bodea Exp $";
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -40,7 +40,7 @@ void *shared_malloc(unsigned int size)
} }
extern int forked; extern int forked;
extern int udpfd, controlfd, tunfd, snoopfd, ifrfd, ifr6fd, rand_fd, cluster_sockfd; extern int cluster_sockfd, tunfd, udpfd, controlfd, daefd, snoopfd, ifrfd, ifr6fd, rand_fd;
extern int *radfds; extern int *radfds;
pid_t fork_and_close() pid_t fork_and_close()
@ -73,15 +73,16 @@ pid_t fork_and_close()
signal(SIGTERM, SIG_DFL); signal(SIGTERM, SIG_DFL);
// Close sockets // Close sockets
if (clifd != -1) close(clifd);
if (cluster_sockfd != -1) close(cluster_sockfd);
if (tunfd != -1) close(tunfd); if (tunfd != -1) close(tunfd);
if (udpfd != -1) close(udpfd); if (udpfd != -1) close(udpfd);
if (controlfd != -1) close(controlfd); if (controlfd != -1) close(controlfd);
if (daefd != -1) close(daefd);
if (snoopfd != -1) close(snoopfd); if (snoopfd != -1) close(snoopfd);
if (ifrfd != -1) close(ifrfd); if (ifrfd != -1) close(ifrfd);
if (ifr6fd != -1) close(ifr6fd); if (ifr6fd != -1) close(ifr6fd);
if (rand_fd != -1) close(rand_fd); if (rand_fd != -1) close(rand_fd);
if (cluster_sockfd != -1) close(cluster_sockfd);
if (clifd != -1) close(clifd);
if (epollfd != -1) close(epollfd); if (epollfd != -1) close(epollfd);
for (i = 0; radfds && i < RADIUS_FDS; i++) for (i = 0; radfds && i < RADIUS_FDS; i++)