add result/error codes to StopCCN
This commit is contained in:
parent
bf06c59c60
commit
fec3781205
1 changed files with 72 additions and 18 deletions
78
l2tpns.c
78
l2tpns.c
|
|
@ -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.85 2005/03/10 03:08:08 bodea Exp $";
|
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.86 2005/03/10 05:47:24 bodea Exp $";
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
@ -1264,7 +1264,7 @@ static void control32(controlt * c, uint16_t avp, uint32_t val, uint8_t m)
|
||||||
c->length += 10;
|
c->length += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add an AVP (32 bit)
|
// add an AVP (string)
|
||||||
static void controls(controlt * c, uint16_t avp, char *val, uint8_t m)
|
static void controls(controlt * c, uint16_t avp, char *val, uint8_t m)
|
||||||
{
|
{
|
||||||
uint16_t l = ((m ? 0x8000 : 0) + strlen(val) + 6);
|
uint16_t l = ((m ? 0x8000 : 0) + strlen(val) + 6);
|
||||||
|
|
@ -1654,12 +1654,12 @@ static void tunnelkill(tunnelidt t, char *reason)
|
||||||
// free tunnel
|
// free tunnel
|
||||||
tunnelclear(t);
|
tunnelclear(t);
|
||||||
LOG(1, 0, t, "Kill tunnel %d: %s\n", t, reason);
|
LOG(1, 0, t, "Kill tunnel %d: %s\n", t, reason);
|
||||||
cli_tunnel_actions[s].action = 0;
|
cli_tunnel_actions[t].action = 0;
|
||||||
cluster_send_tunnel(t);
|
cluster_send_tunnel(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// shut down a tunnel cleanly
|
// shut down a tunnel cleanly
|
||||||
static void tunnelshutdown(tunnelidt t, char *reason)
|
static void tunnelshutdown(tunnelidt t, char *reason, int result, int error, char *msg)
|
||||||
{
|
{
|
||||||
sessionidt s;
|
sessionidt s;
|
||||||
|
|
||||||
|
|
@ -1682,9 +1682,30 @@ static void tunnelshutdown(tunnelidt t, char *reason)
|
||||||
tunnel[t].die = TIME + 700; // Clean up in 70 seconds
|
tunnel[t].die = TIME + 700; // Clean up in 70 seconds
|
||||||
cluster_send_tunnel(t);
|
cluster_send_tunnel(t);
|
||||||
// TBA - should we wait for sessions to stop?
|
// TBA - should we wait for sessions to stop?
|
||||||
{ // Send StopCCN
|
if (result)
|
||||||
|
{
|
||||||
controlt *c = controlnew(4); // sending StopCCN
|
controlt *c = controlnew(4); // sending StopCCN
|
||||||
control16(c, 1, 1, 1); // result code (admin reasons - TBA make error, general error, add message)
|
if (error)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
int l = 4;
|
||||||
|
*(uint16_t *) buf = htons(result);
|
||||||
|
*(uint16_t *) (buf+2) = htons(error);
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
int m = strlen(msg);
|
||||||
|
if (m + 4 > sizeof(buf))
|
||||||
|
m = sizeof(buf) - 4;
|
||||||
|
|
||||||
|
memcpy(buf+4, msg, m);
|
||||||
|
l += m;
|
||||||
|
}
|
||||||
|
|
||||||
|
controlb(c, 1, buf, l, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
control16(c, 1, result, 1);
|
||||||
|
|
||||||
control16(c, 9, t, 1); // assigned tunnel (our end)
|
control16(c, 9, t, 1); // assigned tunnel (our end)
|
||||||
controladd(c, t, 0); // send the message
|
controladd(c, t, 0); // send the message
|
||||||
}
|
}
|
||||||
|
|
@ -1890,6 +1911,10 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
}
|
}
|
||||||
if (l)
|
if (l)
|
||||||
{ // if not a null message
|
{ // if not a null message
|
||||||
|
int result = 0;
|
||||||
|
int error = 0;
|
||||||
|
char *msg = 0;
|
||||||
|
|
||||||
// process AVPs
|
// process AVPs
|
||||||
while (l && !(fatal & 0x80)) // 0x80 = mandatory AVP
|
while (l && !(fatal & 0x80)) // 0x80 = mandatory AVP
|
||||||
{
|
{
|
||||||
|
|
@ -1909,6 +1934,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
{
|
{
|
||||||
LOG(1, s, t, "Unrecognised AVP flags %02X\n", *b);
|
LOG(1, s, t, "Unrecognised AVP flags %02X\n", *b);
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
|
result = 2; // general error
|
||||||
|
error = 3; // reserved field non-zero
|
||||||
|
msg = 0;
|
||||||
continue; // next
|
continue; // next
|
||||||
}
|
}
|
||||||
b += 2;
|
b += 2;
|
||||||
|
|
@ -1916,6 +1944,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
{
|
{
|
||||||
LOG(2, s, t, "Unknown AVP vendor %d\n", ntohs(*(uint16_t *) (b)));
|
LOG(2, s, t, "Unknown AVP vendor %d\n", ntohs(*(uint16_t *) (b)));
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
|
result = 2; // general error
|
||||||
|
error = 6; // generic vendor-specific error
|
||||||
|
msg = "unsupported vendor-specific";
|
||||||
continue; // next
|
continue; // next
|
||||||
}
|
}
|
||||||
b += 2;
|
b += 2;
|
||||||
|
|
@ -1932,18 +1963,27 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
{
|
{
|
||||||
LOG(1, s, t, "Hidden AVP requested, but no L2TP secret.\n");
|
LOG(1, s, t, "Hidden AVP requested, but no L2TP secret.\n");
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
|
result = 2; // general error
|
||||||
|
error = 6; // generic vendor-specific error
|
||||||
|
msg = "secret not specified";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!session[s].random_vector_length)
|
if (!session[s].random_vector_length)
|
||||||
{
|
{
|
||||||
LOG(1, s, t, "Hidden AVP requested, but no random vector.\n");
|
LOG(1, s, t, "Hidden AVP requested, but no random vector.\n");
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
|
result = 2; // general error
|
||||||
|
error = 6; // generic
|
||||||
|
msg = "no random vector";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (n < 8)
|
if (n < 8)
|
||||||
{
|
{
|
||||||
LOG(2, s, t, "Short hidden AVP.\n");
|
LOG(2, s, t, "Short hidden AVP.\n");
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
|
result = 2; // general error
|
||||||
|
error = 2; // length is wrong
|
||||||
|
msg = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1955,7 +1995,13 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
orig_len = ntohs(*(uint16_t *) b);
|
orig_len = ntohs(*(uint16_t *) b);
|
||||||
if (orig_len > n + 2)
|
if (orig_len > n + 2)
|
||||||
{
|
{
|
||||||
|
LOG(1, s, t, "Original length %d too long in hidden AVP of length %d; wrong secret?\n",
|
||||||
|
orig_len, n);
|
||||||
|
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
|
result = 2; // general error
|
||||||
|
error = 2; // length is wrong
|
||||||
|
msg = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2004,6 +2050,9 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
{ // allow 0.0 and 1.0
|
{ // allow 0.0 and 1.0
|
||||||
LOG(1, s, t, " Bad protocol version %04X\n", version);
|
LOG(1, s, t, " Bad protocol version %04X\n", version);
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
|
result = 5; // unspported protocol version
|
||||||
|
error = 0x0100; // supported version
|
||||||
|
msg = 0;
|
||||||
continue; // next
|
continue; // next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2180,14 +2229,20 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
session[s].random_vector_length = n;
|
session[s].random_vector_length = n;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
{
|
||||||
|
static char e[] = "unknown AVP 0xXXXX";
|
||||||
LOG(2, s, t, " Unknown AVP type %d\n", mtype);
|
LOG(2, s, t, " Unknown AVP type %d\n", mtype);
|
||||||
fatal = flags;
|
fatal = flags;
|
||||||
|
result = 2; // general error
|
||||||
|
error = 8; // unknown mandatory AVP
|
||||||
|
sprintf((msg = e) + 14, "%04x", mtype);
|
||||||
continue; // next
|
continue; // next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// process message
|
// process message
|
||||||
if (fatal & 0x80)
|
if (fatal & 0x80)
|
||||||
tunnelshutdown(t, "Unknown Mandatory AVP");
|
tunnelshutdown(t, "Invalid mandatory AVP", result, error, msg);
|
||||||
else
|
else
|
||||||
switch (message)
|
switch (message)
|
||||||
{
|
{
|
||||||
|
|
@ -2212,8 +2267,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
break;
|
break;
|
||||||
case 4: // StopCCN
|
case 4: // StopCCN
|
||||||
controlnull(t); // ack
|
controlnull(t); // ack
|
||||||
tunnelshutdown(t, "Stopped"); // Shut down cleanly
|
tunnelshutdown(t, "Stopped", 0, 0, 0); // Shut down cleanly
|
||||||
tunnelkill(t, "Stopped"); // Immediately force everything dead
|
|
||||||
break;
|
break;
|
||||||
case 6: // HELLO
|
case 6: // HELLO
|
||||||
controlnull(t); // simply ACK
|
controlnull(t); // simply ACK
|
||||||
|
|
@ -2295,7 +2349,7 @@ void processudp(uint8_t * buf, int len, struct sockaddr_in *addr)
|
||||||
default:
|
default:
|
||||||
STAT(tunnel_rx_errors);
|
STAT(tunnel_rx_errors);
|
||||||
if (mandatory)
|
if (mandatory)
|
||||||
tunnelshutdown(t, "Unknown message type");
|
tunnelshutdown(t, "Unknown message type", 2, 6, "unknown message type");
|
||||||
else
|
else
|
||||||
LOG(1, s, t, "Unknown message type %d\n", message);
|
LOG(1, s, t, "Unknown message type %d\n", message);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2540,7 +2594,7 @@ static int regular_cleanups(void)
|
||||||
if (a & CLI_TUN_KILL)
|
if (a & CLI_TUN_KILL)
|
||||||
{
|
{
|
||||||
LOG(2, 0, t, "Dropping tunnel by CLI\n");
|
LOG(2, 0, t, "Dropping tunnel by CLI\n");
|
||||||
tunnelshutdown(t, "Requested by administrator");
|
tunnelshutdown(t, "Requested by administrator", 1, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3773,7 +3827,7 @@ static void sigquit_handler(int sig)
|
||||||
for (i = 1; i < MAXTUNNEL; i++)
|
for (i = 1; i < MAXTUNNEL; i++)
|
||||||
{
|
{
|
||||||
if (tunnel[i].ip || tunnel[i].state)
|
if (tunnel[i].ip || tunnel[i].state)
|
||||||
tunnelshutdown(i, "L2TPNS Closing");
|
tunnelshutdown(i, "L2TPNS Closing", 6, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue