add Acct-Terminate-Cause to RADIUS stop records

This commit is contained in:
Brendan O'Dea 2006-04-13 11:14:35 +00:00
parent 0251304ce2
commit 1b6a7a95e6
8 changed files with 186 additions and 50 deletions

View file

@ -1,8 +1,9 @@
* Wed Apr 5 2006 Brendan O'Dea <bod@optus.net> 2.1.17 * Thu Apr 13 2006 Brendan O'Dea <bod@optus.net> 2.1.17
- Fix IPCP length test to allow Terminate-Request (4 bytes). - Fix IPCP length test to allow Terminate-Request (4 bytes).
- Send nsctl responses back using the correct source address (thanks ltd). - Send nsctl responses back using the correct source address (thanks ltd).
- Similarly set the source for DAE responses; use bind_address when - Similarly set the source for DAE responses; use bind_address when
handling forwarded packets on the master. handling forwarded packets on the master.
- Add Acct-Terminate-Cause to RADIUS stop records.
* Thu Feb 23 2006 Brendan O'Dea <bod@optus.net> 2.1.16 * Thu Feb 23 2006 Brendan O'Dea <bod@optus.net> 2.1.16
- Send configured magic-no in LCP EchoReq when LCP is opened. - Send configured magic-no in LCP EchoReq when LCP is opened.

