From b96fbc3f966b012720d2b74b1dfd2a0ab95086cf Mon Sep 17 00:00:00 2001
From: Dmitry Kozlov <xeb@mail.ru>
Date: Mon, 20 Sep 2010 01:09:07 +0400
Subject: fixed many bugs and memory leaks

---
 accel-pptpd/CMakeLists.txt        |   3 +-
 accel-pptpd/accel-pptpd.conf      |  29 +++++---
 accel-pptpd/auth/auth_chap_md5.c  |  14 ++--
 accel-pptpd/auth/auth_mschap_v1.c |  16 ++--
 accel-pptpd/auth/auth_mschap_v2.c |  22 +++---
 accel-pptpd/auth/auth_pap.c       |  14 ++--
 accel-pptpd/ctrl/pptp.c           |  19 +++--
 accel-pptpd/extra/pppd_compat.c   |  54 +++++++-------
 accel-pptpd/include/memdebug.h    |   1 +
 accel-pptpd/ipdb.c                |   2 +
 accel-pptpd/ippool.c              |   5 +-
 accel-pptpd/iprange.c             |   6 +-
 accel-pptpd/log.c                 |  42 ++++++++++-
 accel-pptpd/logs/log_file.c       |  28 +++----
 accel-pptpd/logs/log_pgsql.c      |  46 +++++++-----
 accel-pptpd/main.c                |  10 ++-
 accel-pptpd/memdebug.c            | 153 ++++++++++++++++++++++++++++++++++++++
 accel-pptpd/memdebug.h            |  27 +++++++
 accel-pptpd/ppp/ipcp_opt_dns.c    |   8 +-
 accel-pptpd/ppp/ipcp_opt_ipaddr.c |   8 +-
 accel-pptpd/ppp/lcp_opt_accomp.c  |   6 +-
 accel-pptpd/ppp/lcp_opt_magic.c   |   6 +-
 accel-pptpd/ppp/lcp_opt_mru.c     |   6 +-
 accel-pptpd/ppp/lcp_opt_pcomp.c   |   6 +-
 accel-pptpd/ppp/ppp.c             |  42 ++++++-----
 accel-pptpd/ppp/ppp_auth.c        |   5 +-
 accel-pptpd/ppp/ppp_ccp.c         |  32 +++++---
 accel-pptpd/ppp/ppp_fsm.c         |   6 +-
 accel-pptpd/ppp/ppp_ipcp.c        |  32 +++++---
 accel-pptpd/ppp/ppp_lcp.c         |  37 ++++++---
 accel-pptpd/ppp/ppp_pd.c          |   2 +
 accel-pptpd/pwdb.c                |   2 +
 accel-pptpd/radius/acct.c         |  14 +++-
 accel-pptpd/radius/auth.c         |   7 +-
 accel-pptpd/radius/dict.c         |  24 +++---
 accel-pptpd/radius/dm_coa.c       |   2 +
 accel-pptpd/radius/packet.c       |  55 +++++++-------
 accel-pptpd/radius/radius.c       |  11 ++-
 accel-pptpd/radius/req.c          |   6 +-
 accel-pptpd/sigchld.c             | 109 +++++++++++++--------------
 accel-pptpd/triton/conf_file.c    |  27 +++----
 accel-pptpd/triton/event.c        |   4 +-
 accel-pptpd/triton/loader.c       |   4 +-
 accel-pptpd/triton/log.c          |   2 +
 accel-pptpd/triton/md.c           |  22 +++++-
 accel-pptpd/triton/mempool.c      |  89 +++++++++++++++++++++-
 accel-pptpd/triton/mempool.h      |  17 ++++-
 accel-pptpd/triton/options.c      |   2 +
 accel-pptpd/triton/timer.c        |  22 +++++-
 accel-pptpd/triton/triton.c       |  60 ++++++++++-----
 accel-pptpd/triton/triton.h       |  20 ++++-
 accel-pptpd/utils.c               |   1 +
 52 files changed, 856 insertions(+), 331 deletions(-)
 create mode 120000 accel-pptpd/include/memdebug.h
 create mode 100644 accel-pptpd/memdebug.c
 create mode 100644 accel-pptpd/memdebug.h

diff --git a/accel-pptpd/CMakeLists.txt b/accel-pptpd/CMakeLists.txt
index b27302ca..ee00a283 100644
--- a/accel-pptpd/CMakeLists.txt
+++ b/accel-pptpd/CMakeLists.txt
@@ -1,7 +1,7 @@
 PROJECT (pptpd)
 cmake_minimum_required(VERSION 2.6)
 
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fvisibility=hidden -D_GNU_SOURCE -DSPINLOCK_GCC")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fvisibility=hidden -D_GNU_SOURCE -DSPINLOCK_GCC -DMEMDEBUG")
 
 INCLUDE_DIRECTORIES(include)
 
@@ -37,6 +37,7 @@ ADD_EXECUTABLE(pptpd
 
 	log.c
 	main.c
+	memdebug.c
 )
 TARGET_LINK_LIBRARIES(pptpd triton rt pthread ssl)
 
diff --git a/accel-pptpd/accel-pptpd.conf b/accel-pptpd/accel-pptpd.conf
index 5ebff71c..230ddba6 100644
--- a/accel-pptpd/accel-pptpd.conf
+++ b/accel-pptpd/accel-pptpd.conf
@@ -33,22 +33,27 @@ dm_coa_secret=testing123
 verbose=1
 
 [client-ip-range]
-192.168.10.20-20
-192.168.10.1/32
+192.168.11.20-20
+192.168.11.6/32
 
 [ip-pool]
-#gw-ip-address=192.168.100.10
-gw=192.168.100.210-211
-tunnel=192.168.100.200-201
+gw-ip-address=192.168.100.1
+#gw=192.168.100.210-211
+#tunnel=192.168.100.200-201
+192.168.100.2-255
+192.168.101.1-255
+192.168.102.1-255
+192.168.103.1-255
 
 [log]
-log-file=/dev/stdout
-log-emerg=/dev/stderr
-#copy=1
-#color=1
-#per-user-dir=per_user
-#per-session-dir=per_session
-#per-session=1
+log-file=general.log
+log-emerg=emerg.log
+log-debug=debug.log
+copy=1
+color=1
+per-user-dir=per_user
+per-session-dir=per_session
+per-session=1
 
 [log-pgsql]
 conninfo=user=log
diff --git a/accel-pptpd/auth/auth_chap_md5.c b/accel-pptpd/auth/auth_chap_md5.c
index 058dc677..7681fb5c 100644
--- a/accel-pptpd/auth/auth_chap_md5.c
+++ b/accel-pptpd/auth/auth_chap_md5.c
@@ -15,6 +15,8 @@
 #include "ppp_lcp.h"
 #include "pwdb.h"
 
+#include "memdebug.h"
+
 #define CHAP_CHALLENGE 1
 #define CHAP_RESPONSE  2
 #define CHAP_SUCCESS   3
@@ -89,7 +91,7 @@ static void print_str(const char *buf,int size)
 
 static struct auth_data_t* auth_data_init(struct ppp_t *ppp)
 {
-	struct chap_auth_data_t *d=malloc(sizeof(*d));
+	struct chap_auth_data_t *d=_malloc(sizeof(*d));
 
 	memset(d,0,sizeof(*d));
 	d->auth.proto=PPP_CHAP;
@@ -102,7 +104,7 @@ static void auth_data_free(struct ppp_t *ppp,struct auth_data_t *auth)
 {
 	struct chap_auth_data_t *d=container_of(auth,typeof(*d),auth);
 
-	free(d);
+	_free(d);
 }
 
 static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth)
@@ -223,7 +225,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
 		ppp_terminate(ad->ppp, 0);
 	}
 
-	name = strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
+	name = _strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
 
 	r = pwdb_check(ad->ppp, name, PPP_CHAP, CHAP_MD5, ad->id, ad->val, VALUE_SIZE, msg->val);
 
@@ -231,7 +233,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
 		passwd = pwdb_get_passwd(ad->ppp,name);
 		if (!passwd)
 		{
-			free(name);
+			_free(name);
 			log_ppp_debug("chap-md5: user not found\n");
 			chap_send_failure(ad);
 			return;
@@ -253,11 +255,11 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
 			chap_send_success(ad);
 			auth_successed(ad->ppp, name);
 		}
-		free(passwd);
+		_free(passwd);
 	} else if (r == PWDB_DENIED) {
 		chap_send_failure(ad);
 		auth_failed(ad->ppp);
-		free(name);
+		_free(name);
 	} else {
 		chap_send_success(ad);
 		auth_successed(ad->ppp, name);
diff --git a/accel-pptpd/auth/auth_mschap_v1.c b/accel-pptpd/auth/auth_mschap_v1.c
index bc54ed46..818d60db 100644
--- a/accel-pptpd/auth/auth_mschap_v1.c
+++ b/accel-pptpd/auth/auth_mschap_v1.c
@@ -17,6 +17,8 @@
 #include "ppp_lcp.h"
 #include "pwdb.h"
 
+#include "memdebug.h"
+
 #define MSCHAP_V1 0x80
 
 #define CHAP_CHALLENGE 1
@@ -101,7 +103,7 @@ static void print_str(const char *buf,int size)
 
 static struct auth_data_t* auth_data_init(struct ppp_t *ppp)
 {
-	struct chap_auth_data_t *d=malloc(sizeof(*d));
+	struct chap_auth_data_t *d=_malloc(sizeof(*d));
 
 	memset(d,0,sizeof(*d));
 	d->auth.proto=PPP_CHAP;
@@ -114,7 +116,7 @@ static void auth_data_free(struct ppp_t *ppp,struct auth_data_t *auth)
 {
 	struct chap_auth_data_t *d=container_of(auth,typeof(*d),auth);
 
-	free(d);
+	_free(d);
 }
 
 static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth)
@@ -234,7 +236,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
 		auth_failed(ad->ppp);
 	}
 
-	name = strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
+	name = _strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
 	if (!name) {
 		log_emerg("mschap-v2: out of memory\n");
 		auth_failed(ad->ppp);
@@ -248,7 +250,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
 	if (r == PWDB_DENIED) {
 		chap_send_failure(ad);
 		auth_failed(ad->ppp);
-		free(name);
+		_free(name);
 	} else {
 		chap_send_success(ad);
 		auth_successed(ad->ppp, name);
@@ -301,7 +303,7 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response
 		return PWDB_DENIED;
 	}
 
-	u_passwd=malloc(strlen(passwd)*2);
+	u_passwd=_malloc(strlen(passwd)*2);
 	for(i=0; i<strlen(passwd); i++)
 	{
 		u_passwd[i*2]=passwd[i];
@@ -317,8 +319,8 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response
 	des_encrypt(ad->val,z_hash+7,nt_hash+8);
 	des_encrypt(ad->val,z_hash+14,nt_hash+16);
 
-	free(passwd);
-	free(u_passwd);
+	_free(passwd);
+	_free(u_passwd);
 
 	return memcmp(nt_hash,msg->nt_hash,24) ? PWDB_DENIED : PWDB_SUCCESS;
 }
diff --git a/accel-pptpd/auth/auth_mschap_v2.c b/accel-pptpd/auth/auth_mschap_v2.c
index 798f6eed..8e507759 100644
--- a/accel-pptpd/auth/auth_mschap_v2.c
+++ b/accel-pptpd/auth/auth_mschap_v2.c
@@ -18,6 +18,8 @@
 #include "ppp_lcp.h"
 #include "pwdb.h"
 
+#include "memdebug.h"
+
 #define MSCHAP_V2 0x81 
 
 #define CHAP_CHALLENGE 1
@@ -116,7 +118,7 @@ static void print_str(const char *buf,int size)
 
 static struct auth_data_t* auth_data_init(struct ppp_t *ppp)
 {
-	struct chap_auth_data_t *d=malloc(sizeof(*d));
+	struct chap_auth_data_t *d=_malloc(sizeof(*d));
 
 	memset(d,0,sizeof(*d));
 	d->auth.proto=PPP_CHAP;
@@ -129,7 +131,7 @@ static void auth_data_free(struct ppp_t *ppp,struct auth_data_t *auth)
 {
 	struct chap_auth_data_t *d=container_of(auth,typeof(*d),auth);
 
-	free(d);
+	_free(d);
 }
 
 static int chap_start(struct ppp_t *ppp, struct auth_data_t *auth)
@@ -199,7 +201,7 @@ static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t
 	if (!passwd)
 		return -1;
 
-	u_passwd=malloc(strlen(passwd)*2);
+	u_passwd=_malloc(strlen(passwd)*2);
 	for(i=0; i<strlen(passwd); i++)
 	{
 		u_passwd[i*2]=passwd[i];
@@ -235,8 +237,8 @@ static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t
 	for(i=0; i<20; i++)
 		sprintf(authenticator+i*2,"%02X",response[i]);
 	
-	free(passwd);
-	free(u_passwd);
+	_free(passwd);
+	_free(u_passwd);
 
 	return 0;
 }
@@ -309,7 +311,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
 		ppp_terminate(ad->ppp, 0);
 	}
 
-	name=strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
+	name=_strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
 	if (!name) {
 		log_emerg("mschap-v2: out of memory\n");
 		auth_failed(ad->ppp);
@@ -327,7 +329,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
 	if (r == PWDB_DENIED) {
 		chap_send_failure(ad);
 		auth_failed(ad->ppp);
-		free(name);
+		_free(name);
 	} else {
 		chap_send_success(ad, msg, authenticator);
 		auth_successed(ad->ppp, name);
@@ -382,7 +384,7 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response
 		return -1;
 	}
 
-	u_passwd=malloc(strlen(passwd)*2);
+	u_passwd=_malloc(strlen(passwd)*2);
 	for(i=0; i<strlen(passwd); i++)
 	{
 		u_passwd[i*2]=passwd[i];
@@ -404,8 +406,8 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response
 	des_encrypt(c_hash,z_hash+7,nt_hash+8);
 	des_encrypt(c_hash,z_hash+14,nt_hash+16);
 
-	free(passwd);
-	free(u_passwd);
+	_free(passwd);
+	_free(u_passwd);
 
 	return memcmp(nt_hash,msg->nt_hash,24);
 }
diff --git a/accel-pptpd/auth/auth_pap.c b/accel-pptpd/auth/auth_pap.c
index 81098ce9..2abf5720 100644
--- a/accel-pptpd/auth/auth_pap.c
+++ b/accel-pptpd/auth/auth_pap.c
@@ -9,6 +9,8 @@
 #include "ppp_lcp.h"
 #include "pwdb.h"
 
+#include "memdebug.h"
+
 #define MSG_FAILED "Authentication failed"
 #define MSG_SUCCESSED "Authentication successed"
 
@@ -63,7 +65,7 @@ static struct ppp_auth_handler_t pap=
 
 static struct auth_data_t* auth_data_init(struct ppp_t *ppp)
 {
-	struct pap_auth_data_t *d=malloc(sizeof(*d));
+	struct pap_auth_data_t *d=_malloc(sizeof(*d));
 
 	memset(d,0,sizeof(*d));
 	d->auth.proto=PPP_PAP;
@@ -76,7 +78,7 @@ static void auth_data_free(struct ppp_t *ppp,struct auth_data_t *auth)
 {
 	struct pap_auth_data_t *d=container_of(auth,typeof(*d),auth);
 
-	free(d);
+	_free(d);
 }
 
 static int pap_start(struct ppp_t *ppp, struct auth_data_t *auth)
@@ -168,8 +170,8 @@ static int pap_recv_req(struct pap_auth_data_t *p,struct pap_hdr_t *hdr)
 		return -1;
 	}
 
-	peer_id=strndup((const char*)peer_id,peer_id_len);
-	passwd=strndup((const char*)ptr,passwd_len);
+	peer_id=_strndup((const char*)peer_id,peer_id_len);
+	passwd=_strndup((const char*)ptr,passwd_len);
 
 	r = pwdb_check(p->ppp, peer_id, PPP_PAP, passwd);
 	if (r == PWDB_NO_IMPL) {
@@ -184,14 +186,14 @@ static int pap_recv_req(struct pap_auth_data_t *p,struct pap_hdr_t *hdr)
 		pap_send_nak(p, hdr->id);
 		auth_failed(p->ppp);
 		ret=-1;
-		free(peer_id);
+		_free(peer_id);
 	} else {
 		pap_send_ack(p, hdr->id);
 		auth_successed(p->ppp, peer_id);
 		ret = 0;
 	}
 
-	free(passwd);
+	_free(passwd);
 
 	return ret;
 }
diff --git a/accel-pptpd/ctrl/pptp.c b/accel-pptpd/ctrl/pptp.c
index dab807c8..b8bb3663 100644
--- a/accel-pptpd/ctrl/pptp.c
+++ b/accel-pptpd/ctrl/pptp.c
@@ -20,6 +20,8 @@
 #include "ppp.h"
 #include "iprange.h"
 
+#include "memdebug.h"
+
 #define STATE_IDLE 0
 #define STATE_ESTB 1
 #define STATE_PPP  2
@@ -73,10 +75,13 @@ static void disconnect(struct pptp_conn_t *conn)
 	triton_event_fire(EV_CTRL_FINISHED, &conn->ppp);
 	
 	triton_context_unregister(&conn->ctx);
+
+	if (conn->ppp.chan_name)
+		_free(conn->ppp.chan_name);
 	
-	free(conn->in_buf);
-	free(conn->out_buf);
-	free(conn);
+	_free(conn->in_buf);
+	_free(conn->out_buf);
+	_free(conn);
 }
 
 static int post_msg(struct pptp_conn_t *conn, void *buf, int size)
