diff --git a/cfg.lex b/cfg.lex
index 20979abe285..04058d789c1 100644
--- a/cfg.lex
+++ b/cfg.lex
@@ -212,6 +212,8 @@ LOGSTDERROR	log_stderror
 LOGFACILITY	log_facility
 LOGNAME		log_name
 LISTEN		listen
+LISTEN_SCTP_SEC		listen_sctp_sec
+SCTP_SEND_TTL_MS	sctp_send_ttl_ms
 MEMGROUP	mem-group
 ALIAS		alias
 AUTO_ALIASES	auto_aliases
@@ -417,6 +419,8 @@ SPACE		[ ]
 <INITIAL>{LOGFACILITY}	{ yylval.strval=yytext; return LOGFACILITY; }
 <INITIAL>{LOGNAME}	{ yylval.strval=yytext; return LOGNAME; }
 <INITIAL>{LISTEN}	{ count(); yylval.strval=yytext; return LISTEN; }
+<INITIAL>{LISTEN_SCTP_SEC}	{ count(); yylval.strval=yytext; return LISTEN_SCTP_SEC; }
+<INITIAL>{SCTP_SEND_TTL_MS}	{ count(); yylval.strval=yytext; return SCTP_SEND_TTL_MS; }
 <INITIAL>{MEMGROUP}	{ count(); yylval.strval=yytext; return MEMGROUP; }
 <INITIAL>{ALIAS}	{ count(); yylval.strval=yytext; return ALIAS; }
 <INITIAL>{AUTO_ALIASES}	{ count(); yylval.strval=yytext; return AUTO_ALIASES; }
diff --git a/cfg.y b/cfg.y
index e48baa808b5..30cd80e1513 100644
--- a/cfg.y
+++ b/cfg.y
@@ -341,6 +341,8 @@ extern int cfg_parse_only_routes;
 %token LOGNAME
 %token AVP_ALIASES
 %token LISTEN
+%token LISTEN_SCTP_SEC
+%token SCTP_SEND_TTL_MS
 %token MEMGROUP
 %token ALIAS
 %token AUTO_ALIASES
@@ -1137,6 +1139,17 @@ assign_stm: DEBUG EQUAL snumber
 		| LISTEN EQUAL  error { yyerror("ip address or hostname "
 						"expected (use quotes if the hostname includes"
 						" config keywords)"); }