123
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.159 2006-04-05 02:13:48 bodea Exp $"; char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.160 2006-04-13 11:14:35 bodea Exp $";
#include <arpa/inet.h> #include <arpa/inet.h>
#include <assert.h> #include <assert.h>
@ -1559,7 +1559,7 @@ void filter_session(sessionidt s, int filter_in, int filter_out)
} }
// start tidy shutdown of session // start tidy shutdown of session
void sessionshutdown(sessionidt s, char *reason, int result, int error) void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_error, int term_cause)
{ {
int walled_garden = session[s].walled_garden; int walled_garden = session[s].walled_garden;
@ -1587,8 +1587,12 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
{ {
// stop, if not already trying // stop, if not already trying
if (radius[r].state != RADIUSSTOP) if (radius[r].state != RADIUSSTOP)
{
radius[r].term_cause = term_cause;
radius[r].term_msg = reason;
radiussend(r, RADIUSSTOP); radiussend(r, RADIUSSTOP);
} }
}
else else
LOG(1, s, session[s].tunnel, "No free RADIUS sessions for Stop message\n"); LOG(1, s, session[s].tunnel, "No free RADIUS sessions for Stop message\n");
@ -1627,18 +1631,18 @@ void sessionshutdown(sessionidt s, char *reason, int result, int error)
if (session[s].throttle_in || session[s].throttle_out) // Unthrottle if throttled. if (session[s].throttle_in || session[s].throttle_out) // Unthrottle if throttled.
throttle_session(s, 0, 0); throttle_session(s, 0, 0);
if (result) if (cdn_result)
{ // Send CDN { // Send CDN
controlt *c = controlnew(14); // sending CDN controlt *c = controlnew(14); // sending CDN
if (error) if (cdn_error)
{ {
uint8_t buf[4]; uint8_t buf[4];
*(uint16_t *) buf = htons(result); *(uint16_t *) buf = htons(cdn_result);
*(uint16_t *) (buf+2) = htons(error); *(uint16_t *) (buf+2) = htons(cdn_error);
controlb(c, 1, buf, 4, 1); controlb(c, 1, buf, 4, 1);
} }
else else
control16(c, 1, result, 1); control16(c, 1, cdn_result, 1);
control16(c, 14, s, 1); // assigned session (our end) control16(c, 14, s, 1); // assigned session (our end)
controladd(c, session[s].far, session[s].tunnel); // send the message controladd(c, session[s].far, session[s].tunnel); // send the message
@ -1744,7 +1748,7 @@ void sessionkill(sessionidt s, char *reason)
} }
session[s].die = TIME; session[s].die = TIME;
sessionshutdown(s, reason, 3, 0); // close radius/routes, etc. sessionshutdown(s, reason, CDN_ADMIN_DISC, TERM_ADMIN_RESET); // close radius/routes, etc.
if (sess_local[s].radius) if (sess_local[s].radius)
radiusclear(sess_local[s].radius, s); // cant send clean accounting data, session is killed radiusclear(sess_local[s].radius, s); // cant send clean accounting data, session is killed
@ -1809,7 +1813,7 @@ static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, cha
// close session // close session
for (s = 1; s <= config->cluster_highest_sessionid ; ++s) for (s = 1; s <= config->cluster_highest_sessionid ; ++s)
if (session[s].tunnel == t) if (session[s].tunnel == t)
sessionshutdown(s, reason, 0, 0); sessionshutdown(s, reason, CDN_NONE, TERM_ADMIN_RESET);
tunnel[t].state = TUNNELDIE; tunnel[t].state = TUNNELDIE;
tunnel[t].die = TIME + 700; // Clean up in 70 seconds tunnel[t].die = TIME + 700; // Clean up in 70 seconds
@ -2048,6 +2052,12 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
int error = 0; int error = 0;
char *msg = 0; char *msg = 0;
// default disconnect cause/message on receipt
// of CDN (set to more specific value from
// attribute 46 if present below).
int disc_cause = TERM_NAS_REQUEST;
char const *disc_reason = "Closed (Received CDN).";
// process AVPs // process AVPs
while (l && !(fatal & 0x80)) // 0x80 = mandatory AVP while (l && !(fatal & 0x80)) // 0x80 = mandatory AVP
{ {
@ -2055,6 +2065,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
uint8_t *b = p; uint8_t *b = p;
uint8_t flags = *p; uint8_t flags = *p;
uint16_t mtype; uint16_t mtype;
if (n > l) if (n > l)
{ {
LOG(1, s, t, "Invalid length in AVP\n"); LOG(1, s, t, "Invalid length in AVP\n");
@ -2191,17 +2202,13 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
} }
break; break;
case 3: // framing capabilities case 3: // framing capabilities
// LOG(4, s, t, "Framing capabilities\n");
break; break;
case 4: // bearer capabilities case 4: // bearer capabilities
// LOG(4, s, t, "Bearer capabilities\n");
break; break;
case 5: // tie breaker case 5: // tie breaker
// We never open tunnels, so we don't care about tie breakers // We never open tunnels, so we don't care about tie breakers
// LOG(4, s, t, "Tie breaker\n");
continue; continue;
case 6: // firmware revision case 6: // firmware revision
// LOG(4, s, t, "Firmware revision\n");
break; break;
case 7: // host name case 7: // host name
memset(tunnel[t].hostname, 0, sizeof(tunnel[t].hostname)); memset(tunnel[t].hostname, 0, sizeof(tunnel[t].hostname));
@ -2356,6 +2363,84 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
memcpy(session[s].random_vector, b, n); memcpy(session[s].random_vector, b, n);
session[s].random_vector_length = n; session[s].random_vector_length = n;
break; break;
case 46: // ppp disconnect cause
if (n >= 5)
{
uint16_t code = ntohs(*(uint16_t *) b);
uint16_t proto = ntohs(*(uint16_t *) (b + 2));
uint8_t dir = *(b + 4);
LOG(4, s, t, " PPP disconnect cause "
"(code=%u, proto=%04X, dir=%u, msg=\"%.*s\")\n",
code, proto, dir, n - 5, b + 5);
switch (code)
{
case 1: // admin disconnect
disc_cause = TERM_ADMIN_RESET;
disc_reason = "Administrative disconnect";
break;
case 3: // lcp terminate
if (dir != 1) break; // 1=peer, 2=local
disc_cause = TERM_USER_REQUEST;
disc_reason = "Normal disconnection";
break;
case 4: // compulsory encryption unavailable
if (dir != 2) break; // 1=refused by peer, 2=local
disc_cause = TERM_USER_ERROR;
disc_reason = "Compulsory encryption refused";
break;
case 5: // lcp: fsm timeout
disc_cause = TERM_PORT_ERROR;
disc_reason = "LCP: FSM timeout";
break;
case 6: // lcp: no recognisable lcp packets received
disc_cause = TERM_PORT_ERROR;
disc_reason = "LCP: no recognisable LCP packets";
break;
case 7: // lcp: magic-no error (possibly looped back)
disc_cause = TERM_PORT_ERROR;
disc_reason = "LCP: magic-no error (possible loop)";
break;
case 8: // lcp: echo request timeout
disc_cause = TERM_PORT_ERROR;
disc_reason = "LCP: echo request timeout";
break;
case 13: // auth: fsm timeout
disc_cause = TERM_SERVICE_UNAVAILABLE;
disc_reason = "Authentication: FSM timeout";
break;
case 15: // auth: unacceptable auth protocol
disc_cause = TERM_SERVICE_UNAVAILABLE;
disc_reason = "Unacceptable authentication protocol";
break;
case 16: // auth: authentication failed
disc_cause = TERM_SERVICE_UNAVAILABLE;
disc_reason = "Authentication failed";
break;
case 17: // ncp: fsm timeout
disc_cause = TERM_SERVICE_UNAVAILABLE;
disc_reason = "NCP: FSM timeout";
break;
case 18: // ncp: no ncps available
disc_cause = TERM_SERVICE_UNAVAILABLE;
disc_reason = "NCP: no NCPs available";
break;
case 19: // ncp: failure to converge on acceptable address
disc_cause = TERM_SERVICE_UNAVAILABLE;
disc_reason = (dir == 1)
? "NCP: too many Configure-Naks received from peer"
: "NCP: too many Configure-Naks sent to peer";
break;
case 20: // ncp: user not permitted to use any address
disc_cause = TERM_SERVICE_UNAVAILABLE;
disc_reason = (dir == 1)
? "NCP: local link address not acceptable to peer"
: "NCP: remote link address not acceptable";
break;
}
}
break;
default: default:
{ {
static char e[] = "unknown AVP 0xXXXX"; static char e[] = "unknown AVP 0xXXXX";
@ -2477,7 +2562,7 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr)
case 14: // CDN case 14: // CDN
controlnull(t); // ack controlnull(t); // ack
sessionshutdown(s, "Closed (Received CDN).", 0, 0); sessionshutdown(s, disc_reason, CDN_NONE, disc_cause);
break; break;
case 0xFFFF: case 0xFFFF:
LOG(1, s, t, "Missing message type\n"); LOG(1, s, t, "Missing message type\n");
@ -2807,7 +2892,7 @@ static void regular_cleanups(double period)
} }
else else
{ {
sessionshutdown(s, "No response to LCP ConfigReq.", 3, 0); sessionshutdown(s, "No response to LCP ConfigReq.", CDN_ADMIN_DISC, TERM_LOST_SERVICE);
STAT(session_timeout); STAT(session_timeout);
} }
@ -2836,7 +2921,7 @@ static void regular_cleanups(double period)
} }
else else
{ {
sessionshutdown(s, "No response to IPCP ConfigReq.", 3, 0); sessionshutdown(s, "No response to IPCP ConfigReq.", CDN_ADMIN_DISC, TERM_LOST_SERVICE);
STAT(session_timeout); STAT(session_timeout);
} }
@ -2902,7 +2987,7 @@ static void regular_cleanups(double period)
// Drop sessions who have not responded within IDLE_TIMEOUT seconds // Drop sessions who have not responded within IDLE_TIMEOUT seconds
if (session[s].last_packet && (time_now - session[s].last_packet >= IDLE_TIMEOUT)) if (session[s].last_packet && (time_now - session[s].last_packet >= IDLE_TIMEOUT))
{ {
sessionshutdown(s, "No response to LCP ECHO requests.", 3, 0); sessionshutdown(s, "No response to LCP ECHO requests.", CDN_ADMIN_DISC, TERM_LOST_SERVICE);
STAT(session_timeout); STAT(session_timeout);
s_actions++; s_actions++;
continue; continue;
@ -2938,7 +3023,7 @@ static void regular_cleanups(double period)
if (a & CLI_SESS_KILL) if (a & CLI_SESS_KILL)
{ {
LOG(2, s, session[s].tunnel, "Dropping session by CLI\n"); LOG(2, s, session[s].tunnel, "Dropping session by CLI\n");
sessionshutdown(s, "Requested by administrator.", 3, 0); sessionshutdown(s, "Requested by administrator.", CDN_ADMIN_DISC, TERM_ADMIN_RESET);
a = 0; // dead, no need to check for other actions a = 0; // dead, no need to check for other actions
s_actions++; s_actions++;
} }
@ -4502,7 +4587,7 @@ int sessionsetup(sessionidt s, tunnelidt t)
if (!session[s].ip) if (!session[s].ip)
{ {
LOG(0, s, t, " No IP allocated. The IP address pool is FULL!\n"); LOG(0, s, t, " No IP allocated. The IP address pool is FULL!\n");
sessionshutdown(s, "No IP addresses available.", 2, 7); // try another sessionshutdown(s, "No IP addresses available.", CDN_TRY_ANOTHER, TERM_SERVICE_UNAVAILABLE);
return 0; return 0;
} }
LOG(3, s, t, " No IP allocated. Assigned %s from pool\n", LOG(3, s, t, " No IP allocated. Assigned %s from pool\n",

View file

@ -1,5 +1,5 @@
// L2TPNS Global Stuff // L2TPNS Global Stuff
// $Id: l2tpns.h,v 1.111 2006-04-05 02:13:48 bodea Exp $ // $Id: l2tpns.h,v 1.112 2006-04-13 11:14:35 bodea Exp $
#ifndef __L2TPNS_H__ #ifndef __L2TPNS_H__
#define __L2TPNS_H__ #define __L2TPNS_H__
@ -345,7 +345,7 @@ typedef struct
} }
tunnelt; tunnelt;
// 160 bytes per radius session // 164 bytes per radius session
typedef struct // outstanding RADIUS requests typedef struct // outstanding RADIUS requests
{ {
sessionidt session; // which session this applies to sessionidt session; // which session this applies to
@ -356,6 +356,8 @@ typedef struct // outstanding RADIUS requests
uint8_t try; // which try we are on uint8_t try; // which try we are on
uint8_t state; // state of radius requests uint8_t state; // state of radius requests
uint8_t chap; // set if CHAP used (is CHAP identifier) uint8_t chap; // set if CHAP used (is CHAP identifier)
uint8_t term_cause; // Stop record: Acct-Terminate-Cause
char const *term_msg; // terminate reason
} }
radiust; radiust;
@ -674,6 +676,36 @@ typedef struct
int used; // session ref count int used; // session ref count
} ip_filtert; } ip_filtert;
// CDN result/error codes
#define CDN_NONE 0, 0
#define CDN_TRY_ANOTHER 2, 7
#define CDN_ADMIN_DISC 3, 0
#define CDN_UNAVAILABLE 4, 0
// RADIUS Acct-Terminate-Cause values
#define TERM_USER_REQUEST 1
#define TERM_LOST_CARRIER 2
#define TERM_LOST_SERVICE 3
#define TERM_IDLE_TIMEOUT 4
#define TERM_SESSION_TIMEOUT 5
#define TERM_ADMIN_RESET 6
#define TERM_ADMIN_REBOOT 7
#define TERM_PORT_ERROR 8
#define TERM_NAS_ERROR 9
#define TERM_NAS_REQUEST 10
#define TERM_NAS_REBOOT 11
#define TERM_PORT_UNNEEDED 12
#define TERM_PORT_PREEMPTED 13
#define TERM_PORT_SUSPENDED 14
#define TERM_SERVICE_UNAVAILABLE 15
#define TERM_CALLBACK 16
#define TERM_USER_ERROR 17
#define TERM_HOST_REQUEST 18
#define TERM_SUPPLICANT_RESTART 19
#define TERM_REAUTHENTICATION_FAILURE 20
#define TERM_PORT_REINIT 21
#define TERM_PORT_DISABLED 22
// arp.c // arp.c
void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip); void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip);
@ -716,7 +748,7 @@ sessionidt sessionbyuser(char *username);
void increment_counter(uint32_t *counter, uint32_t *wrap, uint32_t delta); 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 const *reason, int cdn_result, int cdn_error, int term_cause);
void filter_session(sessionidt s, int filter_in, int filter_out); 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);

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
* Wed Apr 5 2006 Brendan O'Dea <bod@optus.net> 2.1.17-1 * Thu Apr 13 2006 Brendan O'Dea <bod@optus.net> 2.1.17-1
- 2.1.17 release, see /usr/share/doc/l2tpns-2.1.17/Changes - 2.1.17 release, see /usr/share/doc/l2tpns-2.1.17/Changes