@@ -265,7 +270,7 @@ static int pptp_out_call_rqst(struct pptp_conn_t *conn)
 		return -1;
 
 	conn->ppp.fd = pptp_sock;
-	conn->ppp.chan_name = strdup(inet_ntoa(dst_addr.sa_addr.pptp.sin_addr));
+	conn->ppp.chan_name = _strdup(inet_ntoa(dst_addr.sa_addr.pptp.sin_addr));
 
 	triton_event_fire(EV_CTRL_STARTED, &conn->ppp);
 
@@ -486,15 +491,15 @@ static int pptp_connect(struct triton_md_handler_t *h)
 			continue;
 		}
 
-		conn = malloc(sizeof(*conn));
+		conn = _malloc(sizeof(*conn));
 		memset(conn, 0, sizeof(*conn));
 		conn->hnd.fd = sock;
 		conn->hnd.read = pptp_read;
 		conn->hnd.write = pptp_write;
 		conn->ctx.close = pptp_close;
 		conn->ctx.before_switch = log_switch;
-		conn->in_buf = malloc(PPTP_CTRL_SIZE_MAX);
-		conn->out_buf = malloc(PPTP_CTRL_SIZE_MAX);
+		conn->in_buf = _malloc(PPTP_CTRL_SIZE_MAX);
+		conn->out_buf = _malloc(PPTP_CTRL_SIZE_MAX);
 		conn->timeout_timer.expire = pptp_timeout;
 		conn->timeout_timer.period = conf_timeout * 1000;
 		conn->echo_timer.expire = pptp_send_echo;
diff --git a/accel-pptpd/extra/pppd_compat.c b/accel-pptpd/extra/pppd_compat.c
index 1cf67413..dbba96d7 100644
--- a/accel-pptpd/extra/pppd_compat.c
+++ b/accel-pptpd/extra/pppd_compat.c
@@ -16,6 +16,8 @@
 #include "utils.h"
 #include "sigchld.h"
 
+#include "memdebug.h"
+
 static char *conf_ip_up = "/etc/ppp/ip-up";
 static char *conf_ip_down = "/etc/ppp/ip-down";
 static char *conf_ip_change = "/etc/ppp/ip-change";
