File: l2tpns.h

package info (click to toggle)
l2tpns 2.1.21-1.1
  • links: PTS
  • area: main
  • in suites: lenny, squeeze, wheezy
  • size: 820 kB
  • ctags: 1,621
  • sloc: ansic: 16,737; makefile: 160; sh: 142; perl: 139
file content (859 lines) | stat: -rw-r--r-- 25,370 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
// L2TPNS Global Stuff
// $Id: l2tpns.h,v 1.113.2.3 2006/12/02 14:09:14 bodea Exp $

#ifndef __L2TPNS_H__
#define __L2TPNS_H__

#include <netinet/in.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <libcli.h>

#define VERSION	"2.1.21"

// Limits
#define MAXTUNNEL	500		// could be up to 65535
#define MAXSESSION	60000		// could be up to 65535
#define MAXTBFS		6000		// Maximum token bucket filters. Might need up to 2 * session.

#define RADIUS_SHIFT	6
#define RADIUS_FDS	(1 << RADIUS_SHIFT)
#define RADIUS_MASK	((1 << RADIUS_SHIFT) - 1)
#define MAXRADIUS	(1 << (8 + RADIUS_SHIFT))

#define T_UNDEF		(0xffff)	// A tunnel ID that won't ever be used. Mark session as undefined.
#define T_FREE		(0)		// A tunnel ID that won't ever be used. Mark session as free.

#define MAXCONTROL	1000		// max length control message we ever send...
#define MINMTU		576		// minimum recommended MTU (rfc1063)
#define MAXMTU		2600		// arbitrary maximum MTU
#define PPPoE_MRU	1492		// maximum PPPoE MRU (rfc2516: 1500 less PPPoE header (6) and PPP protocol ID (2))
#define MAXETHER	(MAXMTU+18)	// max packet we try sending to tun
#define MAXTEL		96		// telephone number
#define MAXUSER		128		// username
#define MAXPASS		128		// password
#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
#define BUSY_WAIT_TIME	3000		// 5 minutes in 1/10th seconds to wait for radius to cleanup on shutdown

// Constants
#ifndef ETCDIR
#define ETCDIR		"/etc/l2tpns"
#endif

#ifndef LIBDIR
#define LIBDIR		"/usr/lib/l2tpns"
#endif

#ifndef PLUGINDIR
#define PLUGINDIR	LIBDIR		// Plugins
#endif

#ifndef PLUGINCONF
#define PLUGINCONF	ETCDIR		// Plugin config dir
#endif

#ifndef FLASHDIR
#define FLASHDIR	ETCDIR
#endif

#define TUNDEVICE	"/dev/net/tun"
#define RANDOMDEVICE	"/dev/urandom"			// default, not as secure as /dev/random but non-blocking
#define CONFIGFILE	FLASHDIR "/startup-config"	// Configuration file
#define CLIUSERS	FLASHDIR "/users"		// CLI Users file
#define IPPOOLFILE	FLASHDIR "/ip_pool"		// Address pool configuration
#define ACCT_TIME	3000				// 5 minute accounting interval
#define ACCT_SHUT_TIME	600				// 1 minute for counters of shutdown sessions
#define L2TPPORT	1701				// L2TP port
#define RADPORT		1645				// old radius port...
#define DAEPORT		3799				// DAE port
#define PKTARP		0x0806				// ARP packet type
#define PKTIP		0x0800				// IPv4 packet type
#define PKTIPV6		0x86DD				// IPv6 packet type
#define PPPPAP		0xC023
#define PPPCHAP		0xC223
#define PPPLCP		0xC021
#define PPPIPCP		0x8021
#define PPPIPV6CP	0x8057
#define PPPCCP		0x80FD
#define PPPIP		0x0021
#define PPPIPV6		0x0057
#define PPPMP		0x003D
#define MIN_IP_SIZE	0x19

enum {
	ConfigReq = 1,
	ConfigAck,
	ConfigNak,
	ConfigRej,
	TerminateReq,
	TerminateAck,
	CodeRej,
	ProtocolRej,
	EchoReq,
	EchoReply,
	DiscardRequest,
	IdentRequest
};

enum {
	AccessRequest = 1,
	AccessAccept,
	AccessReject,
	AccountingRequest,
	AccountingResponse,
	AccessChallenge = 11,
	DisconnectRequest = 40,
	DisconnectACK,
	DisconnectNAK,
	CoARequest,
	CoAACK,
	CoANAK
};