View file

@ -1,7 +1,7 @@
#ifndef __PLUGIN_H__ #ifndef __PLUGIN_H__
#define __PLUGIN_H__ #define __PLUGIN_H__
#define PLUGIN_API_VERSION 6 #define PLUGIN_API_VERSION 7
#define MAX_PLUGIN_TYPES 30 #define MAX_PLUGIN_TYPES 30
enum enum
@ -37,7 +37,7 @@ struct pluginfuncs
uint16_t (*radiusnew)(sessionidt s); uint16_t (*radiusnew)(sessionidt s);
void (*radiussend)(uint16_t r, uint8_t state); void (*radiussend)(uint16_t r, uint8_t state);
void *(*getconfig)(char *key, enum config_typet type); void *(*getconfig)(char *key, enum config_typet type);
void (*sessionshutdown)(sessionidt s, char *reason, int result, int error); void (*sessionshutdown)(sessionidt s, char const *reason, int result, int error, int term_cause);
void (*sessionkill)(sessionidt s, char *reason); void (*sessionkill)(sessionidt s, char *reason);
void (*throttle)(sessionidt s, int rate_in, int rate_out); void (*throttle)(sessionidt s, int rate_in, int rate_out);
int (*session_changed)(int sid); int (*session_changed)(int sid);

