l2tpns/l2tpns.h
David Parrish 11627344e7 Add log_backtrace
Use multiple radius sockets to allow more concurrent authentication requests
Fix minimum length of IP packets
Add support for reading more than one packet per fd in each processing loop
Add variable cleanup_interval for changing cleanup interval
Bump version to 1.2.0
2004-05-24 04:24:06 +00:00

486 lines
14 KiB
C

// L2TPNS Global Stuff
// $Id: l2tpns.h,v 1.5 2004-05-24 04:24:06 fred_nerk Exp $
#include <netinet/in.h>
#include <stdio.h>
#include <config.h>
#define VERSION "1.2.0"
// Limits
#define MAXTUNNEL 500 // could be up to 65535
#define MAXSESSION 50000 // could be up to 65535
#define RADIUS_SHIFT 5
#define RADIUS_MASK ((unsigned short)(((unsigned short)~0) >> (16 - RADIUS_SHIFT)))
#define MAXRADIUS ((2 << (RADIUS_SHIFT - 1)) * 255)
#define MAXCONTROL 1000 // max length control message we ever send...
#define MAXETHER (1500+18) // max packet we try sending to tap
#define MAXTEL 96 // telephone number
#define MAXPLUGINS 20 // maximum number of plugins to load
#define MAXRADSERVER 10 // max radius servers
#define MAXROUTE 10 // max static routes per session
#define MAXIPPOOL 131072 // max number of ip addresses in pool
#define RINGBUFFER_SIZE 10000 // Number of ringbuffer entries to allocate
#define MAX_LOG_LENGTH 512 // Maximum size of log message
#define ECHO_TIMEOUT 60 // Time between last packet sent and LCP ECHO generation
#define IDLE_TIMEOUT 240 // Time between last packet sent and LCP ECHO generation
// Constants
#define STATISTICS
#define STAT_CALLS
#define RINGBUFFER
#define TAPDEVICE "/dev/net/tun"
#define UDP 17
#define HOMEDIR "/home/l2tpns/" // Base dir for data
#define STATEFILE "/tmp/l2tpns.dump" // State dump file
#define NOSTATEFILE "/tmp/l2tpns.no_state_reload" // If exists, state will not be reloaded
#define CONFIGFILE ETCDIR "/l2tpns.cfg" // Configuration file
#define CLIUSERS ETCDIR "/l2tpns.users" // CLI Users file
#define IPPOOLFILE ETCDIR "/l2tpns.ip_pool" // Address pool configuration
#ifndef LIBDIR
#define LIBDIR "/usr/lib/l2tpns"
#endif
#define ACCT_TIME 3000 // 5 minute accounting interval
#define L2TPPORT 1701 // L2TP port
#define RADPORT 1645 // old radius port...
#define RADAPORT 1646 // old radius accounting port
#define PKTARP 0x0806 // ARP packet type
#define PKTIP 0x0800 // IP packet type
#define PSEUDOMAC 0x0200 // pseudo MAC prefix (local significant MAC)
#define PPPPAP 0xC023
#define PPPCHAP 0xC223
#define PPPLCP 0xC021
#define PPPIPCP 0x8021
#define PPPCCP 0x80FD
#define PPPIP 0x0021
#define PPPMP 0x003D
#define MIN_IP_SIZE 0x20
enum
{
ConfigReq = 1,
ConfigAck,
ConfigNak,
ConfigRej,
TerminateReq,
TerminateAck,
CodeRej,
ProtocolRej,
EchoReq,
EchoReply,
DiscardRequest
};
// Types
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned char u8;
typedef u32 ipt;
typedef u16 portt;
typedef u16 sessionidt;
typedef u16 tunnelidt;
typedef u32 clockt;
typedef u8 hasht[16];
// dump header: update number if internal format changes
#define DUMP_MAGIC "L2TPNS#" VERSION "#"
// structures
typedef struct routes // route
{
ipt ip;
ipt mask;
}
routet;
typedef struct controls // control message
{
struct controls *next; // next in queue
u16 length; // length
u8 buf[MAXCONTROL];
}
controlt;
typedef struct stbft
{
char handle[10];
char in_use;
} tbft;
// 336 bytes per session
typedef struct sessions
{
sessionidt next; // next session in linked list
sessionidt far; // far end session ID
tunnelidt tunnel; // tunnel ID
ipt ip; // IP of session set by RADIUS response
int ip_pool_index; // index to IP pool
unsigned long sid; // session id for hsddb
u16 nr; // next receive
u16 ns; // next send
u32 magic; // ppp magic number
u32 cin, cout; // byte counts
u32 pin, pout; // packet counts
u32 total_cin; // This counter is never reset while a session is open
u32 total_cout; // This counter is never reset while a session is open
u32 id; // session id
clockt opened; // when started
clockt die; // being closed, when to finally free
time_t last_packet; // Last packet from the user (used for idle timeouts)
ipt dns1, dns2; // DNS servers
routet route[MAXROUTE]; // static routes
u16 radius; // which radius session is being used (0 for not waiting on authentication)
u8 flags; // various bit flags
u8 snoop; // are we snooping this session?
u8 throttle; // is this session throttled?
u8 walled_garden; // is this session gardened?
u16 mru; // maximum receive unit
u16 tbf; // filter bucket for throttling
char random_vector[MAXTEL];
int random_vector_length;
char user[129]; // user (needed in seesion for radius stop messages)
char called[MAXTEL]; // called number
char calling[MAXTEL]; // calling number
unsigned long tx_connect_speed;
unsigned long rx_connect_speed;
}
sessiont;
#define SESSIONPFC 1 // PFC negotiated flags
#define SESSIONACFC 2 // ACFC negotiated flags
// 168 bytes per tunnel
typedef struct tunnels
{
tunnelidt far; // far end tunnel ID
ipt ip; // Ip for far end
portt port; // port for far end
u16 window; // Rx window
u16 nr; // next receive
u16 ns; // next send
int state; // current state (tunnelstate enum)
clockt last; // when last control message sent (used for resend timeout)
clockt retry; // when to try resenting pending control
clockt die; // being closed, when to finally free
clockt lastrec; // when the last control message was received
char hostname[128]; // tunnel hostname
char vendor[128]; // LAC vendor
u8 try; // number of retrys on a control message
u16 controlc; // outstaind messages in queue
controlt *controls; // oldest message
controlt *controle; // newest message
}
tunnelt;
// 180 bytes per radius session
typedef struct radiuss // outstanding RADIUS requests
{
sessionidt session; // which session this applies to
hasht auth; // request authenticator
clockt retry; // when to try next
char calling[MAXTEL]; // calling number
char pass[129]; // password
u8 id; // ID for PPP response
u8 try; // which try we are on
u8 state; // state of radius requests
u8 chap; // set if CHAP used (is CHAP identifier)
}
radiust;
typedef struct
{
ipt address;
char assigned; // 1 if assigned, 0 if free
sessionidt session;
clockt last; // last used
char user[129]; // user (try to have ip addresses persistent)
}
ippoolt;
#ifdef RINGBUFFER
struct Tringbuffer
{
struct {
char level;
sessionidt session;
tunnelidt tunnel;
ipt address;
char message[MAX_LOG_LENGTH];
} buffer[RINGBUFFER_SIZE];
int head;
int tail;
};
#endif
/*
* Possible tunnel states
* TUNNELFREE -> TUNNELOPEN -> TUNNELDIE -> TUNNELFREE
*/
enum
{
TUNNELFREE, // Not in use
TUNNELOPEN, // Active tunnel
TUNNELDIE, // Currently closing
TUNNELOPENING // Busy opening
};
enum
{
RADIUSNULL, // Not in use
RADIUSCHAP, // sending CHAP down PPP
RADIUSAUTH, // sending auth to RADIUS server
RADIUSIPCP, // sending IPCP to end user
RADIUSSTART, // sending start accounting to RADIUS server
RADIUSSTOP, // sending stop accounting to RADIUS server
RADIUSWAIT // waiting timeout before available, in case delayed replies
};
struct Tstats
{
time_t start_time;
time_t last_reset;
unsigned long tap_rx_packets;
unsigned long tap_tx_packets;
unsigned long tap_rx_bytes;
unsigned long tap_tx_bytes;
unsigned long tap_rx_errors;
unsigned long tap_tx_errors;
unsigned long tunnel_rx_packets;
unsigned long tunnel_tx_packets;
unsigned long tunnel_rx_bytes;
unsigned long tunnel_tx_bytes;
unsigned long tunnel_rx_errors;
unsigned long tunnel_tx_errors;
unsigned long tunnel_retries;
unsigned long radius_retries;
unsigned long arp_errors;
unsigned long arp_replies;
unsigned long arp_discarded;
unsigned long arp_sent;
unsigned long arp_recv;
unsigned long packets_snooped;
unsigned long tunnel_created;
unsigned long session_created;
unsigned long tunnel_timeout;
unsigned long session_timeout;
unsigned long radius_timeout;
unsigned long radius_overflow;
unsigned long tunnel_overflow;
unsigned long session_overflow;
unsigned long ip_allocated;
unsigned long ip_freed;
#ifdef STAT_CALLS
unsigned long call_processtap;
unsigned long call_processarp;
unsigned long call_processipout;
unsigned long call_processudp;
unsigned long call_sessionbyip;
unsigned long call_sessionbyuser;
unsigned long call_sendarp;
unsigned long call_sendipcp;
unsigned long call_tunnelsend;
unsigned long call_sessionkill;
unsigned long call_sessionshutdown;
unsigned long call_tunnelkill;
unsigned long call_tunnelshutdown;
unsigned long call_assign_ip_address;
unsigned long call_free_ip_address;
unsigned long call_dump_acct_info;
unsigned long call_sessionsetup;
unsigned long call_processpap;
unsigned long call_processchap;
unsigned long call_processlcp;
unsigned long call_processipcp;
unsigned long call_processipin;
unsigned long call_processccp;
unsigned long call_sendchap;
unsigned long call_processrad;
unsigned long call_radiussend;
unsigned long call_radiusretry;
#endif
};
#ifdef STATISTICS
#define STAT(x) _statistics->x++
#define INC_STAT(x,y) _statistics->x += y
#define GET_STAT(x) _statistics->x
#define SET_STAT(x, y) _statistics->x = y
#else
#define STAT(x)
#define INC_STAT(x,y)
#define GET_STAT(x) 0
#define SET_STAT(x, y)
#endif
struct configt
{
int debug; // debugging level
time_t start_time; // time when l2tpns was started
char bandwidth[256]; // current bandwidth
char config_file[128];
int reload_config; // flag to re-read config (set by cli)
int cleanup_interval; // interval between regular cleanups (in seconds)
int multi_read_count; // amount of packets to read per fd in processing loop
char tapdevice[10]; // tap device name
char log_filename[128];
char l2tpsecret[64];
char radiussecret[64];
int radius_accounting;
ipt radiusserver[MAXRADSERVER]; // radius servers
u8 numradiusservers; // radius server count
short num_radfds; // Number of radius filehandles allocated
ipt default_dns1, default_dns2;
ipt snoop_destination_host;
u16 snoop_destination_port;
unsigned long rl_rate;
int save_state;
uint32_t cluster_address;
int ignore_cluster_updates;
char accounting_dir[128];
ipt bind_address;
int target_uid;
int dump_speed;
char plugins[64][MAXPLUGINS];
char old_plugins[64][MAXPLUGINS];
int next_tbf; // Next HTB id available to use
};
struct config_descriptt
{
char *key;
int offset;
int size;
enum { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IP } type;
};
// arp.c
void sendarp(int ifr_idx, const unsigned char* mac, ipt ip);
// ppp.c
void processpap(tunnelidt t, sessionidt s, u8 * p, u16 l);
void processchap(tunnelidt t, sessionidt s, u8 * p, u16 l);
void processlcp(tunnelidt t, sessionidt s, u8 * p, u16 l);
void processipcp(tunnelidt t, sessionidt s, u8 * p, u16 l);
void processipin(tunnelidt t, sessionidt s, u8 * p, u16 l);
void processccp(tunnelidt t, sessionidt s, u8 * p, u16 l);
void sendchap(tunnelidt t, sessionidt s);
u8 *makeppp(u8 * b, u8 * p, int l, tunnelidt t, sessionidt s, u16 mtype);
u8 *findppp(u8 * b, u8 mtype);
void initlcp(tunnelidt t, sessionidt s);
void dumplcp(char *p, int l);
// radius.c
void initrad(void);
void radiussend(u16 r, u8 state);
void processrad(u8 *buf, int len, char socket_index);
void radiusretry(u16 r);
u16 radiusnew(sessionidt s);
void radiusclear(u16 r, sessionidt s);
// throttle.c
int throttle_session(sessionidt s, int throttle);
// rl.c
void init_rl();
u16 rl_create_tbf();
u16 rl_get_tbf();
void rl_done_tbf(u16 t);
void rl_destroy_tbf(u16 t);
// l2tpns.c
clockt now(void);
clockt backoff(u8 try);
void routeset(ipt ip, ipt mask, ipt gw, u8 add);
void inittap(void);
void initudp(void);
void initdata(void);
void initippool();
sessionidt sessionbyip(ipt ip);
sessionidt sessionbyuser(char *username);
void sessionshutdown(sessionidt s, char *reason);
void sessionsendarp(sessionidt s);
void send_garp(ipt ip);
void sessionkill(sessionidt s, char *reason);
void control16(controlt * c, u16 avp, u16 val, u8 m);
void control32(controlt * c, u16 avp, u32 val, u8 m);
void controls(controlt * c, u16 avp, char *val, u8 m);
void controlb(controlt * c, u16 avp, char *val, unsigned int len, u8 m);
controlt *controlnew(u16 mtype);
void controlnull(tunnelidt t);
void controladd(controlt * c, tunnelidt t, sessionidt s);
void tunnelsend(u8 * buf, u16 l, tunnelidt t);
void tunnelkill(tunnelidt t, char *reason);
void tunnelshutdown(tunnelidt t, char *reason);
void sendipcp(tunnelidt t, sessionidt s);
void processipout(u8 * buf, int len);
void processarp(u8 * buf, int len);
void processudp(u8 * buf, int len, struct sockaddr_in *addr);
void processtap(u8 * buf, int len);
void processcontrol(u8 * buf, int len, struct sockaddr_in *addr);
int assign_ip_address(sessionidt s);
void free_ip_address(sessionidt s);
void snoop_send_packet(char *packet, u16 size);
void dump_acct_info();
void mainloop(void);
#define log _log
#ifndef log_hex
#define log_hex(a,b,c,d) do{if (a <= config->debug) _log_hex(a,0,0,0,b,c,d);}while (0)
#endif
void _log(int level, ipt address, sessionidt s, tunnelidt t, const char *format, ...) __attribute__((format (printf, 5, 6)));
void _log_hex(int level, ipt address, sessionidt s, tunnelidt t, const char *title, const char *data, int maxsize);
void build_chap_response(char *challenge, u8 id, u16 challenge_length, char **challenge_response);
int sessionsetup(tunnelidt t, sessionidt s, u8 routes);
int cluster_send_session(int s);
int cluster_send_tunnel(int t);
int cluster_send_goodbye();
void init_cli();
void cli_do_file(FILE *fh);
void cli_do(int sockfd);
#ifdef RINGBUFFER
void ringbuffer_dump(FILE *stream);
#endif
void initplugins();
int run_plugins(int plugin_type, void *data);
void add_plugin(char *plugin_name);
void remove_plugin(char *plugin_name);
void tunnelclear(tunnelidt t);
void host_unreachable(ipt destination, u16 id, ipt source, char *packet, int packet_len);
extern tunnelt *tunnel;
extern sessiont *session;
#define sessionfree (session[0].next)
#define log_backtrace(count, max) \
if (count++ < max) { \
void *array[20]; \
char **strings; \
int size, i; \
log(0, 0, 0, t, "Backtrace follows"); \
size = backtrace(array, 10); \
strings = backtrace_symbols(array, size); \
if (strings) for (i = 0; i < size; i++) \
{ \
log(0, 0, 0, t, "%s\n", strings[i]); \
} \
free(strings); \
}