@@ -75,7 +77,7 @@ static void ip_change_handler(struct sigchld_handler_t *h, int status)
 
 static void ev_ppp_starting(struct ppp_t *ppp)
 {
-	struct pppd_compat_pd_t *pd = malloc(sizeof(*pd));
+	struct pppd_compat_pd_t *pd = _malloc(sizeof(*pd));
 
 	if (!pd) {
 		log_emerg("pppd_compat: out of memory\n");
@@ -134,14 +136,15 @@ static void ev_ppp_finished(struct ppp_t *ppp)
 	if (!pd)
 		return;
 	
-	if (pd->started) {
-		pthread_mutex_lock(&pd->ip_up_hnd.lock);
-		if (pd->ip_up_hnd.pid) {
-			log_ppp_warn("pppd_compat: ip-up is not yet finished, terminating it ...\n");
-			kill(pd->ip_up_hnd.pid, SIGTERM);
-			pthread_mutex_unlock(&pd->ip_up_hnd.lock);
-		}
+	if (!pd->started)
+		goto skip;
+
+	pthread_mutex_lock(&pd->ip_up_hnd.lock);
+	if (pd->ip_up_hnd.pid) {
+		log_ppp_warn("pppd_compat: ip-up is not yet finished, terminating it ...\n");
+		kill(pd->ip_up_hnd.pid, SIGTERM);
 	}
+	pthread_mutex_unlock(&pd->ip_up_hnd.lock);
 
 	argv[4] = ipaddr;
 	argv[5] = peer_ipaddr;
@@ -163,22 +166,21 @@ static void ev_ppp_finished(struct ppp_t *ppp)
 	} else
 		log_error("pppd_compat: fork: %s\n", strerror(errno));
 
-	if (pd->started) {
-		pthread_mutex_lock(&pd->ip_up_hnd.lock);
-		if (pd->ip_up_hnd.pid) {
-			log_ppp_warn("pppd_compat: ip-up is not yet finished, killing it ...\n");
-			kill(pd->ip_up_hnd.pid, SIGKILL);
-			pthread_mutex_unlock(&pd->ip_up_hnd.lock);
-			sigchld_unregister_handler(&pd->ip_up_hnd);
-		} else
-			pthread_mutex_unlock(&pd->ip_up_hnd.lock);
-	}
+	pthread_mutex_lock(&pd->ip_up_hnd.lock);
+	if (pd->ip_up_hnd.pid) {
+		log_ppp_warn("pppd_compat: ip-up is not yet finished, killing it ...\n");
+		kill(pd->ip_up_hnd.pid, SIGKILL);
+		pthread_mutex_unlock(&pd->ip_up_hnd.lock);
+		sigchld_unregister_handler(&pd->ip_up_hnd);
+	} else
+		pthread_mutex_unlock(&pd->ip_up_hnd.lock);
 
+skip:
 	if (pd->radattr_saved)
 		remove_radattr(ppp);
 	
 	list_del(&pd->pd.entry);
-	free(pd);
+	_free(pd);
 }
 
 static void ev_radius_access_accept(struct ev_radius_t *ev)
@@ -230,7 +232,7 @@ static void remove_radattr(struct ppp_t *ppp)
 {
 	char *fname;
 
-	fname = malloc(PATH_MAX);
+	fname = _malloc(PATH_MAX);
 	if (!fname) {
 		log_emerg("pppd_compat: out of memory\n");
 		return;
@@ -243,7 +245,7 @@ static void remove_radattr(struct ppp_t *ppp)
 	sprintf(fname, "%s_old.%s", conf_radattr_prefix, ppp->ifname);
 	unlink(fname);
 
-	free(fname);
+	_free(fname);
 }
 
 static void write_radattr(struct ppp_t *ppp, struct rad_packet_t *pack, int save_old)
@@ -254,17 +256,17 @@ static void write_radattr(struct ppp_t *ppp, struct rad_packet_t *pack, int save
 	char *fname1, *fname2;
 	int i;
 
-	fname1 = malloc(PATH_MAX);
+	fname1 = _malloc(PATH_MAX);
 	if (!fname1) {
 		log_emerg("pppd_compat: out of memory\n");
 		return;
 	}
 
 	if (save_old) {
-		fname2 = malloc(PATH_MAX);
+		fname2 = _malloc(PATH_MAX);
 		if (!fname2) {
 			log_emerg("pppd_compat: out of memory\n");
-			free(fname1);
+			_free(fname1);
 			return;
 		}
 	}
@@ -309,9 +311,9 @@ static void write_radattr(struct ppp_t *ppp, struct rad_packet_t *pack, int save
 	} else
 		log_ppp_warn("pppd_compat: failed to create '%s': %s\n", fname1, strerror(errno));
 	
-	free(fname1);
+	_free(fname1);
 	if (save_old)
-		free(fname2);
+		_free(fname2);
 }
 
 static struct pppd_compat_pd_t *find_pd(struct ppp_t *ppp)
diff --git a/accel-pptpd/include/memdebug.h b/accel-pptpd/include/memdebug.h
new file mode 120000
index 00000000..3ee61bc2
--- /dev/null
+++ b/accel-pptpd/include/memdebug.h
@@ -0,0 +1 @@
+../memdebug.h
\ No newline at end of file
diff --git a/accel-pptpd/ipdb.c b/accel-pptpd/ipdb.c
index 62a99e9f..a08d3be2 100644
--- a/accel-pptpd/ipdb.c
+++ b/accel-pptpd/ipdb.c
@@ -1,6 +1,8 @@
 #include "triton.h"
 #include "ipdb.h"
 
+#include "memdebug.h"
+
 static LIST_HEAD(ipdb_handlers);
 
 __export struct ipdb_item_t *ipdb_get(struct ppp_t *ppp)
diff --git a/accel-pptpd/ippool.c b/accel-pptpd/ippool.c
index eb79b02a..ec50a9bf 100644
--- a/accel-pptpd/ippool.c
+++ b/accel-pptpd/ippool.c
@@ -9,6 +9,8 @@
 #include "list.h"
 #include "triton/spinlock.h"
 
+#include "memdebug.h"
+
 struct ippool_item_t
 {
 	struct list_head entry;
@@ -148,9 +150,6 @@ static void generate_pool(void)
 		it->it.peer_addr = peer_addr->addr;
 
 		list_add_tail(&it->entry, &ippool);
-		
-		free(addr);
-		free(peer_addr);
 	}
 }
 
diff --git a/accel-pptpd/iprange.c b/accel-pptpd/iprange.c
index 317b66dc..0b1997e9 100644
--- a/accel-pptpd/iprange.c
+++ b/accel-pptpd/iprange.c
@@ -8,6 +8,8 @@
 
 #include "iprange.h"
 
+#include "memdebug.h"
+
 struct iprange_t
 {
 	struct list_head entry;
@@ -39,7 +41,7 @@ static struct iprange_t *parse1(const char *str)
 	if (m == 0 || m > 32)
 		return NULL;
 	
-	r = malloc(sizeof(*r));
+	r = _malloc(sizeof(*r));
 	r->prefix = (f4 << 24) | (f3 << 16) | (f2 << 8) | f1;
 	r->mask = 0;
 
@@ -69,7 +71,7 @@ static struct iprange_t *parse2(const char *str)
 	if (m < f4 || m > 255)
 		return NULL;
 	
-	r = malloc(sizeof(*r));
+	r = _malloc(sizeof(*r));
 	r->prefix = (f4 << 24) | (f3 << 16) | (f2 << 8) | f1;
 	r->end = (m << 24) | (f3 << 16) | (f2 << 8) | f1;
 	r->mask = 0;
diff --git a/accel-pptpd/log.c b/accel-pptpd/log.c
index fbd50674..b0f6d520 100644
--- a/accel-pptpd/log.c
+++ b/accel-pptpd/log.c
@@ -13,12 +13,15 @@
 
 #include "log.h"
 
+#include "memdebug.h"
+
 struct log_pd_t
 {
 	struct ppp_pd_t pd;
 	struct ppp_t *ppp;
 	struct list_head msgs;
 	struct log_msg_t *msg;
+	int authorized:1;
 };
 
 struct _log_msg_t
@@ -43,6 +46,7 @@ static __thread struct _log_msg_t *cur_msg;
 static __thread char stat_buf[LOG_MAX_SIZE+1];
 
 static FILE *emerg_file;
+static FILE *debug_file;
 
 static void *pd_key;
 
@@ -50,6 +54,7 @@ static void _log_free_msg(struct _log_msg_t *msg);
 static struct log_msg_t *clone_msg(struct _log_msg_t *msg);
 static int add_msg(struct _log_msg_t *msg, const char *buf);
 static struct log_pd_t *find_pd(struct ppp_t *ppp);
+static void write_msg(FILE *f, struct _log_msg_t *msg, struct ppp_t *ppp);
 
 static void do_log(int level, const char *fmt, va_list ap, struct ppp_t *ppp)
 {
@@ -61,6 +66,7 @@ static void do_log(int level, const char *fmt, va_list ap, struct ppp_t *ppp)
 		return;
 
 	vsnprintf(stat_buf, LOG_MAX_SIZE, fmt, ap);
+
 	if (!cur_msg) {
 		cur_msg = mempool_alloc(_msg_pool);
 		if (!cur_msg)
@@ -77,13 +83,16 @@ static void do_log(int level, const char *fmt, va_list ap, struct ppp_t *ppp)
 	if (stat_buf[strlen(stat_buf) - 1] != '\n')
 		return;
 
+	if (debug_file)
+		write_msg(debug_file, cur_msg, ppp);
+
 	if (ppp && !ppp->username) {
 		lpd = find_pd(ppp);
 		list_add_tail(&cur_msg->entry, &lpd->msgs);
 	}
 
 	list_for_each_entry(t, &targets, entry) {
-		if (ppp) {
+		if (ppp && ppp->username) {
 			if (t->session_log) {
 				m = clone_msg(cur_msg);
 				if (!m)
@@ -304,9 +313,25 @@ static struct log_pd_t *find_pd(struct ppp_t *ppp)
 	abort();
 }
 
+static void write_msg(FILE *f, struct _log_msg_t *msg, struct ppp_t *ppp)
+{
+	struct log_chunk_t *chunk;
+
+	if (ppp)
+		sprintf(stat_buf,"%s: %s: ", ppp->ifname, ppp->sessionid);
+	else
+		stat_buf[0] = 0;
+	
+	list_for_each_entry(chunk, &msg->chunks, entry)
+		strcat(stat_buf, chunk->msg);
+	
+	fwrite(stat_buf, strlen(stat_buf), 1, f);
+	fflush(f);
+}
+
 static void ev_ctrl_starting(struct ppp_t *ppp)
 {
-	struct log_pd_t *lpd = malloc(sizeof(*lpd));
+	struct log_pd_t *lpd = _malloc(sizeof(*lpd));
 	if (!lpd) {
 		log_emerg("log: out of memory\n");
 		return;
@@ -331,7 +356,7 @@ static void ev_ctrl_finished(struct ppp_t *ppp)
 		abort();
 	}
 
-	if (ppp->username) {
+	if (lpd->authorized) {
 		if (!list_empty(&lpd->msgs)) {
 			log_emerg("log:BUG: lpd->msgs is not empty\n");
 			abort();
@@ -358,7 +383,7 @@ static void ev_ctrl_finished(struct ppp_t *ppp)
 	}
 
 	list_del(&lpd->pd.entry);
-	free(lpd);
+	_free(lpd);
 }
 
 static void ev_ppp_authorized(struct ppp_t *ppp)
@@ -387,6 +412,8 @@ static void ev_ppp_authorized(struct ppp_t *ppp)
 
 		_log_free_msg(msg);
 	}
+
+	lpd->authorized = 1;
 }
 
 void __export log_switch(struct triton_context_t *ctx, void *arg)
@@ -410,6 +437,13 @@ static void __init log_init(void)
 			fprintf(stderr, "log:open: %s\n", strerror(errno));
 	}
 
+	opt = conf_get_opt("log", "log-debug");
+	if (opt) {
+		debug_file = fopen(opt, "a");
+		if (!emerg_file)
+			fprintf(stderr, "log:open: %s\n", strerror(errno));
+	}
+
 	opt = conf_get_opt("log", "copy");
 	if (opt && atoi(opt) > 0)
 		conf_copy = 1;
diff --git a/accel-pptpd/logs/log_file.c b/accel-pptpd/logs/log_file.c
index 10a575ef..f5bded9d 100644
--- a/accel-pptpd/logs/log_file.c
+++ b/accel-pptpd/logs/log_file.c
@@ -10,6 +10,8 @@
 #include "ppp.h"
 #include "spinlock.h"
 
+#include "memdebug.h"
+
 #define RED_COLOR     "\033[1;31m"
 #define GREEN_COLOR   "\033[1;32m"
 #define YELLOW_COLOR  "\033[1;33m"
@@ -171,7 +173,7 @@ static int log_write(struct triton_md_handler_t *h)
 			triton_md_unregister_handler(&lf->hnd);
 			close(lf->hnd.fd);
 			triton_context_unregister(&lf->ctx);
-			free(lf->lpd);
+			_free(lf->lpd);
 			return 1;
 		}
 		lf->sleeping = 1;
@@ -261,13 +263,13 @@ static void per_user_session_start(struct ppp_t *ppp)
 	struct log_file_pd_t *lpd;
 	char *fname;
 	
-	fname = malloc(PATH_MAX + 32);
+	fname = _malloc(PATH_MAX + 32);
 	if (!fname) {
 		log_emerg("log_file: out of memory\n");
 		return;
 	}
 
-	lpd = malloc(sizeof(*lpd));
+	lpd = _malloc(sizeof(*lpd));
 	if (!lpd) {
 		log_emerg("log_file: out of memory\n");
 		goto out_err;
@@ -296,26 +298,26 @@ static void per_user_session_start(struct ppp_t *ppp)
 	
 
 	list_add_tail(&lpd->pd.entry, &ppp->pd_list);
-	free(fname);
+	_free(fname);
 	return;
 
 out_err:
-	free(fname);
+	_free(fname);
 	if (lpd)
-		free(lpd);
+		_free(lpd);
 }
 static void per_session_start(struct ppp_t *ppp)
 {
 	struct log_file_pd_t *lpd;
 	char *fname;
 	
-	fname = malloc(PATH_MAX + 32);
+	fname = _malloc(PATH_MAX + 32);
 	if (!fname) {
 		log_emerg("log_file: out of memory\n");
 		return;
 	}
 
-	lpd = malloc(sizeof(*lpd));
+	lpd = _malloc(sizeof(*lpd));
 	if (!lpd) {
 		log_emerg("log_file: out of memory\n");
 		goto out_err;
@@ -336,13 +338,13 @@ static void per_session_start(struct ppp_t *ppp)
 		goto out_err;
 	
 	list_add_tail(&lpd->pd.entry, &ppp->pd_list);
-	free(fname);
+	_free(fname);
 	return;
 
 out_err:
-	free(fname);
+	_free(fname);
 	if (lpd)
-		free(lpd);
+		_free(lpd);
 }
 
 static void session_stop(struct ppp_t *ppp, void *pd_key)
@@ -400,10 +402,10 @@ static void __init init(void)
 	
 	opt = conf_get_opt("log", "log-file");
 	if (opt) {
-		log_file = malloc(sizeof(*log_file));
+		log_file = _malloc(sizeof(*log_file));
 		memset(log_file, 0, sizeof(*log_file));
 		if (log_file_init(log_file, opt)) {
-			free(log_file);
+			_free(log_file);
 			log_file = NULL;
 		}
 	}
diff --git a/accel-pptpd/logs/log_pgsql.c b/accel-pptpd/logs/log_pgsql.c
index cd06881d..f9cf7ed2 100644
--- a/accel-pptpd/logs/log_pgsql.c
+++ b/accel-pptpd/logs/log_pgsql.c
@@ -10,6 +10,8 @@
 #include "list.h"
 #include "ppp.h"
 
+#include "memdebug.h"
+
 static char *conf_conninfo;
 static int conf_queue_max = 1000;
 static char *conf_query;
@@ -48,22 +50,30 @@ static void unpack_msg(struct log_msg_t *msg)
 		log_buf[0] = 0;
 }
 
-static void set_hdr(struct log_msg_t *msg)
+static void set_hdr(struct log_msg_t *msg, struct ppp_t *ppp)
 {
 	struct tm tm;
 
 	localtime_r(&msg->timestamp.tv_sec, &tm);
 
 	strftime(msg->hdr->msg, LOG_CHUNK_SIZE, "%Y-%m-%d %H:%M:%S", &tm);
-	msg->hdr->len = strlen(msg->hdr->msg);
+	msg->hdr->len = strlen(msg->hdr->msg) + 1;
+	if (ppp && ppp->username) {
+		strcpy(msg->hdr->msg + msg->hdr->len, ppp->username);
+		msg->hdr->len += strlen(ppp->username) + 1;
+		strcpy(msg->hdr->msg + msg->hdr->len, ppp->sessionid);
+		msg->hdr->len += strlen(ppp->sessionid) + 1;
+	} else 
+		memset(msg->hdr->msg + msg->hdr->len, 0, 2);
+		
 }
 
 static void write_next_msg(void)
 {
 	struct log_msg_t *msg;
-	struct ppp_t *ppp;
 	const char *paramValues[4];
 	int paramFormats[4] = {0, 0, 0, 0};
+	char *ptr1, *ptr2;
 
 	spin_lock(&queue_lock);
 	if (!list_empty(&msg_queue)) {
@@ -72,18 +82,13 @@ static void write_next_msg(void)
 		--queue_size;
 		spin_unlock(&queue_lock);
 
-		set_hdr(msg);
 		unpack_msg(msg);
 
-		ppp = msg->tpd;
-		if (ppp) {
-			paramValues[1] = ppp->username;
-			paramValues[2] = ppp->sessionid;
-		} else {
-			paramValues[1] = NULL;
-			paramValues[2] = NULL;
-		}
-		
+		ptr1 = strchr(msg->hdr->msg, 0);
+		ptr2 = strchr(ptr1 + 1, 0);
+
+		paramValues[1] = ptr1[1] ? ptr1 + 1 : NULL;
+		paramValues[2] = ptr2[1] ? ptr2 + 1 : NULL;
 		paramValues[0] = msg->hdr->msg;
 		paramValues[3] = log_buf;
 
@@ -138,30 +143,33 @@ static void wakeup_log(void)
 
 static void queue_log(struct log_msg_t *msg)
 {
-	int r = 0;
+	int r = 0, f = 0;
 	spin_lock(&queue_lock);
 	if (queue_size < conf_queue_max) {
 		list_add_tail(&msg->entry, &msg_queue);
 		++queue_size;
 		r = sleeping;
 		sleeping = 0;
-	}
+	} else
+		f = 1;
 	spin_unlock(&queue_lock);
 
 	if (r)
 		triton_context_call(&pgsql_ctx, (void (*)(void*))wakeup_log, NULL);
+	else if (f)
+		log_free_msg(msg);
 }
 
 
 static void general_log(struct log_msg_t *msg)
 {
-	msg->tpd = NULL;
+	set_hdr(msg, NULL);
 	queue_log(msg);
 }
 
 static void session_log(struct ppp_t *ppp, struct log_msg_t *msg)
 {
-	msg->tpd = ppp;
+	set_hdr(msg, ppp);
 	queue_log(msg);
 }
 
@@ -253,11 +261,11 @@ static void __init init(void)
 		opt = conf_get_opt("log-pgsql", "log-table");
 		if (!opt || strlen(opt) > 32)
 			opt = "log";
-		conf_query = malloc(sizeof(QUERY_TEMPLATE) + strlen(opt));
+		conf_query = _malloc(sizeof(QUERY_TEMPLATE) + strlen(opt));
 		sprintf(conf_query, QUERY_TEMPLATE, opt);
 	}
 
-	log_buf = malloc(LOG_MAX_SIZE + 1);
+	log_buf = _malloc(LOG_MAX_SIZE + 1);
 	if (!log_buf) {
 		log_emerg("log_pgsql: out of memory\n");
 		return;
diff --git a/accel-pptpd/main.c b/accel-pptpd/main.c
index c60d35fb..147c248c 100644
--- a/accel-pptpd/main.c
+++ b/accel-pptpd/main.c
@@ -8,6 +8,8 @@
 
 #include "triton/triton.h"
 
+#include "memdebug.h"
+
 static int goto_daemon;
 static char *pid_file;
 static char *conf_file;
@@ -29,7 +31,7 @@ static int parse_cmdline(char ***argv)
 		_exit(EXIT_FAILURE);
 	}
 
-	*argv = malloc(ARG_MAX * sizeof(void *));
+	*argv = _malloc(ARG_MAX * sizeof(void *));
 	memset(*argv, 0, ARG_MAX * sizeof(void *));
 
 	for(i = 0; i < ARG_MAX; i++) {
@@ -69,7 +71,7 @@ static void __init __main(void)
 	if (!conf_file)
 		goto usage;
 
-	if (triton_init(conf_file, "modules"))
+	if (triton_init(conf_file))
 		_exit(EXIT_FAILURE);
 
 	return;
@@ -86,6 +88,9 @@ int main(int argc, char **argv)
 {
 	sigset_t set;
 
+	if (triton_load_modules("modules"))
+		return EXIT_FAILURE;
+
 	if (goto_daemon) {
 		pid_t pid = fork();
 		if (pid > 0)
@@ -121,6 +126,7 @@ int main(int argc, char **argv)
 	triton_run();
 	
 	sigfillset(&set);
+	sigdelset(&set, SIGINT);
 	sigdelset(&set, SIGTERM);
 	sigdelset(&set, SIGSEGV);
 	sigdelset(&set, SIGILL);
diff --git a/accel-pptpd/memdebug.c b/accel-pptpd/memdebug.c
new file mode 100644
index 00000000..780f16b8
--- /dev/null
+++ b/accel-pptpd/memdebug.c
@@ -0,0 +1,153 @@
+#undef MEMDEBUG
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+#include <signal.h>
+
+#include "spinlock.h"
+#include "list.h"
+
+#define __init __attribute__((constructor))
+#define __export __attribute__((visibility("default")))
+
+#undef offsetof
+#ifdef __compiler_offsetof
+#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
+#else
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#define container_of(ptr, type, member) ({			\
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
+	(type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+#define MAGIC1 0x1122334455667788llu
+
+struct mem_t
+{
+	struct list_head entry;
+	char fname[PATH_MAX];
+	int line;
+	size_t size;
+	uint64_t magic2;
+	uint64_t magic1;
+	char data[0];
+};
+
+static LIST_HEAD(mem_list);
+static spinlock_t mem_list_lock;
+
+struct mem_t *_md_malloc(size_t size, const char *fname, int line)
+{
+	struct mem_t *mem = malloc(sizeof(*mem) + size + 8);
+	strcpy(mem->fname, fname);
+	mem->line = line;
+	mem->size = size;
+	mem->magic1 = MAGIC1;
+	mem->magic2 = (uint64_t)random() * (uint64_t)random();
+	*(uint64_t*)(mem->data + size) = mem->magic2;
+
+	spin_lock(&mem_list_lock);
+	list_add_tail(&mem->entry, &mem_list);
+	spin_unlock(&mem_list_lock);
+
+	return mem;
+}
+
+void __export *md_malloc(size_t size, const char *fname, int line)
+{
+	struct mem_t *mem = _md_malloc(size, fname, line);
+
+	return mem->data;
+}
+
+void __export md_free(void *ptr, const char *fname, int line)
+{
+	struct mem_t *mem = container_of(ptr, typeof(*mem), data);
+
+	if (!ptr) {
+		printf("free null pointer at %s:%i\n", fname, line);
+		abort();
+	}
+	
+	if (mem->magic1 != MAGIC1) {
+		printf("memory corruption:\nfree at %s:%i\n", fname, line);
+		abort();
+	}
+
+	if (mem->magic2 != *(uint64_t*)(mem->data + mem->size)) {
+		printf("memory corruption:\nmalloc(%lu) at %s:%i\nfree at %s:%i\n", mem->size, mem->fname, mem->line, fname, line);
+		abort();
+	}
+	
+	mem->magic1 = 0;
+	mem->magic2 = 0;
+
+	spin_lock(&mem_list_lock);
+	list_del(&mem->entry);
+	spin_unlock(&mem_list_lock);
+
+	free(mem);
+	return;
+}
+
+void __export *md_realloc(void *ptr, size_t size, const char *fname, int line)
+{
+	struct mem_t *mem = container_of(ptr, typeof(*mem), data);
+	struct mem_t *mem2;
+	
+	if (mem->magic1 != MAGIC1) {
+		printf("memory corruption:\nfree at %s:%i\n", fname, line);
+		abort();
+	}
+
+	if (mem->magic2 != *(uint64_t*)(mem->data + mem->size)) {
+		printf("memory corruption:\nmalloc(%lu) at %s:%i\nfree at %s:%i\n", mem->size, mem->fname, mem->line, fname, line);
+		abort();
+	}
+
+	mem2 = _md_malloc(size, fname, line);
+	memcpy(mem2->data, mem->data, mem->size);
+	
+	md_free(mem->data, fname, line);
+
+	return mem2->data;
+}
+
+char __export *md_strdup(const char *ptr, const char *fname, int line)
+{
+	struct mem_t *mem = _md_malloc(strlen(ptr) + 1, fname, line);
+	memcpy(mem->data, ptr, strlen(ptr) + 1);
+	return mem->data;
+}
+
+char __export *md_strndup(const char *ptr, size_t n, const char *fname, int line)
+{
+	struct mem_t *mem = _md_malloc(n + 1, fname, line);
+	memcpy(mem->data, ptr, n);
+	mem->data[n] = 0;
+	return mem->data;
+}
+
+static void siginfo(int num)
+{
+	struct mem_t *mem;
+	size_t total = 0;
+
+	spin_lock(&mem_list_lock);
+	list_for_each_entry(mem, &mem_list, entry) {
+		printf("%s:%i %lu\n", mem->fname, mem->line, mem->size);
+		total += mem->size;
+	}
+	spin_unlock(&mem_list_lock);
+	printf("total = %lu\n", total);
+}
+
+static void __init init(void)
+{
+	signal(36, siginfo);
+}
diff --git a/accel-pptpd/memdebug.h b/accel-pptpd/memdebug.h
new file mode 100644
index 00000000..ad57f4a8
--- /dev/null
+++ b/accel-pptpd/memdebug.h
@@ -0,0 +1,27 @@
+#ifndef __MEMDEBUG_H
+#define __MEMDEBUG_H
+
+#ifdef MEMDEBUG
+
+#include <sys/types.h>
+
+#define _malloc(size) md_malloc(size, __FILE__, __LINE__)
+#define _realloc(ptr, size) md_realloc(ptr, size, __FILE__, __LINE__)
+#define _free(ptr) md_free(ptr, __FILE__, __LINE__)
+#define _strdup(str) md_strdup(str, __FILE__, __LINE__)
+#define _strndup(str, size) md_strndup(str, size, __FILE__, __LINE__)
+
+void *md_malloc(size_t size, const char *fname, int line);
+void *md_realloc(void *ptr, size_t size, const char *fname, int line);
+void md_free(void *ptr, const char *fname, int line);
+char* md_strdup(const char *ptr, const char *fname, int line);
+char* md_strndup(const char *ptr, size_t size, const char *fname, int line);
+
+#else
+#define _malloc(size) malloc(size)
+#define _realloc(ptr, size) realloc(ptr, size)
+#define _free(ptr) free(ptr)
+#endif
+
+#endif
+
diff --git a/accel-pptpd/ppp/ipcp_opt_dns.c b/accel-pptpd/ppp/ipcp_opt_dns.c
index b7417989..16ef7af4 100644
--- a/accel-pptpd/ppp/ipcp_opt_dns.c
+++ b/accel-pptpd/ppp/ipcp_opt_dns.c
@@ -7,6 +7,8 @@
 #include "log.h"
 #include "ipdb.h"
 
+#include "memdebug.h"
+
 static struct ipcp_option_t *dns1_init(struct ppp_ipcp_t *ipcp);
 static struct ipcp_option_t *dns2_init(struct ppp_ipcp_t *ipcp);
 static void dns_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt);
@@ -43,7 +45,7 @@ static struct ipcp_option_handler_t dns2_opt_hnd=
 
 static struct ipcp_option_t *dns1_init(struct ppp_ipcp_t *ipcp)
 {
-	struct dns_option_t *dns_opt=malloc(sizeof(*dns_opt));
+	struct dns_option_t *dns_opt=_malloc(sizeof(*dns_opt));
 	memset(dns_opt,0,sizeof(*dns_opt));
 	dns_opt->opt.id=CI_DNS1;
 	dns_opt->opt.len=6;
@@ -53,7 +55,7 @@ static struct ipcp_option_t *dns1_init(struct ppp_ipcp_t *ipcp)
 
 static struct ipcp_option_t *dns2_init(struct ppp_ipcp_t *ipcp)
 {
-	struct dns_option_t *dns_opt=malloc(sizeof(*dns_opt));
+	struct dns_option_t *dns_opt=_malloc(sizeof(*dns_opt));
 	memset(dns_opt,0,sizeof(*dns_opt));
 	dns_opt->opt.id=CI_DNS2;
 	dns_opt->opt.len=6;
@@ -65,7 +67,7 @@ static void dns_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt)
 {
 	struct dns_option_t *dns_opt=container_of(opt,typeof(*dns_opt),opt);
 
-	free(dns_opt);
+	_free(dns_opt);
 }
 
 static int dns_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr)
diff --git a/accel-pptpd/ppp/ipcp_opt_ipaddr.c b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
index 1f9af3e7..963d4736 100644
--- a/accel-pptpd/ppp/ipcp_opt_ipaddr.c
+++ b/accel-pptpd/ppp/ipcp_opt_ipaddr.c
@@ -13,6 +13,8 @@
 #include "ipdb.h"
 #include "iprange.h"
 
+#include "memdebug.h"
+
 static struct ipcp_option_t *ipaddr_init(struct ppp_ipcp_t *ipcp);
 static void ipaddr_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt);
 static int ipaddr_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr);
@@ -39,7 +41,7 @@ static struct ipcp_option_handler_t ipaddr_opt_hnd=
 
 static struct ipcp_option_t *ipaddr_init(struct ppp_ipcp_t *ipcp)
 {
-	struct ipaddr_option_t *ipaddr_opt=malloc(sizeof(*ipaddr_opt));
+	struct ipaddr_option_t *ipaddr_opt=_malloc(sizeof(*ipaddr_opt));
 	memset(ipaddr_opt,0,sizeof(*ipaddr_opt));
 	ipaddr_opt->opt.id=CI_ADDR;
 	ipaddr_opt->opt.len=6;
@@ -54,7 +56,7 @@ static void ipaddr_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt)
 	if (ipaddr_opt->ip)
 		ipdb_put(ipcp->ppp, ipaddr_opt->ip);
 
-	free(ipaddr_opt);
+	_free(ipaddr_opt);
 }
 
 static int ipaddr_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr)
@@ -65,7 +67,7 @@ static int ipaddr_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o
 	if (!ipaddr_opt->ip) {
 		ipaddr_opt->ip = ipdb_get(ipcp->ppp);
 		if (!ipaddr_opt->ip) {
-			log_ppp_warn("ppp:ipcp: no free IP address\n");
+			log_ppp_warn("ppp:ipcp: no _free IP address\n");
 			return -1;
 		}
 	}
diff --git a/accel-pptpd/ppp/lcp_opt_accomp.c b/accel-pptpd/ppp/lcp_opt_accomp.c
index c4c221ce..8545f9d7 100644
--- a/accel-pptpd/ppp/lcp_opt_accomp.c
+++ b/accel-pptpd/ppp/lcp_opt_accomp.c
@@ -6,6 +6,8 @@
 #include "ppp_lcp.h"
 #include "log.h"
 
+#include "memdebug.h"
+
 static struct lcp_option_t *accomp_init(struct ppp_lcp_t *lcp);
 static void accomp_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt);
 static int accomp_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
@@ -31,7 +33,7 @@ static struct lcp_option_handler_t accomp_opt_hnd=
 
 static struct lcp_option_t *accomp_init(struct ppp_lcp_t *lcp)
 {
-	struct accomp_option_t *accomp_opt=malloc(sizeof(*accomp_opt));
+	struct accomp_option_t *accomp_opt=_malloc(sizeof(*accomp_opt));
 	memset(accomp_opt,0,sizeof(*accomp_opt));
 	accomp_opt->accomp=0;
 	accomp_opt->opt.id=CI_ACCOMP;
@@ -44,7 +46,7 @@ static void accomp_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt)
 {
 	struct accomp_option_t *accomp_opt=container_of(opt,typeof(*accomp_opt),opt);
 
-	free(accomp_opt);
+	_free(accomp_opt);
 }
 
 static int accomp_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
diff --git a/accel-pptpd/ppp/lcp_opt_magic.c b/accel-pptpd/ppp/lcp_opt_magic.c
index d6094c0c..cec40ce4 100644
--- a/accel-pptpd/ppp/lcp_opt_magic.c
+++ b/accel-pptpd/ppp/lcp_opt_magic.c
@@ -6,6 +6,8 @@
 #include "ppp_lcp.h"
 #include "log.h"
 
+#include "memdebug.h"
+
 static struct lcp_option_t *magic_init(struct ppp_lcp_t *lcp);
 static void magic_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt);
 static int magic_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
@@ -29,7 +31,7 @@ static struct lcp_option_handler_t magic_opt_hnd=
 
 static struct lcp_option_t *magic_init(struct ppp_lcp_t *lcp)
 {
-	struct magic_option_t *magic_opt=malloc(sizeof(*magic_opt));
+	struct magic_option_t *magic_opt=_malloc(sizeof(*magic_opt));
 	memset(magic_opt,0,sizeof(*magic_opt));
 	magic_opt->magic=random();
 	magic_opt->opt.id=CI_MAGIC;
@@ -44,7 +46,7 @@ static void magic_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt)
 {
 	struct magic_option_t *magic_opt=container_of(opt,typeof(*magic_opt),opt);
 
-	free(magic_opt);
+	_free(magic_opt);
 }
 
 static int magic_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
diff --git a/accel-pptpd/ppp/lcp_opt_mru.c b/accel-pptpd/ppp/lcp_opt_mru.c
index fc79db38..4dc96851 100644
--- a/accel-pptpd/ppp/lcp_opt_mru.c
+++ b/accel-pptpd/ppp/lcp_opt_mru.c
@@ -11,6 +11,8 @@
 #include "ppp_lcp.h"
 #include "log.h"
 
+#include "memdebug.h"
+
 #define MAX_MTU 1436
 
 static struct lcp_option_t *mru_init(struct ppp_lcp_t *lcp);
@@ -41,7 +43,7 @@ static struct lcp_option_handler_t mru_opt_hnd=
 
 static struct lcp_option_t *mru_init(struct ppp_lcp_t *lcp)
 {
-	struct mru_option_t *mru_opt=malloc(sizeof(*mru_opt));
+	struct mru_option_t *mru_opt=_malloc(sizeof(*mru_opt));
 	memset(mru_opt,0,sizeof(*mru_opt));
 	mru_opt->mtu=0;
 	mru_opt->mru=MAX_MTU;
@@ -55,7 +57,7 @@ static void mru_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt)
 {
 	struct mru_option_t *mru_opt=container_of(opt,typeof(*mru_opt),opt);
 
-	free(mru_opt);
+	_free(mru_opt);
 }
 
 static int mru_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
diff --git a/accel-pptpd/ppp/lcp_opt_pcomp.c b/accel-pptpd/ppp/lcp_opt_pcomp.c
index 8700bf49..0ff4d11f 100644
--- a/accel-pptpd/ppp/lcp_opt_pcomp.c
+++ b/accel-pptpd/ppp/lcp_opt_pcomp.c
@@ -6,6 +6,8 @@
 #include "ppp_lcp.h"
 #include "log.h"
 
+#include "memdebug.h"
+
 static struct lcp_option_t *pcomp_init(struct ppp_lcp_t *lcp);
 static void pcomp_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt);
 static int pcomp_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
@@ -31,7 +33,7 @@ static struct lcp_option_handler_t pcomp_opt_hnd=
 
 static struct lcp_option_t *pcomp_init(struct ppp_lcp_t *lcp)
 {
-	struct pcomp_option_t *pcomp_opt=malloc(sizeof(*pcomp_opt));
+	struct pcomp_option_t *pcomp_opt=_malloc(sizeof(*pcomp_opt));
 	memset(pcomp_opt,0,sizeof(*pcomp_opt));
 	pcomp_opt->pcomp=0;
 	pcomp_opt->opt.id=CI_PCOMP;
@@ -44,7 +46,7 @@ static void pcomp_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt)
 {
 	struct pcomp_option_t *pcomp_opt=container_of(opt,typeof(*pcomp_opt),opt);
 
-	free(pcomp_opt);
+	_free(pcomp_opt);
 }
 
 static int pcomp_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
diff --git a/accel-pptpd/ppp/ppp.c b/accel-pptpd/ppp/ppp.c
index 87c8e8e0..4deb1356 100644
--- a/accel-pptpd/ppp/ppp.c
+++ b/accel-pptpd/ppp/ppp.c
@@ -19,6 +19,8 @@
 #include "ppp_fsm.h"
 #include "log.h"
 
+#include "memdebug.h"
+
 int conf_ppp_verbose;
 
 static LIST_HEAD(layers);
@@ -34,24 +36,25 @@ struct layer_node_t
 static int ppp_chan_read(struct triton_md_handler_t*);
 static int ppp_unit_read(struct triton_md_handler_t*);
 static void init_layers(struct ppp_t *);
-static void free_layers(struct ppp_t *);
+static void _free_layers(struct ppp_t *);
 static void start_first_layer(struct ppp_t *);
 
 void __export ppp_init(struct ppp_t *ppp)
 {
 	memset(ppp,0,sizeof(*ppp));
+	INIT_LIST_HEAD(&ppp->layers);
 	INIT_LIST_HEAD(&ppp->chan_handlers);
 	INIT_LIST_HEAD(&ppp->unit_handlers);
 	INIT_LIST_HEAD(&ppp->pd_list);
 }
 
-static void free_ppp(struct ppp_t *ppp)
+static void _free_ppp(struct ppp_t *ppp)
 {
-	free(ppp->chan_buf);
-	free(ppp->unit_buf);
+	_free(ppp->chan_buf);
+	_free(ppp->unit_buf);
 
 	if (ppp->username)
-		free(ppp->username);
+		_free(ppp->username);
 }
 
 static void generate_sessionid(struct ppp_t *ppp)
@@ -121,8 +124,8 @@ int __export establish_ppp(struct ppp_t *ppp)
 
 	log_ppp_info("connect: ppp%i <--> pptp(%s)\n",ppp->unit_idx,ppp->chan_name);
 	
-	ppp->chan_buf=malloc(PPP_MRU);
-	ppp->unit_buf=malloc(PPP_MRU);
+	ppp->chan_buf=_malloc(PPP_MRU);
+	ppp->unit_buf=_malloc(PPP_MRU);
 
 	init_layers(ppp);
 
@@ -166,7 +169,7 @@ exit_close_unit:
 exit_close_chan:
 	close(ppp->chan_fd);
 
-	free_ppp(ppp);
+	_free_ppp(ppp);
 
 	return -1;
 }
