l2tp.c 27.4 KB
Newer Older
K
Kozlov Dmitry 已提交
1 2 3 4 5 6 7 8 9 10 11 12
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
13
#include <linux/socket.h>
14 15 16
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_pppox.h>
K
Kozlov Dmitry 已提交
17 18 19 20 21 22 23

#include "triton.h"
#include "mempool.h"
#include "log.h"
#include "ppp.h"
#include "events.h"
#include "utils.h"
24
#include "iprange.h"
25
#include "cli.h"
K
Kozlov Dmitry 已提交
26 27 28 29 30 31

#include "memdebug.h"

#include "l2tp.h"
#include "attr_defs.h"

32 33 34 35
#ifndef SOL_PPPOL2TP
#define SOL_PPPOL2TP 273
#endif

K
Kozlov Dmitry 已提交
36
#define STATE_WAIT_SCCCN 1
37 38 39 40 41 42 43
#define STATE_WAIT_ICRQ  2
#define STATE_WAIT_ICCN  3
#define STATE_WAIT_OCRP  4
#define STATE_WAIT_OCCN  5
#define STATE_ESTB       6
#define STATE_PPP        7
#define STATE_FIN        8
K
Kozlov Dmitry 已提交
44 45 46
#define STATE_CLOSE      0

int conf_verbose = 0;
47 48 49 50 51 52
static int conf_timeout = 60;
static int conf_rtimeout = 5;
static int conf_retransmit = 5;
static int conf_hello_interval = 60;
static int conf_dir300_quirk = 0;
static const char *conf_host_name = "accel-ppp";
K
Kozlov Dmitry 已提交
53

D
Dmitry Kozlov 已提交
54 55
static unsigned int stat_active;
static unsigned int stat_starting;
56

K
Kozlov Dmitry 已提交
57 58 59 60 61 62 63 64 65 66
struct l2tp_serv_t
{
	struct triton_context_t ctx;
	struct triton_md_handler_t hnd;
	struct sockaddr_in addr;
};

struct l2tp_conn_t
{
	struct triton_context_t ctx;
67
	struct triton_md_handler_t hnd;
K
Kozlov Dmitry 已提交
68
	struct triton_timer_t timeout_timer;
69 70
	struct triton_timer_t rtimeout_timer;
	struct triton_timer_t hello_timer;
K
Kozlov Dmitry 已提交
71

72 73
	int tunnel_fd;

K
Kozlov Dmitry 已提交
74 75 76 77 78 79 80 81 82 83 84 85
	struct sockaddr_in addr;
	uint16_t tid;
	uint16_t sid;
	uint16_t peer_tid;
	uint16_t peer_sid;
	uint32_t framing_cap;

	int retransmit;
	uint16_t Ns, Nr;
	struct list_head send_queue;

	int state;
86 87
	int state1;
	int state2;
K
Kozlov Dmitry 已提交
88 89 90 91 92 93 94 95 96 97 98 99

	struct ppp_ctrl_t ctrl;
	struct ppp_t ppp;
};

static pthread_mutex_t l2tp_lock = PTHREAD_MUTEX_INITIALIZER;
static struct l2tp_conn_t **l2tp_conn;
static uint16_t l2tp_tid;

static mempool_t l2tp_conn_pool;

static void l2tp_timeout(struct triton_timer_t *t);
100 101
static void l2tp_rtimeout(struct triton_timer_t *t);
static void l2tp_send_HELLO(struct triton_timer_t *t);
K
Kozlov Dmitry 已提交
102
static void l2tp_send_SCCRP(struct l2tp_conn_t *conn);
103
static int l2tp_send(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack, int log_debug);
104
static int l2tp_conn_read(struct triton_md_handler_t *);
K
Kozlov Dmitry 已提交
105

106
static void l2tp_disconnect(struct l2tp_conn_t *conn)
K
Kozlov Dmitry 已提交
107
{
108
	struct l2tp_packet_t *pack;
K
Kozlov Dmitry 已提交
109

110 111
	triton_md_unregister_handler(&conn->hnd);
	close(conn->hnd.fd);
K
Kozlov Dmitry 已提交
112 113 114 115

	if (conn->timeout_timer.tpd)
		triton_timer_del(&conn->timeout_timer);

116 117 118 119 120
	if (conn->rtimeout_timer.tpd)
		triton_timer_del(&conn->rtimeout_timer);

	if (conn->hello_timer.tpd)
		triton_timer_del(&conn->hello_timer);
K
Kozlov Dmitry 已提交
121 122

	if (conn->state == STATE_PPP) {
123
		__sync_sub_and_fetch(&stat_active, 1);
124
		conn->state = STATE_FIN;
125
		ppp_terminate(&conn->ppp, TERM_USER_REQUEST, 1);
126
	} else if (conn->state != STATE_FIN)
127
		__sync_sub_and_fetch(&stat_starting, 1);
K
Kozlov Dmitry 已提交
128 129 130 131 132

	pthread_mutex_lock(&l2tp_lock);
	l2tp_conn[conn->tid] = NULL;
	pthread_mutex_unlock(&l2tp_lock);

133 134 135 136 137 138
	if (conn->ppp.fd != -1)
		close(conn->ppp.fd);
	
	if (conn->tunnel_fd != -1)
		close(conn->tunnel_fd);

K
Kozlov Dmitry 已提交
139 140
	triton_event_fire(EV_CTRL_FINISHED, &conn->ppp);
	
141
	log_ppp_info1("disconnected\n");
K
Kozlov Dmitry 已提交
142 143 144

	triton_context_unregister(&conn->ctx);

145 146 147 148 149
	while (!list_empty(&conn->send_queue)) {
		pack = list_entry(conn->send_queue.next, typeof(*pack), entry);
		list_del(&pack->entry);
		l2tp_packet_free(pack);
	}
K
Kozlov Dmitry 已提交
150 151 152 153 154 155

	if (conn->ppp.chan_name)
		_free(conn->ppp.chan_name);
	
	_free(conn->ctrl.calling_station_id);
	_free(conn->ctrl.called_station_id);
K
Kozlov Dmitry 已提交
156

K
Kozlov Dmitry 已提交
157 158 159
	mempool_free(conn);
}