// PPP phases
enum {
    	Dead,
	Establish,
	Authenticate,
	Network,
	Terminate
};

// PPP states
enum {
	Initial,
	Starting,
	Closed,
	Stopped,
	Closing,
	Stopping,
	RequestSent,
	AckReceived,
	AckSent,
	Opened
};

// reset state machine counters
#define initialise_restart_count(_s, _fsm)			\
	sess_local[_s]._fsm.conf_sent =				\
	sess_local[_s]._fsm.nak_sent = 0

// no more attempts
#define zero_restart_count(_s, _fsm) ({				\
	sess_local[_s]._fsm.conf_sent =				\
		config->ppp_max_configure;			\
	sess_local[_s]._fsm.restart =				\
		time_now + config->ppp_restart_time;		\
})

// increment ConfReq counter and reset timer
#define restart_timer(_s, _fsm) ({				\
	sess_local[_s]._fsm.conf_sent++;			\
	sess_local[_s]._fsm.restart =				\
		time_now + config->ppp_restart_time;		\
})

// stop timer on change to state where timer does not run
#define change_state(_s, _fsm, _new) ({				\
	if (_new != session[_s].ppp._fsm)			\
	{ 							\
		switch (_new)					\
		{						\
		case Initial:					\
		case Starting:					\
		case Closed:					\
		case Stopped:					\
		case Opened:					\
			sess_local[_s]._fsm.restart = 0;	\
			initialise_restart_count(_s, _fsm);	\
		}						\
		session[_s].ppp._fsm = _new;			\
		cluster_send_session(_s);			\
	}							\
})

// Types
typedef uint16_t sessionidt;
typedef uint16_t tunnelidt;
typedef uint32_t clockt;
typedef uint8_t hasht[16];

// CLI actions
struct cli_session_actions {
	char action;
	in_addr_t snoop_ip;
	uint16_t snoop_port;
	int throttle_in;
	int throttle_out;
	int filter_in;
	int filter_out;
};

#define CLI_SESS_KILL		0x01
#define CLI_SESS_SNOOP		0x02
#define CLI_SESS_NOSNOOP	0x04
#define CLI_SESS_THROTTLE	0x08
#define CLI_SESS_NOTHROTTLE	0x10
#define CLI_SESS_FILTER		0x20
#define CLI_SESS_NOFILTER	0x40

struct cli_tunnel_actions {
	char action;
};

#define CLI_TUN_KILL		0x01

// structures
typedef struct			// route
{
	in_addr_t ip;
	in_addr_t mask;
}
routet;

typedef struct controls		// control message
{
	struct controls *next;	// next in queue
	uint16_t length;	// length
	uint8_t buf[MAXCONTROL];
}
controlt;

typedef struct
{
	sessionidt next;		// next session in linked list
	sessionidt far;			// far end session ID
	tunnelidt tunnel;		// near end tunnel ID
	uint8_t flags;			// session flags: see SESSION_*
	struct {
		uint8_t phase;		// PPP phase
		uint8_t lcp:4;		//   LCP    state
		uint8_t ipcp:4;		//   IPCP   state
		uint8_t ipv6cp:4;	//   IPV6CP state
		uint8_t ccp:4;		//   CCP    state
	} ppp;
	char reserved_1[2];		// unused: padding
	in_addr_t ip;			// IP of session set by RADIUS response (host byte order).
	int ip_pool_index;		// index to IP pool
	uint32_t unique_id;		// unique session id
	char reserved_2[4];		// unused: was ns/nr
	uint32_t magic;			// ppp magic number
	uint32_t pin, pout;		// packet counts
	uint32_t cin, cout;		// byte counts
	uint32_t cin_wrap, cout_wrap;	// byte counter wrap count (RADIUS accounting giagawords)
	uint32_t cin_delta, cout_delta;	// byte count changes (for dump_session())
	uint16_t throttle_in;		// upstream throttle rate (kbps)
	uint16_t throttle_out;		// downstream throttle rate
	uint8_t filter_in;		// input filter index (to ip_filters[N-1]; 0 if none)
	uint8_t filter_out;		// output filter index
	uint16_t mru;			// maximum receive unit
	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)
	in_addr_t dns1, dns2;		// DNS servers
	routet route[MAXROUTE];		// static routes
	uint16_t tbf_in;		// filter bucket for throttling in from the user.
	uint16_t tbf_out;		// filter bucket for throttling out to the user.
	int random_vector_length;
	uint8_t random_vector[MAXTEL];
	char user[MAXUSER];		// user (needed in seesion for radius stop messages)
	char called[MAXTEL];		// called number
	char calling[MAXTEL];		// calling number
	uint32_t tx_connect_speed;
	uint32_t rx_connect_speed;
	in_addr_t snoop_ip;		// Interception destination IP
	uint16_t snoop_port;		// Interception destination port
	uint8_t walled_garden;		// is this session gardened?
	uint8_t ipv6prefixlen;		// IPv6 route prefix length
	struct in6_addr ipv6route;	// Static IPv6 route
	char reserved_3[11];		// Space to expand structure without changing HB_VERSION
}
sessiont;