@@ -183,15 +186,20 @@ static void destablish_ppp(struct ppp_t *ppp)
 	ppp->unit_fd = -1;
 	ppp->chan_fd = -1;
 
-	free(ppp->unit_buf);
-	free(ppp->chan_buf);
+	_free(ppp->unit_buf);
+	_free(ppp->chan_buf);
 
-	free_layers(ppp);
+	_free_layers(ppp);
 	
 	log_ppp_debug("ppp destablished\n");
 
 	triton_event_fire(EV_PPP_FINISHED, ppp);
 	ppp->ctrl->finished(ppp);
+
+	if (ppp->username) {
+		_free(ppp->username);
+		ppp->username = NULL;
+	}
 }
 
 void print_buf(uint8_t *buf,int size)
@@ -424,7 +432,7 @@ int __export ppp_register_layer(const char *name, struct ppp_layer_t *layer)
 			continue;
 		if (order<n->order)
 		{
-			n1=malloc(sizeof(*n1));
+			n1=_malloc(sizeof(*n1));
 			memset(n1,0,sizeof(*n1));
 			n1->order=order;
 			INIT_LIST_HEAD(&n1->items);
@@ -433,7 +441,7 @@ int __export ppp_register_layer(const char *name, struct ppp_layer_t *layer)
 		}
 		goto insert;
 	}
-	n1=malloc(sizeof(*n1));
+	n1=_malloc(sizeof(*n1));
 	memset(n1,0,sizeof(*n1));
 	n1->order=order;
 	INIT_LIST_HEAD(&n1->items);
@@ -455,10 +463,8 @@ static void init_layers(struct ppp_t *ppp)
 	struct ppp_layer_t *l;
 	struct ppp_layer_data_t *d;
 
-	INIT_LIST_HEAD(&ppp->layers);
-
 	list_for_each_entry(n,&layers,entry) {
-		n1 = (struct layer_node_t*)malloc(sizeof(*n1));
+		n1 = _malloc(sizeof(*n1));
 		memset(n1, 0, sizeof(*n1));
 		INIT_LIST_HEAD(&n1->items);
 		list_add_tail(&n1->entry, &ppp->layers);
@@ -472,7 +478,7 @@ static void init_layers(struct ppp_t *ppp)
 	}
 }
 
-static void free_layers(struct ppp_t *ppp)
+static void _free_layers(struct ppp_t *ppp)
 {
 	struct layer_node_t *n;
 	struct ppp_layer_data_t *d;
@@ -485,7 +491,7 @@ static void free_layers(struct ppp_t *ppp)
 			d->layer->free(d);
 		}
 		list_del(&n->entry);
-		free(n);
+		_free(n);
 	}
 }
 
diff --git a/accel-pptpd/ppp/ppp_auth.c b/accel-pptpd/ppp/ppp_auth.c
index 5ad7444e..d141b817 100644
--- a/accel-pptpd/ppp/ppp_auth.c
+++ b/accel-pptpd/ppp/ppp_auth.c
@@ -9,6 +9,7 @@
 
 #include "ppp_auth.h"
 
+#include "memdebug.h"
 
 static LIST_HEAD(auth_handlers);
 static int extra_opt_len=0;
@@ -247,7 +248,7 @@ print_d:
 
 static struct ppp_layer_data_t *auth_layer_init(struct ppp_t *ppp)
 {
-	struct auth_layer_data_t *ad=(struct auth_layer_data_t*)malloc(sizeof(*ad));
+	struct auth_layer_data_t *ad = _malloc(sizeof(*ad));
 
 	log_ppp_debug("auth_layer_init\n");
 	
@@ -294,7 +295,7 @@ static void auth_layer_free(struct ppp_layer_data_t *ld)
 
 	log_ppp_debug("auth_layer_free\n");
 	
-	free(ad);
+	_free(ad);
 }
 
 void __export auth_successed(struct ppp_t *ppp, char *username)
diff --git a/accel-pptpd/ppp/ppp_ccp.c b/accel-pptpd/ppp/ppp_ccp.c
index 8f240bc9..301c2385 100644
--- a/accel-pptpd/ppp/ppp_ccp.c
+++ b/accel-pptpd/ppp/ppp_ccp.c
@@ -11,6 +11,8 @@
 #include "ppp.h"
 #include "ppp_ccp.h"
 