34
ppp.c
View file

@ -1,6 +1,6 @@
// L2TPNS PPP Stuff // L2TPNS PPP Stuff
char const *cvs_id_ppp = "$Id: ppp.c,v 1.97 2006-03-27 03:01:08 bodea Exp $"; char const *cvs_id_ppp = "$Id: ppp.c,v 1.98 2006-04-13 11:14:35 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -40,7 +40,7 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{ {
LOG(1, s, t, "Short PAP %u bytes\n", l); LOG(1, s, t, "Short PAP %u bytes\n", l);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
sessionshutdown(s, "Short PAP packet.", 3, 0); sessionshutdown(s, "Short PAP packet.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
@ -48,7 +48,7 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{ {
LOG(1, s, t, "Length mismatch PAP %u/%u\n", hl, l); LOG(1, s, t, "Length mismatch PAP %u/%u\n", hl, l);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
sessionshutdown(s, "PAP length mismatch.", 3, 0); sessionshutdown(s, "PAP length mismatch.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
l = hl; l = hl;
@ -57,7 +57,7 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{ {
LOG(1, s, t, "Unexpected PAP code %d\n", *p); LOG(1, s, t, "Unexpected PAP code %d\n", *p);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
sessionshutdown(s, "Unexpected PAP code.", 3, 0); sessionshutdown(s, "Unexpected PAP code.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
@ -110,7 +110,7 @@ void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
else else
{ {
LOG(1, s, t, "No RADIUS session available to authenticate session...\n"); LOG(1, s, t, "No RADIUS session available to authenticate session...\n");
sessionshutdown(s, "No free RADIUS sessions.", 4, 0); sessionshutdown(s, "No free RADIUS sessions.", CDN_UNAVAILABLE, TERM_SERVICE_UNAVAILABLE);
} }
} }
else else
@ -152,7 +152,7 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{ {
LOG(1, s, t, "Short CHAP %u bytes\n", l); LOG(1, s, t, "Short CHAP %u bytes\n", l);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
sessionshutdown(s, "Short CHAP packet.", 3, 0); sessionshutdown(s, "Short CHAP packet.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
@ -160,7 +160,7 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{ {
LOG(1, s, t, "Length mismatch CHAP %u/%u\n", hl, l); LOG(1, s, t, "Length mismatch CHAP %u/%u\n", hl, l);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
sessionshutdown(s, "CHAP length mismatch.", 3, 0); sessionshutdown(s, "CHAP length mismatch.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
l = hl; l = hl;
@ -169,7 +169,7 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{ {
LOG(1, s, t, "Unexpected CHAP response code %d\n", *p); LOG(1, s, t, "Unexpected CHAP response code %d\n", *p);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
sessionshutdown(s, "CHAP length mismatch.", 3, 0); sessionshutdown(s, "CHAP length mismatch.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
@ -190,7 +190,7 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{ {
LOG(1, s, t, "Wrong CHAP response ID %d (should be %d) (%d)\n", p[1], radius[r].id, r); LOG(1, s, t, "Wrong CHAP response ID %d (should be %d) (%d)\n", p[1], radius[r].id, r);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
sessionshutdown(s, "Unexpected CHAP response ID.", 3, 0); sessionshutdown(s, "Unexpected CHAP response ID.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
@ -198,7 +198,7 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{ {
LOG(1, s, t, "Bad CHAP response length %d\n", l < 5 ? -1 : p[4]); LOG(1, s, t, "Bad CHAP response length %d\n", l < 5 ? -1 : p[4]);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
sessionshutdown(s, "Bad CHAP response length.", 3, 0); sessionshutdown(s, "Bad CHAP response length.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
@ -208,7 +208,7 @@ void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
{ {
LOG(1, s, t, "CHAP user too long %d\n", l - 16); LOG(1, s, t, "CHAP user too long %d\n", l - 16);
STAT(tunnel_rx_errors); STAT(tunnel_rx_errors);
sessionshutdown(s, "CHAP username too long.", 3, 0); sessionshutdown(s, "CHAP username too long.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
@ -814,7 +814,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
default: default:
LOG(2, s, t, "LCP: remote sent %s for type %u?\n", ppp_code(*p), type); LOG(2, s, t, "LCP: remote sent %s for type %u?\n", ppp_code(*p), type);
sessionshutdown(s, "Unable to negotiate LCP.", 3, 0); sessionshutdown(s, "Unable to negotiate LCP.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
x -= length; x -= length;
@ -823,7 +823,7 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
if (!authtype) if (!authtype)
{ {
sessionshutdown(s, "Unsupported authentication.", 3, 0); sessionshutdown(s, "Unsupported authentication.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
@ -878,11 +878,11 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
if (config->debug > 3) dumplcp(q, l); if (config->debug > 3) dumplcp(q, l);
tunnelsend(b, l + (q - b), t); // send it tunnelsend(b, l + (q - b), t); // send it
sessionshutdown(s, "Remote end closed connection.", 3, 0); sessionshutdown(s, "Remote end closed connection.", CDN_ADMIN_DISC, TERM_USER_REQUEST);
} }
else if (*p == TerminateAck) else if (*p == TerminateAck)
{ {
sessionshutdown(s, "Connection closed.", 3, 0); sessionshutdown(s, "Connection closed.", CDN_ADMIN_DISC, TERM_NAS_REQUEST);
} }
else if (*p == ProtocolRej) else if (*p == ProtocolRej)
{ {
@ -1039,7 +1039,7 @@ void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
q = ppp_conf_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr)); q = ppp_conf_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr));
if (!q || (q != oq && *response == ConfigRej)) if (!q || (q != oq && *response == ConfigRej))
{ {
sessionshutdown(s, "Can't negotiate IPCP.", 3, 0); sessionshutdown(s, "Can't negotiate IPCP.", CDN_ADMIN_DISC, TERM_USER_ERROR);
return; return;
} }
} }
@ -1757,7 +1757,7 @@ void sendchap(sessionidt s, tunnelidt t)
radius[r].retry = backoff(radius[r].try++); radius[r].retry = backoff(radius[r].try++);
if (radius[r].try > 5) if (radius[r].try > 5)
{ {
sessionshutdown(s, "CHAP timeout.", 3, 0); sessionshutdown(s, "CHAP timeout.", CDN_ADMIN_DISC, TERM_REAUTHENTICATION_FAILURE);
STAT(tunnel_tx_errors); STAT(tunnel_tx_errors);
return ; return ;
} }

View file

@ -1,6 +1,6 @@
// L2TPNS Radius Stuff // L2TPNS Radius Stuff
char const *cvs_id_radius = "$Id: radius.c,v 1.48 2006-04-05 02:13:48 bodea Exp $"; char const *cvs_id_radius = "$Id: radius.c,v 1.49 2006-04-13 11:14:35 bodea Exp $";
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
@ -158,7 +158,7 @@ void radiussend(uint16_t r, uint8_t state)
if (s) if (s)
{ {
if (state == RADIUSAUTH) if (state == RADIUSAUTH)
sessionshutdown(s, "RADIUS timeout.", 3, 0); sessionshutdown(s, "RADIUS timeout.", CDN_ADMIN_DISC, TERM_REAUTHENTICATION_FAILURE);
else else
{ {
LOG(1, s, session[s].tunnel, "RADIUS timeout, but in state %s so don't timeout session\n", LOG(1, s, session[s].tunnel, "RADIUS timeout, but in state %s so don't timeout session\n",
@ -248,8 +248,8 @@ void radiussend(uint16_t r, uint8_t state)
p += p[1]; p += p[1];
} }
} }
else if (state == RADIUSSTART || state == RADIUSSTOP || state == RADIUSINTERIM) else // accounting
{ // accounting {
*p = 40; // accounting type *p = 40; // accounting type
p[1] = 6; p[1] = 6;
*(uint32_t *) (p + 2) = htonl(state - RADIUSSTART + 1); // start=1, stop=2, interim=3 *(uint32_t *) (p + 2) = htonl(state - RADIUSSTART + 1); // start=1, stop=2, interim=3
@ -304,6 +304,24 @@ void radiussend(uint16_t r, uint8_t state)
p[1] = 6; p[1] = 6;
*(uint32_t *) (p + 2) = htonl(session[s].cout_wrap); *(uint32_t *) (p + 2) = htonl(session[s].cout_wrap);
p += p[1]; p += p[1];
if (state == RADIUSSTOP && radius[r].term_cause)
{
*p = 49; // acct-terminate-cause
p[1] = 6;
*(uint32_t *) (p + 2) = htonl(radius[r].term_cause);
p += p[1];
if (radius[r].term_msg)
{
*p = 26; // vendor-specific
*(uint32_t *) (p + 2) = htonl(9); // Cisco
p[6] = 1; // Cisco-AVPair
p[7] = 2 + sprintf((char *) p + 8, "disc-cause-ext=%s", radius[r].term_msg);
p[1] = p[7] + 6;
p += p[1];
}
}
} }
{ {
@ -994,7 +1012,7 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struc
LOG(3, s, t, " DAE Disconnect %d (%s)\n", s, session[s].user); LOG(3, s, t, " DAE Disconnect %d (%s)\n", s, session[s].user);
r_code = DisconnectACK; r_code = DisconnectACK;
sessionshutdown(s, "Requested by PoD", 3, 0); // disconnect session sessionshutdown(s, "Requested by PoD", CDN_ADMIN_DISC, TERM_ADMIN_RESET); // disconnect session
break; break;
case CoARequest: // Change of Authorization case CoARequest: // Change of Authorization

View file

@ -5,7 +5,7 @@
/* session control */ /* session control */
char const *cvs_id = "$Id: sessionctl.c,v 1.4 2005-10-11 09:04:53 bodea Exp $"; char const *cvs_id = "$Id: sessionctl.c,v 1.5 2006-04-13 11:14:35 bodea Exp $";
int plugin_api_version = PLUGIN_API_VERSION; int plugin_api_version = PLUGIN_API_VERSION;
static struct pluginfuncs *f = 0; static struct pluginfuncs *f = 0;
@ -58,7 +58,7 @@ int plugin_control(struct param_control *data)
reason = "Requested by administrator."; reason = "Requested by administrator.";
if (data->argv[0][0] == 'd') if (data->argv[0][0] == 'd')
f->sessionshutdown(session, reason, 3, 0); f->sessionshutdown(session, reason, CDN_ADMIN_DISC, TERM_ADMIN_RESET);
else else
f->sessionkill(session, reason); f->sessionkill(session, reason);