160
static int l2tp_terminate(struct l2tp_conn_t *conn, int res, int err)
K
Kozlov Dmitry 已提交
161 162 163 164
{
	struct l2tp_packet_t *pack;
	struct l2tp_avp_result_code rc = {res, err};

165 166
	log_ppp_debug("l2tp: terminate (%i, %i)\n", res, err);

K
Kozlov Dmitry 已提交
167
	pack = l2tp_packet_alloc(2, Message_Type_Stop_Ctrl_Conn_Notify, &conn->addr);
168 169
	if (!pack)
		return -1;
K
Kozlov Dmitry 已提交
170
	
171
	if (l2tp_packet_add_int16(pack, Assigned_Tunnel_ID, conn->tid, 1))
K
Kozlov Dmitry 已提交
172
		goto out_err;
173
	if (l2tp_packet_add_octets(pack, Result_Code, (uint8_t *)&rc, sizeof(rc), 0))
K
Kozlov Dmitry 已提交
174 175
		goto out_err;

176
	l2tp_send(conn, pack, 0);
K
Kozlov Dmitry 已提交
177

178 179 180
	conn->state = STATE_FIN;

	return 0;
K
Kozlov Dmitry 已提交
181 182 183

out_err:
	l2tp_packet_free(pack);
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
	return -1;
}

static void l2tp_ppp_started(struct ppp_t *ppp)
{
	struct l2tp_conn_t *conn = container_of(ppp, typeof(*conn), ppp);
	
	log_ppp_debug("l2tp: ppp started\n");
	
	if (conf_hello_interval)
		triton_timer_add(&conn->ctx, &conn->hello_timer, 0);
}

static void l2tp_ppp_finished(struct ppp_t *ppp)
{
	struct l2tp_conn_t *conn = container_of(ppp, typeof(*conn), ppp);

	log_ppp_debug("l2tp: ppp finished\n");

	if (conn->state != STATE_FIN) {
204
		__sync_sub_and_fetch(&stat_active, 1);
205 206 207 208 209 210 211 212 213 214
		if (l2tp_terminate(conn, 0, 0))
			triton_context_call(&conn->ctx, (triton_event_func)l2tp_disconnect, conn);
	}
}

static void l2tp_conn_close(struct triton_context_t *ctx)
{
	struct l2tp_conn_t *conn = container_of(ctx, typeof(*conn), ctx);
	
	if (conn->state == STATE_PPP) {
215
		__sync_sub_and_fetch(&stat_active, 1);
216
		conn->state = STATE_FIN;
217
		ppp_terminate(&conn->ppp, TERM_ADMIN_RESET, 1);
218 219 220 221
	}
	
	if (l2tp_terminate(conn, 0, 0))
		l2tp_disconnect(conn);
K
Kozlov Dmitry 已提交
222 223
}