+#include "memdebug.h"
+
 struct recv_opt_t
 {
 	struct list_head entry;
@@ -35,6 +37,8 @@ static void ccp_options_init(struct ppp_ccp_t *ccp)
 	struct ccp_option_t *lopt;
 	struct ccp_option_handler_t *h;
 
+	ccp->conf_req_len = sizeof(struct ccp_hdr_t);
+
 	list_for_each_entry(h,&option_handlers,entry)
 	{
 		lopt=h->init(ccp);
@@ -61,7 +65,7 @@ static void ccp_options_free(struct ppp_ccp_t *ccp)
 
 static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp)
 {
-	struct ppp_ccp_t *ccp=malloc(sizeof(*ccp));
+	struct ppp_ccp_t *ccp=_malloc(sizeof(*ccp));
 	memset(ccp,0,sizeof(*ccp));
 	
 	log_ppp_debug("ccp_layer_init\n");
@@ -123,7 +127,7 @@ void ccp_layer_free(struct ppp_layer_data_t *ld)
 	ccp_options_free(ccp);
 	ppp_fsm_free(&ccp->fsm);
 
-	free(ccp);
+	_free(ccp);
 }
 
 static void ccp_layer_up(struct ppp_fsm_t *fsm)
@@ -156,7 +160,7 @@ static void print_ropt(struct recv_opt_t *ropt)
 static int send_conf_req(struct ppp_fsm_t *fsm)
 {
 	struct ppp_ccp_t *ccp=container_of(fsm,typeof(*ccp),fsm);
-	uint8_t *buf=malloc(ccp->conf_req_len), *ptr=buf;
+	uint8_t *buf=_malloc(ccp->conf_req_len), *ptr=buf;
 	struct ccp_hdr_t *ccp_hdr=(struct ccp_hdr_t*)ptr;
 	struct ccp_option_t *lopt;
 	int n;
@@ -188,6 +192,8 @@ static int send_conf_req(struct ppp_fsm_t *fsm)
 	ccp_hdr->len=htons((ptr-buf)-2);
 	ppp_unit_send(ccp->ppp,ccp_hdr,ptr-buf);
 
+	_free(buf);
+
 	return 0;
 }
 
@@ -205,7 +211,7 @@ static void send_conf_ack(struct ppp_fsm_t *fsm)
 static void send_conf_nak(struct ppp_fsm_t *fsm)
 {
 	struct ppp_ccp_t *ccp=container_of(fsm,typeof(*ccp),fsm);
-	uint8_t *buf=malloc(ccp->conf_req_len), *ptr=buf;
+	uint8_t *buf=_malloc(ccp->conf_req_len), *ptr=buf;
 	struct ccp_hdr_t *ccp_hdr=(struct ccp_hdr_t*)ptr;
 	struct recv_opt_t *ropt;
 
@@ -232,12 +238,14 @@ static void send_conf_nak(struct ppp_fsm_t *fsm)
 
 	ccp_hdr->len=htons((ptr-buf)-2);
 	ppp_unit_send(ccp->ppp,ccp_hdr,ptr-buf);
+
+	_free(buf);
 }
 
 static void send_conf_rej(struct ppp_fsm_t *fsm)
 {
 	struct ppp_ccp_t *ccp=container_of(fsm,typeof(*ccp),fsm);
-	uint8_t *buf=malloc(ccp->ropt_len), *ptr=buf;
+	uint8_t *buf=_malloc(ccp->ropt_len + sizeof(struct ccp_hdr_t)), *ptr=buf;
 	struct ccp_hdr_t *ccp_hdr=(struct ccp_hdr_t*)ptr;
 	struct recv_opt_t *ropt;
 
@@ -266,6 +274,8 @@ static void send_conf_rej(struct ppp_fsm_t *fsm)
 
 	ccp_hdr->len=htons((ptr-buf)-2);
 	ppp_unit_send(ccp->ppp,ccp_hdr,ptr-buf);
+
+	_free(buf);
 }
 
 static int ccp_recv_conf_req(struct ppp_ccp_t *ccp,uint8_t *data,int size)
@@ -281,7 +291,7 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp,uint8_t *data,int size)
 	{
 		hdr=(struct ccp_opt_hdr_t *)data;
 
-		ropt=malloc(sizeof(*ropt));
+		ropt=_malloc(sizeof(*ropt));
 		memset(ropt,0,sizeof(*ropt));
 		if (hdr->len>size) ropt->len=size;
 		else ropt->len=hdr->len;
@@ -353,7 +363,7 @@ static void ccp_free_conf_req(struct ppp_ccp_t *ccp)
 	{
 		ropt=list_entry(ccp->ropt_list.next,typeof(*ropt),entry);
 		list_del(&ropt->entry);
-		free(ropt);
+		_free(ropt);
 	}
 }
 
@@ -534,16 +544,16 @@ static void ccp_recv(struct ppp_handler_t*h)
 				ppp_fsm_recv_conf_rej(&ccp->fsm);
 			break;
 		case TERMREQ:
-			term_msg=strndup((char*)(hdr+1),ntohs(hdr->len));
+			term_msg=_strndup((char*)(hdr+1),ntohs(hdr->len));
 			log_ppp_debug("recv [CCP TermReq id=%x \"%s\"]\n",hdr->id,term_msg);
-			free(term_msg);
+			_free(term_msg);
 			ppp_fsm_recv_term_req(&ccp->fsm);
 			ppp_terminate(ccp->ppp, 0);
 			break;
 		case TERMACK:
-			term_msg=strndup((char*)(hdr+1),ntohs(hdr->len));
+			term_msg=_strndup((char*)(hdr+1),ntohs(hdr->len));
 			log_ppp_debug("recv [CCP TermAck id=%x \"%s\"]\n",hdr->id,term_msg);
-			free(term_msg);
+			_free(term_msg);
 			ppp_fsm_recv_term_ack(&ccp->fsm);
 			break;
 		case CODEREJ:
diff --git a/accel-pptpd/ppp/ppp_fsm.c b/accel-pptpd/ppp/ppp_fsm.c
index 0e11b660..3b8d854d 100644
--- a/accel-pptpd/ppp/ppp_fsm.c
+++ b/accel-pptpd/ppp/ppp_fsm.c
@@ -8,6 +8,8 @@
 #include "ppp_lcp.h"
 #include "log.h"
 
+#include "memdebug.h"
+
 static int conf_max_terminate = 2;
 static int conf_max_configure = 5;
 static int conf_max_failure = 5;