#define AUTHPAP		1	// allow PAP
#define AUTHCHAP	2	// allow CHAP

typedef struct
{
	// packet counters
	uint32_t pin;
	uint32_t pout;

	// byte counters
	uint32_t cin;
	uint32_t cout;

	// PPP restart timer/counters
	struct {
		time_t restart;
		int conf_sent;
		int nak_sent;
	} lcp, ipcp, ipv6cp, ccp;

	// identifier for Protocol-Reject, Code-Reject
	uint8_t lcp_ident;

	// authentication to use
	int lcp_authtype;

	// our MRU
	uint16_t ppp_mru;

	// DoS prevention
	clockt last_packet_out;
	uint32_t packets_out;
	uint32_t packets_dropped;

	// RADIUS session in use
	uint16_t radius;

	// interim RADIUS
	time_t last_interim;

	// last LCP Echo
	time_t last_echo;
} sessionlocalt;

// session flags
#define SESSION_PFC	(1 << 0)	// use Protocol-Field-Compression
#define SESSION_ACFC	(1 << 1)	// use Address-and-Control-Field-Compression
#define SESSION_STARTED	(1 << 2)	// RADIUS Start record sent

// 168 bytes per tunnel
typedef struct
{
	tunnelidt far;		// far end tunnel ID
	in_addr_t ip;		// Ip for far end
	uint16_t port;		// port for far end
	uint16_t window;	// Rx window
	uint16_t nr;		// next receive
	uint16_t 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 resending 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
	uint8_t try;		// number of retrys on a control message
	uint16_t controlc;	// outstaind messages in queue
	controlt *controls;	// oldest message
	controlt *controle;	// newest message
}
tunnelt;