+		| LISTEN_SCTP_SEC EQUAL  ip {
+							if (init_su(&sctp_sec_addr, $3, 0)!=0){
+								LM_CRIT("cfg. parser: failed"
+										" to add secondary sctp address\n");
+								break;
+							}
+						}
+		| LISTEN_SCTP_SEC EQUAL  error { yyerror("ip address expected"); }
+		| SCTP_SEND_TTL_MS EQUAL NUMBER { IFOR();
+								sctp_send_ttl_ms=$3; }
+		| SCTP_SEND_TTL_MS EQUAL error { yyerror("number expected"); }
 		| MEMGROUP EQUAL STRING COLON multi_string { IFOR();
 							/* convert STIRNG ($3) to an ID */
 							/* update the memstats type for each module */
diff --git a/globals.h b/globals.h
index 118537c669d..c84690aa54e 100644
--- a/globals.h
+++ b/globals.h
@@ -150,4 +150,7 @@ extern int disable_503_translation;
 
 extern int enable_asserts;
 extern int abort_on_assert;
+
+extern union sockaddr_union sctp_sec_addr;
+extern uint32_t sctp_send_ttl_ms;
 #endif
diff --git a/main.c b/main.c
index 86d132789cf..de1aed266d0 100644
--- a/main.c
+++ b/main.c
@@ -314,6 +314,8 @@ int is_main = 1; /* flag = is this the  "main" process? */
 char* pid_file = 0; /* filename as asked by user */
 char* pgid_file = 0;
 
+union sockaddr_union sctp_sec_addr = { .s.sa_family = 0 };
+uint32_t sctp_send_ttl_ms = 0;
 
 /**
  * Clean up on exit. This should be called before exiting.
diff --git a/modules/proto_sctp/sctp_server.c b/modules/proto_sctp/sctp_server.c
index f1a302dec8a..a4e20fc9da6 100644
--- a/modules/proto_sctp/sctp_server.c
+++ b/modules/proto_sctp/sctp_server.c
@@ -43,6 +43,7 @@
 	#include <linux/types.h>
 	#include <linux/errqueue.h>
 #endif
+#include <fcntl.h>
 
 #include "../../mem/shm_mem.h"
 #include "../../sr_module.h"
@@ -89,16 +90,32 @@ int proto_sctp_init_listener(struct socket_info* sock_info)
 	}
 #endif
 
+#ifdef SCTP_EVENTS
+	struct sctp_event_subscribe ev_s = {0};
+	ev_s.sctp_association_event = 1;
+	ev_s.sctp_send_failure_event = 1;
+
+	if(setsockopt(sock_info->socket, IPPROTO_SCTP, SCTP_EVENTS, &ev_s, sizeof(ev_s)) == -1) {
+		LM_WARN("setsockopt SCTP_EVENTS: %s (%d)\n",
+				strerror(errno), errno);
+	}
+#endif
+
 	/* this sockopt causes a kernel panic in some sctp implementations.
 	 * commenting it out. -gmarmon */
 
-	/* tos
 	optval=tos;
-	if (setsockopt(sock_info->socket, IPPROTO_IP, IP_TOS, (void*)&optval,
-			sizeof(optval)) ==-1){
-		LM_WARN("setsockopt tos: %s\n", strerror(errno));
+	if (addr->s.sa_family == AF_INET) {
+		if (setsockopt(sock_info->socket, IPPROTO_IP, IP_TOS, (void*)&optval,
+				sizeof(optval)) ==-1){
+			LM_WARN("setsockopt tos: %s\n", strerror(errno));
+		}
+	} else if (addr->s.sa_family == AF_INET6) {
+		if (setsockopt(sock_info->socket, IPPROTO_IPV6, IPV6_TCLASS, (void*)&optval,
+				sizeof(optval)) ==-1){
+			LM_WARN("setsockopt v6 tos: %s\n", strerror(errno));
+		}
 	}
-    */
 
 #if defined (__linux__) && defined(SCTP_ERRORS)
 	/* will SCTP_ERRORS ever be defined? -gmarmon */
@@ -125,6 +142,30 @@ int proto_sctp_init_listener(struct socket_info* sock_info)
 					" local address, try site local or global\n");
 		goto error;
 	}