@@ -372,7 +374,7 @@ void ppp_fsm_recv_term_req(struct ppp_fsm_t *layer)
 	{
 		case FSM_Opened:
 			if (layer->layer_down) layer->layer_down(layer);
-			send_term_req(layer);
+			//send_term_req(layer);
 			send_term_ack(layer);
 			//if (layer->zero_req_cnt) layer->zero_req_cnt(layer);
 			zero_req_counter(layer);
@@ -381,7 +383,7 @@ void ppp_fsm_recv_term_req(struct ppp_fsm_t *layer)
 		case FSM_Req_Sent:
 		case FSM_Ack_Rcvd:
 		case FSM_Ack_Sent:
-			send_term_req(layer);
+			send_term_ack(layer);
 			layer->fsm_state=FSM_Req_Sent;
 			break;
 		default:
diff --git a/accel-pptpd/ppp/ppp_ipcp.c b/accel-pptpd/ppp/ppp_ipcp.c
index b8dfe7f7..f3c20a64 100644
--- a/accel-pptpd/ppp/ppp_ipcp.c
+++ b/accel-pptpd/ppp/ppp_ipcp.c
@@ -11,6 +11,8 @@
 #include "ppp.h"
 #include "ppp_ipcp.h"
 
+#include "memdebug.h"
+
 struct recv_opt_t
 {
 	struct list_head entry;
@@ -35,6 +37,8 @@ static void ipcp_options_init(struct ppp_ipcp_t *ipcp)
 	struct ipcp_option_t *lopt;
 	struct ipcp_option_handler_t *h;
 
+	ipcp->conf_req_len = sizeof(struct ipcp_hdr_t);
+	
 	list_for_each_entry(h,&option_handlers,entry)
 	{
 		lopt=h->init(ipcp);
@@ -61,7 +65,7 @@ static void ipcp_options_free(struct ppp_ipcp_t *ipcp)
 
 static struct ppp_layer_data_t *ipcp_layer_init(struct ppp_t *ppp)
 {
-	struct ppp_ipcp_t *ipcp=malloc(sizeof(*ipcp));
+	struct ppp_ipcp_t *ipcp=_malloc(sizeof(*ipcp));
 	memset(ipcp,0,sizeof(*ipcp));
 	
 	log_ppp_debug("ipcp_layer_init\n");
@@ -123,7 +127,7 @@ void ipcp_layer_free(struct ppp_layer_data_t *ld)
 	ipcp_options_free(ipcp);
 	ppp_fsm_free(&ipcp->fsm);
 
-	free(ipcp);
+	_free(ipcp);
 }
 
 static void ipcp_layer_up(struct ppp_fsm_t *fsm)
@@ -156,7 +160,7 @@ static void print_ropt(struct recv_opt_t *ropt)
 static int send_conf_req(struct ppp_fsm_t *fsm)
 {
 	struct ppp_ipcp_t *ipcp=container_of(fsm,typeof(*ipcp),fsm);
-	uint8_t *buf=malloc(ipcp->conf_req_len), *ptr=buf;
+	uint8_t *buf=_malloc(ipcp->conf_req_len), *ptr=buf;
 	struct ipcp_hdr_t *ipcp_hdr=(struct ipcp_hdr_t*)ptr;
 	struct ipcp_option_t *lopt;
 	int n;
@@ -194,6 +198,8 @@ static int send_conf_req(struct ppp_fsm_t *fsm)
 	ipcp_hdr->len=htons((ptr-buf)-2);
 	ppp_unit_send(ipcp->ppp,ipcp_hdr,ptr-buf);
 
+	_free(buf);
+
 	return 0;
 }
 
@@ -211,7 +217,7 @@ static void send_conf_ack(struct ppp_fsm_t *fsm)
 static void send_conf_nak(struct ppp_fsm_t *fsm)
 {
 	struct ppp_ipcp_t *ipcp=container_of(fsm,typeof(*ipcp),fsm);
-	uint8_t *buf=malloc(ipcp->conf_req_len), *ptr=buf;
+	uint8_t *buf=_malloc(ipcp->conf_req_len), *ptr=buf;
 	struct ipcp_hdr_t *ipcp_hdr=(struct ipcp_hdr_t*)ptr;
 	struct recv_opt_t *ropt;
 
@@ -238,12 +244,14 @@ static void send_conf_nak(struct ppp_fsm_t *fsm)
 
 	ipcp_hdr->len=htons((ptr-buf)-2);
 	ppp_unit_send(ipcp->ppp,ipcp_hdr,ptr-buf);
+
+	_free(buf);
 }
 
 static void send_conf_rej(struct ppp_fsm_t *fsm)
 {
 	struct ppp_ipcp_t *ipcp=container_of(fsm,typeof(*ipcp),fsm);
-	uint8_t *buf=malloc(ipcp->ropt_len), *ptr=buf;
+	uint8_t *buf=_malloc(ipcp->ropt_len + sizeof(struct ipcp_hdr_t)), *ptr=buf;
 	struct ipcp_hdr_t *ipcp_hdr=(struct ipcp_hdr_t*)ptr;
 	struct recv_opt_t *ropt;
 
@@ -272,6 +280,8 @@ static void send_conf_rej(struct ppp_fsm_t *fsm)
 
 	ipcp_hdr->len=htons((ptr-buf)-2);
 	ppp_unit_send(ipcp->ppp,ipcp_hdr,ptr-buf);
+
+	_free(buf);
 }
 
 static int ipcp_recv_conf_req(struct ppp_ipcp_t *ipcp,uint8_t *data,int size)
@@ -287,7 +297,7 @@ static int ipcp_recv_conf_req(struct ppp_ipcp_t *ipcp,uint8_t *data,int size)
 	{
 		hdr=(struct ipcp_opt_hdr_t *)data;
 
-		ropt=malloc(sizeof(*ropt));
+		ropt=_malloc(sizeof(*ropt));
 		memset(ropt,0,sizeof(*ropt));
 		if (hdr->len>size) ropt->len=size;
 		else ropt->len=hdr->len;
@@ -350,7 +360,7 @@ static void ipcp_free_conf_req(struct ppp_ipcp_t *ipcp)
 	{
 		ropt=list_entry(ipcp->ropt_list.next,typeof(*ropt),entry);
 		list_del(&ropt->entry);
-		free(ropt);
+		_free(ropt);
 	}
 }
 
@@ -531,16 +541,16 @@ static void ipcp_recv(struct ppp_handler_t*h)
 				ppp_fsm_recv_conf_rej(&ipcp->fsm);
 			break;
 		case TERMREQ:
-			term_msg=strndup((char*)(hdr+1),ntohs(hdr->len));
+			term_msg=_strndup((char*)(hdr+1),ntohs(hdr->len));
 			log_ppp_debug("recv [IPCP TermReq id=%x \"%s\"]\n",hdr->id,term_msg);
-			free(term_msg);
+			_free(term_msg);
 			ppp_fsm_recv_term_req(&ipcp->fsm);
 			ppp_terminate(ipcp->ppp, 0);
 			break;
 		case TERMACK:
-			term_msg=strndup((char*)(hdr+1),ntohs(hdr->len));
+			term_msg=_strndup((char*)(hdr+1),ntohs(hdr->len));
 			log_ppp_debug("recv [IPCP TermAck id=%x \"%s\"]\n",hdr->id,term_msg);
-			free(term_msg);
+			_free(term_msg);
 			ppp_fsm_recv_term_ack(&ipcp->fsm);
 			break;
 		case CODEREJ:
diff --git a/accel-pptpd/ppp/ppp_lcp.c b/accel-pptpd/ppp/ppp_lcp.c
index b5afb5a3..a85b3d12 100644
--- a/accel-pptpd/ppp/ppp_lcp.c
+++ b/accel-pptpd/ppp/ppp_lcp.c
@@ -11,6 +11,8 @@
 #include "ppp.h"
 #include "ppp_lcp.h"
 
+#include "memdebug.h"
+
 struct recv_opt_t
 {
 	struct list_head entry;
@@ -42,6 +44,8 @@ static void lcp_options_init(struct ppp_lcp_t *lcp)
 
 	INIT_LIST_HEAD(&lcp->options);
 
+	lcp->conf_req_len = sizeof(struct lcp_hdr_t);
+
 	list_for_each_entry(h,&option_handlers,entry)
 	{
 		lopt=h->init(lcp);
@@ -68,7 +72,7 @@ static void lcp_options_free(struct ppp_lcp_t *lcp)
 
 static struct ppp_layer_data_t *lcp_layer_init(struct ppp_t *ppp)
 {
-	struct ppp_lcp_t *lcp=malloc(sizeof(*lcp));
+	struct ppp_lcp_t *lcp=_malloc(sizeof(*lcp));
 	memset(lcp,0,sizeof(*lcp));
 	
 	log_ppp_debug("lcp_layer_init\n");
@@ -131,7 +135,7 @@ void lcp_layer_free(struct ppp_layer_data_t *ld)
 	lcp_options_free(lcp);
 	ppp_fsm_free(&lcp->fsm);
 	
-	free(lcp);
+	_free(lcp);
 }
 
 static void lcp_layer_up(struct ppp_fsm_t *fsm)
@@ -146,6 +150,7 @@ static void lcp_layer_up(struct ppp_fsm_t *fsm)
 static void lcp_layer_down(struct ppp_fsm_t *fsm)
 {
 	struct ppp_lcp_t *lcp=container_of(fsm,typeof(*lcp),fsm);
+	ppp_fsm_close(&lcp->fsm);
 	log_ppp_debug("lcp_layer_finished\n");
 	stop_echo(lcp);
 	ppp_layer_finished(lcp->ppp,&lcp->ld);
@@ -167,7 +172,7 @@ static void print_ropt(struct recv_opt_t *ropt)
 static int send_conf_req(struct ppp_fsm_t *fsm)
 {
 	struct ppp_lcp_t *lcp=container_of(fsm,typeof(*lcp),fsm);
-	uint8_t *buf=malloc(lcp->conf_req_len), *ptr=buf;
+	uint8_t *buf=_malloc(lcp->conf_req_len), *ptr=buf;
 	struct lcp_hdr_t *lcp_hdr=(struct lcp_hdr_t*)ptr;
 	struct lcp_option_t *lopt;
 	int n;
@@ -207,6 +212,8 @@ static int send_conf_req(struct ppp_fsm_t *fsm)
 	lcp_hdr->len=htons((ptr-buf)-2);
 	ppp_chan_send(lcp->ppp,lcp_hdr,ptr-buf);
 
+	_free(buf);
+
 	return 0;
 }
 
@@ -224,7 +231,7 @@ static void send_conf_ack(struct ppp_fsm_t *fsm)
 static void send_conf_nak(struct ppp_fsm_t *fsm)
 {
 	struct ppp_lcp_t *lcp=container_of(fsm,typeof(*lcp),fsm);
-	uint8_t *buf=malloc(lcp->conf_req_len), *ptr=buf;
+	uint8_t *buf=_malloc(lcp->conf_req_len), *ptr=buf;
 	struct lcp_hdr_t *lcp_hdr=(struct lcp_hdr_t*)ptr;
 	struct recv_opt_t *ropt;
 
@@ -256,7 +263,7 @@ static void send_conf_nak(struct ppp_fsm_t *fsm)
 static void send_conf_rej(struct ppp_fsm_t *fsm)
 {
 	struct ppp_lcp_t *lcp=container_of(fsm,typeof(*lcp),fsm);
-	uint8_t *buf=malloc(lcp->ropt_len), *ptr=buf;
+	uint8_t *buf=_malloc(lcp->ropt_len + sizeof(struct lcp_hdr_t)), *ptr=buf;
 	struct lcp_hdr_t *lcp_hdr=(struct lcp_hdr_t*)ptr;
 	struct recv_opt_t *ropt;
 
@@ -285,6 +292,8 @@ static void send_conf_rej(struct ppp_fsm_t *fsm)
 
 	lcp_hdr->len=htons((ptr-buf)-2);
 	ppp_chan_send(lcp->ppp,lcp_hdr,ptr-buf);
+
+	_free(buf);
 }
 
 static int lcp_recv_conf_req(struct ppp_lcp_t *lcp,uint8_t *data,int size)
@@ -300,7 +309,7 @@ static int lcp_recv_conf_req(struct ppp_lcp_t *lcp,uint8_t *data,int size)
 	{
 		hdr=(struct lcp_opt_hdr_t *)data;
 
-		ropt=malloc(sizeof(*ropt));
+		ropt=_malloc(sizeof(*ropt));
 		if (hdr->len>size) ropt->len=size;
 		else ropt->len=hdr->len;
 		ropt->hdr=hdr;
@@ -362,7 +371,7 @@ static void lcp_free_conf_req(struct ppp_lcp_t *lcp)
 	{
 		ropt=list_entry(lcp->ropt_list.next,typeof(*ropt),entry);
 		list_del(&ropt->entry);
-		free(ropt);
+		_free(ropt);
 	}
 }
 
@@ -594,29 +603,35 @@ static void lcp_recv(struct ppp_handler_t*h)
 			if (lcp_recv_conf_ack(lcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN))
 				ppp_terminate(lcp->ppp, 0);
 			else
+				if (lcp->fsm.recv_id!=lcp->fsm.id)
+					break;
 				ppp_fsm_recv_conf_ack(&lcp->fsm);
 			break;
 		case CONFNAK:
 			lcp_recv_conf_nak(lcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
+			if (lcp->fsm.recv_id!=lcp->fsm.id)
+				break;
 			ppp_fsm_recv_conf_rej(&lcp->fsm);
 			break;
 		case CONFREJ:
 			if (lcp_recv_conf_rej(lcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN))
 				ppp_terminate(lcp->ppp, 0);
 			else
+				if (lcp->fsm.recv_id!=lcp->fsm.id)
+					break;
 				ppp_fsm_recv_conf_rej(&lcp->fsm);
 			break;
 		case TERMREQ:
-			term_msg=strndup((char*)(hdr+1),ntohs(hdr->len)-4);
+			term_msg=_strndup((char*)(hdr+1),ntohs(hdr->len)-4);
 			log_ppp_debug("recv [LCP TermReq id=%x \"%s\"]\n",hdr->id,term_msg);
-			free(term_msg);
+			_free(term_msg);
 			ppp_fsm_recv_term_req(&lcp->fsm);
 			ppp_terminate(lcp->ppp, 0);
 			break;
 		case TERMACK:
-			term_msg=strndup((char*)(hdr+1),ntohs(hdr->len)-4);
+			term_msg=_strndup((char*)(hdr+1),ntohs(hdr->len)-4);
 			log_ppp_debug("recv [LCP TermAck id=%x \"%s\"]\n",hdr->id,term_msg);
-			free(term_msg);
+			_free(term_msg);
 			ppp_fsm_recv_term_ack(&lcp->fsm);
 			break;
 		case CODEREJ:
diff --git a/accel-pptpd/ppp/ppp_pd.c b/accel-pptpd/ppp/ppp_pd.c
index fe51bc01..f7702083 100644
--- a/accel-pptpd/ppp/ppp_pd.c
+++ b/accel-pptpd/ppp/ppp_pd.c
@@ -1,5 +1,7 @@
 #include "ppp.h"
 
+#include "memdebug.h"
+
 int ppp_store_pd(struct ppp_t *ppp, pd_key_t key, void *data)
 {
 	struct ppp_pd_t *pd;
diff --git a/accel-pptpd/pwdb.c b/accel-pptpd/pwdb.c
index 24515ec6..4c0ab02e 100644
--- a/accel-pptpd/pwdb.c
+++ b/accel-pptpd/pwdb.c
@@ -4,6 +4,8 @@
 
 #include "pwdb.h"
 
+#include "memdebug.h"
+
 static LIST_HEAD(pwdb_handlers);
 
 int __export pwdb_check(struct ppp_t *ppp, const char *username, int type, ...)
diff --git a/accel-pptpd/radius/acct.c b/accel-pptpd/radius/acct.c
index 72e6df34..6004138d 100644
--- a/accel-pptpd/radius/acct.c
+++ b/accel-pptpd/radius/acct.c
@@ -10,6 +10,8 @@
 #include "log.h"
 #include "radius_p.h"
 
+#include "memdebug.h"
+
 static int req_set_RA(struct rad_req_t *req, const char *secret)
 {
 	MD5_CTX ctx;
@@ -49,6 +51,9 @@ static int rad_acct_read(struct triton_md_handler_t *h)
 {
 	struct rad_req_t *req = container_of(h, typeof(*req), hnd);
 
+	if (req->reply)
+		rad_packet_free(req->reply);
+
 	req->reply = rad_packet_recv(h->fd, NULL);
 	if (!req->reply)
 		return 0;
@@ -63,7 +68,8 @@ static int rad_acct_read(struct triton_md_handler_t *h)
 		req->reply = NULL;
 	} else {
 		req->pack->id++;
-		triton_timer_del(&req->timeout);
+		if (req->timeout.tpd)
+			triton_timer_del(&req->timeout);
 	}
 
 	return 0;
@@ -159,6 +165,12 @@ void rad_acct_stop(struct radius_pd_t *rpd)
 		req_set_stat(rpd->acct_req, rpd->ppp);
 		req_set_RA(rpd->acct_req, conf_acct_secret);
 		/// !!! rad_req_add_val(rpd->acct_req, "Acct-Terminate-Cause", "");
+		
+		if (rpd->acct_req->reply) {
+			rad_packet_free(rpd->acct_req->reply);
+			rpd->acct_req->reply = NULL;
+		}
+
 		for(i = 0; i < conf_max_try; i++) {
 			if (rad_req_send(rpd->acct_req))
 				break;
diff --git a/accel-pptpd/radius/auth.c b/accel-pptpd/radius/auth.c
index 92406b34..46adbd7a 100644
--- a/accel-pptpd/radius/auth.c
+++ b/accel-pptpd/radius/auth.c
@@ -9,6 +9,7 @@
 
 #include "radius_p.h"
 
+#include "memdebug.h"
 
 static uint8_t* encrypt_password(const char *passwd, const char *secret, const uint8_t *RA, int *epasswd_len)
 {
@@ -19,7 +20,7 @@ static uint8_t* encrypt_password(const char *passwd, const char *secret, const u
 	
 	chunk_cnt = (strlen(passwd) - 1) / 16 + 1;
 	
-	epasswd = malloc(chunk_cnt * 16);
+	epasswd = _malloc(chunk_cnt * 16);
 	if (!epasswd) {
 		log_emerg("radius: out of memory\n");
 		return NULL;
@@ -93,11 +94,11 @@ int rad_auth_pap(struct radius_pd_t *rpd, const char *username, va_list args)
 		goto out;
 
 	if (rad_packet_add_octets(req->pack, "User-Password", epasswd, epasswd_len)) {
-		free(epasswd);
+		_free(epasswd);
 		goto out;
 	}
 
-	free(epasswd);
+	_free(epasswd);
 
 	r = rad_auth_send(req);
 	if (r == PWDB_SUCCESS) {
diff --git a/accel-pptpd/radius/dict.c b/accel-pptpd/radius/dict.c
index bd7a4ef3..54cf895e 100644
--- a/accel-pptpd/radius/dict.c
+++ b/accel-pptpd/radius/dict.c
@@ -8,6 +8,8 @@
 #include "radius_p.h"
 #include "log.h"
 
+#include "memdebug.h"
+
 static struct rad_dict_t *dict;
 
 static char *skip_word(char *ptr)
@@ -216,19 +218,19 @@ int rad_dict_load(const char *fname)
 	INIT_LIST_HEAD(&dict->items);
 	INIT_LIST_HEAD(&dict->vendors);
 
-	path = malloc(PATH_MAX);
+	path = _malloc(PATH_MAX);
 	if (!path) {
 		log_emerg("radius: out of memory\n");
 		goto out_free_dict;
 	}
 
-	fname1 = malloc(PATH_MAX);
+	fname1 = _malloc(PATH_MAX);
 	if (!fname1) {
 		log_emerg("radius: out of memory\n");
 		goto out_free_path;
 	}
 
-	buf = malloc(BUF_SIZE);
+	buf = _malloc(BUF_SIZE);
 	if (!buf) {
 		log_emerg("radius: out of memory\n");
 		goto out_free_fname1;
@@ -239,9 +241,9 @@ int rad_dict_load(const char *fname)
 	r = dict_load(fname);
 
 out_free_fname1:
-	free(fname1);
+	_free(fname1);
 out_free_path:
-	free(path);
+	_free(path);
 out_free_dict:
 	if (r)
 		rad_dict_free(dict);
@@ -258,16 +260,16 @@ void rad_dict_free(struct rad_dict_t *dict)
 		while (!list_empty(&attr->values)) {
 			val = list_entry(attr->values.next, typeof(*val), entry);
 			list_del(&val->entry);
-			free((char*)val->name);
+			_free((char*)val->name);
 			if (attr->type == ATTR_TYPE_STRING)
-				free((char*)val->val.string);
-			free(val);
+				_free((char*)val->val.string);
+			_free(val);
 		}
 		list_del(&attr->entry);
-		free((char*)attr->name);
-		free(attr);
+		_free((char*)attr->name);
+		_free(attr);
 	}
-	free(dict);
+	_free(dict);
 }
 
 static struct rad_dict_attr_t *dict_find_attr(struct list_head *items, const char *name)
diff --git a/accel-pptpd/radius/dm_coa.c b/accel-pptpd/radius/dm_coa.c
index f515f873..af7c0fe9 100644
--- a/accel-pptpd/radius/dm_coa.c
+++ b/accel-pptpd/radius/dm_coa.c
@@ -17,6 +17,8 @@
 
 #include "radius_p.h"
 
+#include "memdebug.h"
+
 #define PD_COA_PORT 3799
 
 struct dm_coa_serv_t
diff --git a/accel-pptpd/radius/packet.c b/accel-pptpd/radius/packet.c
index 9e7df01d..8623f523 100644
--- a/accel-pptpd/radius/packet.c
+++ b/accel-pptpd/radius/packet.c
@@ -10,11 +10,13 @@
 
 #include "radius_p.h"
 
+#include "memdebug.h"
+
 struct rad_packet_t *rad_packet_alloc(int code)
 {
 	struct rad_packet_t *pack;
 
-	pack = malloc(sizeof(*pack));
+	pack = _malloc(sizeof(*pack));
 	if (!pack) {
 		log_emerg("radius:packet: out of memory\n");
 		return NULL;
@@ -43,9 +45,9 @@ int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA)
 	uint8_t *ptr;
 
 	if (pack->buf)
-		ptr = realloc(pack->buf, pack->len);
+		ptr = _realloc(pack->buf, pack->len);
 	else
-		ptr = malloc(pack->len);
+		ptr = _malloc(pack->len);
 
 	if (!ptr) {
 		log_emerg("radius:packet: out of memory\n");
@@ -105,7 +107,7 @@ struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr)
 	if (!pack)
 		return NULL;
 
-	pack->buf = malloc(REQ_LENGTH_MAX);
+	pack->buf = _malloc(REQ_LENGTH_MAX);
 	if (!pack->buf) {
 		log_emerg("radius:packet: out of memory\n");
 		goto out_err;
@@ -169,7 +171,7 @@ struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr)
 			vendor = NULL;
 		da = rad_dict_find_attr_id(vendor, id);
 		if (da) {
-			attr = malloc(sizeof(*attr));
+			attr = _malloc(sizeof(*attr));
 			if (!attr) {
 				log_emerg("radius:packet: out of memory\n");
 				goto out_err;
@@ -180,20 +182,20 @@ struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr)
 			attr->len = len;
 			switch (da->type) {
 				case ATTR_TYPE_STRING:
-					attr->val.string = malloc(len+1);
+					attr->val.string = _malloc(len+1);
 					if (!attr->val.string) {
 						log_emerg("radius:packet: out of memory\n");
-						free(attr);
+						_free(attr);
 						goto out_err;
 					}
 					memcpy(attr->val.string, ptr, len);
 					attr->val.string[len] = 0;
 					break;
 				case ATTR_TYPE_OCTETS:
-					attr->val.octets = malloc(len);
+					attr->val.octets = _malloc(len);
 					if (!attr->val.octets) {
 						log_emerg("radius:packet: out of memory\n");
-						free(attr);
+						_free(attr);
 						goto out_err;
 					}
 					memcpy(attr->val.octets, ptr, len);
@@ -225,17 +227,18 @@ void rad_packet_free(struct rad_packet_t *pack)
 	struct rad_attr_t *attr;
 	
 	if (pack->buf)
-		free(pack->buf);
+		_free(pack->buf);
 
 	while(!list_empty(&pack->attrs)) {
 		attr = list_entry(pack->attrs.next, typeof(*attr), entry);
-		if (attr->attr->type == ATTR_TYPE_STRING || attr->attr->type == ATTR_TYPE_OCTETS)
-			free(attr->val.string);
+		log_ppp_debug("free: %s\n", attr->attr->name);
 		list_del(&attr->entry);
-		free(attr);
+		if (attr->attr->type == ATTR_TYPE_STRING || attr->attr->type == ATTR_TYPE_OCTETS)
+			_free(attr->val.string);
+		_free(attr);
 	}
 
-	free(pack);
+	_free(pack);
 }
 
 void rad_packet_print(struct rad_packet_t *pack, void (*print)(const char *fmt, ...))
@@ -323,7 +326,7 @@ int rad_packet_add_int(struct rad_packet_t *pack, const char *name, int val)
 	if (!attr)
 		return -1;
 	
-	ra = malloc(sizeof(*ra));
+	ra = _malloc(sizeof(*ra));
 	if (!ra)
 		return -1;
 
@@ -362,7 +365,7 @@ int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, uint8_t *
 	if (!attr)
 		return -1;
 	
-	ra = malloc(sizeof(*ra));
+	ra = _malloc(sizeof(*ra));
 	if (!ra) {
 		log_emerg("radius: out of memory\n");
 		return -1;
@@ -371,10 +374,10 @@ int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, uint8_t *
 	memset(ra, 0, sizeof(*ra));
 	ra->attr = attr;
 	ra->len = len;
-	ra->val.octets = malloc(len);
+	ra->val.octets = _malloc(len);
 	if (!ra->val.octets) {
 		log_emerg("radius: out of memory\n");
-		free(ra);
+		_free(ra);
 		return -1;
 	}
 	memcpy(ra->val.octets, val, len);
@@ -395,7 +398,7 @@ int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char *
 	if (!attr)
 		return -1;
 	
-	ra = malloc(sizeof(*ra));
+	ra = _malloc(sizeof(*ra));
 	if (!ra) {
 		log_emerg("radius: out of memory\n");
 		return -1;
@@ -404,10 +407,10 @@ int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char *
 	memset(ra, 0, sizeof(*ra));
 	ra->attr = attr;
 	ra->len = len;
-	ra->val.string = malloc(len+1);
+	ra->val.string = _malloc(len+1);
 	if (!ra->val.string) {
 		log_emerg("radius: out of memory\n");
-		free(ra);
+		_free(ra);
 		return -1;
 	}
 	memcpy(ra->val.string, val, len);
@@ -430,7 +433,7 @@ int rad_packet_change_str(struct rad_packet_t *pack, const char *name, const cha
 		if (pack->len - ra->len + len >= REQ_LENGTH_MAX)
 			return -1;
 
-		ra->val.string = realloc(ra->val.string, len + 1);
+		ra->val.string = _realloc(ra->val.string, len + 1);
 		if (!ra->val.string) {
 			log_emerg("radius: out of memory\n");
 			return -1;
@@ -463,7 +466,7 @@ int rad_packet_add_val(struct rad_packet_t *pack, const char *name, const char *
 	if (!v)
 		return -1;
 	
-	ra = malloc(sizeof(*ra));
+	ra = _malloc(sizeof(*ra));
 	if (!ra)
 		return -1;
 
@@ -547,7 +550,7 @@ int rad_packet_add_vendor_octets(struct rad_packet_t *pack, const char *vendor_n
 	if (!attr)
 		return -1;
 	
-	ra = malloc(sizeof(*ra));
+	ra = _malloc(sizeof(*ra));
 	if (!ra) {
 		log_emerg("radius: out of memory\n");
 		return -1;
@@ -557,10 +560,10 @@ int rad_packet_add_vendor_octets(struct rad_packet_t *pack, const char *vendor_n
 	ra->vendor = vendor;
 	ra->attr = attr;
 	ra->len = len;
-	ra->val.octets = malloc(len);
+	ra->val.octets = _malloc(len);
 	if (!ra->val.octets) {
 		log_emerg("radius: out of memory\n");
-		free(ra);
+		_free(ra);
 		return -1;
 	}
 	memcpy(ra->val.octets, val, len);
diff --git a/accel-pptpd/radius/radius.c b/accel-pptpd/radius/radius.c
index 04e41332..8a5e7b85 100644
--- a/accel-pptpd/radius/radius.c
+++ b/accel-pptpd/radius/radius.c
@@ -13,6 +13,8 @@
 
 #include "radius_p.h"
 
+#include "memdebug.h"
+
 #define CHAP_MD5 5
 #define MSCHAP_V1 0x80
 #define MSCHAP_V2 0x81
@@ -102,7 +104,7 @@ static struct ipdb_item_t *get_ip(struct ppp_t *ppp)
 
 static void ppp_starting(struct ppp_t *ppp)
 {
-	struct radius_pd_t *pd = malloc(sizeof(*pd));
+	struct radius_pd_t *pd = _malloc(sizeof(*pd));
 
 	memset(pd, 0, sizeof(*pd));
 	pd->pd.key = &pd_key;
@@ -138,11 +140,14 @@ static void ppp_finished(struct ppp_t *ppp)
 	pthread_mutex_unlock(&rpd->lock);
 	pthread_rwlock_unlock(&sessions_lock);
 
+	if (rpd->acct_req)
+		rad_req_free(rpd->acct_req);
+
 	if (rpd->dm_coa_req)
 		rad_packet_free(rpd->dm_coa_req);
 
 	list_del(&rpd->pd.entry);
-	free(rpd);
+	_free(rpd);
 }
 
 struct radius_pd_t *find_pd(struct ppp_t *ppp)
@@ -242,7 +247,7 @@ static struct pwdb_t pwdb = {
 
 static int parse_server(const char *opt, char **name, int *port, char **secret)
 {
-	char *str = strdup(opt);
+	char *str = _strdup(opt);
 	char *p1, *p2;
 
 	p1 = strstr(str, ":");
diff --git a/accel-pptpd/radius/req.c b/accel-pptpd/radius/req.c
index a9192bb4..ac41f199 100644
--- a/accel-pptpd/radius/req.c
+++ b/accel-pptpd/radius/req.c
@@ -11,6 +11,8 @@
 #include "log.h"
 #include "radius_p.h"
 
+#include "memdebug.h"
+
 static int urandom_fd;
 
 static int rad_req_read(struct triton_md_handler_t *h);
@@ -18,7 +20,7 @@ static void rad_req_timeout(struct triton_timer_t *t);
 
 struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *username)
 {
-	struct rad_req_t *req = malloc(sizeof(*req));
+	struct rad_req_t *req = _malloc(sizeof(*req));
 
 	if (!req)
 		return NULL;
@@ -101,7 +103,7 @@ void rad_req_free(struct rad_req_t *req)
 		rad_packet_free(req->pack);
 	if (req->reply)
 		rad_packet_free(req->reply);
-	free(req);
+	_free(req);
 }
 
 static int make_socket(struct rad_req_t *req)
diff --git a/accel-pptpd/sigchld.c b/accel-pptpd/sigchld.c
index 478f44c7..3843e4f7 100644
--- a/accel-pptpd/sigchld.c
+++ b/accel-pptpd/sigchld.c
@@ -11,32 +11,57 @@
 
 #include "sigchld.h"
 
+#include "memdebug.h"
+
 static LIST_HEAD(handlers);
-static int refs;
-static int sleeping = 1;
+static int lock_refs;
 static pthread_mutex_t handlers_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t refs_lock = PTHREAD_MUTEX_INITIALIZER;
-
-static struct triton_context_t sigchld_ctx;
+static pthread_cond_t refs_cond = PTHREAD_COND_INITIALIZER;
+static pthread_t sigchld_thr;
 
-static void sigchld_handler(void *arg)
+static void* sigchld_thread(void *arg)
 {
+	sigset_t set;
 	struct sigchld_handler_t *h, *h0;
 	pid_t pid;
-	int status;
+	int status, sig;
+
+	sigfillset(&set);
+	pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+	sigemptyset(&set);
+	sigaddset(&set, SIGUSR1);
+	sigaddset(&set, SIGQUIT);
+	sigaddset(&set, SIGSEGV);
+	sigaddset(&set, SIGFPE);
+	sigaddset(&set, SIGILL);
+	sigaddset(&set, SIGBUS);
+	sigaddset(&set, SIGCHLD);
+	pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+
+	sigemptyset(&set);
+	sigaddset(&set, SIGCHLD);
+	sigaddset(&set, SIGQUIT);
 
 	while (1) {	
-		pid = waitpid(0, &status, WNOHANG);
-		pthread_mutex_lock(&handlers_lock);
-		if (pid == 0 || (pid == -1 && errno == ECHILD)) {
-			sleeping = 1;
-			pthread_mutex_unlock(&handlers_lock);
-			return;
-		} else if (pid < 0) {
-			pthread_mutex_unlock(&handlers_lock);
+		pid = waitpid(0, &status, 0);
+		if (pid < 0) {
+			if (errno == EINTR)
+				continue;
+			if (errno == ECHILD) {
+				sigwait(&set, &sig);
+				if (sig == SIGQUIT)
+					break;
+				continue;
+			}
 			log_error("sigchld: waitpid: %s\n", strerror(errno));
-			return;
+			continue;
 		}
+
+		pthread_mutex_lock(&handlers_lock);
+		while (lock_refs)
+			pthread_cond_wait(&refs_cond, &handlers_lock);
+
 		h0 = NULL;
 		list_for_each_entry(h, &handlers, entry) {
 			if (h->pid == pid) {
@@ -53,6 +78,8 @@ static void sigchld_handler(void *arg)
 			pthread_mutex_unlock(&h0->lock);
 		}
 	}
+
+	return NULL;
 }
 
 void __export sigchld_register_handler(struct sigchld_handler_t *h)
@@ -78,57 +105,21 @@ void __export sigchld_unregister_handler(struct sigchld_handler_t *h)
 
 void __export sigchld_lock()
 {
-	sigset_t set;
-
-	pthread_mutex_lock(&refs_lock);
-	if (refs == 0) {
-		sigemptyset(&set);
-		sigaddset(&set, SIGCHLD);
-		sigprocmask(SIG_BLOCK, &set, NULL);
-	}
-	++refs;
-	pthread_mutex_unlock(&refs_lock);
+	pthread_mutex_lock(&handlers_lock);
+	++lock_refs;
+	pthread_mutex_unlock(&handlers_lock);
 }
 
 void __export sigchld_unlock()
 {
-	sigset_t set;
-
-	pthread_mutex_lock(&refs_lock);
-	if (refs == 1) {
-		sigemptyset(&set);
-		sigaddset(&set, SIGCHLD);
-		sigprocmask(SIG_UNBLOCK, &set, NULL);
-	}
-	--refs;
-	pthread_mutex_unlock(&refs_lock);
-
-}
-
-static void sigchld(int num)
-{
-	int s;
-	
 	pthread_mutex_lock(&handlers_lock);
-	s = sleeping;
-	sleeping = 0;
+	if (--lock_refs == 0)
+		pthread_cond_signal(&refs_cond);
 	pthread_mutex_unlock(&handlers_lock);
-
-	if (s)
-		triton_context_call(&sigchld_ctx, sigchld_handler, NULL);
 }
 
 static void __init init(void)
 {
-	struct sigaction sa_sigchld = {
-		.sa_handler = sigchld,
-		.sa_flags = SA_NOCLDSTOP,
-	};
-
-	if (sigaction(SIGCHLD, &sa_sigchld, NULL)) {
-		fprintf(stderr, "sigchld: sigaction: %s\n", strerror(errno));
-		return;
-	}
-
-	triton_context_register(&sigchld_ctx, NULL);
+	if (pthread_create(&sigchld_thr, NULL, sigchld_thread, NULL))
+		fprintf(stderr, "sigchld: pthread_create: %s\n", strerror(errno));
 }
diff --git a/accel-pptpd/triton/conf_file.c b/accel-pptpd/triton/conf_file.c
index c6ba7453..6eb2e7a8 100644
--- a/accel-pptpd/triton/conf_file.c
+++ b/accel-pptpd/triton/conf_file.c
@@ -5,6 +5,8 @@
 
 #include "triton_p.h"
 
+#include "memdebug.h"
+
 struct sect_t
 {
 	struct list_head entry;
@@ -35,15 +37,14 @@ int conf_load(const char *fname)
 		return -1;
 	}
 	
-	buf = malloc(1024);
-	path0 = malloc(4096);
-	path = malloc(4096);
+	buf = _malloc(1024);
+	path0 = _malloc(4096);
+	path = _malloc(4096);
 	
 	getcwd(path0, 1024);
 	
 	while(!feof(f)) {
-		buf = fgets(buf, 1024, f);
-		if (!buf)
+		if (!fgets(buf, 1024, f))
 			break;
 		++cur_line;
 		if (buf[strlen(buf) - 1] == '\n')
@@ -103,9 +104,9 @@ int conf_load(const char *fname)
 		sect_add_item(cur_sect, str, str2);
 	}
 	
-	free(buf);
-	free(path);
-	free(path0);
+	_free(buf);
+	_free(path);
+	_free(path0);
 	fclose(f);
 
 	return 0;
@@ -132,9 +133,9 @@ static struct conf_sect_t *find_sect(const char *name)
 
 static struct conf_sect_t *create_sect(const char *name)
 {
-	struct sect_t *s = malloc(sizeof(struct sect_t));
+	struct sect_t *s = _malloc(sizeof(struct sect_t));
 	
-	s->sect = malloc(sizeof(struct conf_sect_t));
+	s->sect = _malloc(sizeof(struct conf_sect_t));
 	s->sect->name = (char*)strdup(name);
 	INIT_LIST_HEAD(&s->sect->items);
 	
@@ -145,10 +146,10 @@ static struct conf_sect_t *create_sect(const char *name)
 
 static void sect_add_item(struct conf_sect_t *sect, const char *name, const char *val)
 {
-	struct conf_option_t *opt = malloc(sizeof(struct conf_option_t));
+	struct conf_option_t *opt = _malloc(sizeof(struct conf_option_t));
 	
-	opt->name = strdup(name);
-	opt->val = val ? strdup(val) : NULL;
+	opt->name = _strdup(name);
+	opt->val = val ? _strdup(val) : NULL;
 	
 	list_add_tail(&opt->entry, &sect->items);
 }
diff --git a/accel-pptpd/triton/event.c b/accel-pptpd/triton/event.c
index 442543f2..d45eca01 100644
--- a/accel-pptpd/triton/event.c
+++ b/accel-pptpd/triton/event.c
@@ -4,6 +4,8 @@
 
 #include "triton_p.h"
 
+#include "memdebug.h"
+
 static int max_events = 1024;
 static struct _triton_event_t **events;
 
@@ -76,7 +78,7 @@ int __export triton_event_register_handler(int ev_id, triton_event_func func)
 				h->func = NULL;
 			else {
 				list_del(&h->entry);
-				free(h);
+				_free(h);
 			}
 			return 0;
 		}
diff --git a/accel-pptpd/triton/loader.c b/accel-pptpd/triton/loader.c
index 24d1cbcb..a8b9c500 100644
--- a/accel-pptpd/triton/loader.c
+++ b/accel-pptpd/triton/loader.c
@@ -7,6 +7,8 @@
 
 #include "triton_p.h"
 
+#include "memdebug.h"
+
 int load_modules(const char *name)
 {
 	struct conf_sect_t *sect;
@@ -40,7 +42,7 @@ int load_modules(const char *name)
 
 out_err:
 	chdir(cwd);
-	free(cwd);
+	_free(cwd);
 	return -1;
 }
 
diff --git a/accel-pptpd/triton/log.c b/accel-pptpd/triton/log.c
index 4504db4f..7bb55598 100644
--- a/accel-pptpd/triton/log.c
+++ b/accel-pptpd/triton/log.c
@@ -3,6 +3,8 @@
 
 #include "triton_p.h"
 
+#include "memdebug.h"
+
 static FILE *f_error;
 static FILE *f_debug;
 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
diff --git a/accel-pptpd/triton/md.c b/accel-pptpd/triton/md.c
index 05d814cc..06b2b30b 100644
--- a/accel-pptpd/triton/md.c
+++ b/accel-pptpd/triton/md.c
@@ -8,6 +8,8 @@
 
 #include "triton_p.h"
 
+#include "memdebug.h"
+
 extern int max_events;
 
 static int epoll_fd;
@@ -26,7 +28,7 @@ int md_init(void)
 		return -1;
 	}
 
-	epoll_events = malloc(max_events * sizeof(struct epoll_event));
+	epoll_events = _malloc(max_events * sizeof(struct epoll_event));
 	if (!epoll_events) {
 		fprintf(stderr,"md:cann't allocate memory\n");
 		return -1;
@@ -54,6 +56,20 @@ static void *md_thread(void *arg)
 {
 	int i,n,r;
 	struct _triton_md_handler_t *h;
+	sigset_t set;
+
+	sigfillset(&set);
+	pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+	sigemptyset(&set);
+	sigaddset(&set, SIGQUIT);
+	sigaddset(&set, SIGSEGV);
+	sigaddset(&set, SIGFPE);
+	sigaddset(&set, SIGILL);
+	sigaddset(&set, SIGBUS);
+	sigdelset(&set, 35);
+	sigdelset(&set, 36);
+	pthread_sigmask(SIG_UNBLOCK, &set, NULL);
 
 	while(1) {
 		n = epoll_wait(epoll_fd, epoll_events, max_events, -1);
@@ -100,6 +116,8 @@ void __export triton_md_register_handler(struct triton_context_t *ctx, struct tr
 	spin_lock(&h->ctx->lock);
 	list_add_tail(&h->entry, &h->ctx->handlers);
 	spin_unlock(&h->ctx->lock);
+
+	__sync_fetch_and_add(&triton_stat.md_handler_count, 1);
 }
 void __export triton_md_unregister_handler(struct triton_md_handler_t *ud)
 {
@@ -113,6 +131,8 @@ void __export triton_md_unregister_handler(struct triton_md_handler_t *ud)
 	spin_unlock(&h->ctx->lock);
 	sched_yield();
 	mempool_free(h);
+	
+	__sync_fetch_and_sub(&triton_stat.md_handler_count, 1);
 }
 int __export triton_md_enable_handler(struct triton_md_handler_t *ud, int mode)
 {
diff --git a/accel-pptpd/triton/mempool.c b/accel-pptpd/triton/mempool.c
index 6d9172a1..34739b43 100644
--- a/accel-pptpd/triton/mempool.c
+++ b/accel-pptpd/triton/mempool.c
@@ -1,11 +1,15 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <signal.h>
 
 #include "triton_p.h"
 
+#include "memdebug.h"
+
 struct _mempool_t
 {
+	struct list_head entry;
 	int size;
 	struct list_head items;
 	spinlock_t lock;
@@ -20,9 +24,12 @@ struct _item_t
 	char ptr[0];
 };
 
+static LIST_HEAD(pools);
+static spinlock_t pools_lock = SPINLOCK_INITIALIZER;
+
 __export mempool_t *mempool_create(int size)
 {
-	struct _mempool_t *p = malloc(sizeof(*p));
+	struct _mempool_t *p = _malloc(sizeof(*p));
 
 	memset(p, 0, sizeof(*p));
 	INIT_LIST_HEAD(&p->items);
@@ -30,35 +37,82 @@ __export mempool_t *mempool_create(int size)
 	p->size = size;
 	p->magic = (uint64_t)random() * (uint64_t)random();
 
+	spin_lock(&pools_lock);
+	list_add_tail(&p->entry, &pools);
+	spin_unlock(&pools_lock);
+
 	return (mempool_t *)p;
 }
 
+#ifndef MEMDEBUG
 __export void *mempool_alloc(mempool_t *pool)
 {
 	struct _mempool_t *p = (struct _mempool_t *)pool;
 	struct _item_t *it;
+	uint32_t size = sizeof(*it) + p->size;
+
+	spin_lock(&p->lock);
+	if (!list_empty(&p->items)) {
+		it = list_entry(p->items.next, typeof(*it), entry);
+		list_del(&it->entry);
+		spin_unlock(&p->lock);
+		
+		__sync_fetch_and_sub(&triton_stat.mempool_available, size);
+		
+		return it->ptr;
+	}
+	spin_unlock(&p->lock);
+
+	it = _malloc(size);
+	if (!it) {
+		triton_log_error("mempool: out of memory\n");
+		return NULL;
+	}
+	it->owner = p;
+	it->magic = p->magic;
+
+	__sync_fetch_and_add(&triton_stat.mempool_allocated, size);
+
+	return it->ptr;
+}
+#endif
+
+void __export *mempool_alloc_md(mempool_t *pool, const char *fname, int line)
+{
+	struct _mempool_t *p = (struct _mempool_t *)pool;
+	struct _item_t *it;
+	uint32_t size = sizeof(*it) + p->size;
 
 	spin_lock(&p->lock);
 	if (!list_empty(&p->items)) {
 		it = list_entry(p->items.next, typeof(*it), entry);
 		list_del(&it->entry);
 		spin_unlock(&p->lock);
+		
+		__sync_fetch_and_sub(&triton_stat.mempool_available, size);
+		
 		return it->ptr;
 	}
 	spin_unlock(&p->lock);
-	it = malloc(sizeof(*it) + p->size);
+
+	it = md_malloc(size, fname, line);
 	if (!it) {
 		triton_log_error("mempool: out of memory\n");
 		return NULL;
 	}
 	it->owner = p;
 	it->magic = p->magic;
+
+	__sync_fetch_and_add(&triton_stat.mempool_allocated, size);
+
 	return it->ptr;
 }
 
+
 __export void mempool_free(void *ptr)
 {
 	struct _item_t *it = container_of(ptr, typeof(*it), ptr);
+	uint32_t size = sizeof(*it) + it->owner->size;
 
 	if (it->magic != it->owner->magic) {
 		triton_log_error("mempool: memory corruption detected");
@@ -67,5 +121,36 @@ __export void mempool_free(void *ptr)
 	spin_lock(&it->owner->lock);
 	list_add_tail(&it->entry,&it->owner->items);
 	spin_unlock(&it->owner->lock);
+
+	__sync_fetch_and_add(&triton_stat.mempool_available, size);
+}
+
+void sigclean(int num)
+{
+	struct _mempool_t *p;
+	struct _item_t *it;
+	uint32_t size;
+
+	triton_log_error("mempool: clean\n");
+
+	spin_lock(&pools_lock);
+	list_for_each_entry(p, &pools, entry) {
+		size = sizeof(*it) + p->size;
+		spin_lock(&p->lock);
+		while (!list_empty(&p->items)) {
+			it = list_entry(p->items.next, typeof(*it), entry);
+			list_del(&it->entry);
+			_free(it);
+			__sync_fetch_and_sub(&triton_stat.mempool_allocated, size);
+			__sync_fetch_and_sub(&triton_stat.mempool_available, size);
+		}
+		spin_unlock(&p->lock);
+	}
+	spin_unlock(&pools_lock);
+}
+
+static void __init init(void)
+{
+	signal(35, sigclean);
 }
 
diff --git a/accel-pptpd/triton/mempool.h b/accel-pptpd/triton/mempool.h
index e8bcaf6a..d3539215 100644
--- a/accel-pptpd/triton/mempool.h
+++ b/accel-pptpd/triton/mempool.h
@@ -1,10 +1,25 @@
 #ifndef __TRITON_MEMPOOL_H
 #define __TRITON_MEMPOOL_H
 
+#include <stdint.h>
+
+struct mempool_stat_t
+{
+	uint32_t allocated;	
+	uint32_t available;
+};
+
 typedef void * mempool_t;
 mempool_t *mempool_create(int size);
-void *mempool_alloc(mempool_t*);
 void mempool_free(void*);
+struct mempool_stat_t mempool_get_stat(void);
+
+#ifdef MEMDEBUG
+void *mempool_alloc_md(mempool_t*, const char *fname, int line);
+#define mempool_alloc(pool) mempool_alloc_md(pool, __FILE__, __LINE__)
+#else
+void *mempool_alloc(mempool_t*);
+#endif
 
 #endif
 
diff --git a/accel-pptpd/triton/options.c b/accel-pptpd/triton/options.c
index ba7fc564..a5214e21 100644
--- a/accel-pptpd/triton/options.c
+++ b/accel-pptpd/triton/options.c
@@ -4,6 +4,8 @@
 #include "triton_p.h"
 #include "conf_file.h"
 
+#include "memdebug.h"
+
 static struct conf_file_sect_t *sect=NULL;
 
 static const char* find_option(const char *name)
diff --git a/accel-pptpd/triton/timer.c b/accel-pptpd/triton/timer.c
index d2249786..53abd3b9 100644
--- a/accel-pptpd/triton/timer.c
+++ b/accel-pptpd/triton/timer.c
@@ -9,6 +9,8 @@
 
 #include "triton_p.h"
 
+#include "memdebug.h"
+
 extern int max_events;
 static int epoll_fd;
 static struct epoll_event *epoll_events;
@@ -26,7 +28,7 @@ int timer_init(void)
 		return -1;
 	}
 
-	epoll_events = malloc(max_events * sizeof(struct epoll_event));
+	epoll_events = _malloc(max_events * sizeof(struct epoll_event));
 	if (!epoll_events) {
 		fprintf(stderr,"timer:cann't allocate memory\n");
 		return -1;
@@ -55,7 +57,19 @@ void *timer_thread(void *arg)
 {
 	int i,n,r;
 	struct _triton_timer_t *t;
-	
+	sigset_t set;
+
+	sigfillset(&set);
+	pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+	sigemptyset(&set);
+	sigaddset(&set, SIGQUIT);
+	sigaddset(&set, SIGSEGV);
+	sigaddset(&set, SIGFPE);
+	sigaddset(&set, SIGILL);
+	sigaddset(&set, SIGBUS);
+	pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+
 	while(1) {
 		n = epoll_wait(epoll_fd, epoll_events, max_events, -1);
 		if (n < 0) {
@@ -129,6 +143,8 @@ int __export triton_timer_add(struct triton_context_t *ctx, struct triton_timer_
 		return -1;
 	}
 
+	__sync_fetch_and_add(&triton_stat.timer_count, 1);
+	
 	return 0;
 }
 int __export triton_timer_mod(struct triton_timer_t *ud,int abs_time)
@@ -165,5 +181,7 @@ void __export triton_timer_del(struct triton_timer_t *ud)
 	sched_yield();
 	mempool_free(t);
 	ud->tpd = NULL;
+	
+	__sync_fetch_and_sub(&triton_stat.timer_count, 1);
 }
 
diff --git a/accel-pptpd/triton/triton.c b/accel-pptpd/triton/triton.c
index 9b9fd753..95930647 100644
--- a/accel-pptpd/triton/triton.c
+++ b/accel-pptpd/triton/triton.c
@@ -6,6 +6,7 @@
 #include <unistd.h>
 
 #include "triton_p.h"
+#include "memdebug.h"
 
 int thread_count = 1;
 int max_events = 64;
@@ -25,6 +26,8 @@ static int terminate;
 static mempool_t *ctx_pool;
 static mempool_t *call_pool;
 
+__export struct triton_stat_t triton_stat;
+
 void triton_thread_wakeup(struct _triton_thread_t *thread)
 {
 	pthread_kill(thread->thread, SIGUSR1);
@@ -33,25 +36,21 @@ void triton_thread_wakeup(struct _triton_thread_t *thread)
 static void* triton_thread(struct _triton_thread_t *thread)
 {
 	sigset_t set;
-	int sig;
 
 	sigfillset(&set);
-	pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-	sigdelset(&set, SIGUSR1);
-	sigdelset(&set, SIGQUIT);
 	sigdelset(&set, SIGSEGV);
 	sigdelset(&set, SIGFPE);
 	sigdelset(&set, SIGILL);
 	sigdelset(&set, SIGBUS);
-	pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+	pthread_sigmask(SIG_SETMASK, &set, NULL);
 
-	sigemptyset(&set);
-	sigaddset(&set, SIGUSR1);
-	sigaddset(&set, SIGQUIT);
+	sigdelset(&set, SIGUSR1);
+	sigdelset(&set, SIGQUIT);
 
 	while (1) {
-		sigwait(&set, &sig);
+		__sync_fetch_and_sub(&triton_stat.thread_active, 1);
+		sigsuspend(&set);
+		__sync_fetch_and_add(&triton_stat.thread_active, 1);
 
 cont:
 		if (thread->ctx->ud->before_switch)
@@ -72,6 +71,7 @@ cont:
 			thread->ctx->thread = thread;
 			thread->ctx->queued = 0;
 			spin_unlock(&thread->ctx->lock);
+			__sync_fetch_and_sub(&triton_stat.context_pending, 1);
 			goto cont;
 		} else {
 			if (!terminate)
@@ -142,7 +142,7 @@ static void ctx_thread(struct _triton_context_t *ctx)
 
 struct _triton_thread_t *create_thread()
 {
-	struct _triton_thread_t *thread = malloc(sizeof(*thread));
+	struct _triton_thread_t *thread = _malloc(sizeof(*thread));
 	if (!thread)
 		return NULL;
 
@@ -152,6 +152,9 @@ struct _triton_thread_t *create_thread()
 		return NULL;
 	}
 
+	triton_stat.thread_count++;
+	triton_stat.thread_active++;
+
 	return thread;
 }
 
@@ -165,6 +168,7 @@ int triton_queue_ctx(struct _triton_context_t *ctx)
 		list_add_tail(&ctx->entry2, &ctx_queue);
 		spin_unlock(&threads_lock);
 		ctx->queued = 1;
+		__sync_fetch_and_add(&triton_stat.context_pending, 1);
 		return 0;
 	}
 
@@ -195,15 +199,15 @@ int __export triton_context_register(struct triton_context_t *ud, void *bf_arg)
 
 	if (getcontext(&ctx->uctx)) {
 		triton_log_error("getcontext: %s\n", strerror(errno));
-		free(ctx);
+		_free(ctx);
 		return -1;
 	}
 
 	ctx->uctx.uc_stack.ss_size = CTX_STACK_SIZE;
-	ctx->uctx.uc_stack.ss_sp = malloc(CTX_STACK_SIZE);
+	ctx->uctx.uc_stack.ss_sp = _malloc(CTX_STACK_SIZE);
 	if (!ctx->uctx.uc_stack.ss_sp) {
 		triton_log_error("out of memory\n");
-		free(ctx);
+		_free(ctx);
 		return -1;
 	}
 	makecontext(&ctx->uctx, (void (*)())ctx_thread, 1, ctx);
@@ -214,12 +218,21 @@ int __export triton_context_register(struct triton_context_t *ud, void *bf_arg)
 	list_add_tail(&ctx->entry, &ctx_list);
 	spin_unlock(&ctx_list_lock);
 
+	__sync_fetch_and_add(&triton_stat.context_count, 1);
+
 	return 0;
 }
 
 void __export triton_context_unregister(struct triton_context_t *ud)
 {
 	struct _triton_context_t *ctx = (struct _triton_context_t *)ud->tpd;
+	struct _triton_ctx_call_t *call;
+
+	while (!list_empty(&ctx->pending_calls)) {
+		call = list_entry(ctx->pending_calls.next, typeof(*call), entry);
+		list_del(&call->entry);
+		mempool_free(call);
+	}
 
 	if (!list_empty(&ctx->handlers)) {
 		triton_log_error("BUG:ctx:triton_unregister_ctx: handlers is not empty");
@@ -246,10 +259,14 @@ void __export triton_context_unregister(struct triton_context_t *ud)
 		abort();
 	}
 
+	_free(ctx->uctx.uc_stack.ss_sp);
+
 	ctx->need_free = 1;
 	spin_lock(&ctx_list_lock);
 	list_del(&ctx->entry);
 	spin_unlock(&ctx_list_lock);
+	
+	__sync_fetch_and_sub(&triton_stat.context_count, 1);
 }
 void __export triton_context_schedule(struct triton_context_t *ud)
 {
@@ -263,6 +280,8 @@ void __export triton_context_schedule(struct triton_context_t *ud)
 
 	if (swapcontext(&ctx->uctx, uctx))
 		triton_log_error("swaswpntext: %s\n", strerror(errno));
+	
+	__sync_fetch_and_add(&triton_stat.context_sleeping, 1);
 }
 
 void __export triton_context_wakeup(struct triton_context_t *ud)
@@ -277,6 +296,8 @@ void __export triton_context_wakeup(struct triton_context_t *ud)
 
 	if (r)
 		triton_thread_wakeup(ctx->thread);
+	
+	__sync_fetch_and_sub(&triton_stat.context_sleeping, 1);
 }
 
 int __export triton_context_call(struct triton_context_t *ud, void (*func)(void *), void *arg)
@@ -302,12 +323,12 @@ int __export triton_context_call(struct triton_context_t *ud, void (*func)(void
 	return 0;
 }
 
-int __export triton_init(const char *conf_file, const char *mod_sect)
+int __export triton_init(const char *conf_file)
 {
 	ctx_pool = mempool_create(sizeof(struct _triton_context_t));
 	call_pool = mempool_create(sizeof(struct _triton_ctx_call_t));
 
-	default_ctx = malloc(sizeof(*default_ctx));
+	default_ctx = _malloc(sizeof(*default_ctx));
 	if (!default_ctx) {
 		fprintf(stderr,"cann't allocate memory\n");
 		return -1;
@@ -329,9 +350,14 @@ int __export triton_init(const char *conf_file, const char *mod_sect)
 	if (event_init())
 		return -1;
 
+	return 0;
+}
+
+int __export triton_load_modules(const char *mod_sect)
+{
 	if (load_modules(mod_sect))
 		return -1;
-
+	
 	return 0;
 }
 
diff --git a/accel-pptpd/triton/triton.h b/accel-pptpd/triton/triton.h
index 8510a512..c3c9d2a9 100644
--- a/accel-pptpd/triton/triton.h
+++ b/accel-pptpd/triton/triton.h
@@ -2,6 +2,7 @@
 #define TRITON_H
 
 #include <sys/time.h>
+#include <stdint.h>
 
 #include "list.h"
 
@@ -49,6 +50,22 @@ struct conf_sect_t
 	struct list_head items;
 };
 
+struct triton_stat_t
+{
+	uint32_t mempool_allocated;
+	uint32_t mempool_available;
+	uint32_t thread_count;
+	uint32_t thread_active;
+	uint32_t context_count;
+	uint32_t context_sleeping;
+	uint32_t context_pending;
+	uint32_t md_handler_count;
+	uint32_t md_handler_pending;
+	uint32_t timer_count;
+	uint32_t timer_pending;
+};
+
+extern struct triton_stat_t triton_stat;
 int triton_context_register(struct triton_context_t *, void *arg);
 void triton_context_unregister(struct triton_context_t *);
 void triton_context_schedule(struct triton_context_t *);
@@ -82,7 +99,8 @@ char *conf_get_opt(const char *sect, const char *name);
 #define TRITON_ERR_NOMSG  -6
 #define TRITON_ERR_BUSY   -5
 
-int triton_init(const char *conf_file, const char *mod_sect);
+int triton_init(const char *conf_file);
+int triton_load_modules(const char *md_sect);
 void triton_run(void);
 void triton_terminate(void);
 
diff --git a/accel-pptpd/utils.c b/accel-pptpd/utils.c
index fd59b005..491e6507 100644
--- a/accel-pptpd/utils.c
+++ b/accel-pptpd/utils.c
@@ -3,6 +3,7 @@
 #include "triton.h"
 #include "utils.h"
 
+#include "memdebug.h"
 
 void __export u_inet_ntoa(in_addr_t addr, char *str)
 {
-- 
cgit v1.2.3