// 164 bytes per radius session
typedef struct			// outstanding RADIUS requests
{
	sessionidt session;	// which session this applies to
	hasht auth;		// request authenticator
	clockt retry;		// when to try next
	char pass[129];		// password
	uint8_t id;		// ID for PPP response
	uint8_t try;		// which try we are on
	uint8_t state;		// state of radius requests
	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;

typedef struct
{
	in_addr_t	address;	// Host byte order..
	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;
		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
	TUNNELUNDEF,		// Undefined
};

enum
{
	RADIUSNULL,             // Not in use
	RADIUSCHAP,             // sending CHAP down PPP
	RADIUSAUTH,             // sending auth to RADIUS server
	RADIUSSTART,            // sending start accounting to RADIUS server
	RADIUSSTOP,             // sending stop accounting to RADIUS server
	RADIUSINTERIM,		// sending interim accounting to RADIUS server
	RADIUSWAIT,		// waiting timeout before available, in case delayed replies
};

struct Tstats
{
    time_t	start_time;
    time_t	last_reset;

    uint32_t	tun_rx_packets;
    uint32_t	tun_tx_packets;
    uint32_t	tun_rx_bytes;
    uint32_t	tun_tx_bytes;
    uint32_t	tun_rx_errors;
    uint32_t	tun_tx_errors;
    uint32_t	tun_rx_dropped;

    uint32_t	tunnel_rx_packets;
    uint32_t	tunnel_tx_packets;
    uint32_t	tunnel_rx_bytes;
    uint32_t	tunnel_tx_bytes;
    uint32_t	tunnel_rx_errors;
    uint32_t	tunnel_tx_errors;

    uint32_t	tunnel_retries;
    uint32_t	radius_retries;

    uint32_t	arp_sent;

    uint32_t	packets_snooped;

    uint32_t	tunnel_created;
    uint32_t	session_created;
    uint32_t	tunnel_timeout;
    uint32_t	session_timeout;
    uint32_t	radius_timeout;
    uint32_t	radius_overflow;
    uint32_t	tunnel_overflow;
    uint32_t	session_overflow;

    uint32_t	ip_allocated;
    uint32_t	ip_freed;

    uint32_t	c_forwarded;
    uint32_t	recv_forward;

    uint32_t	select_called;
    uint32_t	multi_read_used;
    uint32_t	multi_read_exceeded;

#ifdef STATISTICS
    uint32_t	call_processtun;
    uint32_t	call_processipout;
    uint32_t	call_processipv6out;
    uint32_t	call_processudp;
    uint32_t	call_sessionbyip;
    uint32_t	call_sessionbyipv6;
    uint32_t	call_sessionbyuser;
    uint32_t	call_sendarp;
    uint32_t	call_sendipcp;
    uint32_t	call_sendipv6cp;
    uint32_t	call_processipv6cp;
    uint32_t	call_tunnelsend;
    uint32_t	call_sessionkill;
    uint32_t	call_sessionshutdown;
    uint32_t	call_tunnelkill;
    uint32_t	call_tunnelshutdown;
    uint32_t	call_assign_ip_address;
    uint32_t	call_free_ip_address;
    uint32_t	call_dump_acct_info;
    uint32_t	call_sessionsetup;
    uint32_t	call_processpap;
    uint32_t	call_processchap;
    uint32_t	call_processlcp;
    uint32_t	call_processipcp;
    uint32_t	call_processipin;
    uint32_t	call_processipv6in;
    uint32_t	call_processccp;
    uint32_t	call_sendchap;
    uint32_t	call_processrad;
    uint32_t	call_radiussend;
    uint32_t	call_radiusretry;
    uint32_t    call_random_data;
#endif
};

#ifdef STATISTICS

#ifdef STAT_CALLS
#define CSTAT(x)	STAT(call_ ## x)
#else
#define CSTAT(x)
#endif

#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 CSTAT(x)
#define STAT(x)
#define INC_STAT(x,y)
#define GET_STAT(x)	0
#define SET_STAT(x, y)
#endif

typedef struct
{
	int		debug;				// debugging level
	time_t		start_time;			// time when l2tpns was started
	char		bandwidth[256];			// current bandwidth
	char		pid_file[256];			// file to write PID to on startup
	int		wrote_pid;
	clockt		current_time;			// 1/10ths of a second since the process started.
							// means that we can only run a given process
							// for 13 years without re-starting!

	char		config_file[128];
	int		reload_config;			// flag to re-read config (set by cli)
	int		multi_read_count;		// amount of packets to read per fd in processing loop

	char		tundevice[10];			// tun device name
	char		log_filename[128];

	char		l2tp_secret[64];		// L2TP shared secret
	int		l2tp_mtu;			// MTU of interface used for L2TP

	char		random_device[256];		// random device path, defaults to RANDOMDEVICE

	int		ppp_restart_time;		// timeout for PPP restart
	int		ppp_max_configure;		// max lcp configure requests to send
	int		ppp_max_failure;		// max lcp configure naks to send

	char		radiussecret[64];
	int		radius_accounting;
	int		radius_interim;
	in_addr_t	radiusserver[MAXRADSERVER];	// radius servers
	uint16_t	radiusport[MAXRADSERVER];	// radius base ports
	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
	int		radius_authtypes;
	int		radius_authprefer;

	int		allow_duplicate_users;		// allow multiple logins with the same username

	in_addr_t	default_dns1, default_dns2;

	unsigned long	rl_rate;			// default throttle rate
	int		num_tbfs;			// number of throttle buckets

	char		accounting_dir[128];
	in_addr_t	bind_address;
	in_addr_t	peer_address;
	int		send_garp;			// Set to true to garp for vip address on startup

	int		target_uid;
	int		dump_speed;
	char		plugins[64][MAXPLUGINS];
	char		old_plugins[64][MAXPLUGINS];

	int		next_tbf;			// Next HTB id available to use
	int		scheduler_fifo;			// If the system has multiple CPUs, use FIFO scheduling
							// policy for this process.
	int		lock_pages;			// Lock pages into memory.
	int		icmp_rate;			// Max number of ICMP unreachable per second to send
	int		max_packets;			// DoS prevention: per session limit of packets/0.1s

	in_addr_t	cluster_address;		// Multicast address of cluster.
							// Send to this address to have everyone hear.
	char		cluster_interface[64];		// Which interface to listen for multicast on.
	int		cluster_iam_master;		// Are we the cluster master???
	int		cluster_iam_uptodate;		// Set if we've got a full set of state from the master.
	in_addr_t	cluster_master_address;		// The network address of the cluster master.
							// Zero if i am the cluster master.
	int		cluster_seq_number;		// Sequence number of the next heartbeat we'll send out
							// (or the seq number we're next expecting if we're a slave).
	int		cluster_undefined_sessions;	// How many sessions we're yet to receive from the master.
	int		cluster_undefined_tunnels;	// How many tunnels we're yet to receive from the master.
	int		cluster_highest_sessionid;
	int		cluster_highest_tunnelid;
	clockt		cluster_last_hb;		// Last time we saw a heartbeat from the master.
	int		cluster_last_hb_ver;		// Heartbeat version last seen from master
	int		cluster_num_changes;		// Number of changes queued.

	int		cluster_mcast_ttl;		// TTL for multicast packets
	int		cluster_hb_interval;		// How often to send a heartbeat.
	int		cluster_hb_timeout;		// How many missed heartbeats trigger an election.
	uint64_t	cluster_table_version;		// # state changes processed by cluster

	struct in6_addr ipv6_prefix;			// Our IPv6 network pool.


	int		cluster_master_min_adv;		// Master advertises routes while the number of up to date
							// slaves is less than this value.

#ifdef BGP
#define BGP_NUM_PEERS	2
	uint16_t as_number;
	struct {
		char name[64];
	    	uint16_t as;
		int keepalive;
		int hold;
	} neighbour[BGP_NUM_PEERS];
#endif
} configt;

enum config_typet { INT, STRING, UNSIGNED_LONG, SHORT, BOOL, IPv4, IPv6 };
typedef struct
{
	char *key;
	int offset;
	int size;
	enum config_typet type;
} config_descriptt;

typedef struct
{
	uint8_t op;	// operation
#define FILTER_PORT_OP_NONE	0 // all ports match
#define FILTER_PORT_OP_EQ	1
#define FILTER_PORT_OP_NEQ	2
#define FILTER_PORT_OP_GT	3
#define FILTER_PORT_OP_LT	4
#define FILTER_PORT_OP_RANGE	5
	uint16_t port;	// port (host byte order)
	uint16_t port2;	// range
} ip_filter_portt;

typedef struct
{
	int action;		// permit/deny
#define FILTER_ACTION_DENY	1
#define FILTER_ACTION_PERMIT	2
	uint8_t proto;		// protocol: IPPROTO_* (netinet/in.h)
	in_addr_t src_ip;	// source ip (network byte order)
	in_addr_t src_wild;
	ip_filter_portt src_ports;
	in_addr_t dst_ip;	// dest ip
	in_addr_t dst_wild;
	ip_filter_portt dst_ports;
	uint8_t frag;		// apply to non-initial fragments
	uint8_t tcp_flag_op;	// match type: any, all, established
#define FILTER_FLAG_OP_ANY	1
#define FILTER_FLAG_OP_ALL	2
#define FILTER_FLAG_OP_EST	3
	uint8_t tcp_sflags;	// flags set
	uint8_t tcp_cflags;	// flags clear
	uint32_t counter;	// match count
} ip_filter_rulet;

#define TCP_FLAG_FIN	0x01
#define TCP_FLAG_SYN	0x02
#define TCP_FLAG_RST	0x04
#define TCP_FLAG_PSH	0x08
#define TCP_FLAG_ACK	0x10
#define TCP_FLAG_URG	0x20

#define MAXFILTER		32
#define MAXFILTER_RULES		32
typedef struct
{
    	char name[32];		// ACL name
	int extended;		// type: 0 = standard, 1 = extended
	ip_filter_rulet rules[MAXFILTER_RULES];
	int used;		// session ref count
} 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
void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip);