224
static int l2tp_tunnel_alloc(struct l2tp_serv_t *serv, struct l2tp_packet_t *pack, struct in_pktinfo *pkt_info, struct l2tp_attr_t *assigned_tid, struct l2tp_attr_t *framing_cap)
K
Kozlov Dmitry 已提交
225 226
{
	struct l2tp_conn_t *conn;
227
	struct sockaddr_in addr;
K
Kozlov Dmitry 已提交
228
	uint16_t tid;
229
	//char *opt;
230
	int flag = 1;
K
Kozlov Dmitry 已提交
231 232 233 234

	conn = mempool_alloc(l2tp_conn_pool);
	if (!conn) {
		log_emerg("l2tp: out of memory\n");
235
		return -1;
K
Kozlov Dmitry 已提交
236 237 238
	}

	memset(conn, 0, sizeof(*conn));
239 240 241 242 243 244 245 246
	INIT_LIST_HEAD(&conn->send_queue);

	conn->hnd.fd = socket(PF_INET, SOCK_DGRAM, 0);
	if (conn->hnd.fd < 0) {
		log_error("l2tp: socket: %s\n", strerror(errno));
		mempool_free(conn);
		return -1;
	}
247 248
	
	fcntl(conn->hnd.fd, F_SETFD, fcntl(conn->hnd.fd, F_GETFD) | FD_CLOEXEC);
249 250 251

	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
252
	addr.sin_addr = pkt_info->ipi_addr;
253 254
	addr.sin_port = htons(L2TP_PORT);

255
  setsockopt(conn->hnd.fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
256 257 258 259 260
	if (bind(conn->hnd.fd, &addr, sizeof(addr))) {
		log_error("l2tp: bind: %s\n", strerror(errno));
		goto out_err;
	}
	
261 262 263 264 265 266 267 268 269
	if (connect(conn->hnd.fd, (struct sockaddr *)&pack->addr, sizeof(addr))) {
		log_error("l2tp: connect: %s\n", strerror(errno));
		goto out_err;
	}
 
	if (fcntl(conn->hnd.fd, F_SETFL, O_NONBLOCK)) {
    log_emerg("l2tp: failed to set nonblocking mode: %s\n", strerror(errno));
		goto out_err;
	}
K
Kozlov Dmitry 已提交
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286

	pthread_mutex_lock(&l2tp_lock);
	for (tid = l2tp_tid + 1; tid != l2tp_tid; tid++) {
		if (tid == L2TP_MAX_TID)
			tid = 1;
		if (!l2tp_conn[tid]) {
			l2tp_conn[tid] = conn;
			conn->tid = tid;
			break;
		}
	}
	pthread_mutex_unlock(&l2tp_lock);

	if (!conn->tid) {
		if (conf_verbose)
			log_warn("l2tp: no free tid available\n");
		mempool_free(conn);
287
		return -1;
K
Kozlov Dmitry 已提交
288 289
	}

290
	conn->sid = 1;
K
Kozlov Dmitry 已提交
291 292 293 294 295

	memcpy(&conn->addr, &pack->addr, sizeof(pack->addr));
	conn->peer_tid = assigned_tid->val.uint16;
	conn->framing_cap = framing_cap->val.uint32;

296 297 298
	conn->ctx.before_switch = log_switch;
	conn->ctx.close = l2tp_conn_close;
	conn->hnd.read = l2tp_conn_read;
K
Kozlov Dmitry 已提交
299 300
	conn->timeout_timer.expire = l2tp_timeout;
	conn->timeout_timer.period = conf_timeout * 1000;
301 302 303 304
	conn->rtimeout_timer.expire = l2tp_rtimeout;
	conn->rtimeout_timer.period = conf_rtimeout * 1000;
	conn->hello_timer.expire = l2tp_send_HELLO;
	conn->hello_timer.period = conf_hello_interval * 1000;
K
Kozlov Dmitry 已提交
305
	conn->ctrl.ctx = &conn->ctx;
K
Kozlov Dmitry 已提交
306
	conn->ctrl.type = CTRL_TYPE_L2TP;
K
Kozlov Dmitry 已提交
307
	conn->ctrl.name = "l2tp";
308 309 310
	conn->ctrl.started = l2tp_ppp_started;
	conn->ctrl.finished = l2tp_ppp_finished;
	conn->ctrl.max_mtu = 1420;
K
Kozlov Dmitry 已提交
311 312 313 314

	conn->ctrl.calling_station_id = _malloc(17);
	conn->ctrl.called_station_id = _malloc(17);
	u_inet_ntoa(conn->addr.sin_addr.s_addr, conn->ctrl.calling_station_id);
315
	u_inet_ntoa(addr.sin_addr.s_addr, conn->ctrl.called_station_id);
K
Kozlov Dmitry 已提交
316 317 318

	ppp_init(&conn->ppp);
	conn->ppp.ctrl = &conn->ctrl;
319 320
	conn->ppp.fd = -1;
	conn->tunnel_fd = -1;
K
Kozlov Dmitry 已提交
321 322

	triton_context_register(&conn->ctx, &conn->ppp);
323 324
	triton_md_register_handler(&conn->ctx, &conn->hnd);
	triton_md_enable_handler(&conn->hnd, MD_MODE_READ);
K
Kozlov Dmitry 已提交
325 326 327 328
	triton_context_wakeup(&conn->ctx);

	if (conf_verbose) {
		log_switch(&conn->ctx, &conn->ppp);
329 330
		log_ppp_info2("recv ");
		l2tp_packet_print(pack, log_ppp_info2);
K
Kozlov Dmitry 已提交
331 332 333
	}

	triton_context_call(&conn->ctx, (triton_event_func)l2tp_send_SCCRP, conn);
334

335
	__sync_add_and_fetch(&stat_starting, 1);
336

337 338 339 340 341 342
	return 0;

out_err:
	close(conn->hnd.fd);
	mempool_free(conn);
	return -1;
K
Kozlov Dmitry 已提交
343 344 345 346
}

static int l2tp_connect(struct l2tp_conn_t *conn)
{
347
	struct sockaddr_pppol2tp pppox_addr;
348 349 350
	int arg = 1;

	memset(&pppox_addr, 0, sizeof(pppox_addr));
351 352 353 354 355 356 357
	pppox_addr.sa_family = AF_PPPOX;
	pppox_addr.sa_protocol = PX_PROTO_OL2TP;
	pppox_addr.pppol2tp.fd = conn->hnd.fd;
	memcpy(&pppox_addr.pppol2tp.addr, &conn->addr, sizeof(conn->addr));
	pppox_addr.pppol2tp.s_tunnel = conn->tid;
	pppox_addr.pppol2tp.d_tunnel = conn->peer_tid;

358 359 360 361 362
	conn->tunnel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
	if (!conn->ppp.fd) {
		log_ppp_error("l2tp: socket(AF_PPPOX): %s\n", strerror(errno));
		return -1;
	}
363 364
	
	fcntl(conn->tunnel_fd, F_SETFD, fcntl(conn->tunnel_fd, F_GETFD) | FD_CLOEXEC);
365 366 367

	conn->ppp.fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
	if (!conn->ppp.fd) {
368 369
		close(conn->tunnel_fd);
		conn->tunnel_fd = -1;
370 371 372
		log_ppp_error("l2tp: socket(AF_PPPOX): %s\n", strerror(errno));
		return -1;
	}
373 374
	
	fcntl(conn->ppp.fd, F_SETFD, fcntl(conn->ppp.fd, F_GETFD) | FD_CLOEXEC);
375

376 377 378 379 380 381 382 383 384 385
	if (connect(conn->tunnel_fd, (struct sockaddr *)&pppox_addr, sizeof(pppox_addr)) < 0) {
		log_ppp_error("l2tp: connect(tunnel): %s\n", strerror(errno));
		return -1;
	}

	pppox_addr.pppol2tp.s_session = conn->sid;
	pppox_addr.pppol2tp.d_session = conn->peer_sid;

	if (connect(conn->ppp.fd, (struct sockaddr *)&pppox_addr, sizeof(pppox_addr)) < 0) {
		log_ppp_error("l2tp: connect(session): %s\n", strerror(errno));
386 387 388
		return -1;
	}

389
	if (setsockopt(conn->ppp.fd, SOL_PPPOL2TP, PPPOL2TP_SO_LNSMODE, &arg, sizeof(arg))) {
390 391
		log_ppp_error("l2tp: setsockopt: %s\n", strerror(errno));
		return -1;
392
	}
K
Kozlov Dmitry 已提交
393

394 395 396 397
	conn->ppp.chan_name = _strdup(inet_ntoa(conn->addr.sin_addr));
	
	triton_event_fire(EV_CTRL_STARTED, &conn->ppp);

398
	if (establish_ppp(&conn->ppp))
399 400
		return -1;

401 402
	__sync_sub_and_fetch(&stat_starting, 1);
	__sync_add_and_fetch(&stat_active, 1);
403

404 405
	conn->state = STATE_PPP;
	
K
Kozlov Dmitry 已提交
406 407 408
	return 0;
}

409
static void l2tp_rtimeout(struct triton_timer_t *t)
K
Kozlov Dmitry 已提交
410
{
411
	struct l2tp_conn_t *conn = container_of(t, typeof(*conn), rtimeout_timer);
K
Kozlov Dmitry 已提交
412 413 414 415 416 417 418 419
	struct l2tp_packet_t *pack;

	if (!list_empty(&conn->send_queue)) {
		log_ppp_debug("l2tp: retransmit (%i)\n", conn->retransmit);
		if (++conn->retransmit <= conf_retransmit) {
			pack = list_entry(conn->send_queue.next, typeof(*pack), entry);
			pack->hdr.Nr = htons(conn->Nr + 1);
			if (conf_verbose) {
420 421
				log_ppp_debug("send ");
				l2tp_packet_print(pack, log_ppp_debug);
K
Kozlov Dmitry 已提交
422
			}
423
			if (l2tp_packet_send(conn->hnd.fd, pack) == 0)
K
Kozlov Dmitry 已提交
424
				return;
425 426
		} else
			l2tp_disconnect(conn);
K
Kozlov Dmitry 已提交
427
	}
428 429 430 431 432 433
}

static void l2tp_timeout(struct triton_timer_t *t)
{
	struct l2tp_conn_t *conn = container_of(t, typeof(*conn), timeout_timer);
	log_ppp_debug("l2tp: timeout\n");
K
Kozlov Dmitry 已提交
434 435 436
	l2tp_disconnect(conn);
}

437
static int l2tp_send(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack, int log_debug)
K
Kozlov Dmitry 已提交
438 439 440 441
{
	conn->retransmit = 0;

	pack->hdr.tid = htons(conn->peer_tid);
442
	//pack->hdr.sid = htons(conn->peer_sid);
K
Kozlov Dmitry 已提交
443
	pack->hdr.Nr = htons(conn->Nr + 1);
444 445 446 447
	pack->hdr.Ns = htons(conn->Ns);

	if (!list_empty(&pack->attrs))
		conn->Ns++;
K
Kozlov Dmitry 已提交
448 449

	if (conf_verbose) {
450 451 452 453
		if (log_debug) {
			log_ppp_debug("send ");
			l2tp_packet_print(pack, log_ppp_debug);
		} else {
454 455
			log_ppp_info2("send ");
			l2tp_packet_print(pack, log_ppp_info2);
456
		}
K
Kozlov Dmitry 已提交
457 458
	}

459
	if (l2tp_packet_send(conn->hnd.fd, pack))
K
Kozlov Dmitry 已提交
460 461
		goto out_err;

462
	if (!list_empty(&pack->attrs)) {
K
Kozlov Dmitry 已提交
463
		list_add_tail(&pack->entry, &conn->send_queue);
464 465
		if (!conn->rtimeout_timer.tpd)
			triton_timer_add(&conn->ctx, &conn->rtimeout_timer, 0);
K
Kozlov Dmitry 已提交
466 467
	} else
		l2tp_packet_free(pack);
K
Kozlov Dmitry 已提交
468
	
469
	return 0;
K
Kozlov Dmitry 已提交
470 471 472

out_err:
	l2tp_packet_free(pack);
473
	return -1;
K
Kozlov Dmitry 已提交
474 475
}

476
static int l2tp_send_ZLB(struct l2tp_conn_t *conn)
K
Kozlov Dmitry 已提交
477 478 479 480
{
	struct l2tp_packet_t *pack;

	pack = l2tp_packet_alloc(2, 0, &conn->addr);
481 482 483
	if (!pack)
		return -1;

484
	if (l2tp_send(conn, pack, 1))
485 486 487 488 489 490 491 492 493 494 495
		return -1;

	return 0;
}

static void l2tp_send_HELLO(struct triton_timer_t *t)
{
	struct l2tp_conn_t *conn = container_of(t, typeof(*conn), hello_timer);
	struct l2tp_packet_t *pack;

	pack = l2tp_packet_alloc(2, Message_Type_Hello, &conn->addr);
K
Kozlov Dmitry 已提交
496 497 498 499 500
	if (!pack) {
		l2tp_disconnect(conn);
		return;
	}

501
	if (l2tp_send(conn, pack, 1))
502
		l2tp_disconnect(conn);
K
Kozlov Dmitry 已提交
503 504 505 506 507 508 509
}

static void l2tp_send_SCCRP(struct l2tp_conn_t *conn)
{
	struct l2tp_packet_t *pack;

	pack = l2tp_packet_alloc(2, Message_Type_Start_Ctrl_Conn_Reply, &conn->addr);
510 511
	if (!pack)
		goto out;
K
Kozlov Dmitry 已提交
512
	
513
	if (l2tp_packet_add_int16(pack, Protocol_Version, L2TP_V2_PROTOCOL_VERSION, 1))
K
Kozlov Dmitry 已提交
514
		goto out_err;
515
	if (l2tp_packet_add_string(pack, Host_Name, conf_host_name, 1))
K
Kozlov Dmitry 已提交
516
		goto out_err;
517
	if (l2tp_packet_add_int32(pack, Framing_Capabilities, conn->framing_cap, 1))
K
Kozlov Dmitry 已提交
518
		goto out_err;
519
	if (l2tp_packet_add_int16(pack, Assigned_Tunnel_ID, conn->tid, 1))
K
Kozlov Dmitry 已提交
520
		goto out_err;
521 522
	if (l2tp_packet_add_string(pack, Vendor_Name, "accel-ppp", 0))
		goto out_err;
K
Kozlov Dmitry 已提交
523

524
	if (l2tp_send(conn, pack, 0))
525
		goto out;
K
Kozlov Dmitry 已提交
526

527 528 529 530
	if (!conn->timeout_timer.tpd)
		triton_timer_add(&conn->ctx, &conn->timeout_timer, 0);
	else
		triton_timer_mod(&conn->timeout_timer, 0);
K
Kozlov Dmitry 已提交
531 532 533 534 535 536 537

	conn->state = STATE_WAIT_SCCCN;

	return;

out_err:
	l2tp_packet_free(pack);
538
out:
K
Kozlov Dmitry 已提交
539 540 541
	l2tp_disconnect(conn);
}

542
static int l2tp_send_ICRP(struct l2tp_conn_t *conn)
K
Kozlov Dmitry 已提交
543 544 545
{
	struct l2tp_packet_t *pack;

546 547 548
	pack = l2tp_packet_alloc(2, Message_Type_Incoming_Call_Reply, &conn->addr);
	if (!pack)
		return -1;
K
Kozlov Dmitry 已提交
549

550 551 552
	pack->hdr.sid = htons(conn->peer_sid);
	
	if (l2tp_packet_add_int16(pack, Assigned_Session_ID, conn->sid, 1))
K
Kozlov Dmitry 已提交
553 554
		goto out_err;

555
	l2tp_send(conn, pack, 0);
K
Kozlov Dmitry 已提交
556

557 558 559 560 561 562 563 564
	if (!conn->timeout_timer.tpd)
		triton_timer_add(&conn->ctx, &conn->timeout_timer, 0);
	else
		triton_timer_mod(&conn->timeout_timer, 0);
	
	conn->state1 = STATE_WAIT_ICCN;
	
	return 0;
K
Kozlov Dmitry 已提交
565 566 567

out_err:
	l2tp_packet_free(pack);
568 569 570
	return -1;
}

571
/*static int l2tp_send_OCRQ(struct l2tp_conn_t *conn)
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
{
	struct l2tp_packet_t *pack;

	pack = l2tp_packet_alloc(2, Message_Type_Outgoing_Call_Request, &conn->addr);
	if (!pack)
		return -1;
	
	pack->hdr.sid = htons(conn->peer_sid);

	if (l2tp_packet_add_int16(pack, Assigned_Session_ID, conn->sid, 1))
		goto out_err;
	if (l2tp_packet_add_int32(pack, Call_Serial_Number, 0, 1))
		goto out_err;
	if (l2tp_packet_add_int32(pack, Minimum_BPS, 100, 1))
		goto out_err;
	if (l2tp_packet_add_int32(pack, Maximum_BPS, 100000, 1))
		goto out_err;
	if (l2tp_packet_add_int32(pack, Bearer_Type, 3, 1))
		goto out_err;
	if (l2tp_packet_add_int32(pack, Framing_Type, 3, 1))
		goto out_err;
	if (l2tp_packet_add_string(pack, Called_Number, "", 1))
		goto out_err;

596
	if (l2tp_send(conn, pack, 0))
597 598 599 600 601 602 603 604 605 606 607 608 609 610
		return -1;

	if (!conn->timeout_timer.tpd)
		triton_timer_add(&conn->ctx, &conn->timeout_timer, 0);
	else
		triton_timer_mod(&conn->timeout_timer, 0);
	
	conn->state2 = STATE_WAIT_OCRP;
	
	return 0;

out_err:
	l2tp_packet_free(pack);
	return -1;
611
}*/
K
Kozlov Dmitry 已提交
612

613

614
static int l2tp_recv_SCCRQ(struct l2tp_serv_t *serv, struct l2tp_packet_t *pack, struct in_pktinfo *pkt_info)
K
Kozlov Dmitry 已提交
615 616 617 618 619 620 621 622
{
	struct l2tp_attr_t *attr;
	struct l2tp_attr_t *protocol_version = NULL;
	struct l2tp_attr_t *assigned_tid = NULL;
	struct l2tp_attr_t *assigned_cid = NULL;
	struct l2tp_attr_t *framing_cap = NULL;
	struct l2tp_attr_t *router_id = NULL;
	
D
Dmitry Kozlov 已提交
623
	if (ppp_shutdown)
624 625
		return 0;

K
Kozlov Dmitry 已提交
626 627 628 629 630 631 632 633 634 635 636 637 638 639
	list_for_each_entry(attr, &pack->attrs, entry) {
		switch (attr->attr->id) {
			case Protocol_Version:
				protocol_version = attr;
				break;
			case Framing_Capabilities:
				framing_cap = attr;
				break;
			case Assigned_Tunnel_ID:
				assigned_tid = attr;
				break;
			case Challenge:
				if (conf_verbose)
					log_warn("l2tp: Challenge in SCCRQ is not supported\n");
640
				return -1;
K
Kozlov Dmitry 已提交
641 642 643 644 645 646 647 648 649
			case Assigned_Connection_ID:
				assigned_cid = attr;
				break;
			case Router_ID:
				router_id = attr;
				break;
			case Message_Digest:
				if (conf_verbose)
					log_warn("l2tp: Message-Digest is not supported\n");
650
				return -1;
K
Kozlov Dmitry 已提交
651 652 653 654 655 656 657
		}
	}

	if (assigned_tid) {
		if (!protocol_version) {
			if (conf_verbose)
				log_warn("l2tp: SCCRQ: no Protocol-Version present in message\n");
658
			return -1;
K
Kozlov Dmitry 已提交
659 660 661 662
		}
		if (protocol_version->val.uint16 != L2TP_V2_PROTOCOL_VERSION) {
			if (conf_verbose)
				log_warn("l2tp: protocol version %02x is not supported\n", protocol_version->val.uint16);
663
			return -1;
K
Kozlov Dmitry 已提交
664 665 666 667
		}
		if (!framing_cap) {
			if (conf_verbose)
				log_warn("l2tp: SCCRQ: no Framing-Capabilities present in message\n");
668
			return -1;
K
Kozlov Dmitry 已提交
669 670
		}
		
671
		if (l2tp_tunnel_alloc(serv, pack, pkt_info, assigned_tid, framing_cap))
672
			return -1;
K
Kozlov Dmitry 已提交
673 674 675

	} else if (assigned_cid) {
		// not yet implemented
676
		return 0;
K
Kozlov Dmitry 已提交
677 678 679
	} else {
		if (conf_verbose)
			log_warn("l2tp: SCCRQ: no Assigned-Tunnel-ID or Assigned-Connection-ID present in message\n");
680
		return -1;
K
Kozlov Dmitry 已提交
681
	}
682 683

	return 0;
K
Kozlov Dmitry 已提交
684 685
}

686
static int l2tp_recv_SCCCN(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
K
Kozlov Dmitry 已提交
687 688
{
	if (conn->state == STATE_WAIT_SCCCN) {
689 690 691
		triton_timer_mod(&conn->timeout_timer, 0);
		conn->state = STATE_ESTB;
		conn->state1 = STATE_WAIT_ICRQ;
K
Kozlov Dmitry 已提交
692 693 694
	}
	else
		log_ppp_warn("l2tp: unexpected SCCCN\n");
695 696
	
	return 0;
K
Kozlov Dmitry 已提交
697 698
}

699
static int l2tp_recv_StopCCN(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
K
Kozlov Dmitry 已提交
700
{
701 702
	l2tp_send_ZLB(conn);
	return -1;
K
Kozlov Dmitry 已提交
703 704
}

705
static int l2tp_recv_HELLO(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
K
Kozlov Dmitry 已提交
706
{
707 708 709 710
	if (l2tp_send_ZLB(conn))
		return -1;
	
	return 0;
K
Kozlov Dmitry 已提交
711 712
}

713
static int l2tp_recv_ICRQ(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
K
Kozlov Dmitry 已提交
714 715 716 717
{
	struct l2tp_attr_t *attr;
	struct l2tp_attr_t *assigned_sid = NULL;

718 719 720
	if (conn->state1 != STATE_WAIT_ICRQ) {
		log_ppp_warn("l2tp: unexpected ICRQ\n");
		return 0;
K
Kozlov Dmitry 已提交
721 722 723 724 725 726 727
	}

	list_for_each_entry(attr, &pack->attrs, entry) {
		switch(attr->attr->id) {
			case Assigned_Session_ID:
				assigned_sid = attr;
				break;
728
			case Message_Type:
K
Kozlov Dmitry 已提交
729 730
			case Call_Serial_Number:
			case Bearer_Type:
731
			case Calling_Number:
K
Kozlov Dmitry 已提交
732 733
			case Called_Number:
			case Sub_Address:
734
			case Physical_Channel_ID:
K
Kozlov Dmitry 已提交
735 736 737 738
				break;
			default:
				if (attr->M) {
					if (conf_verbose) {
739 740 741 742
						log_ppp_warn("l2tp: ICRQ: unknown attribute %i\n", attr->attr->id);
						if (l2tp_terminate(conn, 2, 8))
							return -1;
						return 0;
K
Kozlov Dmitry 已提交
743 744 745 746 747 748 749
					}
				}
		}
	}

	if (!assigned_sid) {
		if (conf_verbose)
750 751 752
			log_ppp_warn("l2tp: ICRQ: no Assigned-Session-ID attribute present in message\n");
		if (l2tp_terminate(conn, 2, 0))
			return -1;
K
Kozlov Dmitry 已提交
753 754 755 756
	}

	conn->peer_sid = assigned_sid->val.uint16;

757 758 759
	if (l2tp_send_ICRP(conn))
		return -1;
		
K
Kozlov Dmitry 已提交
760 761
	/*if (l2tp_send_OCRQ(conn))
		return -1;*/
762 763
	
	return 0;
K
Kozlov Dmitry 已提交
764 765
}

766
static int l2tp_recv_ICCN(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
K
Kozlov Dmitry 已提交
767
{
768 769 770 771 772 773
	if (conn->state1 != STATE_WAIT_ICCN) {
		log_ppp_warn("l2tp: unexpected ICCN\n");
		return 0;
	}

	conn->state1 = STATE_ESTB;
K
Kozlov Dmitry 已提交
774

775 776 777 778 779 780 781 782 783 784 785 786
	if (l2tp_connect(conn)) {
		if (l2tp_terminate(conn, 2, 0))
			return -1;
		return 0;
	}

	if (l2tp_send_ZLB(conn))
		return -1;
	
	triton_timer_del(&conn->timeout_timer);

	return 0;
K
Kozlov Dmitry 已提交
787 788
}

789
static int  l2tp_recv_OCRP(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
K
Kozlov Dmitry 已提交
790
{
791 792 793 794 795 796
	if (conn->state2 != STATE_WAIT_OCRP) {
		log_ppp_warn("l2tp: unexpected OCRP\n");
		return 0;
	}

	conn->state2 = STATE_WAIT_OCCN;
K
Kozlov Dmitry 已提交
797

798
	return 0;
K
Kozlov Dmitry 已提交
799 800
}

801
static int l2tp_recv_OCCN(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
K
Kozlov Dmitry 已提交
802
{
803 804 805 806 807 808
	if (conn->state2 != STATE_WAIT_OCCN) {
		log_ppp_warn("l2tp: unexpected OCCN\n");
		return 0;
	}

	conn->state2 = STATE_ESTB;
K
Kozlov Dmitry 已提交
809

810
	return 0;
K
Kozlov Dmitry 已提交
811 812
}

813
static int l2tp_recv_CDN(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
K
Kozlov Dmitry 已提交
814
{
815 816 817 818
	if (ntohs(pack->hdr.sid) != conn->sid) {
		if (conf_verbose)
			log_warn("l2tp: sid %i is incorrect\n", ntohs(pack->hdr.sid));
		return 0;
K
Kozlov Dmitry 已提交
819 820
	}

821
	if (conn->state == STATE_PPP) {
822
		__sync_sub_and_fetch(&stat_active, 1);
823
		conn->state = STATE_FIN;
824
		ppp_terminate(&conn->ppp, TERM_USER_REQUEST, 1);
K
Kozlov Dmitry 已提交
825
	}
826 827 828 829 830 831
	
	if (l2tp_terminate(conn, 0, 0))
		return -1;
	
	return 0;
}
K
Kozlov Dmitry 已提交
832

833 834 835 836 837 838 839 840 841 842 843 844
static int l2tp_recv_SLI(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
{
	return 0;
}

static int l2tp_conn_read(struct triton_md_handler_t *h)
{
	struct l2tp_conn_t *conn = container_of(h, typeof(*conn), hnd);
	struct l2tp_packet_t *pack, *p;
	struct l2tp_attr_t *msg_type;

	while (1) {
845
		if (l2tp_recv(h->fd, &pack, NULL))
846 847 848 849 850
			return 0;

		if (!pack)
			continue;

K
Kozlov Dmitry 已提交
851
		if (ntohs(pack->hdr.tid) != conn->tid && (pack->hdr.tid || !conf_dir300_quirk)) {
852 853
			if (conf_verbose)
				log_warn("l2tp: incorrect tid %i in tunnel %i\n", ntohs(pack->hdr.tid), conn->tid);
K
Kozlov Dmitry 已提交
854
			l2tp_packet_free(pack);
855
			continue;
K
Kozlov Dmitry 已提交
856 857
		}

858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
		if (ntohs(pack->hdr.Ns) == conn->Nr + 1) {
			if (!list_empty(&pack->attrs))
				conn->Nr++;
			if (!list_empty(&conn->send_queue)) {
				p = list_entry(conn->send_queue.next, typeof(*pack), entry);
				list_del(&p->entry);
				l2tp_packet_free(p);
				conn->retransmit = 0;
			}
			if (!list_empty(&conn->send_queue))
				triton_timer_mod(&conn->rtimeout_timer, 0);
			else {
				if (conn->rtimeout_timer.tpd)
					triton_timer_del(&conn->rtimeout_timer);
				if (conn->state == STATE_FIN)
					goto drop;
			}
		} else {
			if (ntohs(pack->hdr.Ns) < conn->Nr + 1 || (ntohs(pack->hdr.Ns > 32767 && conn->Nr + 1 < 32767))) {
				log_ppp_debug("duplicate packet\n");
				if (l2tp_send_ZLB(conn))
					goto drop;
			} else
				log_ppp_debug("reordered packet\n");
			l2tp_packet_free(pack);
			continue;
		}
K
Kozlov Dmitry 已提交
885

886 887 888 889
		if (list_empty(&pack->attrs)) {
			l2tp_packet_free(pack);
			continue;
		}
K
Kozlov Dmitry 已提交
890

891 892 893
		msg_type = list_entry(pack->attrs.next, typeof(*msg_type), entry);

		if (msg_type->attr->id != Message_Type) {
K
Kozlov Dmitry 已提交
894
			if (conf_verbose)
895 896 897
				log_ppp_error("l2tp: first attribute is not Message-Type, dropping connection...\n");
			goto drop;
		}
K
Kozlov Dmitry 已提交
898

899 900 901 902 903
		if (conf_verbose) {
			if (msg_type->val.uint16 == Message_Type_Hello) {
				log_ppp_debug("recv ");
				l2tp_packet_print(pack, log_ppp_debug);
			} else {
904 905
				log_ppp_info2("recv ");
				l2tp_packet_print(pack, log_ppp_info2);
906 907 908
			}
		}

909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
		switch (msg_type->val.uint16) {
			case Message_Type_Start_Ctrl_Conn_Connected:
				if (l2tp_recv_SCCCN(conn, pack))
					goto drop;
				break;
			case Message_Type_Stop_Ctrl_Conn_Notify:
				if (l2tp_recv_StopCCN(conn, pack))
					goto drop;
				break;
			case Message_Type_Hello:
				if (l2tp_recv_HELLO(conn, pack))
					goto drop;
				break;
			case Message_Type_Incoming_Call_Request:
				if (l2tp_recv_ICRQ(conn, pack))
					goto drop;
				break;
			case Message_Type_Incoming_Call_Connected:
				if (l2tp_recv_ICCN(conn, pack))
					goto drop;
				break;
			case Message_Type_Outgoing_Call_Reply:
				if (l2tp_recv_OCRP(conn, pack))
					goto drop;
				break;
			case Message_Type_Outgoing_Call_Connected:
				if (l2tp_recv_OCCN(conn, pack))
					goto drop;
				break;
			case Message_Type_Call_Disconnect_Notify:
				if (l2tp_recv_CDN(conn, pack))
					goto drop;
				break;
			case Message_Type_Set_Link_Info:
				if (l2tp_recv_SLI(conn, pack))
					goto drop;
				break;
			case Message_Type_Start_Ctrl_Conn_Request:
			case Message_Type_Start_Ctrl_Conn_Reply:
			case Message_Type_Outgoing_Call_Request:
			case Message_Type_Incoming_Call_Reply:
			case Message_Type_WAN_Error_Notify:
				if (conf_verbose)
					log_warn("l2tp: unexpected Message-Type %i\n", msg_type->val.uint16);
				break;
			default:
				if (conf_verbose)
					log_warn("l2tp: unknown Message-Type %i\n", msg_type->val.uint16);
				if (msg_type->M) {
					if (l2tp_terminate(conn, 2, 8))
						goto drop;
				}
		}
K
Kozlov Dmitry 已提交
962

963 964
		l2tp_packet_free(pack);
	}
K
Kozlov Dmitry 已提交
965 966 967 968

drop:
	l2tp_packet_free(pack);
	l2tp_disconnect(conn);
969
	return -1;
K
Kozlov Dmitry 已提交
970 971 972 973 974 975 976
}

static int l2tp_udp_read(struct triton_md_handler_t *h)
{
	struct l2tp_serv_t *serv = container_of(h, typeof(*serv), hnd);
	struct l2tp_packet_t *pack;
	struct l2tp_attr_t *msg_type;
977
	struct in_pktinfo pkt_info;
K
Kozlov Dmitry 已提交
978 979

	while (1) {
980
		if (l2tp_recv(h->fd, &pack, &pkt_info))
K
Kozlov Dmitry 已提交
981 982 983 984 985
			break;

		if (!pack)
			continue;

986 987 988
		if (iprange_client_check(pack->addr.sin_addr.s_addr)) {
			log_warn("l2tp: IP is out of client-ip-range, droping connection...\n");
			goto skip;
K
Kozlov Dmitry 已提交
989 990
		}

991 992 993
		if (pack->hdr.tid)
			goto skip;

K
Kozlov Dmitry 已提交
994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
		if (list_empty(&pack->attrs)) {
			if (conf_verbose)
				log_warn("l2tp: to Message-Type attribute present\n");
			goto skip;
		}

		msg_type = list_entry(pack->attrs.next, typeof(*msg_type), entry);
		if (msg_type->attr->id != Message_Type) {
			if (conf_verbose)
				log_warn("l2tp: first attribute is not Message-Type\n");
			goto skip;
		}

		if (msg_type->val.uint16 == Message_Type_Start_Ctrl_Conn_Request)
1008
			l2tp_recv_SCCRQ(serv, pack, &pkt_info);
K
Kozlov Dmitry 已提交
1009 1010 1011
		else {
			if (conf_verbose) {
				log_warn("recv (unexpected) ");
1012
				l2tp_packet_print(pack, log_ppp_warn);
K
Kozlov Dmitry 已提交
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
			}
		}
skip:
		l2tp_packet_free(pack);
	}

	return 0;
}

static void l2tp_udp_close(struct triton_context_t *ctx)
{
	struct l2tp_serv_t *serv = container_of(ctx, typeof(*serv), ctx);
1025 1026 1027
	triton_md_unregister_handler(&serv->hnd);
	close(serv->hnd.fd);
	triton_context_unregister(&serv->ctx);
K
Kozlov Dmitry 已提交
1028 1029 1030 1031
}

static struct l2tp_serv_t udp_serv =
{
1032 1033 1034
	.hnd.read = l2tp_udp_read,
	.ctx.close = l2tp_udp_close,
	.ctx.before_switch = log_switch,
K
Kozlov Dmitry 已提交
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
};

/*static struct l2tp_serv_t ip_serv =
{
	.hnd.read=l2t_ip_read,
	.ctx.close=l2tp_ip_close,
};*/

static void start_udp_server(void)
{
D
Dmitry Kozlov 已提交
1045
	struct sockaddr_in addr;
K
Kozlov Dmitry 已提交
1046
	char *opt;
1047
	int flag = 1;
K
Kozlov Dmitry 已提交
1048 1049

	udp_serv.hnd.fd = socket(PF_INET, SOCK_DGRAM, 0);
D
Dmitry Kozlov 已提交
1050 1051 1052 1053
	if (udp_serv.hnd.fd < 0) {
		log_emerg("l2tp: socket: %s\n", strerror(errno));
		return;
	}
1054 1055
	
	fcntl(udp_serv.hnd.fd, F_SETFD, fcntl(udp_serv.hnd.fd, F_GETFD) | FD_CLOEXEC);
K
Kozlov Dmitry 已提交
1056 1057

	memset(&addr, 0, sizeof(addr));
D
Dmitry Kozlov 已提交
1058 1059
	addr.sin_family = AF_INET;
	addr.sin_port = htons(L2TP_PORT);
K
Kozlov Dmitry 已提交
1060 1061 1062 1063 1064 1065

	opt = conf_get_opt("l2tp", "bind");
	if (opt)
		addr.sin_addr.s_addr = inet_addr(opt);
	else
		addr.sin_addr.s_addr = htonl(INADDR_ANY);
1066

D
Dmitry Kozlov 已提交
1067 1068 1069 1070
	setsockopt(udp_serv.hnd.fd, SOL_SOCKET, SO_REUSEADDR, &udp_serv.hnd.fd, sizeof(udp_serv.hnd.fd));
	setsockopt(udp_serv.hnd.fd, SOL_SOCKET, SO_NO_CHECK, &udp_serv.hnd.fd, sizeof(udp_serv.hnd.fd));

	if (bind (udp_serv.hnd.fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
1071
		log_emerg("l2tp: bind: %s\n", strerror(errno));
K
Kozlov Dmitry 已提交
1072
		close(udp_serv.hnd.fd);
D
Dmitry Kozlov 已提交
1073 1074
		return;
	}
K
Kozlov Dmitry 已提交
1075 1076

	if (fcntl(udp_serv.hnd.fd, F_SETFL, O_NONBLOCK)) {
1077 1078 1079 1080 1081 1082 1083
		log_emerg("l2tp: failed to set nonblocking mode: %s\n", strerror(errno));
		close(udp_serv.hnd.fd);
		return;
	}

	if (setsockopt(udp_serv.hnd.fd, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag))) {
		log_emerg("l2tp: setsockopt(IP_PKTINFO): %s\n", strerror(errno));
K
Kozlov Dmitry 已提交
1084
		close(udp_serv.hnd.fd);
D
Dmitry Kozlov 已提交
1085
		return;
K
Kozlov Dmitry 已提交
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
	}

	memcpy(&udp_serv.addr, &addr, sizeof(addr));

	triton_context_register(&udp_serv.ctx, NULL);
	triton_md_register_handler(&udp_serv.ctx, &udp_serv.hnd);
	triton_md_enable_handler(&udp_serv.hnd, MD_MODE_READ);
	triton_context_wakeup(&udp_serv.ctx);
}

1096 1097
static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client)
{
K
Kozlov Dmitry 已提交
1098 1099 1100
	cli_send(client, "l2tp:\r\n");
	cli_sendv(client, "  starting: %u\r\n", stat_starting);
	cli_sendv(client, "  active: %u\r\n", stat_active);
1101 1102 1103 1104

	return CLI_CMD_OK;
}

K
Kozlov Dmitry 已提交
1105 1106 1107 1108 1109 1110
void __export l2tp_get_stat(unsigned int **starting, unsigned int **active)
{
	*starting = &stat_starting;
	*active = &stat_active;
}

1111
static void load_config(void)
K
Kozlov Dmitry 已提交
1112
{
1113
	const char *opt;
K
Kozlov Dmitry 已提交
1114 1115 1116 1117 1118

	opt = conf_get_opt("l2tp", "verbose");
	if (opt && atoi(opt) > 0)
		conf_verbose = 1;

K
Kozlov Dmitry 已提交
1119
	opt = conf_get_opt("l2tp", "hello-interval");
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
	if (opt && atoi(opt) > 0)
		conf_hello_interval = atoi(opt);

	opt = conf_get_opt("l2tp", "timeout");
	if (opt && atoi(opt) > 0)
		conf_timeout = atoi(opt);

	opt = conf_get_opt("l2tp", "rtimeout");
	if (opt && atoi(opt) > 0)
		conf_rtimeout = atoi(opt);

	opt = conf_get_opt("l2tp", "retransmit");
	if (opt && atoi(opt) > 0)
		conf_retransmit = atoi(opt);

	opt = conf_get_opt("l2tp", "host-name");
1136
	if (opt)
1137
		conf_host_name = opt;
1138
	else
1139
		conf_host_name = "accel-ppp";
K
Kozlov Dmitry 已提交
1140 1141 1142 1143
	
	opt = conf_get_opt("l2tp", "dir300_quirk");
	if (opt)
		conf_dir300_quirk = atoi(opt);
1144 1145
}

1146
static void l2tp_init(void)
1147 1148 1149 1150 1151 1152 1153
{
	l2tp_conn = malloc(L2TP_MAX_TID * sizeof(void *));
	memset(l2tp_conn, 0, L2TP_MAX_TID * sizeof(void *));

	l2tp_conn_pool = mempool_create(sizeof(struct l2tp_conn_t));

	load_config();
1154

K
Kozlov Dmitry 已提交
1155
	start_udp_server();
1156

K
Kozlov Dmitry 已提交
1157
	cli_register_simple_cmd2(&show_stat_exec, NULL, 2, "show", "stat");
1158 1159
	
	triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
K
Kozlov Dmitry 已提交
1160 1161
}

1162
DEFINE_INIT(22, l2tp_init);