+	if (sctp_sec_addr.s.sa_family != 0) {
+		if (sctp_bindx(sock_info->socket,
+			(struct sockaddr *)&sctp_sec_addr, 1,
+			SCTP_BINDX_ADD_ADDR) == -1)
+				LM_ERR("bindx(%x, %p) : %s\n",
+						sock_info->socket, &sctp_sec_addr.s,
+						strerror(errno));
+		else
+			LM_INFO("sctp bindx success to: %s\n",
+				inet_ntoa(((struct sockaddr_in *)&sctp_sec_addr)->sin_addr));
+	}
+
+	/* make non-blocking sending */
+	optval=fcntl(sock_info->socket, F_GETFL);
+	if (optval==-1){
+		LM_ERR("fnctl failed with %s [%d]\n", strerror(errno), errno);
+		goto error;
+	}
+	if (fcntl(sock_info->socket, F_SETFL, optval|O_NONBLOCK)==-1){
+		LM_ERR("fcntl: set non-blocking failed with %s [%d]\n",
+				strerror(errno), errno);
+		goto error;
+	}
+
 	if(listen(sock_info->socket, LISTEN_BACKLOG)<0){
 		LM_ERR("listen(%x, %d) on %s: %s\n",
 				sock_info->socket,
@@ -139,11 +180,37 @@ int proto_sctp_init_listener(struct socket_info* sock_info)
 	return -1;
 }
 
+static char *sctp_assoc_change_state2s(short int state)
+{
+	char *s;
+
+	switch(state) {
+		case SCTP_COMM_UP:
+			s = "SCTP_COMM_UP";
+			break;
+		case SCTP_COMM_LOST:
+			s = "SCTP_COMM_LOST";
+			break;
+		case SCTP_RESTART:
+			s = "SCTP_RESTART";
+			break;
+		case SCTP_SHUTDOWN_COMP:
+			s = "SCTP_SHUTDOWN_COMP";
+			break;
+		case SCTP_CANT_STR_ASSOC:
+			s = "SCTP_CANT_STR_ASSOC";
+			break;
+		default:
+			s = "UNKNOWN";
+			break;
+	};
+	return s;
+}
 
 int proto_sctp_read(struct socket_info *si, int* bytes_read)
 {
 	struct receive_info ri;
-	int len;
+	int len, msg_flags = 0;
 	static char buf [BUF_SIZE+1];
 	char *tmp;
 	unsigned int fromlen;
@@ -151,7 +218,7 @@ int proto_sctp_read(struct socket_info *si, int* bytes_read)
 
 	fromlen=sockaddru_len(si->su);
 	len = sctp_recvmsg(si->socket, buf, BUF_SIZE, &ri.src_su.s, &fromlen,
-		&sinfo, 0);
+		&sinfo, &msg_flags);
 	if (len==-1){
 		if (errno==EAGAIN){
 			LM_DBG("packet with bad checksum received\n");
@@ -163,6 +230,43 @@ int proto_sctp_read(struct socket_info *si, int* bytes_read)
 		return -2;
 	}
 
+	if (msg_flags & MSG_NOTIFICATION) {
+		union sctp_notification *snp = (union sctp_notification *)buf;
+
+		switch(snp->sn_header.sn_type) {
+			case SCTP_ASSOC_CHANGE:
+				su2ip_addr(&ri.src_ip, &ri.src_su);
+				if (snp->sn_assoc_change.sac_state == SCTP_COMM_UP)
+					LM_NOTICE("SCTP_ASSOC_CHANGE assoc_id: %d, peer ip:%s,"
+						"peer port:%d, state: %s\n",
+						snp->sn_assoc_change.sac_assoc_id,
+						ip_addr2a(&ri.src_ip),
+						su_getport(&ri.src_su),
+						sctp_assoc_change_state2s(snp->sn_assoc_change.sac_state));
+				else
+					LM_ERR("SCTP_ASSOC_CHANGE assoc_id: %d, peer ip:%s, "
+						"peer port:%d, state: %s\n",
+						snp->sn_assoc_change.sac_assoc_id,
+						ip_addr2a(&ri.src_ip),
+						su_getport(&ri.src_su),
+						sctp_assoc_change_state2s(snp->sn_assoc_change.sac_state));
+				break;
+			case SCTP_SEND_FAILED:
+				su2ip_addr(&ri.src_ip, &ri.src_su);
+				LM_ERR("SCTP_SEND_FAILED assoc_id: %d, peer ip:%s, "
+					"peer port:%d, error: %d\n",
+					snp->sn_send_failed.ssf_assoc_id,
+					ip_addr2a(&ri.src_ip),
+					su_getport(&ri.src_su),
+					snp->sn_send_failed.ssf_error);
+				break;
+			default:
+				LM_INFO("unexpected sctp notification type: %d\n",
+					snp->sn_header.sn_type);
+		}
+		return 0;
+	}
+
 	/* we must 0-term the messages, receive_msg expects it */
 	buf[len]=0; /* no need to save the previous char */
 
@@ -197,19 +301,21 @@ int proto_sctp_send(struct socket_info *source, char *buf, unsigned len,
 
 	tolen=sockaddru_len(*to);
 again:
-	n=sctp_sendmsg(source->socket, buf, len, &to->s, tolen, 0, 0, 0, 0, 0);
+	n=sctp_sendmsg(source->socket, buf, len, &to->s, tolen, 0, SCTP_UNORDERED, 0, sctp_send_ttl_ms, 0);
 #ifdef XL_DEBUG
 	LM_INFO("send status: %d\n", n);
 #endif
 	if (n==-1){
-		LM_ERR("sctp_sendmsg(sock,%p,%d,%p,%d,0,0,0,0,0): %s(%d)\n",
-				buf,len,&to->s,tolen, strerror(errno),errno);
-
 		if (errno==EINTR) goto again;
 		if (errno==EINVAL) {
 			LM_CRIT("invalid sendtoparameters\n"
 			"one possible reason is the server is bound to localhost and\n"
 			"attempts to send to the net\n");
+		} else if(errno == EAGAIN || errno == EWOULDBLOCK) {
+			LM_ERR(L_ERR, "sctp_sendmsg failed, send buffer full\n");
+		} else {
+			LM_ERR("sctp_sendmsg(sock,%p,%d,%p,%d...): %s(%d)\n",
+				buf,len,&to->s,tolen, strerror(errno),errno);
 		}
 	}
 	return n;
diff --git a/modules/sip_i/isup.c b/modules/sip_i/isup.c
index e8e22ef8cd7..99e748b12d3 100644
--- a/modules/sip_i/isup.c
+++ b/modules/sip_i/isup.c
@@ -152,6 +152,27 @@ static struct isup_subfield calling_party_num_subf[] = {
 	{str_init("Address signal"), {0, {{0, 0}}, {0}}},
 	SUBF_INIT_EMPTY};
 
+static struct isup_subfield generic_num_subf[] = {
+	{str_init("Number qualifier indicator"), {3,
+		{str_init("additional called party num"), str_init("additional connected num"),
+		 str_init("additional calling party num")}, {1,5,6}}},
+	{str_init("Odd/even indicator"), {2,
+		{str_init("even"), str_init("odd")}, {0,1}}},
+	{str_init("Nature of address indicator"), {4,
+		{str_init("subscriber"), str_init("unknown"), str_init("national"),
+		 str_init("international")}, {1,2,3,4}}},
+	{str_init("Number Incomplete indicator"), {2,
+		{str_init("complete"), str_init("incomplete")}, {0,1}}},
+	{str_init("Numbering plan indicator"), {3,
+		{str_init("ISDN"), str_init("Data"), str_init("Telex")}, {1,3,4}}},
+	{str_init("Address presentation restricted indicator"), {4,
+		{str_init("allowed"), str_init("restricted"), str_init("not available"),
+		 str_init("reserved")}, {0,1,2,3}}},
+	{str_init("Screening indicator"), {2,
+		{str_init("user"), str_init("network")}, {1,3}}},
+	{str_init("Address signal"), {0, {{0, 0}}, {0}}},
+	SUBF_INIT_EMPTY};
+
 static struct isup_subfield backward_call_ind_subf[] = {
 	{str_init("Charge indicator"), {2,
 		{str_init("no indication"), str_init("no charge")}, {0,1}}},
@@ -745,6 +766,64 @@ int calling_party_num_writef(int param_idx, int subfield_idx, unsigned char *par
 	return 0;
 }
 
+void generic_num_parsef(int subfield_idx, unsigned char *param_val, int len,
+									int *int_res, str *str_res)
+{
+	int idx[] =   {0,1,1,2,2,2,2};
+	int shift[] = {0,7,0,7,4,2,0};
+	int mask[] =  {0xff,1,0x7f,1,7,3,3};
+	int oddeven = (param_val[1] >> 7) & 0x1;
+
+	if (subfield_idx < 0 || subfield_idx > 7) {
+		LM_ERR("BUG - bad subfield\n");
+		return;
+	}
+
+	switch (subfield_idx) {
+	case 1:
+		*int_res = oddeven;
+		break;
+	case 7:
+		isup_get_number(str_res, param_val + 3, len - 3, oddeven);
+		break;
+	default:
+		*int_res = (param_val[idx[subfield_idx]] >> shift[subfield_idx]) & mask[subfield_idx];
+	}
+}
+
+int generic_num_writef(int param_idx, int subfield_idx, unsigned char *param_val, int *len,
+								pv_value_t *val)
+{
+	int new_val;
+	int num_len, oddeven;
+	str num;
+	int idx[] =   {0,1,1,2,2,2,2};
+	int mask[] =  {0xff,0x80,0x7f,0x80,0x70,0xc,0x3};
+	int shift[] = {0,7,0,7,4,2,0};
+
+	NUM_PARAM_GET_VAL_PV(7);
+
+	if (subfield_idx < 0 || subfield_idx > 7) {
+		LM_ERR("BUG - bad subfield\n");
+		return -1;
+	}
+
+	if (subfield_idx == 7) {
+		isup_put_number(param_val + 2, num, &num_len, &oddeven);
+		/* also set oddeven, just in case it wasn't already */
+		param_val[1] = SET_BITS(param_val[1], 0x80, 7, oddeven);
+	} else
+		param_val[idx[subfield_idx]] = SET_BITS(param_val[idx[subfield_idx]],
+										mask[subfield_idx], shift[subfield_idx], new_val);
+
+	if (subfield_idx == 7)
+		*len = num_len + 2;
+	else if (*len == 0)
+		*len = 2;
+
+	return 0;
+}
+
 void backward_call_ind_parsef(int subfield_idx, unsigned char *param_val, int len,
 									int *int_res, str *str_res)
 {
@@ -1144,7 +1223,7 @@ struct isup_param_data isup_params[NO_ISUP_PARAMS] = {
 	{ISUP_PARM_CORRELATION_ID, str_init("Correlation id"), NULL, NULL, NULL, NULL, 0},
 	{ISUP_PARM_SCF_ID, str_init("SCF id"), NULL, NULL, NULL, NULL, 0},
 	{ISUP_PARM_CALL_DIVERSION_TREATMENT_IND, str_init("Call diversion treatment indicators"), NULL, NULL, NULL, NULL, 0},
-	{ISUP_PARM_CALLED_IN_NUMBER, str_init("Called IN number"), NULL, NULL, NULL, NULL, 0},
+	{ISUP_PARM_CALLED_IN_NUMBER, str_init("Called IN number"), original_called_num_parsef, original_called_num_writef, original_called_num_subf, NULL, 0},
 	{ISUP_PARM_CALL_OFFERING_TREATMENT_IND, str_init("Call offering treatment indicators"), NULL, NULL, NULL, NULL, 0},
 	{ISUP_PARM_CHARGED_PARTY_IDENT, str_init("Charged party identification"), NULL, NULL, NULL, NULL, 0},
 	{ISUP_PARM_CONFERENCE_TREATMENT_IND, str_init("Conference treatment indicators"), NULL, NULL, NULL, NULL, 0},
@@ -1171,7 +1250,7 @@ struct isup_param_data isup_params[NO_ISUP_PARAMS] = {
 	{ISUP_PARM_REDIRECT_FORWARD_INFO, str_init("Redirect forward information"), NULL, NULL, NULL, NULL, 0},
 	{ISUP_PARM_REDIRECT_BACKWARD_INFO, str_init("Redirect backward information"), NULL, NULL, NULL, NULL, 0},
 	{ISUP_PARM_NUM_PORTABILITY_FORWARD_INFO, str_init("Number portability forward information"), NULL, NULL, NULL, NULL, 0},
-	{ISUP_PARM_GENERIC_ADDR, str_init("Generic Number"), NULL, NULL, NULL, NULL, 0},
+	{ISUP_PARM_GENERIC_ADDR, str_init("Generic Number"), generic_num_parsef, generic_num_writef, generic_num_subf, NULL, 0},
 	{ISUP_PARM_GENERIC_DIGITS, str_init("Generic Digits"), NULL, NULL, NULL, NULL, 0},
 	{ISUP_PARM_EGRESS_SERV, str_init("Egress Service"), NULL, NULL, NULL, NULL, 0},
 	{ISUP_PARM_JIP, str_init("Jurisdiction Information Parameter"), NULL, NULL, NULL, NULL, 0},
diff --git a/modules/tm/timer.c b/modules/tm/timer.c
index 1aa851c143d..d11b190aeee 100644
--- a/modules/tm/timer.c
+++ b/modules/tm/timer.c
@@ -286,7 +286,7 @@ inline static void retransmission_handler( struct timer_link *retr_tl )
 	/* re-transmission */
 	if ( r_buf->activ_type==TYPE_LOCAL_CANCEL
 		|| r_buf->activ_type==TYPE_REQUEST ) {
-			LM_DBG("retransmission_handler : request resending"
+			LM_INFO("retransmission_handler : request resending"
 				" (t=%p, %.9s ... )\n", r_buf->my_T, r_buf->buffer.s);
 			set_t(r_buf->my_T);
 			if (SEND_BUFFER( r_buf )==0) {