// ppp.c
void processpap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void processchap(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void lcp_open(sessionidt s, tunnelidt t);
void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void processipcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void processipv6cp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void processipin(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void processipv6in(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void processccp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l);
void sendchap(sessionidt s, tunnelidt t);
uint8_t *makeppp(uint8_t *b, int size, uint8_t *p, int l, sessionidt s, tunnelidt t, uint16_t mtype);
void sendlcp(sessionidt s, tunnelidt t);
void send_ipin(sessionidt s, uint8_t *buf, int len);
void sendccp(sessionidt s, tunnelidt t);
void protoreject(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l, uint16_t proto);


// radius.c
void initrad(void);
void radiussend(uint16_t r, uint8_t state);
void processrad(uint8_t *buf, int len, char socket_index);
void radiusretry(uint16_t r);
uint16_t radiusnew(sessionidt s);
void radiusclear(uint16_t r, sessionidt s);
void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struct in_addr *local);


// l2tpns.c
clockt backoff(uint8_t try);
void send_ipv6_ra(sessionidt s, tunnelidt t, struct in6_addr *ip);
void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add);
sessionidt sessionbyip(in_addr_t ip);
sessionidt sessionbyipv6(struct in6_addr ip);
sessionidt sessionbyuser(char *username);
void increment_counter(uint32_t *counter, uint32_t *wrap, uint32_t delta);
void random_data(uint8_t *buf, int len);
void sessionkill(sessionidt s, char *reason);
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 send_garp(in_addr_t ip);
void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t);
int tun_write(uint8_t *data, int size);
void adjust_tcp_mss(sessionidt s, tunnelidt t, uint8_t *buf, int len, uint8_t *tcp);
void sendipcp(sessionidt s, tunnelidt t);
void sendipv6cp(sessionidt s, tunnelidt t);
void processudp(uint8_t *buf, int len, struct sockaddr_in *addr);
void snoop_send_packet(uint8_t *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 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_open(struct cli_def *cli, char *command, char **argv, int argc);

#undef LOG
#undef LOG_HEX
#define LOG(D, s, t, f, ...)	({ if (D <= config->debug) _log(D, s, t, f, ## __VA_ARGS__); })
#define LOG_HEX(D, t, d, s)	({ if (D <= config->debug) _log_hex(D, t, d, s); })

void _log(int level, sessionidt s, tunnelidt t, const char *format, ...) __attribute__((format (printf, 4, 5)));
void _log_hex(int level, const char *title, const uint8_t *data, int maxsize);


int sessionsetup(sessionidt s, tunnelidt t);
int run_plugins(int plugin_type, void *data);
void rebuild_address_pool(void);
void throttle_session(sessionidt s, int rate_in, int rate_out);
int load_session(sessionidt, sessiont *);
void become_master(void);	// We're the master; kick off any required master initializations.


// cli.c
void init_cli(char *hostname);
void cli_do_file(FILE *fh);
void cli_do(int sockfd);
int cli_arg_help(struct cli_def *cli, int cr_ok, char *entry, ...);


// icmp.c
void host_unreachable(in_addr_t destination, uint16_t id, in_addr_t source, uint8_t *packet, int packet_len);


extern tunnelt *tunnel;
extern sessiont *session;
extern sessionlocalt *sess_local;
extern ippoolt *ip_address_pool;
#define sessionfree (session[0].next)


extern configt *config;
extern time_t basetime;		// Time when this process started.
extern time_t time_now;		// Seconds since EPOCH.
extern char main_quit;
extern uint32_t last_id;
extern struct Tstats *_statistics;
extern in_addr_t my_address;
extern int clifd;
extern int epollfd;

struct event_data {
	enum {
	    	FD_TYPE_CLI,
	    	FD_TYPE_CLUSTER,
	    	FD_TYPE_TUN,
	    	FD_TYPE_UDP,
	    	FD_TYPE_CONTROL,
	    	FD_TYPE_DAE,
		FD_TYPE_RADIUS,
		FD_TYPE_BGP,
	} type;
	int index; // for RADIUS, BGP
};

#define TIME (config->current_time)

extern uint16_t MRU;
extern uint16_t MSS;

// macros for handling help in cli commands
#define CLI_HELP_REQUESTED	(argc > 0 && argv[argc-1][strlen(argv[argc-1])-1] == '?')
#define CLI_HELP_NO_ARGS	(argc > 1 || argv[0][1]) ? CLI_OK : cli_arg_help(cli, 1, NULL)

// CVS identifiers (for "show version file")
extern char const *cvs_id_arp;
extern char const *cvs_id_cli;
extern char const *cvs_id_cluster;
extern char const *cvs_id_constants;
extern char const *cvs_id_control;
extern char const *cvs_id_icmp;
extern char const *cvs_id_l2tpns;
extern char const *cvs_id_ll;
extern char const *cvs_id_md5;
extern char const *cvs_id_ppp;
extern char const *cvs_id_radius;
extern char const *cvs_id_tbf;
extern char const *cvs_id_util;

#endif /* __L2TPNS_H__ */